8148481: Devirtualize Klass::vtable
Summary: Move remainder of vtable related methods to Klass
Reviewed-by: cjplummer, coleenp
--- 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();
}