8076492: Make common code from template interpreter code

Move case statement out of assembly code

Reviewed-by: minqi, sspitsyn, dholmes
This commit is contained in:
Coleen Phillimore 2015-04-01 22:03:17 -04:00
parent d350f07d51
commit f0035b701e
7 changed files with 74 additions and 107 deletions

View file

@ -2138,30 +2138,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
__ br(Assembler::EQ, resolved); __ br(Assembler::EQ, resolved);
// resolve first time through // resolve first time through
address entry; address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
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;
}
__ mov(temp, (int) bytecode()); __ mov(temp, (int) bytecode());
__ call_VM(noreg, entry, temp); __ call_VM(noreg, entry, temp);

View file

@ -2177,22 +2177,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist
__ cmpdi(CCR0, Rscratch, (int)code); __ cmpdi(CCR0, Rscratch, (int)code);
__ beq(CCR0, Lresolved); __ beq(CCR0, Lresolved);
address entry = NULL; address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
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;
}
__ li(R4_ARG2, code); __ li(R4_ARG2, code);
__ call_VM(noreg, entry, R4_ARG2, true); __ call_VM(noreg, entry, R4_ARG2, true);

View file

@ -2070,23 +2070,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
__ br(Assembler::equal, false, Assembler::pt, resolved); __ br(Assembler::equal, false, Assembler::pt, resolved);
__ delayed()->set(code, O1); __ delayed()->set(code, O1);
address entry; address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
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;
}
// first time invocation - must resolve first // first time invocation - must resolve first
__ call_VM(noreg, entry, O1); __ call_VM(noreg, entry, O1);
// Update registers with resolved info // Update registers with resolved info

View file

@ -2520,22 +2520,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
__ jcc(Assembler::equal, resolved); __ jcc(Assembler::equal, resolved);
// resolve first time through // resolve first time through
address entry; address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
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;
}
__ movl(temp, code); __ movl(temp, code);
__ call_VM(noreg, entry, temp); __ call_VM(noreg, entry, temp);
// Update registers with resolved info // Update registers with resolved info

View file

@ -1942,7 +1942,7 @@ run:
cache = cp->entry_at(index); cache = cp->entry_at(index);
if (!cache->is_resolved((Bytecodes::Code)opcode)) { 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); handle_exception);
cache = cp->entry_at(index); cache = cp->entry_at(index);
} }
@ -2040,7 +2040,7 @@ run:
u2 index = Bytes::get_native_u2(pc+1); u2 index = Bytes::get_native_u2(pc+1);
ConstantPoolCacheEntry* cache = cp->entry_at(index); ConstantPoolCacheEntry* cache = cp->entry_at(index);
if (!cache->is_resolved((Bytecodes::Code)opcode)) { 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); handle_exception);
cache = cp->entry_at(index); cache = cp->entry_at(index);
} }
@ -2416,7 +2416,7 @@ run:
// This kind of CP cache entry does not need to match the flags byte, because // 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. // there is a 1-1 relation between bytecode type and CP entry type.
if (! cache->is_resolved((Bytecodes::Code) opcode)) { 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); handle_exception);
cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index); cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
} }
@ -2447,7 +2447,7 @@ run:
ConstantPoolCacheEntry* cache = cp->entry_at(index); ConstantPoolCacheEntry* cache = cp->entry_at(index);
if (! cache->is_resolved((Bytecodes::Code) opcode)) { 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); handle_exception);
cache = cp->entry_at(index); cache = cp->entry_at(index);
} }
@ -2480,7 +2480,7 @@ run:
ConstantPoolCacheEntry* cache = cp->entry_at(index); ConstantPoolCacheEntry* cache = cp->entry_at(index);
if (!cache->is_resolved((Bytecodes::Code)opcode)) { 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); handle_exception);
cache = cp->entry_at(index); cache = cp->entry_at(index);
} }
@ -2571,7 +2571,7 @@ run:
// out so c++ compiler has a chance for constant prop to fold everything possible away. // out so c++ compiler has a chance for constant prop to fold everything possible away.
if (!cache->is_resolved((Bytecodes::Code)opcode)) { 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); handle_exception);
cache = cp->entry_at(index); cache = cp->entry_at(index);
} }

View file

