duke@435: /* jrose@1145: * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: #include "incls/_precompiled.incl" duke@435: #include "incls/_templateInterpreter.cpp.incl" duke@435: duke@435: #ifndef CC_INTERP duke@435: duke@435: # define __ _masm-> duke@435: duke@435: void TemplateInterpreter::initialize() { duke@435: if (_code != NULL) return; duke@435: // assertions duke@435: assert((int)Bytecodes::number_of_codes <= (int)DispatchTable::length, duke@435: "dispatch table too small"); duke@435: duke@435: AbstractInterpreter::initialize(); duke@435: duke@435: TemplateTable::initialize(); duke@435: duke@435: // generate interpreter duke@435: { ResourceMark rm; duke@435: TraceTime timer("Interpreter generation", TraceStartupTime); duke@435: int code_size = InterpreterCodeSize; duke@435: NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space duke@435: _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, duke@435: "Interpreter"); duke@435: InterpreterGenerator g(_code); duke@435: if (PrintInterpreter) print(); duke@435: } duke@435: duke@435: // initialize dispatch table duke@435: _active_table = _normal_table; duke@435: } duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: // Implementation of EntryPoint duke@435: duke@435: EntryPoint::EntryPoint() { duke@435: assert(number_of_states == 9, "check the code below"); duke@435: _entry[btos] = NULL; duke@435: _entry[ctos] = NULL; duke@435: _entry[stos] = NULL; duke@435: _entry[atos] = NULL; duke@435: _entry[itos] = NULL; duke@435: _entry[ltos] = NULL; duke@435: _entry[ftos] = NULL; duke@435: _entry[dtos] = NULL; duke@435: _entry[vtos] = NULL; duke@435: } duke@435: duke@435: duke@435: EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { duke@435: assert(number_of_states == 9, "check the code below"); duke@435: _entry[btos] = bentry; duke@435: _entry[ctos] = centry; duke@435: _entry[stos] = sentry; duke@435: _entry[atos] = aentry; duke@435: _entry[itos] = ientry; duke@435: _entry[ltos] = lentry; duke@435: _entry[ftos] = fentry; duke@435: _entry[dtos] = dentry; duke@435: _entry[vtos] = ventry; duke@435: } duke@435: duke@435: duke@435: void EntryPoint::set_entry(TosState state, address entry) { duke@435: assert(0 <= state && state < number_of_states, "state out of bounds"); duke@435: _entry[state] = entry; duke@435: } duke@435: duke@435: duke@435: address EntryPoint::entry(TosState state) const { duke@435: assert(0 <= state && state < number_of_states, "state out of bounds"); duke@435: return _entry[state]; duke@435: } duke@435: duke@435: duke@435: void EntryPoint::print() { duke@435: tty->print("["); duke@435: for (int i = 0; i < number_of_states; i++) { duke@435: if (i > 0) tty->print(", "); duke@435: tty->print(INTPTR_FORMAT, _entry[i]); duke@435: } duke@435: tty->print("]"); duke@435: } duke@435: duke@435: duke@435: bool EntryPoint::operator == (const EntryPoint& y) { duke@435: int i = number_of_states; duke@435: while (i-- > 0) { duke@435: if (_entry[i] != y._entry[i]) return false; duke@435: } duke@435: return true; duke@435: } duke@435: duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: // Implementation of DispatchTable duke@435: duke@435: EntryPoint DispatchTable::entry(int i) const { duke@435: assert(0 <= i && i < length, "index out of bounds"); duke@435: return duke@435: EntryPoint( duke@435: _table[btos][i], duke@435: _table[ctos][i], duke@435: _table[stos][i], duke@435: _table[atos][i], duke@435: _table[itos][i], duke@435: _table[ltos][i], duke@435: _table[ftos][i], duke@435: _table[dtos][i], duke@435: _table[vtos][i] duke@435: ); duke@435: } duke@435: duke@435: duke@435: void DispatchTable::set_entry(int i, EntryPoint& entry) { duke@435: assert(0 <= i && i < length, "index out of bounds"); duke@435: assert(number_of_states == 9, "check the code below"); duke@435: _table[btos][i] = entry.entry(btos); duke@435: _table[ctos][i] = entry.entry(ctos); duke@435: _table[stos][i] = entry.entry(stos); duke@435: _table[atos][i] = entry.entry(atos); duke@435: _table[itos][i] = entry.entry(itos); duke@435: _table[ltos][i] = entry.entry(ltos); duke@435: _table[ftos][i] = entry.entry(ftos); duke@435: _table[dtos][i] = entry.entry(dtos); duke@435: _table[vtos][i] = entry.entry(vtos); duke@435: } duke@435: duke@435: duke@435: bool DispatchTable::operator == (DispatchTable& y) { duke@435: int i = length; duke@435: while (i-- > 0) { duke@435: EntryPoint t = y.entry(i); // for compiler compatibility (BugId 4150096) duke@435: if (!(entry(i) == t)) return false; duke@435: } duke@435: return true; duke@435: } duke@435: duke@435: address TemplateInterpreter::_remove_activation_entry = NULL; duke@435: address TemplateInterpreter::_remove_activation_preserving_args_entry = NULL; duke@435: duke@435: duke@435: address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NULL; duke@435: address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL; duke@435: address TemplateInterpreter::_throw_ArithmeticException_entry = NULL; duke@435: address TemplateInterpreter::_throw_ClassCastException_entry = NULL; jrose@1145: address TemplateInterpreter::_throw_WrongMethodType_entry = NULL; duke@435: address TemplateInterpreter::_throw_NullPointerException_entry = NULL; duke@435: address TemplateInterpreter::_throw_StackOverflowError_entry = NULL; duke@435: address TemplateInterpreter::_throw_exception_entry = NULL; duke@435: duke@435: #ifndef PRODUCT duke@435: EntryPoint TemplateInterpreter::_trace_code; duke@435: #endif // !PRODUCT duke@435: EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries]; duke@435: EntryPoint TemplateInterpreter::_earlyret_entry; duke@435: EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ]; duke@435: EntryPoint TemplateInterpreter::_continuation_entry; duke@435: EntryPoint TemplateInterpreter::_safept_entry; duke@435: duke@435: address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; duke@435: address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; duke@435: duke@435: DispatchTable TemplateInterpreter::_active_table; duke@435: DispatchTable TemplateInterpreter::_normal_table; duke@435: DispatchTable TemplateInterpreter::_safept_table; duke@435: address TemplateInterpreter::_wentry_point[DispatchTable::length]; duke@435: duke@435: TemplateInterpreterGenerator::TemplateInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) { duke@435: _unimplemented_bytecode = NULL; duke@435: _illegal_bytecode_sequence = NULL; duke@435: } duke@435: duke@435: static const BasicType types[Interpreter::number_of_result_handlers] = { duke@435: T_BOOLEAN, duke@435: T_CHAR , duke@435: T_BYTE , duke@435: T_SHORT , duke@435: T_INT , duke@435: T_LONG , duke@435: T_VOID , duke@435: T_FLOAT , duke@435: T_DOUBLE , duke@435: T_OBJECT duke@435: }; duke@435: duke@435: void TemplateInterpreterGenerator::generate_all() { duke@435: AbstractInterpreterGenerator::generate_all(); duke@435: duke@435: { CodeletMark cm(_masm, "error exits"); duke@435: _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); duke@435: _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); duke@435: } duke@435: duke@435: #ifndef PRODUCT duke@435: if (TraceBytecodes) { duke@435: CodeletMark cm(_masm, "bytecode tracing support"); duke@435: Interpreter::_trace_code = duke@435: EntryPoint( duke@435: generate_trace_code(btos), duke@435: generate_trace_code(ctos), duke@435: generate_trace_code(stos), duke@435: generate_trace_code(atos), duke@435: generate_trace_code(itos), duke@435: generate_trace_code(ltos), duke@435: generate_trace_code(ftos), duke@435: generate_trace_code(dtos), duke@435: generate_trace_code(vtos) duke@435: ); duke@435: } duke@435: #endif // !PRODUCT duke@435: duke@435: { CodeletMark cm(_masm, "return entry points"); duke@435: for (int i = 0; i < Interpreter::number_of_return_entries; i++) { duke@435: Interpreter::_return_entry[i] = duke@435: EntryPoint( duke@435: generate_return_entry_for(itos, i), duke@435: generate_return_entry_for(itos, i), duke@435: generate_return_entry_for(itos, i), duke@435: generate_return_entry_for(atos, i), duke@435: generate_return_entry_for(itos, i), duke@435: generate_return_entry_for(ltos, i), duke@435: generate_return_entry_for(ftos, i), duke@435: generate_return_entry_for(dtos, i), duke@435: generate_return_entry_for(vtos, i) duke@435: ); duke@435: } duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "earlyret entry points"); duke@435: Interpreter::_earlyret_entry = duke@435: EntryPoint( duke@435: generate_earlyret_entry_for(btos), duke@435: generate_earlyret_entry_for(ctos), duke@435: generate_earlyret_entry_for(stos), duke@435: generate_earlyret_entry_for(atos), duke@435: generate_earlyret_entry_for(itos), duke@435: generate_earlyret_entry_for(ltos), duke@435: generate_earlyret_entry_for(ftos), duke@435: generate_earlyret_entry_for(dtos), duke@435: generate_earlyret_entry_for(vtos) duke@435: ); duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "deoptimization entry points"); duke@435: for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) { duke@435: Interpreter::_deopt_entry[i] = duke@435: EntryPoint( duke@435: generate_deopt_entry_for(itos, i), duke@435: generate_deopt_entry_for(itos, i), duke@435: generate_deopt_entry_for(itos, i), duke@435: generate_deopt_entry_for(atos, i), duke@435: generate_deopt_entry_for(itos, i), duke@435: generate_deopt_entry_for(ltos, i), duke@435: generate_deopt_entry_for(ftos, i), duke@435: generate_deopt_entry_for(dtos, i), duke@435: generate_deopt_entry_for(vtos, i) duke@435: ); duke@435: } duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "result handlers for native calls"); duke@435: // The various result converter stublets. duke@435: int is_generated[Interpreter::number_of_result_handlers]; duke@435: memset(is_generated, 0, sizeof(is_generated)); duke@435: duke@435: for (int i = 0; i < Interpreter::number_of_result_handlers; i++) { duke@435: BasicType type = types[i]; duke@435: if (!is_generated[Interpreter::BasicType_as_index(type)]++) { duke@435: Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type); duke@435: } duke@435: } duke@435: } duke@435: duke@435: for (int j = 0; j < number_of_states; j++) { duke@435: const TosState states[] = {btos, ctos, stos, itos, ltos, ftos, dtos, atos, vtos}; jrose@1161: int index = Interpreter::TosState_as_index(states[j]); jrose@1161: Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3); jrose@1161: Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "continuation entry points"); duke@435: Interpreter::_continuation_entry = duke@435: EntryPoint( duke@435: generate_continuation_for(btos), duke@435: generate_continuation_for(ctos), duke@435: generate_continuation_for(stos), duke@435: generate_continuation_for(atos), duke@435: generate_continuation_for(itos), duke@435: generate_continuation_for(ltos), duke@435: generate_continuation_for(ftos), duke@435: generate_continuation_for(dtos), duke@435: generate_continuation_for(vtos) duke@435: ); duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "safepoint entry points"); duke@435: Interpreter::_safept_entry = duke@435: EntryPoint( duke@435: generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), duke@435: generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)) duke@435: ); duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "exception handling"); duke@435: // (Note: this is not safepoint safe because thread may return to compiled code) duke@435: generate_throw_exception(); duke@435: } duke@435: duke@435: { CodeletMark cm(_masm, "throw exception entrypoints"); duke@435: Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException"); duke@435: Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); duke@435: Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); duke@435: Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); jrose@1145: Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler(); duke@435: Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); duke@435: Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); duke@435: } duke@435: duke@435: duke@435: duke@435: #define method_entry(kind) \ duke@435: { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ duke@435: Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ duke@435: } duke@435: duke@435: // all non-native method kinds duke@435: method_entry(zerolocals) duke@435: method_entry(zerolocals_synchronized) duke@435: method_entry(empty) duke@435: method_entry(accessor) duke@435: method_entry(abstract) jrose@1145: method_entry(method_handle) duke@435: method_entry(java_lang_math_sin ) duke@435: method_entry(java_lang_math_cos ) duke@435: method_entry(java_lang_math_tan ) duke@435: method_entry(java_lang_math_abs ) duke@435: method_entry(java_lang_math_sqrt ) duke@435: method_entry(java_lang_math_log ) duke@435: method_entry(java_lang_math_log10) duke@435: duke@435: // all native method kinds (must be one contiguous block) duke@435: Interpreter::_native_entry_begin = Interpreter::code()->code_end(); duke@435: method_entry(native) duke@435: method_entry(native_synchronized) duke@435: Interpreter::_native_entry_end = Interpreter::code()->code_end(); duke@435: duke@435: #undef method_entry duke@435: duke@435: // Bytecodes duke@435: set_entry_points_for_all_bytes(); duke@435: set_safepoints_for_all_bytes(); duke@435: } duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: duke@435: address TemplateInterpreterGenerator::generate_error_exit(const char* msg) { duke@435: address entry = __ pc(); duke@435: __ stop(msg); duke@435: return entry; duke@435: } duke@435: duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: duke@435: void TemplateInterpreterGenerator::set_entry_points_for_all_bytes() { duke@435: for (int i = 0; i < DispatchTable::length; i++) { duke@435: Bytecodes::Code code = (Bytecodes::Code)i; duke@435: if (Bytecodes::is_defined(code)) { duke@435: set_entry_points(code); duke@435: } else { duke@435: set_unimplemented(i); duke@435: } duke@435: } duke@435: } duke@435: duke@435: duke@435: void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { duke@435: for (int i = 0; i < DispatchTable::length; i++) { duke@435: Bytecodes::Code code = (Bytecodes::Code)i; duke@435: if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry); duke@435: } duke@435: } duke@435: duke@435: duke@435: void TemplateInterpreterGenerator::set_unimplemented(int i) { duke@435: address e = _unimplemented_bytecode; duke@435: EntryPoint entry(e, e, e, e, e, e, e, e, e); duke@435: Interpreter::_normal_table.set_entry(i, entry); duke@435: Interpreter::_wentry_point[i] = _unimplemented_bytecode; duke@435: } duke@435: duke@435: duke@435: void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { duke@435: CodeletMark cm(_masm, Bytecodes::name(code), code); duke@435: // initialize entry points duke@435: assert(_unimplemented_bytecode != NULL, "should have been generated before"); duke@435: assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); duke@435: address bep = _illegal_bytecode_sequence; duke@435: address cep = _illegal_bytecode_sequence; duke@435: address sep = _illegal_bytecode_sequence; duke@435: address aep = _illegal_bytecode_sequence; duke@435: address iep = _illegal_bytecode_sequence; duke@435: address lep = _illegal_bytecode_sequence; duke@435: address fep = _illegal_bytecode_sequence; duke@435: address dep = _illegal_bytecode_sequence; duke@435: address vep = _unimplemented_bytecode; duke@435: address wep = _unimplemented_bytecode; duke@435: // code for short & wide version of bytecode duke@435: if (Bytecodes::is_defined(code)) { duke@435: Template* t = TemplateTable::template_for(code); duke@435: assert(t->is_valid(), "just checking"); duke@435: set_short_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); duke@435: } duke@435: if (Bytecodes::wide_is_defined(code)) { duke@435: Template* t = TemplateTable::template_for_wide(code); duke@435: assert(t->is_valid(), "just checking"); duke@435: set_wide_entry_point(t, wep); duke@435: } duke@435: // set entry points duke@435: EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); duke@435: Interpreter::_normal_table.set_entry(code, entry); duke@435: Interpreter::_wentry_point[code] = wep; duke@435: } duke@435: duke@435: duke@435: void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { duke@435: assert(t->is_valid(), "template must exist"); jcoomes@1844: assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); duke@435: wep = __ pc(); generate_and_dispatch(t); duke@435: } duke@435: duke@435: duke@435: void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) { duke@435: assert(t->is_valid(), "template must exist"); duke@435: switch (t->tos_in()) { twisti@1506: case btos: twisti@1506: case ctos: twisti@1506: case stos: twisti@1506: ShouldNotReachHere(); // btos/ctos/stos should use itos. twisti@1506: break; duke@435: case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; duke@435: case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; duke@435: case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; duke@435: case ftos: vep = __ pc(); __ pop(ftos); fep = __ pc(); generate_and_dispatch(t); break; duke@435: case dtos: vep = __ pc(); __ pop(dtos); dep = __ pc(); generate_and_dispatch(t); break; duke@435: case vtos: set_vtos_entry_points(t, bep, cep, sep, aep, iep, lep, fep, dep, vep); break; duke@435: default : ShouldNotReachHere(); break; duke@435: } duke@435: } duke@435: duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: duke@435: void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) { duke@435: if (PrintBytecodeHistogram) histogram_bytecode(t); duke@435: #ifndef PRODUCT duke@435: // debugging code duke@435: if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode(); duke@435: if (PrintBytecodePairHistogram) histogram_bytecode_pair(t); duke@435: if (TraceBytecodes) trace_bytecode(t); duke@435: if (StopInterpreterAt > 0) stop_interpreter_at(); duke@435: __ verify_FPU(1, t->tos_in()); duke@435: #endif // !PRODUCT duke@435: int step; duke@435: if (!t->does_dispatch()) { duke@435: step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode()); duke@435: if (tos_out == ilgl) tos_out = t->tos_out(); duke@435: // compute bytecode size duke@435: assert(step > 0, "just checkin'"); duke@435: // setup stuff for dispatching next bytecode duke@435: if (ProfileInterpreter && VerifyDataPointer duke@435: && methodDataOopDesc::bytecode_has_profile(t->bytecode())) { duke@435: __ verify_method_data_pointer(); duke@435: } duke@435: __ dispatch_prolog(tos_out, step); duke@435: } duke@435: // generate template duke@435: t->generate(_masm); duke@435: // advance duke@435: if (t->does_dispatch()) { duke@435: #ifdef ASSERT duke@435: // make sure execution doesn't go beyond this point if code is broken duke@435: __ should_not_reach_here(); duke@435: #endif // ASSERT duke@435: } else { duke@435: // dispatch to next bytecode duke@435: __ dispatch_epilog(tos_out, step); duke@435: } duke@435: } duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: // Entry points duke@435: duke@435: address TemplateInterpreter::return_entry(TosState state, int length) { duke@435: guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); duke@435: return _return_entry[length].entry(state); duke@435: } duke@435: duke@435: duke@435: address TemplateInterpreter::deopt_entry(TosState state, int length) { duke@435: guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); duke@435: return _deopt_entry[length].entry(state); duke@435: } duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: // Suport for invokes duke@435: duke@435: int TemplateInterpreter::TosState_as_index(TosState state) { duke@435: assert( state < number_of_states , "Invalid state in TosState_as_index"); duke@435: assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds"); duke@435: return (int)state; duke@435: } duke@435: duke@435: duke@435: //------------------------------------------------------------------------------------------------------------------------ duke@435: // Safepoint suppport duke@435: duke@435: static inline void copy_table(address* from, address* to, int size) { duke@435: // Copy non-overlapping tables. The copy has to occur word wise for MT safety. duke@435: while (size-- > 0) *to++ = *from++; duke@435: } duke@435: duke@435: void TemplateInterpreter::notice_safepoints() { duke@435: if (!_notice_safepoints) { duke@435: // switch to safepoint dispatch table duke@435: _notice_safepoints = true; duke@435: copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); duke@435: } duke@435: } duke@435: duke@435: // switch from the dispatch table which notices safepoints back to the duke@435: // normal dispatch table. So that we can notice single stepping points, duke@435: // keep the safepoint dispatch table if we are single stepping in JVMTI. duke@435: // Note that the should_post_single_step test is exactly as fast as the duke@435: // JvmtiExport::_enabled test and covers both cases. duke@435: void TemplateInterpreter::ignore_safepoints() { duke@435: if (_notice_safepoints) { duke@435: if (!JvmtiExport::should_post_single_step()) { duke@435: // switch to normal dispatch table duke@435: _notice_safepoints = false; duke@435: copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address)); duke@435: } duke@435: } duke@435: } duke@435: cfang@1335: //------------------------------------------------------------------------------------------------------------------------ cfang@1335: // Deoptimization support duke@435: cfang@1335: // If deoptimization happens, this function returns the point of next bytecode to continue execution cfang@1335: address TemplateInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) { cfang@1335: return AbstractInterpreter::deopt_continue_after_entry(method, bcp, callee_parameters, is_top_frame); cfang@1335: } duke@435: cfang@1335: // If deoptimization happens, this function returns the point where the interpreter reexecutes cfang@1335: // the bytecode. cfang@1335: // Note: Bytecodes::_athrow (C1 only) and Bytecodes::_return are the special cases cfang@1335: // that do not return "Interpreter::deopt_entry(vtos, 0)" cfang@1335: address TemplateInterpreter::deopt_reexecute_entry(methodOop method, address bcp) { duke@435: assert(method->contains(bcp), "just checkin'"); duke@435: Bytecodes::Code code = Bytecodes::java_code_at(bcp); duke@435: if (code == Bytecodes::_return) { cfang@1335: // This is used for deopt during registration of finalizers cfang@1335: // during Object.. We simply need to resume execution at cfang@1335: // the standard return vtos bytecode to pop the frame normally. cfang@1335: // reexecuting the real bytecode would cause double registration cfang@1335: // of the finalizable object. cfang@1335: return _normal_table.entry(Bytecodes::_return).entry(vtos); duke@435: } else { cfang@1335: return AbstractInterpreter::deopt_reexecute_entry(method, bcp); cfang@1335: } cfang@1335: } cfang@1335: cfang@1335: // If deoptimization happens, the interpreter should reexecute this bytecode. cfang@1335: // This function mainly helps the compilers to set up the reexecute bit. cfang@1335: bool TemplateInterpreter::bytecode_should_reexecute(Bytecodes::Code code) { cfang@1335: if (code == Bytecodes::_return) { cfang@1335: //Yes, we consider Bytecodes::_return as a special case of reexecution cfang@1335: return true; cfang@1335: } else { cfang@1335: return AbstractInterpreter::bytecode_should_reexecute(code); duke@435: } duke@435: } duke@435: duke@435: #endif // !CC_INTERP