From b35f73bec878c712e9fed512361b5fa424dc3fda Mon Sep 17 00:00:00 2001
Date: Thu, 21 Sep 2023 15:15:17 +0800
Subject: add make-Appcds-jsa-rw-region-deterministic

---
 .../share/vm/classfile/classFileParser.hpp    |  1 +
 .../share/vm/classfile/classLoaderData.hpp    |  2 +-
 .../src/share/vm/classfile/defaultMethods.cpp |  6 +++-
 hotspot/src/share/vm/classfile/dictionary.cpp |  6 +++-
 hotspot/src/share/vm/classfile/dictionary.hpp |  2 +-
 .../share/vm/classfile/systemDictionary.cpp   | 24 ++++++++++++++--
 .../share/vm/classfile/systemDictionary.hpp   |  2 +-
 .../src/share/vm/memory/metaspaceShared.cpp   | 28 +++++++++++--------
 hotspot/src/share/vm/runtime/mutex.cpp        |  2 +-
 hotspot/src/share/vm/runtime/os.cpp           |  5 +++-
 hotspot/src/share/vm/runtime/os.hpp           |  2 +-
 hotspot/src/share/vm/runtime/synchronizer.cpp |  2 +-
 12 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp
index 1900f0abf..dda7c92d9 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp
@@ -42,6 +42,7 @@ class FieldLayoutInfo;
 // The bytes describing the class file structure is read from a Stream object
 
 class ClassFileParser VALUE_OBJ_CLASS_SPEC {
+  friend class SystemDictionary; 
  private:
   bool _need_verify;
   bool _relax_verify;
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index 7155257ed..0bb2e1000 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -211,7 +211,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
   JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
 
   void set_next(ClassLoaderData* next) { _next = next; }
-  ClassLoaderData* next() const        { return _next; }
 
   ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies);
   ~ClassLoaderData();
@@ -238,6 +237,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
   void clear_claimed()          { _claimed = 0; }
   bool claimed() const          { return _claimed == 1; }
   bool claim();
+  ClassLoaderData* next() const        { return _next; }
 
   bool is_alive(BoolObjectClosure* is_alive_closure) const;
 
diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp
index 196622aed..0becb35ed 100644
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp
@@ -909,7 +909,11 @@ static void switchover_constant_pool(BytecodeConstantPool* bpool,
   if (new_methods->length() > 0) {
     ConstantPool* cp = bpool->create_constant_pool(CHECK);
     if (cp != klass->constants()) {
-      klass->class_loader_data()->add_to_deallocate_list(klass->constants());
+      ClassLoaderData* loader_data = klass->class_loader_data();
+      while (DumpSharedSpaces && loader_data->next() != NULL) {
+        loader_data = loader_data->next();
+      }
+      loader_data->add_to_deallocate_list(klass->constants());
       klass->set_constants(cp);
       cp->set_pool_holder(klass);
 
diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp
index d41372ecc..530c3fdfb 100644
--- a/hotspot/src/share/vm/classfile/dictionary.cpp
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp
@@ -196,7 +196,7 @@ void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
   _pd_cache_table->roots_oops_do(strong, weak);
 }
 
-void Dictionary::remove_classes_in_error_state() {
+void Dictionary::remove_classes_in_error_state(void f(Klass*)) {
   assert(DynamicDumpSharedSpaces || DumpSharedSpaces, "supported only when dumping");
   DictionaryEntry* probe = NULL;
   for (int index = 0; index < table_size(); index++) {
@@ -209,6 +209,7 @@ void Dictionary::remove_classes_in_error_state() {
           _current_class_entry = NULL;
         }
         free_entry(probe);
+        f(ik);
         ResourceMark rm;
         tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name());
         continue;
@@ -420,6 +421,9 @@ void Dictionary::add_protection_domain(int index, unsigned int hash,
                                        instanceKlassHandle klass,
                                        ClassLoaderData* loader_data, Handle protection_domain,
                                        TRAPS) {
+  if (DumpSharedSpaces) {
+    return;
+  }
   Symbol*  klass_name = klass->name();
   DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data);
 
diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp
index 9ed0defb8..8a88fa2e4 100644
--- a/hotspot/src/share/vm/classfile/dictionary.hpp
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp
@@ -103,7 +103,7 @@ public:
   void methods_do(void f(Method*));
 
   void unlink(BoolObjectClosure* is_alive);
-  void remove_classes_in_error_state();
+  void remove_classes_in_error_state(void f(Klass*));
 
   // Classes loaded by the bootstrap loader are always strongly reachable.
   // If we're not doing class unloading, all classes are strongly reachable.
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp
index 9089a762d..c8f66e830 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp
@@ -1170,6 +1170,26 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
                               parsed_name,
                               verify,
                               THREAD);
+    if (DumpSharedSpaces && k.is_null()) {
+      if (loader_data) {
+        ClassLoaderData* cld = loader_data;
+        while (cld->next() != NULL)
+          cld = cld->next();
+        ConstantPool* cp = parser._cp;
+        if (cp) {
+          cld->add_to_deallocate_list(cp);
+        }
+        Array<Method*>* m = parser._methods;
+        if (m) {
+          for (int i = 0; i < m->length(); i++) {
+            Method* method = m->at(i);
+            if (method != NULL) {
+              cld->add_to_deallocate_list(method);
+            }
+          }
+        }
+      }
+    }
     const char* pkg = "java/";
     size_t pkglen = strlen(pkg);
     if (!HAS_PENDING_EXCEPTION &&
@@ -2036,8 +2056,8 @@ void SystemDictionary::methods_do(void f(Method*)) {
   invoke_method_table()->methods_do(f);
 }
 
-void SystemDictionary::remove_classes_in_error_state() {
-  dictionary()->remove_classes_in_error_state();
+void SystemDictionary::remove_classes_in_error_state(void f(Klass*)) {
+  dictionary()->remove_classes_in_error_state(f);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp
index cfc15c20e..e39c1de62 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp
@@ -347,7 +347,7 @@ public:
   static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive = true);
 
   // Used by DumpSharedSpaces only to remove classes that failed verification
-  static void remove_classes_in_error_state();
+  static void remove_classes_in_error_state(void f(Klass*));
 
   static int calculate_systemdictionary_size(int loadedclasses);
 
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
index b31d0a3fb..e6bd39d85 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
@@ -216,6 +216,10 @@ static void patch_deallocate_meta_vtables(void** vtbl_list, void* new_vtable_sta
         ((ConstantPool*)m)->remove_unshareable_info();
         *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m);
       }
+      else if (m->is_method()) {
+        ((Method*)m)->remove_unshareable_info();
+        *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m);
+      }
     }
   }
 }
