diff src/share/vm/oops/instanceKlass.cpp @ 13086:096c224171c4

Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/
author Doug Simon <doug.simon@oracle.com>
date Wed, 20 Nov 2013 00:10:38 +0100
parents cefad50507d8 6e1826d5c23e
children 02f27ecb4f3a
line wrap: on
line diff
--- a/src/share/vm/oops/instanceKlass.cpp	Tue Nov 19 17:44:26 2013 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Nov 20 00:10:38 2013 +0100
@@ -238,6 +238,13 @@
   }
 }
 
+// create a new array of vtable_indices for default methods
+Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
+  Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL);
+  assert(default_vtable_indices() == NULL, "only create once");
+  set_default_vtable_indices(vtable_indices);
+  return vtable_indices;
+}
 
 InstanceKlass::InstanceKlass(int vtable_len,
                              int itable_len,
@@ -263,6 +270,8 @@
   set_array_klasses(NULL);
   set_methods(NULL);
   set_method_ordering(NULL);
+  set_default_methods(NULL);
+  set_default_vtable_indices(NULL);
   set_local_interfaces(NULL);
   set_transitive_interfaces(NULL);
   init_implementor();
@@ -311,7 +320,8 @@
 
 void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
                                        Array<Method*>* methods) {
-  if (methods != NULL && methods != Universe::the_empty_method_array()) {
+  if (methods != NULL && methods != Universe::the_empty_method_array() &&
+      !methods->is_shared()) {
     for (int i = 0; i < methods->length(); i++) {
       Method* method = methods->at(i);
       if (method == NULL) continue;  // maybe null if error processing
@@ -335,13 +345,14 @@
     // check that the interfaces don't come from super class
     Array<Klass*>* sti = (super_klass == NULL) ? NULL :
                     InstanceKlass::cast(super_klass)->transitive_interfaces();
-    if (ti != sti) {
+    if (ti != sti && ti != NULL && !ti->is_shared()) {
       MetadataFactory::free_array<Klass*>(loader_data, ti);
     }
   }
 
   // local interfaces can be empty
-  if (local_interfaces != Universe::the_empty_klass_array()) {
+  if (local_interfaces != Universe::the_empty_klass_array() &&
+      local_interfaces != NULL && !local_interfaces->is_shared()) {
     MetadataFactory::free_array<Klass*>(loader_data, local_interfaces);
   }
 }
@@ -371,16 +382,37 @@
   deallocate_methods(loader_data, methods());
   set_methods(NULL);
 
-  if (method_ordering() != Universe::the_empty_int_array()) {
+  if (method_ordering() != NULL &&
+      method_ordering() != Universe::the_empty_int_array() &&
+      !method_ordering()->is_shared()) {
     MetadataFactory::free_array<int>(loader_data, method_ordering());
   }
   set_method_ordering(NULL);
 
+  // default methods can be empty
+  if (default_methods() != NULL &&
+      default_methods() != Universe::the_empty_method_array() &&
+      !default_methods()->is_shared()) {
+    MetadataFactory::free_array<Method*>(loader_data, default_methods());
+  }
+  // Do NOT deallocate the default methods, they are owned by superinterfaces.
+  set_default_methods(NULL);
+
+  // default methods vtable indices can be empty
+  if (default_vtable_indices() != NULL &&
+      !default_vtable_indices()->is_shared()) {
+    MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
+  }
+  set_default_vtable_indices(NULL);
+
+
   // This array is in Klass, but remove it with the InstanceKlass since
   // this place would be the only caller and it can share memory with transitive
   // interfaces.
-  if (secondary_supers() != Universe::the_empty_klass_array() &&
-      secondary_supers() != transitive_interfaces()) {
+  if (secondary_supers() != NULL &&
+      secondary_supers() != Universe::the_empty_klass_array() &&
+      secondary_supers() != transitive_interfaces() &&
+      !secondary_supers()->is_shared()) {
     MetadataFactory::free_array<Klass*>(loader_data, secondary_supers());
   }
   set_secondary_supers(NULL);
@@ -389,24 +421,32 @@
   set_transitive_interfaces(NULL);
   set_local_interfaces(NULL);
 
-  MetadataFactory::free_array<jushort>(loader_data, fields());
+  if (fields() != NULL && !fields()->is_shared()) {
+    MetadataFactory::free_array<jushort>(loader_data, fields());
+  }
   set_fields(NULL, 0);
 
   // If a method from a redefined class is using this constant pool, don't
   // delete it, yet.  The new class's previous version will point to this.
   if (constants() != NULL) {
     assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
-    MetadataFactory::free_metadata(loader_data, constants());
+    if (!constants()->is_shared()) {
+      MetadataFactory::free_metadata(loader_data, constants());
+    }
     set_constants(NULL);
   }
 
-  if (inner_classes() != Universe::the_empty_short_array()) {
+  if (inner_classes() != NULL &&
+      inner_classes() != Universe::the_empty_short_array() &&
+      !inner_classes()->is_shared()) {
     MetadataFactory::free_array<jushort>(loader_data, inner_classes());
   }
   set_inner_classes(NULL);
 
-  // We should deallocate the Annotations instance
-  MetadataFactory::free_metadata(loader_data, annotations());
+  // We should deallocate the Annotations instance if it's not in shared spaces.
+  if (annotations() != NULL && !annotations()->is_shared()) {
+    MetadataFactory::free_metadata(loader_data, annotations());
+  }
   set_annotations(NULL);
 }
 
@@ -456,15 +496,29 @@
   return java_lang_Class::signers(java_mirror());
 }
 
-volatile oop InstanceKlass::init_lock() const {
+oop InstanceKlass::init_lock() const {
   // return the init lock from the mirror
-  return java_lang_Class::init_lock(java_mirror());
+  oop lock = java_lang_Class::init_lock(java_mirror());
+  assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state
+         "only fully initialized state can have a null lock");
+  return lock;
+}
+
+// Set the initialization lock to null so the object can be GC'ed.  Any racing
+// threads to get this lock will see a null lock and will not lock.
+// That's okay because they all check for initialized state after getting
+// the lock and return.
+void InstanceKlass::fence_and_clear_init_lock() {
+  // make sure previous stores are all done, notably the init_state.
+  OrderAccess::storestore();
+  java_lang_Class::set_init_lock(java_mirror(), NULL);
+  assert(!is_not_initialized(), "class must be initialized now");
 }
 
 void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
   EXCEPTION_MARK;
-  volatile oop init_lock = this_oop->init_lock();
-  ObjectLocker ol(init_lock, THREAD);
+  oop init_lock = this_oop->init_lock();
+  ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
 
   // abort if someone beat us to the initialization
   if (!this_oop->is_not_initialized()) return;  // note: not equivalent to is_initialized()
@@ -483,6 +537,7 @@
   } else {
     // linking successfull, mark class as initialized
     this_oop->set_init_state (fully_initialized);
+    this_oop->fence_and_clear_init_lock();
     // trace
     if (TraceClassInitialization) {
       ResourceMark rm(THREAD);
@@ -608,8 +663,8 @@
 
   // verification & rewriting
   {
-    volatile oop init_lock = this_oop->init_lock();
-    ObjectLocker ol(init_lock, THREAD);
+    oop init_lock = this_oop->init_lock();
+    ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
     // rewritten will have been set if loader constraint error found
     // on an earlier link attempt
     // don't verify or rewrite if already rewritten
@@ -731,8 +786,8 @@
   // refer to the JVM book page 47 for description of steps
   // Step 1
   {
-    volatile oop init_lock = this_oop->init_lock();
-    ObjectLocker ol(init_lock, THREAD);
+    oop init_lock = this_oop->init_lock();
+    ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
 
     Thread *self = THREAD; // it's passed the current thread
 
@@ -879,9 +934,10 @@
 }
 
 void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
-  volatile oop init_lock = this_oop->init_lock();
-  ObjectLocker ol(init_lock, THREAD);
+  oop init_lock = this_oop->init_lock();
+  ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
   this_oop->set_init_state(state);
+  this_oop->fence_and_clear_init_lock();
   ol.notify_all(CHECK);
 }
 
@@ -1354,32 +1410,44 @@
   return -1;
 }
 
+// find_method looks up the name/signature in the local methods array
 Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
   return InstanceKlass::find_method(methods(), name, signature);
 }
 
+// find_method looks up the name/signature in the local methods array
 Method* InstanceKlass::find_method(
     Array<Method*>* methods, Symbol* name, Symbol* signature) {
+  int hit = find_method_index(methods, name, signature);
+  return hit >= 0 ? methods->at(hit): NULL;
+}
+
+// Used directly for default_methods to find the index into the
+// default_vtable_indices, and indirectly by find_method
+// find_method_index looks in the local methods array to return the index
+// of the matching name/signature
+int InstanceKlass::find_method_index(
+    Array<Method*>* methods, Symbol* name, Symbol* signature) {
   int hit = binary_search(methods, name);
   if (hit != -1) {
     Method* m = methods->at(hit);
     // Do linear search to find matching signature.  First, quick check
     // for common case
-    if (m->signature() == signature) return m;
+    if (m->signature() == signature) return hit;
     // search downwards through overloaded methods
     int i;
     for (i = hit - 1; i >= 0; --i) {
         Method* m = methods->at(i);
         assert(m->is_method(), "must be method");
         if (m->name() != name) break;
-        if (m->signature() == signature) return m;
+        if (m->signature() == signature) return i;
     }
     // search upwards
     for (i = hit + 1; i < methods->length(); ++i) {
         Method* m = methods->at(i);
         assert(m->is_method(), "must be method");
         if (m->name() != name) break;
-        if (m->signature() == signature) return m;
+        if (m->signature() == signature) return i;
     }
     // not found
 #ifdef ASSERT
@@ -1387,9 +1455,8 @@
     assert(index == -1, err_msg("binary search should have found entry %d", index));
 #endif
   }
-  return NULL;
+  return -1;
 }
-
 int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
   return find_method_by_name(methods(), name, end);
 }
@@ -1408,6 +1475,7 @@
   return -1;
 }
 
+// lookup_method searches both the local methods array and all superclasses methods arrays
 Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
   Klass* klass = const_cast<InstanceKlass*>(this);
   while (klass != NULL) {
@@ -1418,6 +1486,21 @@
   return NULL;
 }
 
+// lookup a method in the default methods list then in all transitive interfaces
+// Do NOT return private or static methods
+Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
+                                                         Symbol* signature) const {
+  Method* m = NULL;
+  if (default_methods() != NULL) {
+    m = find_method(default_methods(), name, signature);
+  }
+  // Look up interfaces
+  if (m == NULL) {
+    m = lookup_method_in_all_interfaces(name, signature);
+  }
+  return m;
+}
+
 // lookup a method in all the interfaces that this class implements
 // Do NOT return private or static methods, new in JDK8 which are not externally visible
 // They should only be found in the initial InterfaceMethodRef
@@ -2128,6 +2211,10 @@
            data = mdo->next_data(data)) {
         data->clean_weak_klass_links(is_alive);
       }
