Path: blob/master/src/hotspot/share/interpreter/templateInterpreter.cpp
40949 views
/*1* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "interpreter/interpreter.hpp"26#include "interpreter/interpreterRuntime.hpp"27#include "interpreter/interp_masm.hpp"28#include "interpreter/templateInterpreter.hpp"29#include "interpreter/templateInterpreterGenerator.hpp"30#include "interpreter/templateTable.hpp"31#include "logging/log.hpp"32#include "memory/resourceArea.hpp"33#include "prims/jvmtiExport.hpp"34#include "runtime/safepoint.hpp"35#include "runtime/timerTrace.hpp"36#include "utilities/copy.hpp"3738# define __ _masm->3940void TemplateInterpreter::initialize_stub() {41// assertions42assert(_code == NULL, "must only initialize once");43assert((int)Bytecodes::number_of_codes <= (int)DispatchTable::length,44"dispatch table too small");4546// allocate interpreter47int code_size = InterpreterCodeSize;48NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space49_code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL,50"Interpreter");51}5253void TemplateInterpreter::initialize_code() {54AbstractInterpreter::initialize();5556TemplateTable::initialize();5758// generate interpreter59{ ResourceMark rm;60TraceTime timer("Interpreter generation", TRACETIME_LOG(Info, startuptime));61TemplateInterpreterGenerator g(_code);62// Free the unused memory not occupied by the interpreter and the stubs63_code->deallocate_unused_tail();64}6566if (PrintInterpreter) {67ResourceMark rm;68print();69}7071// initialize dispatch table72_active_table = _normal_table;73}7475//------------------------------------------------------------------------------------------------------------------------76// Implementation of EntryPoint7778EntryPoint::EntryPoint() {79assert(number_of_states == 10, "check the code below");80_entry[btos] = NULL;81_entry[ztos] = NULL;82_entry[ctos] = NULL;83_entry[stos] = NULL;84_entry[atos] = NULL;85_entry[itos] = NULL;86_entry[ltos] = NULL;87_entry[ftos] = NULL;88_entry[dtos] = NULL;89_entry[vtos] = NULL;90}919293EntryPoint::EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) {94assert(number_of_states == 10, "check the code below");95_entry[btos] = bentry;96_entry[ztos] = zentry;97_entry[ctos] = centry;98_entry[stos] = sentry;99_entry[atos] = aentry;100_entry[itos] = ientry;101_entry[ltos] = lentry;102_entry[ftos] = fentry;103_entry[dtos] = dentry;104_entry[vtos] = ventry;105}106107EntryPoint::EntryPoint(address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) {108assert(number_of_states == 10, "check the code below");109_entry[btos] = ientry;110_entry[ztos] = ientry;111_entry[ctos] = ientry;112_entry[stos] = ientry;113_entry[atos] = aentry;114_entry[itos] = ientry;115_entry[ltos] = lentry;116_entry[ftos] = fentry;117_entry[dtos] = dentry;118_entry[vtos] = ventry;119}120121void EntryPoint::set_entry(TosState state, address entry) {122assert(0 <= state && state < number_of_states, "state out of bounds");123_entry[state] = entry;124}125126127address EntryPoint::entry(TosState state) const {128assert(0 <= state && state < number_of_states, "state out of bounds");129return _entry[state];130}131132133void EntryPoint::print() {134tty->print("[");135for (int i = 0; i < number_of_states; i++) {136if (i > 0) tty->print(", ");137tty->print(INTPTR_FORMAT, p2i(_entry[i]));138}139tty->print("]");140}141142143bool EntryPoint::operator == (const EntryPoint& y) {144int i = number_of_states;145while (i-- > 0) {146if (_entry[i] != y._entry[i]) return false;147}148return true;149}150151152//------------------------------------------------------------------------------------------------------------------------153// Implementation of DispatchTable154155EntryPoint DispatchTable::entry(int i) const {156assert(0 <= i && i < length, "index out of bounds");157return158EntryPoint(159_table[btos][i],160_table[ztos][i],161_table[ctos][i],162_table[stos][i],163_table[atos][i],164_table[itos][i],165_table[ltos][i],166_table[ftos][i],167_table[dtos][i],168_table[vtos][i]169);170}171172173void DispatchTable::set_entry(int i, EntryPoint& entry) {174assert(0 <= i && i < length, "index out of bounds");175assert(number_of_states == 10, "check the code below");176_table[btos][i] = entry.entry(btos);177_table[ztos][i] = entry.entry(ztos);178_table[ctos][i] = entry.entry(ctos);179_table[stos][i] = entry.entry(stos);180_table[atos][i] = entry.entry(atos);181_table[itos][i] = entry.entry(itos);182_table[ltos][i] = entry.entry(ltos);183_table[ftos][i] = entry.entry(ftos);184_table[dtos][i] = entry.entry(dtos);185_table[vtos][i] = entry.entry(vtos);186}187188189bool DispatchTable::operator == (DispatchTable& y) {190int i = length;191while (i-- > 0) {192EntryPoint t = y.entry(i); // for compiler compatibility (BugId 4150096)193if (!(entry(i) == t)) return false;194}195return true;196}197198address TemplateInterpreter::_remove_activation_entry = NULL;199address TemplateInterpreter::_remove_activation_preserving_args_entry = NULL;200201202address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NULL;203address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;204address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;205address TemplateInterpreter::_throw_ClassCastException_entry = NULL;206address TemplateInterpreter::_throw_NullPointerException_entry = NULL;207address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;208address TemplateInterpreter::_throw_exception_entry = NULL;209210#ifndef PRODUCT211EntryPoint TemplateInterpreter::_trace_code;212#endif // !PRODUCT213EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries];214EntryPoint TemplateInterpreter::_earlyret_entry;215EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ];216address TemplateInterpreter::_deopt_reexecute_return_entry;217EntryPoint TemplateInterpreter::_safept_entry;218219address TemplateInterpreter::_invoke_return_entry[TemplateInterpreter::number_of_return_addrs];220address TemplateInterpreter::_invokeinterface_return_entry[TemplateInterpreter::number_of_return_addrs];221address TemplateInterpreter::_invokedynamic_return_entry[TemplateInterpreter::number_of_return_addrs];222223DispatchTable TemplateInterpreter::_active_table;224DispatchTable TemplateInterpreter::_normal_table;225DispatchTable TemplateInterpreter::_safept_table;226address TemplateInterpreter::_wentry_point[DispatchTable::length];227228229//------------------------------------------------------------------------------------------------------------------------230// Entry points231232/**233* Returns the return entry table for the given invoke bytecode.234*/235address* TemplateInterpreter::invoke_return_entry_table_for(Bytecodes::Code code) {236switch (code) {237case Bytecodes::_invokestatic:238case Bytecodes::_invokespecial:239case Bytecodes::_invokevirtual:240case Bytecodes::_invokehandle:241return Interpreter::invoke_return_entry_table();242case Bytecodes::_invokeinterface:243return Interpreter::invokeinterface_return_entry_table();244case Bytecodes::_invokedynamic:245return Interpreter::invokedynamic_return_entry_table();246default:247fatal("invalid bytecode: %s", Bytecodes::name(code));248return NULL;249}250}251252/**253* Returns the return entry address for the given top-of-stack state and bytecode.254*/255address TemplateInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) {256guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length");257const int index = TosState_as_index(state);258switch (code) {259case Bytecodes::_invokestatic:260case Bytecodes::_invokespecial:261case Bytecodes::_invokevirtual:262case Bytecodes::_invokehandle:263return _invoke_return_entry[index];264case Bytecodes::_invokeinterface:265return _invokeinterface_return_entry[index];266case Bytecodes::_invokedynamic:267return _invokedynamic_return_entry[index];268default:269assert(!Bytecodes::is_invoke(code), "invoke instructions should be handled separately: %s", Bytecodes::name(code));270address entry = _return_entry[length].entry(state);271vmassert(entry != NULL, "unsupported return entry requested, length=%d state=%d", length, index);272return entry;273}274}275276277address TemplateInterpreter::deopt_entry(TosState state, int length) {278guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length");279address entry = _deopt_entry[length].entry(state);280vmassert(entry != NULL, "unsupported deopt entry requested, length=%d state=%d", length, TosState_as_index(state));281return entry;282}283284//------------------------------------------------------------------------------------------------------------------------285// Suport for invokes286287int TemplateInterpreter::TosState_as_index(TosState state) {288assert( state < number_of_states , "Invalid state in TosState_as_index");289assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds");290return (int)state;291}292293294//------------------------------------------------------------------------------------------------------------------------295// Safepoint support296297static inline void copy_table(address* from, address* to, int size) {298// Copy non-overlapping tables.299if (SafepointSynchronize::is_at_safepoint()) {300// Nothing is using the table at a safepoint so skip atomic word copy.301Copy::disjoint_words((HeapWord*)from, (HeapWord*)to, (size_t)size);302} else {303// Use atomic word copy when not at a safepoint for safety.304Copy::disjoint_words_atomic((HeapWord*)from, (HeapWord*)to, (size_t)size);305}306}307308void TemplateInterpreter::notice_safepoints() {309if (!_notice_safepoints) {310log_debug(interpreter, safepoint)("switching active_table to safept_table.");311// switch to safepoint dispatch table312_notice_safepoints = true;313copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address));314} else {315log_debug(interpreter, safepoint)("active_table is already safept_table; "316"notice_safepoints() call is no-op.");317}318}319320// switch from the dispatch table which notices safepoints back to the321// normal dispatch table. So that we can notice single stepping points,322// keep the safepoint dispatch table if we are single stepping in JVMTI.323// Note that the should_post_single_step test is exactly as fast as the324// JvmtiExport::_enabled test and covers both cases.325void TemplateInterpreter::ignore_safepoints() {326if (_notice_safepoints) {327if (!JvmtiExport::should_post_single_step()) {328log_debug(interpreter, safepoint)("switching active_table to normal_table.");329// switch to normal dispatch table330_notice_safepoints = false;331copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address));332} else {333log_debug(interpreter, safepoint)("single stepping is still active; "334"ignoring ignore_safepoints() call.");335}336} else {337log_debug(interpreter, safepoint)("active_table is already normal_table; "338"ignore_safepoints() call is no-op.");339}340}341342//------------------------------------------------------------------------------------------------------------------------343// Deoptimization support344345// If deoptimization happens, this function returns the point of next bytecode to continue execution346address TemplateInterpreter::deopt_continue_after_entry(Method* method, address bcp, int callee_parameters, bool is_top_frame) {347return AbstractInterpreter::deopt_continue_after_entry(method, bcp, callee_parameters, is_top_frame);348}349350// If deoptimization happens, this function returns the point where the interpreter reexecutes351// the bytecode.352// Note: Bytecodes::_athrow (C1 only) and Bytecodes::_return are the special cases353// that do not return "Interpreter::deopt_entry(vtos, 0)"354address TemplateInterpreter::deopt_reexecute_entry(Method* method, address bcp) {355assert(method->contains(bcp), "just checkin'");356Bytecodes::Code code = Bytecodes::code_at(method, bcp);357if (code == Bytecodes::_return_register_finalizer) {358// This is used for deopt during registration of finalizers359// during Object.<init>. We simply need to resume execution at360// the standard return vtos bytecode to pop the frame normally.361// reexecuting the real bytecode would cause double registration362// of the finalizable object.363return Interpreter::deopt_reexecute_return_entry();364} else {365return AbstractInterpreter::deopt_reexecute_entry(method, bcp);366}367}368369// If deoptimization happens, the interpreter should reexecute this bytecode.370// This function mainly helps the compilers to set up the reexecute bit.371bool TemplateInterpreter::bytecode_should_reexecute(Bytecodes::Code code) {372if (code == Bytecodes::_return) {373//Yes, we consider Bytecodes::_return as a special case of reexecution374return true;375} else {376return AbstractInterpreter::bytecode_should_reexecute(code);377}378}379380InterpreterCodelet* TemplateInterpreter::codelet_containing(address pc) {381return (InterpreterCodelet*)_code->stub_containing(pc);382}383384385