@ -537,7 +537,8 @@ IRT_END
// Fields // 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 // resolve field
fieldDescriptor info; fieldDescriptor info;
constantPoolHandle pool(thread, method(thread)->constants()); constantPoolHandle pool(thread, method(thread)->constants());
@ -552,7 +553,8 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode
} // end JvmtiHideSingleStepping } // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated // 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 // compute auxiliary field attributes
TosState state = as_TosState(info.field_type()); TosState state = as_TosState(info.field_type());
@ -580,7 +582,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode
} }
} }
cache_entry(thread)->set_field( cp_cache_entry->set_field(
get_code, get_code,
put_code, put_code,
info.field_holder(), info.field_holder(),
@ -591,7 +593,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode
info.access_flags().is_volatile(), info.access_flags().is_volatile(),
pool->pool_holder() pool->pool_holder()
); );
IRT_END }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
@ -686,7 +688,8 @@ IRT_ENTRY(void, InterpreterRuntime::_breakpoint(JavaThread* thread, Method* meth
JvmtiExport::post_raw_breakpoint(thread, method, bcp); JvmtiExport::post_raw_breakpoint(thread, method, bcp);
IRT_END 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 // extract receiver from the outgoing argument list if necessary
Handle receiver(thread, NULL); Handle receiver(thread, NULL);
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) { if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
@ -710,7 +713,8 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
{ {
JvmtiHideSingleStepping jhss(thread); JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, receiver, pool, 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()) { if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
int retry_count = 0; int retry_count = 0;
while (info.resolved_method()->is_old()) { while (info.resolved_method()->is_old()) {
@ -721,13 +725,15 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
"Could not resolve to latest version of redefined method"); "Could not resolve to latest version of redefined method");
// method is redefined in the middle of resolve so re-try. // method is redefined in the middle of resolve so re-try.
LinkResolver::resolve_invoke(info, receiver, pool, LinkResolver::resolve_invoke(info, receiver, pool,
get_index_u2_cpcache(thread, bytecode), bytecode, CHECK); get_index_u2_cpcache(thread, bytecode), bytecode,
CHECK);
} }
} }
} // end JvmtiHideSingleStepping } // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated // 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 (bytecode == Bytecodes::_invokeinterface) {
if (TraceItables && Verbose) { if (TraceItables && Verbose) {
@ -762,18 +768,18 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
#endif #endif
switch (info.call_kind()) { switch (info.call_kind()) {
case CallInfo::direct_call: case CallInfo::direct_call:
cache_entry(thread)->set_direct_call( cp_cache_entry->set_direct_call(
bytecode, bytecode,
info.resolved_method()); info.resolved_method());
break; break;
case CallInfo::vtable_call: case CallInfo::vtable_call:
cache_entry(thread)->set_vtable_call( cp_cache_entry->set_vtable_call(
bytecode, bytecode,
info.resolved_method(), info.resolved_method(),
info.vtable_index()); info.vtable_index());
break; break;
case CallInfo::itable_call: case CallInfo::itable_call:
cache_entry(thread)->set_itable_call( cp_cache_entry->set_itable_call(
bytecode, bytecode,
info.resolved_method(), info.resolved_method(),
info.itable_index()); info.itable_index());
@ -781,30 +787,30 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
default: ShouldNotReachHere(); default: ShouldNotReachHere();
} }
} }
IRT_END
// First time execution: Resolve symbols, create a permanent MethodType object. // 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; const Bytecodes::Code bytecode = Bytecodes::_invokehandle;
// resolve method // resolve method
CallInfo info; CallInfo info;
constantPoolHandle pool(thread, method(thread)->constants()); constantPoolHandle pool(thread, method(thread)->constants());
{ {
JvmtiHideSingleStepping jhss(thread); JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, Handle(), pool, LinkResolver::resolve_invoke(info, Handle(), pool,
get_index_u2_cpcache(thread, bytecode), bytecode, CHECK); get_index_u2_cpcache(thread, bytecode), bytecode,
CHECK);
} // end JvmtiHideSingleStepping } // 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. // 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; const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
//TO DO: consider passing BCI to Java. //TO DO: consider passing BCI to Java.
@ -823,8 +829,36 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
ConstantPoolCacheEntry* cp_cache_entry = pool->invokedynamic_cp_cache_entry_at(index); ConstantPoolCacheEntry* cp_cache_entry = pool->invokedynamic_cp_cache_entry_at(index);
cp_cache_entry->set_dynamic_call(pool, info); cp_cache_entry->set_dynamic_call(pool, info);
} }
IRT_END
// 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 // Miscellaneous

View file

@ -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. * 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
@ -52,7 +52,6 @@ class InterpreterRuntime: AllStatic {
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272) // pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
return Bytecodes::code_at(method(thread), bcp(thread)); 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 Bytecode bytecode(JavaThread *thread) { return Bytecode(method(thread), bcp(thread)); }
static int get_index_u1(JavaThread *thread, Bytecodes::Code bc) static int get_index_u1(JavaThread *thread, Bytecodes::Code bc)
{ return bytecode(thread).get_index_u1(bc); } { return bytecode(thread).get_index_u1(bc); }
@ -117,9 +116,17 @@ class InterpreterRuntime: AllStatic {
static void note_no_trap(JavaThread* thread, Method *method, int trap_bci) {} static void note_no_trap(JavaThread* thread, Method *method, int trap_bci) {}
#endif // CC_INTERP #endif // CC_INTERP
static void resolve_from_cache(JavaThread* thread, Bytecodes::Code bytecode);
private:
// Statics & fields // 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 // Synchronization
static void monitorenter(JavaThread* thread, BasicObjectLock* elem); static void monitorenter(JavaThread* thread, BasicObjectLock* elem);
static void monitorexit (JavaThread* thread, BasicObjectLock* elem); static void monitorexit (JavaThread* thread, BasicObjectLock* elem);
@ -127,11 +134,6 @@ class InterpreterRuntime: AllStatic {
static void throw_illegal_monitor_state_exception(JavaThread* thread); static void throw_illegal_monitor_state_exception(JavaThread* thread);
static void new_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 // Breakpoints
static void _breakpoint(JavaThread* thread, Method* method, address bcp); static void _breakpoint(JavaThread* thread, Method* method, address bcp);
static Bytecodes::Code get_original_bytecode_at(JavaThread* thread, Method* method, address bcp); static Bytecodes::Code get_original_bytecode_at(JavaThread* thread, Method* method, address bcp);