mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8219492: Restore static callsite resolution for the current class
Reviewed-by: redestad, lfoltan, vlivanov
This commit is contained in:
parent
a91eebcd1e
commit
b5f55fadff
4 changed files with 36 additions and 19 deletions
|
@ -920,19 +920,23 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
|
||||||
info.call_kind() == CallInfo::vtable_call, "");
|
info.call_kind() == CallInfo::vtable_call, "");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
switch (info.call_kind()) {
|
||||||
|
case CallInfo::direct_call: {
|
||||||
// Get sender or sender's unsafe_anonymous_host, and only set cpCache entry to resolved if
|
// Get sender or sender's unsafe_anonymous_host, and only set cpCache entry to resolved if
|
||||||
// it is not an interface. The receiver for invokespecial calls within interface
|
// it is not an interface. The receiver for invokespecial calls within interface
|
||||||
// methods must be checked for every call.
|
// methods must be checked for every call.
|
||||||
InstanceKlass* sender = pool->pool_holder();
|
InstanceKlass* pool_holder = pool->pool_holder();
|
||||||
sender = sender->is_unsafe_anonymous() ? sender->unsafe_anonymous_host() : sender;
|
InstanceKlass* sender = pool_holder->is_unsafe_anonymous() ?
|
||||||
|
pool_holder->unsafe_anonymous_host() : pool_holder;
|
||||||
|
|
||||||
switch (info.call_kind()) {
|
|
||||||
case CallInfo::direct_call:
|
|
||||||
cp_cache_entry->set_direct_call(
|
cp_cache_entry->set_direct_call(
|
||||||
bytecode,
|
bytecode,
|
||||||
info.resolved_method(),
|
info.resolved_method(),
|
||||||
sender->is_interface());
|
sender->is_interface(),
|
||||||
|
pool_holder);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CallInfo::vtable_call:
|
case CallInfo::vtable_call:
|
||||||
cp_cache_entry->set_vtable_call(
|
cp_cache_entry->set_vtable_call(
|
||||||
bytecode,
|
bytecode,
|
||||||
|
|
|
@ -168,7 +168,8 @@ void ConstantPoolCacheEntry::set_parameter_size(int value) {
|
||||||
void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code,
|
void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code,
|
||||||
const methodHandle& method,
|
const methodHandle& method,
|
||||||
int vtable_index,
|
int vtable_index,
|
||||||
bool sender_is_interface) {
|
bool sender_is_interface,
|
||||||
|
InstanceKlass* pool_holder) {
|
||||||
bool is_vtable_call = (vtable_index >= 0); // FIXME: split this method on this boolean
|
bool is_vtable_call = (vtable_index >= 0); // FIXME: split this method on this boolean
|
||||||
assert(method->interpreter_entry() != NULL, "should have been set at this point");
|
assert(method->interpreter_entry() != NULL, "should have been set at this point");
|
||||||
assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache");
|
assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache");
|
||||||
|
@ -263,11 +264,17 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co
|
||||||
}
|
}
|
||||||
// Don't mark invokestatic to method as resolved if the holder class has not yet completed
|
// Don't mark invokestatic to method as resolved if the holder class has not yet completed
|
||||||
// initialization. An invokestatic must only proceed if the class is initialized, but if
|
// initialization. An invokestatic must only proceed if the class is initialized, but if
|
||||||
// we resolve it before then that class initialization check is skipped.
|
// we resolve it before then that class initialization check is skipped. However if the call
|
||||||
if (invoke_code == Bytecodes::_invokestatic && !method->method_holder()->is_initialized()) {
|
// is from the same class we can resolve as we must be executing with <clinit> on our call stack.
|
||||||
|
if (invoke_code == Bytecodes::_invokestatic &&
|
||||||
|
!method->method_holder()->is_initialized() &&
|
||||||
|
method->method_holder() != pool_holder) {
|
||||||
do_resolve = false;
|
do_resolve = false;
|
||||||
}
|
}
|
||||||
if (do_resolve) {
|
if (do_resolve) {
|
||||||
|
assert(method->method_holder()->is_initialized() ||
|
||||||
|
method->method_holder()->is_reentrant_initialization(Thread::current()),
|
||||||
|
"invalid class initalization state");
|
||||||
set_bytecode_1(invoke_code);
|
set_bytecode_1(invoke_code);
|
||||||
}
|
}
|
||||||
} else if (byte_no == 2) {
|
} else if (byte_no == 2) {
|
||||||
|
@ -310,17 +317,17 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_direct_call(Bytecodes::Code invoke_code, const methodHandle& method,
|
void ConstantPoolCacheEntry::set_direct_call(Bytecodes::Code invoke_code, const methodHandle& method,
|
||||||
bool sender_is_interface) {
|
bool sender_is_interface, InstanceKlass* pool_holder) {
|
||||||
int index = Method::nonvirtual_vtable_index;
|
int index = Method::nonvirtual_vtable_index;
|
||||||
// index < 0; FIXME: inline and customize set_direct_or_vtable_call
|
// index < 0; FIXME: inline and customize set_direct_or_vtable_call
|
||||||
set_direct_or_vtable_call(invoke_code, method, index, sender_is_interface);
|
set_direct_or_vtable_call(invoke_code, method, index, sender_is_interface, pool_holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) {
|
void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) {
|
||||||
// either the method is a miranda or its holder should accept the given index
|
// either the method is a miranda or its holder should accept the given index
|
||||||
assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), "");
|
assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), "");
|
||||||
// index >= 0; FIXME: inline and customize set_direct_or_vtable_call
|
// index >= 0; FIXME: inline and customize set_direct_or_vtable_call
|
||||||
set_direct_or_vtable_call(invoke_code, method, index, false);
|
set_direct_or_vtable_call(invoke_code, method, index, false, NULL /* not used */);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code,
|
void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code,
|
||||||
|
|
|
@ -230,14 +230,16 @@ class ConstantPoolCacheEntry {
|
||||||
Bytecodes::Code invoke_code, // the bytecode used for invoking the method
|
Bytecodes::Code invoke_code, // the bytecode used for invoking the method
|
||||||
const methodHandle& method, // the method/prototype if any (NULL, otherwise)
|
const methodHandle& method, // the method/prototype if any (NULL, otherwise)
|
||||||
int vtable_index, // the vtable index if any, else negative
|
int vtable_index, // the vtable index if any, else negative
|
||||||
bool sender_is_interface
|
bool sender_is_interface, // 'logical' sender (may be host of VMAC)
|
||||||
|
InstanceKlass* pool_holder // class from which the call is made
|
||||||
);
|
);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_direct_call( // sets entry to exact concrete method entry
|
void set_direct_call( // sets entry to exact concrete method entry
|
||||||
Bytecodes::Code invoke_code, // the bytecode used for invoking the method
|
Bytecodes::Code invoke_code, // the bytecode used for invoking the method
|
||||||
const methodHandle& method, // the method to call
|
const methodHandle& method, // the method to call
|
||||||
bool sender_is_interface
|
bool sender_is_interface, // 'logical' sender (may be host of VMAC)
|
||||||
|
InstanceKlass* pool_holder // class from which the call is made
|
||||||
);
|
);
|
||||||
|
|
||||||
void set_vtable_call( // sets entry to vtable index
|
void set_vtable_call( // sets entry to vtable index
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1376,13 +1376,17 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Do not patch call site for static call when the class is not
|
// Do not patch call site for static call to another class
|
||||||
// fully initialized.
|
// when the class is not fully initialized.
|
||||||
if (invoke_code == Bytecodes::_invokestatic &&
|
if (invoke_code == Bytecodes::_invokestatic &&
|
||||||
!callee_method->method_holder()->is_initialized()) {
|
!callee_method->method_holder()->is_initialized() &&
|
||||||
|
callee_method->method_holder() != caller_nm->method()->method_holder()) {
|
||||||
assert(callee_method->method_holder()->is_linked(), "must be");
|
assert(callee_method->method_holder()->is_linked(), "must be");
|
||||||
return callee_method;
|
return callee_method;
|
||||||
}
|
}
|
||||||
|
assert(callee_method->method_holder()->is_initialized() ||
|
||||||
|
callee_method->method_holder()->is_reentrant_initialization(thread),
|
||||||
|
"invalid class initalization state");
|
||||||
|
|
||||||
// JSR 292 key invariant:
|
// JSR 292 key invariant:
|
||||||
// If the resolved method is a MethodHandle invoke target, the call
|
// If the resolved method is a MethodHandle invoke target, the call
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue