8148481: Devirtualize Klass::vtable
authormgerdin
Tue, 19 Jan 2016 12:07:32 +0100
changeset 35900 d64cf9290fc4
parent 35899 0dbc821628fc
child 35901 f5028c67e7cb
8148481: Devirtualize Klass::vtable Summary: Move remainder of vtable related methods to Klass Reviewed-by: cjplummer, coleenp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/src/share/vm/oops/arrayKlass.cpp
hotspot/src/share/vm/oops/arrayKlass.hpp
hotspot/src/share/vm/oops/cpCache.cpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/oops/klass.cpp
hotspot/src/share/vm/oops/klass.hpp
hotspot/src/share/vm/prims/jni.cpp
hotspot/src/share/vm/runtime/reflection.cpp
hotspot/src/share/vm/utilities/debug.cpp
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,7 +168,7 @@
   } else if (!resolved_klass->is_interface()) {
     // A default or miranda method.  Compute the vtable index.
     ResourceMark rm;
-    klassVtable* vt = InstanceKlass::cast(resolved_klass)->vtable();
+    klassVtable* vt = resolved_klass->vtable();
     index = LinkResolver::vtable_index_of_interface_method(resolved_klass,
                            resolved_method);
     assert(index >= 0 , "we should have valid vtable index at this point");
@@ -1227,8 +1227,7 @@
                            resolved_method);
     assert(vtable_index >= 0 , "we should have valid vtable index at this point");
 
-    InstanceKlass* inst = InstanceKlass::cast(recv_klass());
-    selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
+    selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
   } else {
     // at this point we are sure that resolved_method is virtual and not
     // a default or miranda method; therefore, it must have a valid vtable index.
@@ -1243,10 +1242,7 @@
       assert(resolved_method->can_be_statically_bound(), "cannot override this method");
       selected_method = resolved_method;
     } else {
-      // recv_klass might be an arrayKlassOop but all vtables start at
-      // the same place. The cast is to avoid virtual call and assertion.
-      InstanceKlass* inst = (InstanceKlass*)recv_klass();
-      selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
+      selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
     }
   }
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -655,8 +655,7 @@
         vtable_index = LinkResolver::vtable_index_of_interface_method(holder_klass, resolved_method);
         assert(vtable_index >= 0 , "we should have valid vtable index at this point");
 
-        InstanceKlass* inst = InstanceKlass::cast(recv_klass);
-        selected_method = inst->method_at_vtable(vtable_index);
+        selected_method = recv_klass->method_at_vtable(vtable_index);
       } else {
         // at this point we are sure that resolved_method is virtual and not
         // a miranda method; therefore, it must have a valid vtable index.
@@ -671,10 +670,7 @@
           assert(resolved_method->can_be_statically_bound(), "cannot override this method");
           selected_method = resolved_method();
         } else {
-          // recv_klass might be an arrayKlassOop but all vtables start at
-          // the same place. The cast is to avoid virtual call and assertion.
-          InstanceKlass* inst = (InstanceKlass*)recv_klass;
-          selected_method = inst->method_at_vtable(vtable_index);
+          selected_method = recv_klass->method_at_vtable(vtable_index);
         }
       }
       oop result = CompilerToVM::get_jvmci_method(selected_method, CHECK_NULL);
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -117,19 +117,6 @@
          || k == SystemDictionary::Serializable_klass();
 }
 
-
-inline intptr_t* ArrayKlass::start_of_vtable() const {
-  // all vtables start at the same place, that's why we use InstanceKlass::header_size here
-  return ((intptr_t*)this) + InstanceKlass::header_size();
-}
-
-
-klassVtable* ArrayKlass::vtable() const {
-  KlassHandle kh(Thread::current(), this);
-  return new klassVtable(kh, start_of_vtable(), vtable_length() / vtableEntry::size());
-}
-
-
 objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) {
   if (length < 0) {
     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp	Tue Jan 19 12:07:32 2016 +0100
@@ -98,7 +98,6 @@
   bool compute_is_subtype_of(Klass* k);
 
   // Sizing
-  static int header_size()                 { return sizeof(ArrayKlass)/wordSize; }
   static int static_size(int header_size);
 
 #if INCLUDE_SERVICES
@@ -109,12 +108,6 @@
   }
 #endif
 
-  // Java vtable
-  klassVtable* vtable() const;             // return new klassVtable
- protected:
-  inline intptr_t* start_of_vtable() const;
-
- public:
   // Iterators
   void array_klasses_do(void f(Klass* k));
   void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -394,9 +394,7 @@
         int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index());
         if (cpool->tag_at(holder_index).is_klass()) {
           Klass* klass = cpool->resolved_klass_at(holder_index);
-          if (!klass->is_instance_klass())
-            klass = SystemDictionary::Object_klass();
-          return InstanceKlass::cast(klass)->method_at_vtable(f2_as_index());
+          return klass->method_at_vtable(f2_as_index());
         }
       }
       break;
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -364,10 +364,6 @@
   return !is_initialized();
 }
 
-klassVtable* InstanceKlass::vtable() const {
-  return new klassVtable(this, start_of_vtable(), vtable_length() / vtableEntry::size());
-}
-
 klassItable* InstanceKlass::itable() const {
   return new klassItable(instanceKlassHandle(this));
 }
@@ -2667,6 +2663,10 @@
   }
 }
 
