# HG changeset patch # User coleenp # Date 1427940197 14400 # Node ID 1f788eb36811526881fcccc41a9e47f7a8acd10e # Parent 386d3e9878bcc1cb10afce780ab2c6ab6b53a2cd 8076492: Make common code from template interpreter code Summary: Move case statement out of assembly code Reviewed-by: minqi, sspitsyn, dholmes diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp --- 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); diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp --- 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); diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp --- 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 diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/cpu/x86/vm/templateTable_x86.cpp --- 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 diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp --- 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); } diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- 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 diff -r 386d3e9878bc -r 1f788eb36811 hotspot/src/share/vm/interpreter/interpreterRuntime.hpp --- 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);