src/share/vm/oops/klassVtable.cpp

Print this page

        

@@ -58,11 +58,11 @@
 // entered as a public abstract method in C's vtable.  From then on it should
 // treated as any other public method in C for method over-ride purposes.
 void klassVtable::compute_vtable_size_and_num_mirandas(
     int* vtable_length_ret, int* num_new_mirandas,
     GrowableArray<Method*>* all_mirandas, const Klass* super,
-    Array<Method*>* methods, AccessFlags class_flags,
+    Array<Method*>* methods, AccessFlags class_flags, u2 major_version,
     Handle classloader, Symbol* classname, Array<Klass*>* local_interfaces,
     TRAPS) {
   NoSafepointVerifier nsv;
 
   // set up default result values

@@ -75,11 +75,11 @@
   int len = methods->length();
   for (int i = 0; i < len; i++) {
     assert(methods->at(i)->is_method(), "must be a Method*");
     methodHandle mh(THREAD, methods->at(i));
 
-    if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) {
+    if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, major_version, THREAD)) {
       vtable_length += vtableEntry::size(); // we need a new entry
     }
   }
 
   GrowableArray<Method*> new_mirandas(20);

@@ -254,14 +254,19 @@
       initialized = fill_in_mirandas(initialized);
     }
 
     // In class hierarchies where the accessibility is not increasing (i.e., going from private ->
     // package_private -> public/protected), the vtable might actually be smaller than our initial
-    // calculation.
+    // calculation, for classfile versions for which we do not do transitive override
+    // calculations.
+    if (ik()->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) {
+      assert(initialized == _length, "vtable initialization failed");
+    } else {
     assert(initialized <= _length, "vtable initialization failed");
     for(;initialized < _length; initialized++) {
-      put_method_at(NULL, initialized);
+        table()[initialized].clear();
+      }
     }
     NOT_PRODUCT(verify(tty, true));
   }
 }
 

@@ -296,13 +301,13 @@
       if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) {
         if (log_develop_is_enabled(Trace, vtables)) {
           ResourceMark rm(THREAD);
           outputStream* logst = Log(vtables)::trace_stream();
           char* sig = target_method()->name_and_sig_as_C_string();
-          logst->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
+          logst->print("transitive overriding superclass %s with %s index %d, original flags: ",
                        supersuperklass->internal_name(),
-                       _klass->internal_name(), sig, vtable_index);
+                       sig, vtable_index);
           super_method->print_linkage_flags(logst);
           logst->print("overriders flags: ");
           target_method->print_linkage_flags(logst);
           logst->cr();
         }

@@ -328,15 +333,15 @@
   if (log_develop_is_enabled(Trace, vtables)) {
     ResourceMark rm(thread);
     outputStream* logst = Log(vtables)::trace_stream();
     char* sig = target_method()->name_and_sig_as_C_string();
     if (overrides) {
-      logst->print("overriding with %s::%s index %d, original flags: ",
-                   target_klass->internal_name(), sig, i);
+      logst->print("overriding with %s index %d, original flags: ",
+                   sig, i);
     } else {
-      logst->print("NOT overriding with %s::%s index %d, original flags: ",
-                   target_klass->internal_name(), sig, i);
+      logst->print("NOT overriding with %s index %d, original flags: ",
+                   sig, i);
     }
     super_method->print_linkage_flags(logst);
     logst->print("overriders flags: ");
     target_method->print_linkage_flags(logst);
     logst->cr();

@@ -564,10 +569,11 @@
 bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
                                          const Klass* super,
                                          Handle classloader,
                                          Symbol* classname,
                                          AccessFlags class_flags,
+                                         u2 major_version,
                                          TRAPS) {
   if (class_flags.is_interface()) {
     // Interfaces do not use vtables, except for java.lang.Object methods,
     // so there is no point to assigning
     // a vtable index to any of their local methods.  If we refrain from doing this,

@@ -644,12 +650,16 @@
         return false;
       // else keep looking for transitive overrides
       }
     }
 
-    // Start with lookup result and continue to search up
+    // Start with lookup result and continue to search up, for versions supporting transitive override
+    if (major_version >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) {
     k = superk->super(); // haven't found an override match yet; continue to look
+    } else {
+      break;
+    }
   }
 
   // if the target method is public or protected it may have a matching
   // miranda method in the super, whose entry it should re-use.
   // Actually, to handle cases that javac would not generate, we need

@@ -1498,19 +1508,25 @@
 }
 #endif
 
 void vtableEntry::verify(klassVtable* vt, outputStream* st) {
   NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true));
+  KlassHandle vtklass_h = vt->klass();
+  Klass* vtklass = vtklass_h();
+  if (InstanceKlass::cast(vtklass)->major_version() >= klassVtable::VTABLE_TRANSITIVE_OVERRIDE_VERSION) {
   assert(method() != NULL, "must have set method");
+  } 
+  if (method() != NULL) {
   method()->verify();
   // we sub_type, because it could be a miranda method
-  if (!vt->klass()->is_subtype_of(method()->method_holder())) {
+    if (!vtklass_h->is_subtype_of(method()->method_holder())) {
 #ifndef PRODUCT
     print();
 #endif
     fatal("vtableEntry " PTR_FORMAT ": method is from subclass", p2i(this));
   }
+ }
 }
 
 #ifndef PRODUCT
 
 void vtableEntry::print() {