mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8148481: Devirtualize Klass::vtable
Move remainder of vtable related methods to Klass Reviewed-by: cjplummer, coleenp
This commit is contained in:
parent
211dc93a85
commit
3cda485fe5
12 changed files with 44 additions and 73 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue