/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterGenerator.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/templateTable.hpp"
#ifndef CC_INTERP
// assertions
"dispatch table too small");
// generate interpreter
"Interpreter");
if (PrintInterpreter) print();
}
// initialize dispatch table
}
//------------------------------------------------------------------------------------------------------------------------
// Implementation of EntryPoint
}
EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) {
}
}
}
for (int i = 0; i < number_of_states; i++) {
}
}
bool EntryPoint::operator == (const EntryPoint& y) {
int i = number_of_states;
while (i-- > 0) {
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------
// Implementation of DispatchTable
return
);
}
}
bool DispatchTable::operator == (DispatchTable& y) {
int i = length;
while (i-- > 0) {
if (!(entry(i) == t)) return false;
}
return true;
}
#ifndef PRODUCT
#endif // !PRODUCT
TemplateInterpreterGenerator::TemplateInterpreterGenerator(StubQueue* _code): AbstractInterpreterGenerator(_code) {
}
T_CHAR ,
T_BYTE ,
T_SHORT ,
T_INT ,
T_LONG ,
T_VOID ,
T_FLOAT ,
T_DOUBLE ,
};
_illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified");
}
#ifndef PRODUCT
if (TraceBytecodes) {
);
}
#endif // !PRODUCT
for (int i = 0; i < Interpreter::number_of_return_entries; i++) {
);
}
}
);
}
for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) {
);
}
}
// The various result converter stublets.
for (int i = 0; i < Interpreter::number_of_result_handlers; i++) {
Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type);
}
}
}
for (int j = 0; j < number_of_states; j++) {
}
);
}
);
}
// (Note: this is not safepoint safe because thread may return to compiled code)
}
Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException");
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
}
}
// all non-native method kinds
// all native method kinds (must be one contiguous block)
// Bytecodes
}
//------------------------------------------------------------------------------------------------------------------------
return entry;
}
//------------------------------------------------------------------------------------------------------------------------
for (int i = 0; i < DispatchTable::length; i++) {
} else {
}
}
}
for (int i = 0; i < DispatchTable::length; i++) {
if (Bytecodes::is_defined(code)) Interpreter::_safept_table.set_entry(code, Interpreter::_safept_entry);
}
}
EntryPoint entry(e, e, e, e, e, e, e, e, e);
}
// initialize entry points
// code for short & wide version of bytecode
}
set_wide_entry_point(t, wep);
}
// set entry points
}
}
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) {
switch (t->tos_in()) {
case btos:
case ctos:
case stos:
ShouldNotReachHere(); // btos/ctos/stos should use itos.
break;
default : ShouldNotReachHere(); break;
}
}
//------------------------------------------------------------------------------------------------------------------------
if (PrintBytecodeHistogram) histogram_bytecode(t);
#ifndef PRODUCT
// debugging code
if (TraceBytecodes) trace_bytecode(t);
if (StopInterpreterAt > 0) stop_interpreter_at();
#endif // !PRODUCT
int step;
if (!t->does_dispatch()) {
step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());
// compute bytecode size
// setup stuff for dispatching next bytecode
}
}
// generate template
// advance
if (t->does_dispatch()) {
#ifdef ASSERT
// make sure execution doesn't go beyond this point if code is broken
#endif // ASSERT
} else {
// dispatch to next bytecode
}
}
//------------------------------------------------------------------------------------------------------------------------
// Entry points
}
}
//------------------------------------------------------------------------------------------------------------------------
// Suport for invokes
assert(0 <= (int)state && (int)state < TemplateInterpreter::number_of_return_addrs, "index out of bounds");
return (int)state;
}
//------------------------------------------------------------------------------------------------------------------------
// Safepoint suppport
// Copy non-overlapping tables. The copy has to occur word wise for MT safety.
}
void TemplateInterpreter::notice_safepoints() {
if (!_notice_safepoints) {
// switch to safepoint dispatch table
_notice_safepoints = true;
copy_table((address*)&_safept_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address));
}
}
// switch from the dispatch table which notices safepoints back to the
// normal dispatch table. So that we can notice single stepping points,
// keep the safepoint dispatch table if we are single stepping in JVMTI.
// Note that the should_post_single_step test is exactly as fast as the
// JvmtiExport::_enabled test and covers both cases.
void TemplateInterpreter::ignore_safepoints() {
if (_notice_safepoints) {
if (!JvmtiExport::should_post_single_step()) {
// switch to normal dispatch table
_notice_safepoints = false;
copy_table((address*)&_normal_table, (address*)&_active_table, sizeof(_active_table) / sizeof(address));
}
}
}
//------------------------------------------------------------------------------------------------------------------------
// Deoptimization support
// If deoptimization happens, this function returns the point of next bytecode to continue execution
address TemplateInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) {
return AbstractInterpreter::deopt_continue_after_entry(method, bcp, callee_parameters, is_top_frame);
}
// If deoptimization happens, this function returns the point where the interpreter reexecutes
// the bytecode.
// Note: Bytecodes::_athrow (C1 only) and Bytecodes::_return are the special cases
// that do not return "Interpreter::deopt_entry(vtos, 0)"
// This is used for deopt during registration of finalizers
// during Object.<init>. We simply need to resume execution at
// the standard return vtos bytecode to pop the frame normally.
// reexecuting the real bytecode would cause double registration
// of the finalizable object.
} else {
}
}
// If deoptimization happens, the interpreter should reexecute this bytecode.
// This function mainly helps the compilers to set up the reexecute bit.
//Yes, we consider Bytecodes::_return as a special case of reexecution
return true;
} else {
}
}
#endif // !CC_INTERP