+      ParametersTypeData* parameters = mdo->parameters_type_data();
+      if (parameters != NULL) {
+        parameters->clean_weak_klass_links(is_alive);
+      }
     }
   }
 }
@@ -2310,15 +2397,38 @@
 
 
 const char* InstanceKlass::signature_name() const {
+  int hash_len = 0;
+  char hash_buf[40];
+
+  // If this is an anonymous class, append a hash to make the name unique
+  if (is_anonymous()) {
+    assert(EnableInvokeDynamic, "EnableInvokeDynamic was not set.");
+    intptr_t hash = (java_mirror() != NULL) ? java_mirror()->identity_hash() : 0;
+    sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
+    hash_len = (int)strlen(hash_buf);
+  }
+
+  // Get the internal name as a c string
   const char* src = (const char*) (name()->as_C_string());
   const int src_length = (int)strlen(src);
-  char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3);
-  int src_index = 0;
+
+  char* dest = NEW_RESOURCE_ARRAY(char, src_length + hash_len + 3);
+
+  // Add L as type indicator
   int dest_index = 0;
   dest[dest_index++] = 'L';
-  while (src_index < src_length) {
+
+  // Add the actual class name
+  for (int src_index = 0; src_index < src_length; ) {
     dest[dest_index++] = src[src_index++];
   }
+
+  // If we have a hash, append it
+  for (int hash_index = 0; hash_index < hash_len; ) {
+    dest[dest_index++] = hash_buf[hash_index++];
+  }
+
+  // Add the semicolon and the NULL
   dest[dest_index++] = ';';
   dest[dest_index] = '\0';
   return dest;
@@ -2548,6 +2658,42 @@
   return m;
 }
 