+static void print_vtable(vtableEntry* start, int len, outputStream* st) {
+  return print_vtable(reinterpret_cast<intptr_t*>(start), len, st);
+}
+
 void InstanceKlass::print_on(outputStream* st) const {
   assert(is_klass(), "must be klass");
   Klass::print_on(st);
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Tue Jan 19 12:07:32 2016 +0100
@@ -944,12 +944,11 @@
   virtual void collect_statistics(KlassSizeStats *sz) const;
 #endif
 
-  intptr_t* start_of_vtable() const        { return (intptr_t*) ((address)this + in_bytes(vtable_start_offset())); }
-  intptr_t* start_of_itable() const        { return start_of_vtable() + vtable_length(); }
+  intptr_t* start_of_itable()   const { return (intptr_t*)start_of_vtable() + vtable_length(); }
+  intptr_t* end_of_itable()     const { return start_of_itable() + itable_length(); }
+
   int  itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; }
 
-  intptr_t* end_of_itable() const          { return start_of_itable() + itable_length(); }
-
   address static_field_addr(int offset);
 
   OopMapBlock* start_of_nonstatic_oop_maps() const {
@@ -997,9 +996,7 @@
     return !layout_helper_needs_slow_path(layout_helper());
   }
 
-  // Java vtable/itable
-  klassVtable* vtable() const;        // return new klassVtable wrapper
-  inline Method* method_at_vtable(int index);
+  // Java itable
   klassItable* itable() const;        // return new klassItable wrapper
   Method* method_at_itable(Klass* holder, int index, TRAPS);
 
@@ -1249,17 +1246,6 @@
   void oop_verify_on(oop obj, outputStream* st);
 };
 
-inline Method* InstanceKlass::method_at_vtable(int index)  {
-#ifndef PRODUCT
-  assert(index >= 0, "valid vtable index");
-  if (DebugVtables) {
-    verify_vtable_index(index);
-  }
-#endif
-  vtableEntry* ve = (vtableEntry*)start_of_vtable();
-  return ve[index].method();
-}
-
 // for adding methods
 // UNSET_IDNUM return means no more ids available
 inline u2 InstanceKlass::next_method_idnum() {
--- a/hotspot/src/share/vm/oops/klass.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/klass.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -659,6 +659,24 @@
   guarantee(obj->klass()->is_klass(), "klass field is not a klass");
 }
 
+klassVtable* Klass::vtable() const {
+  return new klassVtable(this, start_of_vtable(), vtable_length() / vtableEntry::size());
+}
+
+vtableEntry* Klass::start_of_vtable() const {
+  return (vtableEntry*) ((address)this + in_bytes(vtable_start_offset()));
+}
+
+Method* Klass::method_at_vtable(int index)  {
+#ifndef PRODUCT
+  assert(index >= 0, "valid vtable index");
+  if (DebugVtables) {
+    verify_vtable_index(index);
+  }
+#endif
+  return start_of_vtable()[index].method();
+}
+
 ByteSize Klass::vtable_start_offset() {
   return in_ByteSize(InstanceKlass::header_size() * wordSize);
 }
--- a/hotspot/src/share/vm/oops/klass.hpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/oops/klass.hpp	Tue Jan 19 12:07:32 2016 +0100
@@ -57,6 +57,7 @@
 class PSPromotionManager;
 class KlassSizeStats;
 class fieldDescriptor;
+class vtableEntry;
 
 class Klass : public Metadata {
   friend class VMStructs;
@@ -377,7 +378,7 @@
 #endif
 
   // vtables
-  virtual klassVtable* vtable() const = 0;
+  klassVtable* vtable() const;
   int vtable_length() const { return _vtable_len; }
 
   // subclass check
@@ -443,7 +444,10 @@
 
   void set_vtable_length(int len) { _vtable_len= len; }
 
+  vtableEntry* start_of_vtable() const;
  public:
+  Method* method_at_vtable(int index);
+
   static ByteSize vtable_start_offset();
   static ByteSize vtable_length_offset() {
     return byte_offset_of(Klass, _vtable_len);
--- a/hotspot/src/share/vm/prims/jni.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/prims/jni.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -1131,11 +1131,7 @@
       assert(m->valid_vtable_index(), "no valid vtable index");
       int vtbl_index = m->vtable_index();
       if (vtbl_index != Method::nonvirtual_vtable_index) {
-        Klass* k = h_recv->klass();
-        // k might be an arrayKlassOop but all vtables start at
-        // the same place. The cast is to avoid virtual call and assertion.
-        InstanceKlass *ik = (InstanceKlass*)k;
-        selected_method = ik->method_at_vtable(vtbl_index);
+        selected_method = h_recv->klass()->method_at_vtable(vtbl_index);
       } else {
         // final method
         selected_method = m;
--- a/hotspot/src/share/vm/runtime/reflection.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -939,10 +939,7 @@
         int index = reflected_method->vtable_index();
         method = reflected_method;
         if (index != Method::nonvirtual_vtable_index) {
-          // target_klass might be an arrayKlassOop but all vtables start at
-          // the same place. The cast is to avoid virtual call and assertion.
-          InstanceKlass* inst = (InstanceKlass*)target_klass();
-          method = methodHandle(THREAD, inst->method_at_vtable(index));
+          method = methodHandle(THREAD, target_klass->method_at_vtable(index));
         }
         if (!method.is_null()) {
           // Check for abstract methods as well
--- a/hotspot/src/share/vm/utilities/debug.cpp	Tue Dec 01 10:35:49 2015 +0100
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Tue Jan 19 12:07:32 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -461,7 +461,7 @@
 extern "C" void dump_vtable(address p) {
   Command c("dump_vtable");
   Klass* k = (Klass*)p;
-  InstanceKlass::cast(k)->vtable()->print();
+  k->vtable()->print();
 }