8076492: Make common code from template interpreter code
Summary: Move case statement out of assembly code
Reviewed-by: minqi, sspitsyn, dholmes
--- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp Wed Apr 01 22:03:17 2015 -0400
@@ -2138,30 +2138,7 @@
__ br(Assembler::EQ, resolved);
// resolve first time through
- address entry;
- switch (bytecode()) {
- case Bytecodes::_getstatic:
- case Bytecodes::_putstatic:
- case Bytecodes::_getfield:
- case Bytecodes::_putfield:
- entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put);
- break;
- case Bytecodes::_invokevirtual:
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
- case Bytecodes::_invokeinterface:
- entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
- break;
- case Bytecodes::_invokehandle:
- entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);
- break;
- case Bytecodes::_invokedynamic:
- entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
- break;
- default:
- fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
- break;
- }
+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ mov(temp, (int) bytecode());
__ call_VM(noreg, entry, temp);
--- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Wed Apr 01 22:03:17 2015 -0400
@@ -2177,22 +2177,7 @@
__ cmpdi(CCR0, Rscratch, (int)code);
__ beq(CCR0, Lresolved);
- address entry = NULL;
- switch (code) {
- case Bytecodes::_getstatic : // fall through
- case Bytecodes::_putstatic : // fall through
- case Bytecodes::_getfield : // fall through
- case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break;
- case Bytecodes::_invokevirtual : // fall through
- case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
- case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break;
- case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
- default :
- fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
- break;
- }
+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ li(R4_ARG2, code);
__ call_VM(noreg, entry, R4_ARG2, true);
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Apr 01 22:03:17 2015 -0400
@@ -2070,23 +2070,7 @@
__ br(Assembler::equal, false, Assembler::pt, resolved);
__ delayed()->set(code, O1);
- address entry;
-
- switch (code) {
- case Bytecodes::_getstatic : // fall through
- case Bytecodes::_putstatic : // fall through
- case Bytecodes::_getfield : // fall through
- case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break;
- case Bytecodes::_invokevirtual : // fall through
- case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
- case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break;
- case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
- default:
- fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
- break;
- }
+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
// first time invocation - must resolve first
__ call_VM(noreg, entry, O1);
// Update registers with resolved info
--- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Wed Apr 01 22:03:17 2015 -0400
@@ -2520,22 +2520,7 @@
__ jcc(Assembler::equal, resolved);
// resolve first time through
- address entry;
- switch (code) {
- case Bytecodes::_getstatic : // fall through
- case Bytecodes::_putstatic : // fall through
- case Bytecodes::_getfield : // fall through
- case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break;
- case Bytecodes::_invokevirtual : // fall through
- case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
- case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break;
- case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
- default:
- fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
- break;
- }
+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ movl(temp, code);
__ call_VM(noreg, entry, temp);
// Update registers with resolved info
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Apr 01 22:03:17 2015 -0400
@@ -1942,7 +1942,7 @@
cache = cp->entry_at(index);
if (!cache->is_resolved((Bytecodes::Code)opcode)) {
- CALL_VM(InterpreterRuntime::resolve_get_put(THREAD, (Bytecodes::Code)opcode),
+ CALL_VM(InterpreterRuntime::resolve_from_cache(THREAD, (Bytecodes::Code)opcode),
handle_exception);
cache = cp->entry_at(index);
}
@@ -2040,7 +2040,7 @@
u2 index = Bytes::get_native_u2(pc+1);
ConstantPoolCacheEntry* cache = cp->entry_at(index);
if (!cache->is_resolved((Bytecodes::Code)opcode)) {
- CALL_VM(InterpreterRuntime::resolve_get_put(THREAD, (Bytecodes::Code)opcode),
+ CALL_VM(InterpreterRuntime::resolve_from_cache(THREAD, (Bytecodes::Code)opcode),
handle_exception);
cache = cp->entry_at(index);
}
@@ -2416,7 +2416,7 @@
// This kind of CP cache entry does not need to match the flags byte, because
// there is a 1-1 relation between bytecode type and CP entry type.
if (! cache->is_resolved((Bytecodes::Code) opcode)) {
- CALL_VM(InterpreterRuntime::resolve_invokedynamic(THREAD),
+ CALL_VM(InterpreterRuntime::resolve_from_cache(THREAD, (Bytecodes::Code)opcode),
handle_exception);
cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
}
@@ -2447,7 +2447,7 @@
ConstantPoolCacheEntry* cache = cp->entry_at(index);
if (! cache->is_resolved((Bytecodes::Code) opcode)) {
- CALL_VM(InterpreterRuntime::resolve_invokehandle(THREAD),
+ CALL_VM(InterpreterRuntime::resolve_from_cache(THREAD, (Bytecodes::Code)opcode),
handle_exception);
cache = cp->entry_at(index);
}
@@ -2480,7 +2480,7 @@
ConstantPoolCacheEntry* cache = cp->entry_at(index);
if (!cache->is_resolved((Bytecodes::Code)opcode)) {
- CALL_VM(InterpreterRuntime::resolve_invoke(THREAD, (Bytecodes::Code)opcode),
+ CALL_VM(InterpreterRuntime::resolve_from_cache(THREAD, (Bytecodes::Code)opcode),
handle_exception);
cache = cp->entry_at(index);
}
@@ -2571,7 +2571,7 @@
// out so c++ compiler has a chance for constant prop to fold everything possible away.
if (!cache->is_resolved((Bytecodes::Code)opcode)) {
- CALL_VM(InterpreterRuntime::resolve_invoke(THREAD, (Bytecodes::Code)opcode),
+ CALL_VM(InterpreterRuntime::resolve_from_cache(THREAD, (Bytecodes::Code)opcode),
handle_exception);
cache = cp->entry_at(index);
}
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Apr 01 22:03:17 2015 -0400
@@ -537,7 +537,8 @@
// Fields
//
-IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode))
+void InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode) {
+ Thread* THREAD = thread;
// resolve field
fieldDescriptor info;
constantPoolHandle pool(thread, method(thread)->constants());
@@ -552,7 +553,8 @@
} // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated
- if (already_resolved(thread)) return;
+ ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread);
+ if (cp_cache_entry->is_resolved(bytecode)) return;
// compute auxiliary field attributes
TosState state = as_TosState(info.field_type());
@@ -580,7 +582,7 @@
}
}
- cache_entry(thread)->set_field(
+ cp_cache_entry->set_field(
get_code,
put_code,
info.field_holder(),
@@ -591,7 +593,7 @@
info.access_flags().is_volatile(),
pool->pool_holder()
);
-IRT_END
+}
//------------------------------------------------------------------------------------------------------------------------
@@ -686,7 +688,8 @@
JvmtiExport::post_raw_breakpoint(thread, method, bcp);
IRT_END
-IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode)) {
+void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode) {
+ Thread* THREAD = thread;
// extract receiver from the outgoing argument list if necessary
Handle receiver(thread, NULL);
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
@@ -710,7 +713,8 @@
{
JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, receiver, pool,
- get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
+ get_index_u2_cpcache(thread, bytecode), bytecode,
+ CHECK);
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
int retry_count = 0;
while (info.resolved_method()->is_old()) {
@@ -721,13 +725,15 @@
"Could not resolve to latest version of redefined method");
// method is redefined in the middle of resolve so re-try.
LinkResolver::resolve_invoke(info, receiver, pool,
- get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
+ get_index_u2_cpcache(thread, bytecode), bytecode,
+ CHECK);
}
}
} // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated
- if (already_resolved(thread)) return;
+ ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread);
+ if (cp_cache_entry->is_resolved(bytecode)) return;
if (bytecode == Bytecodes::_invokeinterface) {
if (TraceItables && Verbose) {
@@ -762,18 +768,18 @@
#endif
switch (info.call_kind()) {
case CallInfo::direct_call:
- cache_entry(thread)->set_direct_call(
+ cp_cache_entry->set_direct_call(
bytecode,
info.resolved_method());
break;
case CallInfo::vtable_call:
- cache_entry(thread)->set_vtable_call(
+ cp_cache_entry->set_vtable_call(
bytecode,
info.resolved_method(),
info.vtable_index());
break;
case CallInfo::itable_call:
- cache_entry(thread)->set_itable_call(
+ cp_cache_entry->set_itable_call(
bytecode,
info.resolved_method(),
info.itable_index());
@@ -781,30 +787,30 @@
default: ShouldNotReachHere();
}
}
-IRT_END
// First time execution: Resolve symbols, create a permanent MethodType object.
-IRT_ENTRY(void, InterpreterRuntime::resolve_invokehandle(JavaThread* thread)) {
+void InterpreterRuntime::resolve_invokehandle(JavaThread* thread) {
+ Thread* THREAD = thread;
const Bytecodes::Code bytecode = Bytecodes::_invokehandle;
// resolve method
CallInfo info;
constantPoolHandle pool(thread, method(thread)->constants());
-
{
JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, Handle(), pool,
- get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
+ get_index_u2_cpcache(thread, bytecode), bytecode,
+ CHECK);
} // end JvmtiHideSingleStepping
- cache_entry(thread)->set_method_handle(pool, info);
+ ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread);
+ cp_cache_entry->set_method_handle(pool, info);
}
-IRT_END
-
// First time execution: Resolve symbols, create a permanent CallSite object.
-IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
+void InterpreterRuntime::resolve_invokedynamic(JavaThread* thread) {
+ Thread* THREAD = thread;
const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
//TO DO: consider passing BCI to Java.
@@ -823,9 +829,37 @@
ConstantPoolCacheEntry* cp_cache_entry = pool->invokedynamic_cp_cache_entry_at(index);
cp_cache_entry->set_dynamic_call(pool, info);
}
+
+// This function is the interface to the assembly code. It returns the resolved
+// cpCache entry. This doesn't safepoint, but the helper routines safepoint.
+// This function will check for redefinition!
+IRT_ENTRY(void, InterpreterRuntime::resolve_from_cache(JavaThread* thread, Bytecodes::Code bytecode)) {
+ switch (bytecode) {
+ case Bytecodes::_getstatic:
+ case Bytecodes::_putstatic:
+ case Bytecodes::_getfield:
+ case Bytecodes::_putfield:
+ resolve_get_put(thread, bytecode);
+ break;
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ case Bytecodes::_invokeinterface:
+ resolve_invoke(thread, bytecode);
+ break;
+ case Bytecodes::_invokehandle:
+ resolve_invokehandle(thread);
+ break;
+ case Bytecodes::_invokedynamic:
+ resolve_invokedynamic(thread);
+ break;
+ default:
+ fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode)));
+ break;
+ }
+}
IRT_END
-
//------------------------------------------------------------------------------------------------------------------------
// Miscellaneous
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Apr 01 15:27:04 2015 +0200
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Apr 01 22:03:17 2015 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -52,7 +52,6 @@
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
return Bytecodes::code_at(method(thread), bcp(thread));
}
- static bool already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); }
static Bytecode bytecode(JavaThread *thread) { return Bytecode(method(thread), bcp(thread)); }
static int get_index_u1(JavaThread *thread, Bytecodes::Code bc)
{ return bytecode(thread).get_index_u1(bc); }
@@ -117,9 +116,17 @@
static void note_no_trap(JavaThread* thread, Method *method, int trap_bci) {}
#endif // CC_INTERP
+ static void resolve_from_cache(JavaThread* thread, Bytecodes::Code bytecode);
+ private:
// Statics & fields
- static void resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode);
+ static void resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode);
+ // Calls
+ static void resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode);
+ static void resolve_invokehandle (JavaThread* thread);
+ static void resolve_invokedynamic(JavaThread* thread);
+
+ public:
// Synchronization
static void monitorenter(JavaThread* thread, BasicObjectLock* elem);
static void monitorexit (JavaThread* thread, BasicObjectLock* elem);
@@ -127,11 +134,6 @@
static void throw_illegal_monitor_state_exception(JavaThread* thread);
static void new_illegal_monitor_state_exception(JavaThread* thread);
- // Calls
- static void resolve_invoke (JavaThread* thread, Bytecodes::Code bytecode);
- static void resolve_invokehandle (JavaThread* thread);
- static void resolve_invokedynamic(JavaThread* thread);
-
// Breakpoints
static void _breakpoint(JavaThread* thread, Method* method, address bcp);
static Bytecodes::Code get_original_bytecode_at(JavaThread* thread, Method* method, address bcp);