8255822: Zero: improve build-time JVMTI handling

Reviewed-by: dholmes, ihse
This commit is contained in:
Aleksey Shipilev 2020-11-10 17:23:10 +00:00
parent 6ae5e5b6b7
commit 643969a184
6 changed files with 60 additions and 183 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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>