mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-13 20:05:31 +00:00
8152065: TraceBytecodes breaks the interpreter expression stack
Move trace_bytecode to InterpreterRuntime and make trace_bytecode an IRT_LEAF so that safepoints are not allowed. Reviewed-by: jiangli, dholmes, dcubed
This commit is contained in:
parent
6e0466f618
commit
1954276b28
@ -1967,7 +1967,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
|
||||
__ 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);
|
||||
|
||||
@ -2211,7 +2211,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
|
||||
__ 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);
|
||||
|
||||
|
||||
@ -1966,7 +1966,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
|
||||
|
||||
// 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();
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 @@ void InterpreterMacroAssembler::call_VM_base(Register oop_result,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1830,7 +1830,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
|
||||
__ 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 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
|
||||
__ 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);
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -173,9 +173,6 @@ IRT_END
|
||||
|
||||
|
||||
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_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread,
|
||||
}
|
||||
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
|
||||
|
||||
@ -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 @@ class InterpreterRuntime: AllStatic {
|
||||
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"
|
||||
|
||||
@ -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 @@ address SharedRuntime::native_method_throw_unsatisfied_link_error_entry() {
|
||||
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
|
||||
|
||||
@ -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 @@ class SharedRuntime: AllStatic {
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user