@@ -442,6 +446,7 @@ public:
     _md_vs.initialize(md_rs, SharedMiscDataSize);
     _mc_vs.initialize(mc_rs, SharedMiscCodeSize);
     _class_promote_order = class_promote_order;
+    _global_klass_objects = new GrowableArray<Klass*>(1000);
   }
 
   VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
@@ -465,13 +470,6 @@ void VM_PopulateDumpSharedSpace::doit() {
             SystemDictionary::invoke_method_table()->number_of_entries() == 0,
             "invoke method table is not saved");
 
-  // At this point, many classes have been loaded.
-  // Gather systemDictionary classes in a global array and do everything to
-  // that so we don't have to walk the SystemDictionary again.
-  _global_klass_objects = new GrowableArray<Klass*>(1000);
-  Universe::basic_type_classes_do(collect_classes);
-  SystemDictionary::classes_do(collect_classes);
-
   tty->print_cr("Number of classes %d", _global_klass_objects->length());
   {
     int num_type_array = 0, num_obj_array = 0, num_inst = 0;
@@ -702,7 +700,7 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
 
     // record error message, remove error state, and continue to dump jsa file
     tty->print_cr("Please remove the unverifiable classes from your class list and try again");
-    SystemDictionary::remove_classes_in_error_state();
+    SystemDictionary::remove_classes_in_error_state(collect_classes);
   }
 
   // Copy the dependencies from C_HEAP-alloced GrowableArrays to RO-alloced
@@ -785,6 +783,9 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
   // Rewrite and link classes
   tty->print_cr("Rewriting and linking classes ...");
 
+  // Create here because link_and_cleanup_shared_classes need the _global_klass_objects 
+  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+  VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
   // Link any classes which got missed. This would happen if we have loaded classes that
   // were not explicitly specified in the classlist. E.g., if an interface implemented by class K
   // fails verification, all other interfaces that were not specified in the classlist but
@@ -792,10 +793,13 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
   link_and_cleanup_shared_classes(CATCH);
   tty->print_cr("Rewriting and linking classes: done");
 
-  // Create and dump the shared spaces.   Everything so far is loaded
-  // with the null class loader.
-  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
-  VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
+  // At this point, many classes have been loaded.
+  // Gather systemDictionary classes in a global array and do everything to
+  // that so we don't have to walk the SystemDictionary again.
+  Universe::basic_type_classes_do(collect_classes);
+  SystemDictionary::classes_do(collect_classes);
+
+  // Dump the shared spaces.
   VMThread::execute(&op);
 
   // Since various initialization steps have been undone by this process,
diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp
index 92bd50662..b1159d02e 100644
--- a/hotspot/src/share/vm/runtime/mutex.cpp
+++ b/hotspot/src/share/vm/runtime/mutex.cpp
@@ -276,7 +276,7 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 // Useful for spin loops as the compiler can't optimize it away.
 
 static inline jint MarsagliaXORV (jint x) {
-  if (x == 0) x = 1|os::random() ;
+  if (x == 0) x = 1|os::random(DumpSharedSpaces) ;
   x ^= x << 6;
   x ^= ((unsigned)x) >> 21;
   x ^= x << 7 ;
diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp
index 43d66e85e..ff35e8b3a 100644
--- a/hotspot/src/share/vm/runtime/os.cpp
+++ b/hotspot/src/share/vm/runtime/os.cpp
@@ -770,7 +770,7 @@ void os::init_random(long initval) {
 }
 
 
-long os::random() {
+long os::random(bool skip) {
   /* standard, well-known linear congruential random generator with
    * next_rand = (16807*seed) mod (2**31-1)
    * see
@@ -801,6 +801,9 @@ long os::random() {
     lo &= m;
     ++lo;
   }
+  if (skip) {
+    return lo;
+  }
   return (_rand_seed = lo);
 }
 
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index 988977b17..07beeed8c 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -800,7 +800,7 @@ class os: AllStatic {
   static int   sigexitnum_pd();
 
   // random number generation
-  static long random();                    // return 32bit pseudorandom number
+  static long random(bool skip = false);                    // return 32bit pseudorandom number
   static void init_random(long initval);   // initialize random sequence
 
   // Structured OS Exception support
diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp
index 8400bff11..e83ecd1d2 100644
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp
@@ -1657,7 +1657,7 @@ void ObjectSynchronizer::deflate_idle_monitors() {
 
   // TODO: Add objectMonitor leak detection.
   // Audit/inventory the objectMonitors -- make sure they're all accounted for.
-  GVars.stwRandom = os::random() ;
+  GVars.stwRandom = os::random(DumpSharedSpaces) ;
   GVars.stwCycle ++ ;
 }
 
-- 
2.22.0

