8255822: Zero: improve build-time JVMTI handling
Reviewed-by: dholmes, ihse
This commit is contained in:
parent
6ae5e5b6b7
commit
643969a184
@ -106,17 +106,6 @@ $(eval $(call SetupJvmtiGeneration, jvmti.h, jvmtiH.xsl, \
|
||||
$(eval $(call SetupJvmtiGeneration, jvmti.html, jvmti.xsl, \
|
||||
-PARAM majorversion $(VERSION_FEATURE)))
|
||||
|
||||
JVMTI_BC_SRCDIR := $(TOPDIR)/src/hotspot/share/interpreter/zero
|
||||
|
||||
ifeq ($(call check-jvm-feature, zero), true)
|
||||
$(eval $(call SetupXslTransform, bytecodeInterpreterWithChecks.cpp, \
|
||||
XML_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xml, \
|
||||
XSL_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xsl, \
|
||||
OUTPUT_DIR := $(JVMTI_OUTPUTDIR), \
|
||||
DEPS := $(JVMTI_BC_SRCDIR)/bytecodeInterpreter.cpp, \
|
||||
))
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Copy jvmti.h to include dir
|
||||
|
||||
|
@ -70,10 +70,11 @@ void ZeroInterpreter::initialize_code() {
|
||||
|
||||
// Allow c++ interpreter to do one initialization now that switches are set, etc.
|
||||
BytecodeInterpreter start_msg(BytecodeInterpreter::initialize);
|
||||
if (JvmtiExport::can_post_interpreter_events())
|
||||
BytecodeInterpreter::runWithChecks(&start_msg);
|
||||
else
|
||||
BytecodeInterpreter::run(&start_msg);
|
||||
if (JvmtiExport::can_post_interpreter_events()) {
|
||||
BytecodeInterpreter::run<true>(&start_msg);
|
||||
} else {
|
||||
BytecodeInterpreter::run<false>(&start_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void ZeroInterpreter::invoke_method(Method* method, address entry_point, TRAPS) {
|
||||
@ -169,10 +170,11 @@ void ZeroInterpreter::main_loop(int recurse, TRAPS) {
|
||||
thread->set_last_Java_frame();
|
||||
|
||||
// Call the interpreter
|
||||
if (JvmtiExport::can_post_interpreter_events())
|
||||
BytecodeInterpreter::runWithChecks(istate);
|
||||
else
|
||||
BytecodeInterpreter::run(istate);
|
||||
if (JvmtiExport::can_post_interpreter_events()) {
|
||||
BytecodeInterpreter::run<true>(istate);
|
||||
} else {
|
||||
BytecodeInterpreter::run<false>(istate);
|
||||
}
|
||||
fixup_after_potential_safepoint();
|
||||
|
||||
// Clear the frame anchor
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/threadCritical.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
// no precompiled headers
|
||||
|
||||
@ -153,7 +154,7 @@
|
||||
#endif
|
||||
|
||||
#undef DEBUGGER_SINGLE_STEP_NOTIFY
|
||||
#ifdef VM_JVMTI
|
||||
#if INCLUDE_JVMTI
|
||||
/* NOTE: (kbr) This macro must be called AFTER the PC has been
|
||||
incremented. JvmtiExport::at_single_stepping_point() may cause a
|
||||
breakpoint opcode to get inserted at the current PC to allow the
|
||||
@ -163,33 +164,31 @@
|
||||
to get the current opcode. This will override any other prefetching
|
||||
that might have occurred.
|
||||
*/
|
||||
#define DEBUGGER_SINGLE_STEP_NOTIFY() \
|
||||
{ \
|
||||
if (_jvmti_interp_events) { \
|
||||
if (JvmtiExport::should_post_single_step()) { \
|
||||
DECACHE_STATE(); \
|
||||
SET_LAST_JAVA_FRAME(); \
|
||||
ThreadInVMfromJava trans(THREAD); \
|
||||
JvmtiExport::at_single_stepping_point(THREAD, \
|
||||
istate->method(), \
|
||||
pc); \
|
||||
RESET_LAST_JAVA_FRAME(); \
|
||||
CACHE_STATE(); \
|
||||
if (THREAD->has_pending_popframe() && \
|
||||
!THREAD->pop_frame_in_process()) { \
|
||||
goto handle_Pop_Frame; \
|
||||
} \
|
||||
if (THREAD->jvmti_thread_state() && \
|
||||
THREAD->jvmti_thread_state()->is_earlyret_pending()) { \
|
||||
goto handle_Early_Return; \
|
||||
} \
|
||||
opcode = *pc; \
|
||||
} \
|
||||
} \
|
||||
#define DEBUGGER_SINGLE_STEP_NOTIFY() \
|
||||
{ \
|
||||
if (JVMTI_ENABLED && JvmtiExport::should_post_single_step()) { \
|
||||
DECACHE_STATE(); \
|
||||
SET_LAST_JAVA_FRAME(); \
|
||||
ThreadInVMfromJava trans(THREAD); \
|
||||
JvmtiExport::at_single_stepping_point(THREAD, \
|
||||
istate->method(), \
|
||||
pc); \
|
||||
RESET_LAST_JAVA_FRAME(); \
|
||||
CACHE_STATE(); \
|
||||
if (THREAD->has_pending_popframe() && \
|
||||
!THREAD->pop_frame_in_process()) { \
|
||||
goto handle_Pop_Frame; \
|
||||
} \
|
||||
if (THREAD->jvmti_thread_state() && \
|
||||
THREAD->jvmti_thread_state()->is_earlyret_pending()) { \
|
||||
goto handle_Early_Return; \
|
||||
} \
|
||||
opcode = *pc; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define DEBUGGER_SINGLE_STEP_NOTIFY()
|
||||
#endif
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
/*
|
||||
* CONTINUE - Macro for executing the next opcode.
|
||||
@ -387,22 +386,18 @@
|
||||
|
||||
/*
|
||||
* BytecodeInterpreter::run(interpreterState istate)
|
||||
* BytecodeInterpreter::runWithChecks(interpreterState istate)
|
||||
*
|
||||
* The real deal. This is where byte codes actually get interpreted.
|
||||
* Basically it's a big while loop that iterates until we return from
|
||||
* the method passed in.
|
||||
*
|
||||
* The runWithChecks is used if JVMTI is enabled.
|
||||
*
|
||||
*/
|
||||
#if defined(VM_JVMTI)
|
||||
void
|
||||
BytecodeInterpreter::runWithChecks(interpreterState istate) {
|
||||
#else
|
||||
void
|
||||
BytecodeInterpreter::run(interpreterState istate) {
|
||||
#endif
|
||||
|
||||
// Instantiate two variants of the method for future linking.
|
||||
template void BytecodeInterpreter::run<true>(interpreterState istate);
|
||||
template void BytecodeInterpreter::run<false>(interpreterState istate);
|
||||
|
||||
template<bool JVMTI_ENABLED>
|
||||
void BytecodeInterpreter::run(interpreterState istate) {
|
||||
|
||||
// In order to simplify some tests based on switches set at runtime
|
||||
// we invoke the interpreter a single time after switches are enabled
|
||||
@ -417,9 +412,6 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
if (checkit && *c_addr != c_value) {
|
||||
os::breakpoint();
|
||||
}
|
||||
#ifdef VM_JVMTI
|
||||
static bool _jvmti_interp_events = 0;
|
||||
#endif
|
||||
|
||||
#ifdef ASSERT
|
||||
if (istate->_msg != initialize) {
|
||||
@ -555,9 +547,6 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
switch (istate->msg()) {
|
||||
case initialize: {
|
||||
if (initialized++) ShouldNotReachHere(); // Only one initialize call.
|
||||
#ifdef VM_JVMTI
|
||||
_jvmti_interp_events = JvmtiExport::can_post_interpreter_events();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -667,17 +656,13 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
}
|
||||
THREAD->clr_do_not_unlock();
|
||||
|
||||
// Notify jvmti
|
||||
#ifdef VM_JVMTI
|
||||
if (_jvmti_interp_events) {
|
||||
// Whenever JVMTI puts a thread in interp_only_mode, method
|
||||
// entry/exit events are sent for that thread to track stack depth.
|
||||
if (THREAD->is_interp_only_mode()) {
|
||||
CALL_VM(InterpreterRuntime::post_method_entry(THREAD),
|
||||
handle_exception);
|
||||
}
|
||||
// Notify jvmti.
|
||||
// Whenever JVMTI puts a thread in interp_only_mode, method
|
||||
// entry/exit events are sent for that thread to track stack depth.
|
||||
if (JVMTI_ENABLED && THREAD->is_interp_only_mode()) {
|
||||
CALL_VM(InterpreterRuntime::post_method_entry(THREAD),
|
||||
handle_exception);
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
|
||||
goto run;
|
||||
}
|
||||
@ -1800,8 +1785,7 @@ run:
|
||||
cache = cp->entry_at(index);
|
||||
}
|
||||
|
||||
#ifdef VM_JVMTI
|
||||
if (_jvmti_interp_events) {
|
||||
if (JVMTI_ENABLED) {
|
||||
int *count_addr;
|
||||
oop obj;
|
||||
// Check to see if a field modification watch has been set
|
||||
@ -1820,7 +1804,6 @@ run:
|
||||
handle_exception);
|
||||
}
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
|
||||
oop obj;
|
||||
if ((Bytecodes::Code)opcode == Bytecodes::_getstatic) {
|
||||
@ -1898,8 +1881,7 @@ run:
|
||||
cache = cp->entry_at(index);
|
||||
}
|
||||
|
||||
#ifdef VM_JVMTI
|
||||
if (_jvmti_interp_events) {
|
||||
if (JVMTI_ENABLED) {
|
||||
int *count_addr;
|
||||
oop obj;
|
||||
// Check to see if a field modification watch has been set
|
||||
@ -1925,7 +1907,6 @@ run:
|
||||
handle_exception);
|
||||
}
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
|
||||
// QQQ Need to make this as inlined as possible. Probably need to split all the bytecode cases
|
||||
// out so c++ compiler has a chance for constant prop to fold everything possible away.
|
||||
@ -2404,11 +2385,9 @@ run:
|
||||
if (callee != NULL) {
|
||||
istate->set_callee(callee);
|
||||
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
||||
#ifdef VM_JVMTI
|
||||
if (JvmtiExport::can_post_interpreter_events() && THREAD->is_interp_only_mode()) {
|
||||
if (JVMTI_ENABLED && THREAD->is_interp_only_mode()) {
|
||||
istate->set_callee_entry_point(callee->interpreter_entry());
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
istate->set_bcp_advance(5);
|
||||
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||
}
|
||||
@ -2466,11 +2445,9 @@ run:
|
||||
|
||||
istate->set_callee(callee);
|
||||
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
||||
#ifdef VM_JVMTI
|
||||
if (JvmtiExport::can_post_interpreter_events() && THREAD->is_interp_only_mode()) {
|
||||
if (JVMTI_ENABLED && THREAD->is_interp_only_mode()) {
|
||||
istate->set_callee_entry_point(callee->interpreter_entry());
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
istate->set_bcp_advance(5);
|
||||
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||
}
|
||||
@ -2536,11 +2513,9 @@ run:
|
||||
|
||||
istate->set_callee(callee);
|
||||
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
||||
#ifdef VM_JVMTI
|
||||
if (JvmtiExport::can_post_interpreter_events() && THREAD->is_interp_only_mode()) {
|
||||
if (JVMTI_ENABLED && THREAD->is_interp_only_mode()) {
|
||||
istate->set_callee_entry_point(callee->interpreter_entry());
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
istate->set_bcp_advance(3);
|
||||
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||
}
|
||||
@ -2963,25 +2938,16 @@ run:
|
||||
// (with this note) in anticipation of changing the vm and the tests
|
||||
// simultaneously.
|
||||
|
||||
|
||||
//
|
||||
suppress_exit_event = suppress_exit_event || illegal_state_oop() != NULL;
|
||||
|
||||
// Whenever JVMTI puts a thread in interp_only_mode, method
|
||||
// entry/exit events are sent for that thread to track stack depth.
|
||||
|
||||
|
||||
#ifdef VM_JVMTI
|
||||
if (_jvmti_interp_events) {
|
||||
// Whenever JVMTI puts a thread in interp_only_mode, method
|
||||
// entry/exit events are sent for that thread to track stack depth.
|
||||
if ( !suppress_exit_event && THREAD->is_interp_only_mode() ) {
|
||||
{
|
||||
// Prevent any HandleMarkCleaner from freeing our live handles
|
||||
HandleMark __hm(THREAD);
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::post_method_exit(THREAD));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* VM_JVMTI */
|
||||
if (JVMTI_ENABLED && !suppress_exit_event && THREAD->is_interp_only_mode()) {
|
||||
// Prevent any HandleMarkCleaner from freeing our live handles
|
||||
HandleMark __hm(THREAD);
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::post_method_exit(THREAD));
|
||||
}
|
||||
|
||||
//
|
||||
// See if we are returning any exception
|
||||
@ -3032,13 +2998,6 @@ finish:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the code following this point is only produced once and is not present
|
||||
* in the JVMTI version of the interpreter
|
||||
*/
|
||||
|
||||
#ifndef VM_JVMTI
|
||||
|
||||
// This constructor should only be used to contruct the object to signal
|
||||
// interpreter initialization. All other instances should be created by
|
||||
// the frame manager.
|
||||
@ -3169,5 +3128,3 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
#endif // JVMTI
|
||||
|
@ -503,12 +503,8 @@ static void dup2_x1(intptr_t *tos); /* insert top 2 slots three down */
|
||||
static void dup2_x2(intptr_t *tos); /* insert top 2 slots four down */
|
||||
static void swap(intptr_t *tos); /* swap top two elements */
|
||||
|
||||
// umm don't like this method modifies its object
|
||||
|
||||
// The Interpreter used when
|
||||
template<bool JVMTI_ENABLED>
|
||||
static void run(interpreterState istate);
|
||||
// The interpreter used if JVMTI needs interpreter events
|
||||
static void runWithChecks(interpreterState istate);
|
||||
|
||||
static void astore(intptr_t* topOfStack, int stack_offset,
|
||||
intptr_t* locals, int locals_offset);
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (c) 1997, 2020, 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
|
||||
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.
|
||||
-->
|
||||
<!DOCTYPE processcode [
|
||||
<!ELEMENT processcode ANY>
|
||||
]>
|
||||
<processcode>
|
||||
</processcode>
|
@ -1,39 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (c) 1997, 2020, 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
|
||||
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.
|
||||
-->
|
||||
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
|
||||
|
||||
<xsl:template match="processcode">
|
||||
<xsl:text>
|
||||
#define VM_JVMTI
|
||||
#include "interpreter/zero/bytecodeInterpreter.cpp"
|
||||
</xsl:text>
|
||||
<xsl:text disable-output-escaping = "yes">
|
||||
|
||||
</xsl:text>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
Loading…
Reference in New Issue
Block a user