8148481: Devirtualize Klass::vtable

Move remainder of vtable related methods to Klass

Reviewed-by: cjplummer, coleenp
This commit is contained in:
Mikael Gerdin 2016-01-19 12:07:32 +01:00
parent 211dc93a85
commit 3cda485fe5
12 changed files with 44 additions and 73 deletions

View file

@ -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 @@ CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) {
} 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 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
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 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
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));
}
}

View file

@ -655,8 +655,7 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t
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 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t
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);

View file

@ -117,19 +117,6 @@ bool ArrayKlass::compute_is_subtype_of(Klass* k) {
|| 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());

View file

@ -98,7 +98,6 @@ class ArrayKlass: public Klass {
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 @@ class ArrayKlass: public Klass {
}
#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);

View file

@ -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 @@ Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpo
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;

View file

@ -364,10 +364,6 @@ bool InstanceKlass::should_be_initialized() const {
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(intptr_t* start, int len, outputStream* st) {
}
}
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);

View file

@ -944,12 +944,11 @@ public:
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(); }
int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; }
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; }
address static_field_addr(int offset);
OopMapBlock* start_of_nonstatic_oop_maps() const {
@ -997,9 +996,7 @@ public:
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 @@ public:
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() {

View file

@ -659,6 +659,24 @@ void Klass::oop_verify_on(oop obj, outputStream* st) {
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);
}

View file

@ -57,6 +57,7 @@ class ParCompactionManager;
class PSPromotionManager;
class KlassSizeStats;
class fieldDescriptor;
class vtableEntry;
class Klass : public Metadata {
friend class VMStructs;
@ -377,7 +378,7 @@ protected:
#endif
// vtables
virtual klassVtable* vtable() const = 0;
klassVtable* vtable() const;
int vtable_length() const { return _vtable_len; }
// subclass check
@ -443,7 +444,10 @@ protected:
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);

View file

@ -1131,11 +1131,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
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;

View file

@ -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 @@ static oop invoke(instanceKlassHandle klass,
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

View file

@ -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 blob(CodeBlob* cb) {
extern "C" void dump_vtable(address p) {
Command c("dump_vtable");
Klass* k = (Klass*)p;
InstanceKlass::cast(k)->vtable()->print();
k->vtable()->print();
}