8152065: TraceBytecodes breaks the interpreter expression stack
Summary: Move trace_bytecode to InterpreterRuntime and make trace_bytecode an IRT_LEAF so that safepoints are not allowed.
Reviewed-by: jiangli, dholmes, dcubed
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -1967,7 +1967,7 @@
__ push(RegSet::range(r0, r15), sp);
__ mov(c_rarg2, r0); // Pass itos
__ call_VM(noreg,
- CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode),
+ CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode),
c_rarg1, c_rarg2, c_rarg3);
__ pop(RegSet::range(r0, r15), sp);
__ pop(state);
--- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -2211,7 +2211,7 @@
__ ld(R6_ARG4, tsize*Interpreter::stackElementSize, R15_esp);
__ ld(R5_ARG3, Interpreter::stackElementSize, R15_esp);
__ mflr(R31);
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), /* unused */ R4_ARG2, R5_ARG3, R6_ARG4, false);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), /* unused */ R4_ARG2, R5_ARG3, R6_ARG4, false);
__ mtlr(R31);
__ pop(state);
--- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -1966,7 +1966,7 @@
// Pass a 0 (not used in sparc) and the top of stack to the bytecode tracer
__ mov( Otos_l2, G3_scratch );
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), G0, Otos_l1, G3_scratch);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), G0, Otos_l1, G3_scratch);
__ mov(Lscratch, O7); // restore return address
__ pop(state);
__ retl();
--- a/hotspot/src/cpu/x86/vm/frame_x86.hpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp Fri Mar 18 15:14:22 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -54,44 +54,6 @@
// <- sender sp
// ------------------------------ Asm interpreter ----------------------------------------
-// ------------------------------ C++ interpreter ----------------------------------------
-//
-// Layout of C++ interpreter frame: (While executing in BytecodeInterpreter::run)
-//
-// <- SP (current esp/rsp)
-// [local variables ] BytecodeInterpreter::run local variables
-// ... BytecodeInterpreter::run local variables
-// [local variables ] BytecodeInterpreter::run local variables
-// [old frame pointer ] fp [ BytecodeInterpreter::run's ebp/rbp ]
-// [return pc ] (return to frame manager)
-// [interpreter_state* ] (arg to BytecodeInterpreter::run) --------------
-// [expression stack ] <- last_Java_sp |
-// [... ] * <- interpreter_state.stack |
-// [expression stack ] * <- interpreter_state.stack_base |
-// [monitors ] \ |
-// ... | monitor block size |
-// [monitors ] / <- interpreter_state.monitor_base |
-// [struct interpretState ] <-----------------------------------------|
-// [return pc ] (return to callee of frame manager [1]
-// [locals and parameters ]
-// <- sender sp
-
-// [1] When the C++ interpreter calls a new method it returns to the frame
-// manager which allocates a new frame on the stack. In that case there
-// is no real callee of this newly allocated frame. The frame manager is
-// aware of the additional frame(s) and will pop them as nested calls
-// complete. However, to make it look good in the debugger the frame
-// manager actually installs a dummy pc pointing to RecursiveInterpreterActivation
-// with a fake interpreter_state* parameter to make it easy to debug
-// nested calls.
-
-// Note that contrary to the layout for the assembly interpreter the
-// expression stack allocated for the C++ interpreter is full sized.
-// However this is not as bad as it seems as the interpreter frame_manager
-// will truncate the unused space on successive method calls.
-//
-// ------------------------------ C++ interpreter ----------------------------------------
-
public:
enum {
pc_return_offset = 0,
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -296,7 +296,7 @@
Label L;
cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
jcc(Assembler::equal, L);
- stop("InterpreterMacroAssembler::call_VM_leaf_base:"
+ stop("InterpreterMacroAssembler::call_VM_base:"
" last_sp != NULL");
bind(L);
}
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -1830,7 +1830,7 @@
__ push(state); // save tosca
// pass tosca registers as arguments & call tracer
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode), rcx, rax, rdx);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode), rcx, rax, rdx);
__ mov(rcx, rax); // make sure return address is not destroyed by pop(state)
__ pop(state); // restore tosca
@@ -1847,7 +1847,7 @@
__ movflt(xmm3, xmm0); // Pass ftos
#endif
__ call_VM(noreg,
- CAST_FROM_FN_PTR(address, SharedRuntime::trace_bytecode),
+ CAST_FROM_FN_PTR(address, InterpreterRuntime::trace_bytecode),
c_rarg1, c_rarg2, c_rarg3);
__ pop(c_rarg3);
__ pop(c_rarg2);
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -138,11 +138,11 @@
BytecodeHistogram::_counters[(Bytecodes::Code)opcode]++; \
if (StopInterpreterAt && StopInterpreterAt == BytecodeCounter::_counter_value) os::breakpoint(); \
if (TraceBytecodes) { \
- CALL_VM((void)SharedRuntime::trace_bytecode(THREAD, 0, \
- topOfStack[Interpreter::expr_index_at(1)], \
- topOfStack[Interpreter::expr_index_at(2)]), \
- handle_exception); \
- } \
+ CALL_VM((void)InterpreterRuntime::trace_bytecode(THREAD, 0, \
+ topOfStack[Interpreter::expr_index_at(1)], \
+ topOfStack[Interpreter::expr_index_at(2)]), \
+ handle_exception); \
+ } \
}
#endif
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -173,9 +173,6 @@
IRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* thread, ConstantPool* pool, int index, jint size))
- // Note: no oopHandle for pool & klass needed since they are not used
- // anymore after new_objArray() and no GC can happen before.
- // (This may have to change if this code changes!)
Klass* klass = pool->klass_at(index, CHECK);
objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK);
thread->set_vm_result(obj);
@@ -1414,3 +1411,17 @@
}
IRT_END
#endif // INCLUDE_JVMTI
+
+#ifndef PRODUCT
+// This must be a IRT_LEAF function because the interpreter must save registers on x86 to
+// call this, which changes rsp and makes the interpreter's expression stack not walkable.
+// The generated code still uses call_VM because that will set up the frame pointer for
+// bcp and method.
+IRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
+ const frame f = thread->last_frame();
+ assert(f.is_interpreted_frame(), "must be an interpreted frame");
+ methodHandle mh(thread, f.interpreter_frame_method());
+ BytecodeTracer::trace(mh, f.interpreter_frame_bcp(), tos, tos2);
+ return preserve_this_value;
+IRT_END
+#endif // !PRODUCT
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Fri Mar 18 15:14:22 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -166,6 +166,9 @@
static void popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address);
#endif
+ // bytecode tracing is only used by the TraceBytecodes
+ static intptr_t trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2) PRODUCT_RETURN0;
+
// Platform dependent stuff
#ifdef TARGET_ARCH_x86
# include "interpreterRT_x86.hpp"
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Mar 18 15:14:22 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -991,19 +991,6 @@
return CAST_FROM_FN_PTR(address, &throw_unsatisfied_link_error);
}
-
-#ifndef PRODUCT
-JRT_ENTRY(intptr_t, SharedRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
- const frame f = thread->last_frame();
- assert(f.is_interpreted_frame(), "must be an interpreted frame");
-#ifndef PRODUCT
- methodHandle mh(THREAD, f.interpreter_frame_method());
- BytecodeTracer::trace(mh, f.interpreter_frame_bcp(), tos, tos2);
-#endif // !PRODUCT
- return preserve_this_value;
-JRT_END
-#endif // !PRODUCT
-
JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
assert(obj->is_oop(), "must be a valid oop");
#if INCLUDE_JVMCI
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Mar 09 20:37:04 2016 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Fri Mar 18 15:14:22 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -269,9 +269,6 @@
static address native_method_throw_unsatisfied_link_error_entry();
static address native_method_throw_unsupported_operation_exception_entry();
- // bytecode tracing is only used by the TraceBytecodes
- static intptr_t trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2) PRODUCT_RETURN0;
-
static oop retrieve_receiver(Symbol* sig, frame caller);
static void register_finalizer(JavaThread* thread, oopDesc* obj);