+
+#if INCLUDE_JVMTI
+// update default_methods for redefineclasses for methods that are
+// not yet in the vtable due to concurrent subclass define and superinterface
+// redefinition
+// Note: those in the vtable, should have been updated via adjust_method_entries
+void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods,
+                                           int methods_length, bool* trace_name_printed) {
+  // search the default_methods for uses of either obsolete or EMCP methods
+  if (default_methods() != NULL) {
+    for (int j = 0; j < methods_length; j++) {
+      Method* old_method = old_methods[j];
+      Method* new_method = new_methods[j];
+
+      for (int index = 0; index < default_methods()->length(); index ++) {
+        if (default_methods()->at(index) == old_method) {
+          default_methods()->at_put(index, new_method);
+          if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
+            if (!(*trace_name_printed)) {
+              // RC_TRACE_MESG macro has an embedded ResourceMark
+              RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
+                             external_name(),
+                             old_method->method_holder()->external_name()));
+              *trace_name_printed = true;
+            }
+            RC_TRACE(0x00100000, ("default method update: %s(%s) ",
+                                  new_method->name()->as_C_string(),
+                                  new_method->signature()->as_C_string()));
+          }
+        }
+      }
+    }
+  }
+}
+#endif // INCLUDE_JVMTI
+
 // On-stack replacement stuff
 void InstanceKlass::add_osr_nmethod(nmethod* n) {
   // only one compilation can be active
@@ -2742,11 +2888,21 @@
   st->print(BULLET"methods:           "); methods()->print_value_on(st);                  st->cr();
   if (Verbose || WizardMode) {
     Array<Method*>* method_array = methods();
-    for(int i = 0; i < method_array->length(); i++) {
+    for (int i = 0; i < method_array->length(); i++) {
       st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
     }
   }
-  st->print(BULLET"method ordering:   "); method_ordering()->print_value_on(st);       st->cr();
+  st->print(BULLET"method ordering:   "); method_ordering()->print_value_on(st);      st->cr();
+  st->print(BULLET"default_methods:   "); default_methods()->print_value_on(st);      st->cr();
+  if (Verbose && default_methods() != NULL) {
+    Array<Method*>* method_array = default_methods();
+    for (int i = 0; i < method_array->length(); i++) {
+      st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
+    }
+  }
+  if (default_vtable_indices() != NULL) {
+    st->print(BULLET"default vtable indices:   "); default_vtable_indices()->print_value_on(st);       st->cr();
+  }
   st->print(BULLET"local interfaces:  "); local_interfaces()->print_value_on(st);      st->cr();
   st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr();
   st->print(BULLET"constants:         "); constants()->print_value_on(st);         st->cr();
@@ -3099,6 +3255,19 @@
     }
   }
 
+  // Verify default methods
+  if (default_methods() != NULL) {
+    Array<Method*>* methods = this->default_methods();
+    for (int j = 0; j < methods->length(); j++) {
+      guarantee(methods->at(j)->is_method(), "non-method in methods array");
+    }
+    for (int j = 0; j < methods->length() - 1; j++) {
+      Method* m1 = methods->at(j);
+      Method* m2 = methods->at(j + 1);
+      guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
+    }
+  }
+
   // Verify JNI static field identifiers
   if (jni_ids() != NULL) {
     jni_ids()->verify(this);