aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornever <none@none>2011-05-02 18:53:37 -0700
committernever <none@none>2011-05-02 18:53:37 -0700
commit81bee76dcb7c4a57fa21cb0692672fe2310754f6 (patch)
tree29fb538b4d292d2dddf5a0d7b9e8949cbffe9206 /src
parent89494cf4ded68cf30fc20e772e36016f269dd3d0 (diff)
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
Reviewed-by: kvn, twisti
Diffstat (limited to 'src')
-rw-r--r--src/cpu/sparc/vm/frame_sparc.cpp33
-rw-r--r--src/cpu/sparc/vm/methodHandles_sparc.cpp6
-rw-r--r--src/cpu/sparc/vm/templateInterpreter_sparc.cpp40
-rw-r--r--src/cpu/x86/vm/assembler_x86.cpp37
-rw-r--r--src/cpu/x86/vm/assembler_x86.hpp8
-rw-r--r--src/cpu/x86/vm/frame_x86.cpp22
-rw-r--r--src/cpu/x86/vm/interp_masm_x86_32.cpp26
-rw-r--r--src/cpu/x86/vm/interp_masm_x86_32.hpp8
-rw-r--r--src/cpu/x86/vm/interp_masm_x86_64.cpp50
-rw-r--r--src/cpu/x86/vm/interp_masm_x86_64.hpp9
-rw-r--r--src/cpu/x86/vm/methodHandles_x86.cpp58
-rw-r--r--src/share/vm/opto/loopPredicate.cpp23
-rw-r--r--src/share/vm/runtime/deoptimization.cpp26
-rw-r--r--src/share/vm/runtime/frame.cpp134
-rw-r--r--src/share/vm/runtime/frame.hpp41
-rw-r--r--src/share/vm/runtime/thread.cpp20
-rw-r--r--src/share/vm/runtime/thread.hpp6
-rw-r--r--src/share/vm/utilities/debug.cpp12
18 files changed, 387 insertions, 172 deletions
diff --git a/src/cpu/sparc/vm/frame_sparc.cpp b/src/cpu/sparc/vm/frame_sparc.cpp
index e6fa47a5b..d9dd1700c 100644
--- a/src/cpu/sparc/vm/frame_sparc.cpp
+++ b/src/cpu/sparc/vm/frame_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, 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
@@ -806,3 +806,34 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize) - 1;
return &interpreter_frame_tos_address()[index];
}
+
+
+#ifdef ASSERT
+
+#define DESCRIBE_FP_OFFSET(name) \
+ values.describe(-1, fp() + frame::name##_offset, #name)
+
+void frame::describe_pd(FrameValues& values, int frame_no) {
+ for (int w = 0; w < frame::register_save_words; w++) {
+ values.describe(frame_no, sp() + w, err_msg("register save area word %d", w), 1);
+ }
+
+ if (is_interpreted_frame()) {
+ DESCRIBE_FP_OFFSET(interpreter_frame_d_scratch_fp);
+ DESCRIBE_FP_OFFSET(interpreter_frame_l_scratch_fp);
+ DESCRIBE_FP_OFFSET(interpreter_frame_padding);
+ DESCRIBE_FP_OFFSET(interpreter_frame_oop_temp);
+ }
+
+ if (!is_compiled_frame()) {
+ if (frame::callee_aggregate_return_pointer_words != 0) {
+ values.describe(frame_no, sp() + frame::callee_aggregate_return_pointer_sp_offset, "callee_aggregate_return_pointer_word");
+ }
+ for (int w = 0; w < frame::callee_register_argument_save_area_words; w++) {
+ values.describe(frame_no, sp() + frame::callee_register_argument_save_area_sp_offset + w,
+ err_msg("callee_register_argument_save_area_words %d", w));
+ }
+ }
+}
+
+#endif
diff --git a/src/cpu/sparc/vm/methodHandles_sparc.cpp b/src/cpu/sparc/vm/methodHandles_sparc.cpp
index ac9e39fb6..0533fdab1 100644
--- a/src/cpu/sparc/vm/methodHandles_sparc.cpp
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp
@@ -350,8 +350,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
#ifndef PRODUCT
extern "C" void print_method_handle(oop mh);
void trace_method_handle_stub(const char* adaptername,
- oopDesc* mh) {
- printf("MH %s mh="INTPTR_FORMAT"\n", adaptername, (intptr_t) mh);
+ oopDesc* mh,
+ intptr_t* saved_sp) {
+ tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp);
print_method_handle(mh);
}
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
@@ -361,6 +362,7 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt
__ save_frame(16);
__ set((intptr_t) adaptername, O0);
__ mov(G3_method_handle, O1);
+ __ mov(I5_savedSP, O2);
__ mov(G3_method_handle, L3);
__ mov(Gargs, L4);
__ mov(G5_method_type, L5);
diff --git a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
index 109eacfc4..ac855dad8 100644
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
@@ -1698,35 +1698,21 @@ int AbstractInterpreter::layout_activation(methodOop method,
popframe_extra_args;
int local_words = method->max_locals() * Interpreter::stackElementWords;
- int parm_words = method->size_of_parameters() * Interpreter::stackElementWords;
- NEEDS_CLEANUP;
intptr_t* locals;
- if (caller->is_interpreted_frame()) {
- // Can force the locals area to end up properly overlapping the top of the expression stack.
- intptr_t* Lesp_ptr = caller->interpreter_frame_tos_address() - 1;
- // Note that this computation means we replace size_of_parameters() values from the caller
- // interpreter frame's expression stack with our argument locals
- locals = Lesp_ptr + parm_words;
- int delta = local_words - parm_words;
- int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0;
- *interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS;
+ if (caller->is_compiled_frame()) {
+ // Compiled frames do not allocate a varargs area so place them
+ // next to the register save area.
+ locals = fp + frame::register_save_words + local_words - 1;
+ // Caller wants his own SP back
+ int caller_frame_size = caller->cb()->frame_size();
+ *interpreter_frame->register_addr(I5_savedSP) = (intptr_t)(caller->fp() - caller_frame_size) - STACK_BIAS;
} else {
- assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases");
- // Don't have Lesp available; lay out locals block in the caller
- // adjacent to the register window save area.
- //
- // Compiled frames do not allocate a varargs area which is why this if
- // statement is needed.
- //
- if (caller->is_compiled_frame()) {
- locals = fp + frame::register_save_words + local_words - 1;
- } else {
- locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1;
- }
- if (!caller->is_entry_frame()) {
- // Caller wants his own SP back
- int caller_frame_size = caller->cb()->frame_size();
- *interpreter_frame->register_addr(I5_savedSP) = (intptr_t)(caller->fp() - caller_frame_size) - STACK_BIAS;
+ assert(caller->is_interpreted_frame() || caller->is_entry_frame(), "only possible cases");
+ // The entry and interpreter frames are laid out like normal C
+ // frames so place the locals adjacent to the varargs area.
+ locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1;
+ if (caller->is_interpreted_frame()) {
+ *interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + rounded_cls) - STACK_BIAS;
}
}
if (TraceDeoptimization) {
diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp
index 67e856d27..74e913019 100644
--- a/src/cpu/x86/vm/assembler_x86.cpp
+++ b/src/cpu/x86/vm/assembler_x86.cpp
@@ -6039,6 +6039,43 @@ void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register
call_VM_leaf(entry_point, 3);
}
+void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0) {
+ pass_arg0(this, arg_0);
+ MacroAssembler::call_VM_leaf_base(entry_point, 1);
+}
+
+void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1) {
+
+ LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg"));
+ pass_arg1(this, arg_1);
+ pass_arg0(this, arg_0);
+ MacroAssembler::call_VM_leaf_base(entry_point, 2);
+}
+
+void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) {
+ LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg"));
+ LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg"));
+ pass_arg2(this, arg_2);
+ LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg"));
+ pass_arg1(this, arg_1);
+ pass_arg0(this, arg_0);
+ MacroAssembler::call_VM_leaf_base(entry_point, 3);
+}
+
+void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) {
+ LP64_ONLY(assert(arg_0 != c_rarg3, "smashed arg"));
+ LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg"));
+ LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg"));
+ pass_arg3(this, arg_3);
+ LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg"));
+ LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg"));
+ pass_arg2(this, arg_2);
+ LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg"));
+ pass_arg1(this, arg_1);
+ pass_arg0(this, arg_0);
+ MacroAssembler::call_VM_leaf_base(entry_point, 4);
+}
+
void MacroAssembler::check_and_handle_earlyret(Register java_thread) {
}
diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp
index 4c6b32faf..34e8ed9c8 100644
--- a/src/cpu/x86/vm/assembler_x86.hpp
+++ b/src/cpu/x86/vm/assembler_x86.hpp
@@ -1655,6 +1655,14 @@ class MacroAssembler: public Assembler {
void call_VM_leaf(address entry_point,
Register arg_1, Register arg_2, Register arg_3);
+ // These always tightly bind to MacroAssembler::call_VM_leaf_base
+ // bypassing the virtual implementation
+ void super_call_VM_leaf(address entry_point);
+ void super_call_VM_leaf(address entry_point, Register arg_1);
+ void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2);
+ void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3);
+ void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4);
+
// last Java Frame (fills frame anchor)
void set_last_Java_frame(Register thread,
Register last_java_sp,
diff --git a/src/cpu/x86/vm/frame_x86.cpp b/src/cpu/x86/vm/frame_x86.cpp
index 8f1585fb9..8709a0e86 100644
--- a/src/cpu/x86/vm/frame_x86.cpp
+++ b/src/cpu/x86/vm/frame_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, 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
@@ -669,3 +669,23 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
return &interpreter_frame_tos_address()[index];
}
+
+#ifdef ASSERT
+
+#define DESCRIBE_FP_OFFSET(name) \
+ values.describe(-1, fp() + frame::name##_offset, #name)
+
+void frame::describe_pd(FrameValues& values, int frame_no) {
+ if (is_interpreted_frame()) {
+ DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp);
+ DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
+ DESCRIBE_FP_OFFSET(interpreter_frame_method);
+ DESCRIBE_FP_OFFSET(interpreter_frame_mdx);
+ DESCRIBE_FP_OFFSET(interpreter_frame_cache);
+ DESCRIBE_FP_OFFSET(interpreter_frame_locals);
+ DESCRIBE_FP_OFFSET(interpreter_frame_bcx);
+ DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
+ }
+
+}
+#endif
diff --git a/src/cpu/x86/vm/interp_masm_x86_32.cpp b/src/cpu/x86/vm/interp_masm_x86_32.cpp
index e0d5cf03c..ce3571338 100644
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp
+++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp
@@ -383,32 +383,6 @@ void InterpreterMacroAssembler::store_ptr(int n, Register val) {
movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val);
}
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) {
- MacroAssembler::call_VM_leaf_base(entry_point, 0);
-}
-
-
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1) {
- push(arg_1);
- MacroAssembler::call_VM_leaf_base(entry_point, 1);
-}
-
-
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2) {
- push(arg_2);
- push(arg_1);
- MacroAssembler::call_VM_leaf_base(entry_point, 2);
-}
-
-
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) {
- push(arg_3);
- push(arg_2);
- push(arg_1);
- MacroAssembler::call_VM_leaf_base(entry_point, 3);
-}
-
-
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
lea(rsi, Address(rsp, wordSize));
diff --git a/src/cpu/x86/vm/interp_masm_x86_32.hpp b/src/cpu/x86/vm/interp_masm_x86_32.hpp
index 404b4d572..d08f0fd59 100644
--- a/src/cpu/x86/vm/interp_masm_x86_32.hpp
+++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, 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
@@ -124,12 +124,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
void load_ptr(int n, Register val);
void store_ptr(int n, Register val);
- // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls
- void super_call_VM_leaf(address entry_point);
- void super_call_VM_leaf(address entry_point, Register arg_1);
- void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2);
- void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3);
-
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass. EAX holds the super_klass. Blows ECX
// and EDI. Register sub_klass cannot be any of the above.
diff --git a/src/cpu/x86/vm/interp_masm_x86_64.cpp b/src/cpu/x86/vm/interp_masm_x86_64.cpp
index 428281d00..4b7884cec 100644
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp
@@ -381,56 +381,6 @@ void InterpreterMacroAssembler::store_ptr(int n, Register val) {
}
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) {
- MacroAssembler::call_VM_leaf_base(entry_point, 0);
-}
-
-
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point,
- Register arg_1) {
- if (c_rarg0 != arg_1) {
- mov(c_rarg0, arg_1);
- }
- MacroAssembler::call_VM_leaf_base(entry_point, 1);
-}
-
-
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point,
- Register arg_1,
- Register arg_2) {
- assert(c_rarg0 != arg_2, "smashed argument");
- assert(c_rarg1 != arg_1, "smashed argument");
- if (c_rarg0 != arg_1) {
- mov(c_rarg0, arg_1);
- }
- if (c_rarg1 != arg_2) {
- mov(c_rarg1, arg_2);
- }
- MacroAssembler::call_VM_leaf_base(entry_point, 2);
-}
-
-void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point,
- Register arg_1,
- Register arg_2,
- Register arg_3) {
- assert(c_rarg0 != arg_2, "smashed argument");
- assert(c_rarg0 != arg_3, "smashed argument");
- assert(c_rarg1 != arg_1, "smashed argument");
- assert(c_rarg1 != arg_3, "smashed argument");
- assert(c_rarg2 != arg_1, "smashed argument");
- assert(c_rarg2 != arg_2, "smashed argument");
- if (c_rarg0 != arg_1) {
- mov(c_rarg0, arg_1);
- }
- if (c_rarg1 != arg_2) {
- mov(c_rarg1, arg_2);
- }
- if (c_rarg2 != arg_3) {
- mov(c_rarg2, arg_3);
- }
- MacroAssembler::call_VM_leaf_base(entry_point, 3);
-}
-
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
lea(r13, Address(rsp, wordSize));
diff --git a/src/cpu/x86/vm/interp_masm_x86_64.hpp b/src/cpu/x86/vm/interp_masm_x86_64.hpp
index 62539a735..b203abc7d 100644
--- a/src/cpu/x86/vm/interp_masm_x86_64.hpp
+++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -136,13 +136,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
void load_ptr(int n, Register val);
void store_ptr(int n, Register val);
- // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls
- void super_call_VM_leaf(address entry_point);
- void super_call_VM_leaf(address entry_point, Register arg_1);
- void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2);
- void super_call_VM_leaf(address entry_point,
- Register arg_1, Register arg_2, Register arg_3);
-
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass.
void gen_subtype_check( Register sub_klass, Label &ok_is_subtype );
diff --git a/src/cpu/x86/vm/methodHandles_x86.cpp b/src/cpu/x86/vm/methodHandles_x86.cpp
index 704fb7d35..42a57c132 100644
--- a/src/cpu/x86/vm/methodHandles_x86.cpp
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp
@@ -315,56 +315,38 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
#ifndef PRODUCT
extern "C" void print_method_handle(oop mh);
void trace_method_handle_stub(const char* adaptername,
- oop mh,
- intptr_t* saved_regs,
- intptr_t* entry_sp,
intptr_t* saved_sp,
- intptr_t* saved_bp) {
+ oop mh,
+ intptr_t* sp) {
// called as a leaf from native code: do not block the JVM!
- intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
- intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
- printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n",
- adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
- if (last_sp != saved_sp && last_sp != NULL)
- printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
+ intptr_t* entry_sp = sp + LP64_ONLY(16) NOT_LP64(8);
+ tty->print_cr("MH %s mh="INTPTR_FORMAT" sp="INTPTR_FORMAT" saved_sp="INTPTR_FORMAT")",
+ adaptername, (intptr_t)mh, (intptr_t)entry_sp, saved_sp);
if (Verbose) {
- printf(" reg dump: ");
- int saved_regs_count = (entry_sp-1) - saved_regs;
- // 32 bit: rdi rsi rbp rsp; rbx rdx rcx (*) rax
- int i;
- for (i = 0; i <= saved_regs_count; i++) {
- if (i > 0 && i % 4 == 0 && i != saved_regs_count)
- printf("\n + dump: ");
- printf(" %d: "INTPTR_FORMAT, i, saved_regs[i]);
- }
- printf("\n");
- int stack_dump_count = 16;
- if (stack_dump_count < (int)(saved_bp + 2 - saved_sp))
- stack_dump_count = (int)(saved_bp + 2 - saved_sp);
- if (stack_dump_count > 64) stack_dump_count = 48;
- for (i = 0; i < stack_dump_count; i += 4) {
- printf(" dump at SP[%d] "INTPTR_FORMAT": "INTPTR_FORMAT" "INTPTR_FORMAT" "INTPTR_FORMAT" "INTPTR_FORMAT"\n",
- i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]);
- }
print_method_handle(mh);
}
}
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
if (!TraceMethodHandles) return;
BLOCK_COMMENT("trace_method_handle {");
- __ push(rax);
- __ lea(rax, Address(rsp, wordSize*6)); // entry_sp
__ pusha();
+#ifdef _LP64
+ // Pass arguments carefully since the registers overlap with the calling convention.
+ // rcx: method handle
+ // r13: saved sp
+ __ mov(c_rarg2, rcx); // mh
+ __ mov(c_rarg1, r13); // saved sp
+ __ mov(c_rarg3, rsp); // sp
+ __ movptr(c_rarg0, (intptr_t) adaptername);
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), c_rarg0, c_rarg1, c_rarg2, c_rarg3);
+#else
// arguments:
- __ push(rbp); // interpreter frame pointer
- __ push(rsi); // saved_sp
- __ push(rax); // entry_sp
- __ push(rcx); // mh
- __ push(rcx);
- __ movptr(Address(rsp, 0), (intptr_t) adaptername);
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5);
+ // rcx: method handle
+ // rsi: saved sp
+ __ movptr(rbx, (intptr_t) adaptername);
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), rbx, rsi, rcx, rsp);
+#endif
__ popa();
- __ pop(rax);
BLOCK_COMMENT("} trace_method_handle");
}
#endif //PRODUCT
diff --git a/src/share/vm/opto/loopPredicate.cpp b/src/share/vm/opto/loopPredicate.cpp
index c5ac2c682..d436a572c 100644
--- a/src/share/vm/opto/loopPredicate.cpp
+++ b/src/share/vm/opto/loopPredicate.cpp
@@ -700,32 +700,35 @@ BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
int scale, Node* offset,
Node* init, Node* limit, Node* stride,
Node* range, bool upper) {
- DEBUG_ONLY(ttyLocker ttyl);
- if (TraceLoopPredicate) tty->print("rc_predicate ");
+ stringStream* predString = NULL;
+ if (TraceLoopPredicate) {
+ predString = new stringStream();
+ predString->print("rc_predicate ");
+ }
Node* max_idx_expr = init;
int stride_con = stride->get_int();
if ((stride_con > 0) == (scale > 0) == upper) {
max_idx_expr = new (C, 3) SubINode(limit, stride);
register_new_node(max_idx_expr, ctrl);
- if (TraceLoopPredicate) tty->print("(limit - stride) ");
+ if (TraceLoopPredicate) predString->print("(limit - stride) ");
} else {
- if (TraceLoopPredicate) tty->print("init ");
+ if (TraceLoopPredicate) predString->print("init ");
}
if (scale != 1) {
ConNode* con_scale = _igvn.intcon(scale);
max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
register_new_node(max_idx_expr, ctrl);
- if (TraceLoopPredicate) tty->print("* %d ", scale);
+ if (TraceLoopPredicate) predString->print("* %d ", scale);
}
if (offset && (!offset->is_Con() || offset->get_int() != 0)){
max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
register_new_node(max_idx_expr, ctrl);
if (TraceLoopPredicate)
- if (offset->is_Con()) tty->print("+ %d ", offset->get_int());
- else tty->print("+ offset ");
+ if (offset->is_Con()) predString->print("+ %d ", offset->get_int());
+ else predString->print("+ offset ");
}
CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
@@ -733,7 +736,10 @@ BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
register_new_node(bol, ctrl);
- if (TraceLoopPredicate) tty->print_cr("<u range");
+ if (TraceLoopPredicate) {
+ predString->print_cr("<u range");
+ tty->print(predString->as_string());
+ }
return bol;
}
@@ -957,4 +963,3 @@ bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) {
return hoisted;
}
-
diff --git a/src/share/vm/runtime/deoptimization.cpp b/src/share/vm/runtime/deoptimization.cpp
index 3e03486d3..10ebd8364 100644
--- a/src/share/vm/runtime/deoptimization.cpp
+++ b/src/share/vm/runtime/deoptimization.cpp
@@ -189,6 +189,10 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
assert(thread->deopt_nmethod() == NULL, "Pending deopt!");
thread->set_deopt_nmethod(deoptee.cb()->as_nmethod_or_null());
+ if (VerifyStack) {
+ thread->validate_frame_layout();
+ }
+
// Create a growable array of VFrames where each VFrame represents an inlined
// Java frame. This storage is allocated with the usual system arena.
assert(deoptee.is_compiled_frame(), "Wrong frame type");
@@ -421,6 +425,21 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
frame deopt_sender = stub_frame.sender(&dummy_map); // First is the deoptee frame
deopt_sender = deopt_sender.sender(&dummy_map); // Now deoptee caller
+ // It's possible that the number of paramters at the call site is
+ // different than number of arguments in the callee when method
+ // handles are used. If the caller is interpreted get the real
+ // value so that the proper amount of space can be added to it's
+ // frame.
+ int sender_callee_parameters = callee_parameters;
+ if (deopt_sender.is_interpreted_frame()) {
+ methodHandle method = deopt_sender.interpreter_frame_method();
+ Bytecode_invoke cur = Bytecode_invoke_check(method,
+ deopt_sender.interpreter_frame_bci());
+ Symbol* signature = method->constants()->signature_ref_at(cur.index());
+ ArgumentSizeComputer asc(signature);
+ sender_callee_parameters = asc.size() + cur.has_receiver() ? 1 : 0;
+ }
+
// Compute the amount the oldest interpreter frame will have to adjust
// its caller's stack by. If the caller is a compiled frame then
// we pretend that the callee has no parameters so that the
@@ -435,14 +454,13 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
if (deopt_sender.is_compiled_frame()) {
caller_adjustment = last_frame_adjust(0, callee_locals);
- } else if (callee_locals > callee_parameters) {
+ } else if (callee_locals > sender_callee_parameters) {
// The caller frame may need extending to accommodate
// non-parameter locals of the first unpacked interpreted frame.
// Compute that adjustment.
- caller_adjustment = last_frame_adjust(callee_parameters, callee_locals);
+ caller_adjustment = last_frame_adjust(sender_callee_parameters, callee_locals);
}
-
// If the sender is deoptimized the we must retrieve the address of the handler
// since the frame will "magically" show the original pc before the deopt
// and we'd undo the deopt.
@@ -569,6 +587,8 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
if (VerifyStack) {
ResourceMark res_mark;
+ thread->validate_frame_layout();
+
// Verify that the just-unpacked frames match the interpreter's
// notions of expression stack and locals
vframeArray* cur_array = thread->vframe_array_last();
diff --git a/src/share/vm/runtime/frame.cpp b/src/share/vm/runtime/frame.cpp
index 5c205501a..b5352fc00 100644
--- a/src/share/vm/runtime/frame.cpp
+++ b/src/share/vm/runtime/frame.cpp
@@ -1308,6 +1308,72 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const {
guarantee((current - low_mark) % monitor_size == 0 , "Misaligned bottom of BasicObjectLock*");
guarantee( current >= low_mark , "Current BasicObjectLock* below than low_mark");
}
+
+
+void frame::describe(FrameValues& values, int frame_no) {
+ if (is_entry_frame() || is_compiled_frame() || is_interpreted_frame() || is_native_frame()) {
+ // Label values common to most frames
+ values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no));
+ values.describe(-1, sp(), err_msg("sp for #%d", frame_no));
+ values.describe(-1, fp(), err_msg("fp for #%d", frame_no));
+ }
+ if (is_interpreted_frame()) {
+ methodOop m = interpreter_frame_method();
+ int bci = interpreter_frame_bci();
+
+ // Label the method and current bci
+ values.describe(-1, MAX2(sp(), fp()),
+ FormatBuffer<1024>("#%d method %s @ %d", frame_no, m->name_and_sig_as_C_string(), bci), 2);
+ values.describe(-1, MAX2(sp(), fp()),
+ err_msg("- %d locals %d max stack", m->max_locals(), m->max_stack()), 1);
+ if (m->max_locals() > 0) {
+ intptr_t* l0 = interpreter_frame_local_at(0);
+ intptr_t* ln = interpreter_frame_local_at(m->max_locals() - 1);
+ values.describe(-1, MAX2(l0, ln), err_msg("locals for #%d", frame_no), 1);
+ // Report each local and mark as owned by this frame
+ for (int l = 0; l < m->max_locals(); l++) {
+ intptr_t* l0 = interpreter_frame_local_at(l);
+ values.describe(frame_no, l0, err_msg("local %d", l));
+ }
+ }
+
+ // Compute the actual expression stack size
+ InterpreterOopMap mask;
+ OopMapCache::compute_one_oop_map(m, bci, &mask);
+ intptr_t* tos = NULL;
+ // Report each stack element and mark as owned by this frame
+ for (int e = 0; e < mask.expression_stack_size(); e++) {
+ tos = MAX2(tos, interpreter_frame_expression_stack_at(e));
+ values.describe(frame_no, interpreter_frame_expression_stack_at(e),
+ err_msg("stack %d", e));
+ }
+ if (tos != NULL) {
+ values.describe(-1, tos, err_msg("expression stack for #%d", frame_no), 1);
+ }
+ if (interpreter_frame_monitor_begin() != interpreter_frame_monitor_end()) {
+ values.describe(frame_no, (intptr_t*)interpreter_frame_monitor_begin(), "monitors begin");
+ values.describe(frame_no, (intptr_t*)interpreter_frame_monitor_end(), "monitors end");
+ }
+ } else if (is_entry_frame()) {
+ // For now just label the frame
+ values.describe(-1, MAX2(sp(), fp()), err_msg("#%d entry frame", frame_no), 2);
+ } else if (is_compiled_frame()) {
+ // For now just label the frame
+ nmethod* nm = cb()->as_nmethod_or_null();
+ values.describe(-1, MAX2(sp(), fp()),
+ FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no,
+ nm, nm->method()->name_and_sig_as_C_string(),
+ is_deoptimized_frame() ? " (deoptimized" : ""), 2);
+ } else if (is_native_frame()) {
+ // For now just label the frame
+ nmethod* nm = cb()->as_nmethod_or_null();
+ values.describe(-1, MAX2(sp(), fp()),
+ FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for native method %s", frame_no,
+ nm, nm->method()->name_and_sig_as_C_string()), 2);
+ }
+ describe_pd(values, frame_no);
+}
+
#endif
@@ -1319,3 +1385,71 @@ StackFrameStream::StackFrameStream(JavaThread *thread, bool update) : _reg_map(t
_fr = thread->last_frame();
_is_done = false;
}
+
+
+#ifdef ASSERT
+
+void FrameValues::describe(int owner, intptr_t* location, const char* description, int priority) {
+ FrameValue fv;
+ fv.location = location;
+ fv.owner = owner;
+ fv.priority = priority;
+ fv.description = NEW_RESOURCE_ARRAY(char, strlen(description) + 1);
+ strcpy(fv.description, description);
+ _values.append(fv);
+}
+
+
+bool FrameValues::validate() {
+ _values.sort(compare);
+ bool error = false;
+ FrameValue prev;
+ prev.owner = -1;
+ for (int i = _values.length() - 1; i >= 0; i--) {
+ FrameValue fv = _values.at(i);
+ if (fv.owner == -1) continue;
+ if (prev.owner == -1) {
+ prev = fv;
+ continue;
+ }
+ if (prev.location == fv.location) {
+ if (fv.owner != prev.owner) {
+ tty->print_cr("overlapping storage");
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", prev.location, *prev.location, prev.description);
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", fv.location, *fv.location, fv.description);
+ error = true;
+ }
+ } else {
+ prev = fv;
+ }
+ }
+ return error;
+}
+
+
+void FrameValues::print() {
+ _values.sort(compare);
+ intptr_t* v0 = _values.at(0).location;
+ intptr_t* v1 = _values.at(_values.length() - 1).location;
+ intptr_t* min = MIN2(v0, v1);
+ intptr_t* max = MAX2(v0, v1);
+ intptr_t* cur = max;
+ intptr_t* last = NULL;
+ for (int i = _values.length() - 1; i >= 0; i--) {
+ FrameValue fv = _values.at(i);
+ while (cur > fv.location) {
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT, cur, *cur);
+ cur--;
+ }
+ if (last == fv.location) {
+ const char* spacer = " " LP64_ONLY(" ");
+ tty->print_cr(" %s %s %s", spacer, spacer, fv.description);
+ } else {
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", fv.location, *fv.location, fv.description);
+ last = fv.location;
+ cur--;
+ }
+ }
+}
+
+#endif
diff --git a/src/share/vm/runtime/frame.hpp b/src/share/vm/runtime/frame.hpp
index a48c2af37..66d17a9f7 100644
--- a/src/share/vm/runtime/frame.hpp
+++ b/src/share/vm/runtime/frame.hpp
@@ -60,6 +60,7 @@
typedef class BytecodeInterpreter* interpreterState;
class CodeBlob;
+class FrameValues;
class vframeArray;
@@ -381,6 +382,8 @@ class frame VALUE_OBJ_CLASS_SPEC {
private:
const char* print_name() const;
+ void describe_pd(FrameValues& values, int frame_no);
+
public:
void print_value() const { print_value_on(tty,NULL); }
void print_value_on(outputStream* st, JavaThread *thread) const;
@@ -388,6 +391,9 @@ class frame VALUE_OBJ_CLASS_SPEC {
void interpreter_frame_print_on(outputStream* st) const;
void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const;
+ // Add annotated descriptions of memory locations belonging to this frame to values
+ void describe(FrameValues& values, int frame_no);
+
// Conversion from an VMReg to physical stack location
oop* oopmapreg_to_location(VMReg reg, const RegisterMap* regmap) const;
@@ -472,6 +478,41 @@ class frame VALUE_OBJ_CLASS_SPEC {
};
+#ifdef ASSERT
+// A simple class to describe a location on the stack
+class FrameValue VALUE_OBJ_CLASS_SPEC {
+ public:
+ intptr_t* location;
+ char* description;
+ int owner;
+ int priority;
+};
+
+
+// A collection of described stack values that can print a symbolic
+// description of the stack memory. Interpreter frame values can be
+// in the caller frames so all the values are collected first and then
+// sorted before being printed.
+class FrameValues {
+ private:
+ GrowableArray<FrameValue> _values;
+
+ static int compare(FrameValue* a, FrameValue* b) {
+ if (a->location == b->location) {
+ return a->priority - b->priority;
+ }
+ return a->location - b->location;
+ }
+
+ public:
+ // Used by frame functions to describe locations.
+ void describe(int owner, intptr_t* location, const char* description, int priority = 0);
+
+ bool validate();
+ void print();
+};
+
+#endif
//
// StackFrameStream iterates through the frames of a thread starting from
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index 6cb2deeb4..02f4e7f49 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -31,6 +31,7 @@
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
+#include "interpreter/oopMapCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
@@ -2860,6 +2861,25 @@ void JavaThread::trace_frames() {
}
+// Print or validate the layout of stack frames
+void JavaThread::print_frame_layout(int depth, bool validate_only) {
+ ResourceMark rm;
+ PRESERVE_EXCEPTION_MARK;
+ FrameValues values;
+ int frame_no = 0;
+ for(StackFrameStream fst(this, false); !fst.is_done(); fst.next()) {
+ fst.current()->describe(values, ++frame_no);
+ if (depth == frame_no) break;
+ }
+ if (validate_only) {
+ values.validate();
+ } else {
+ tty->print_cr("[Describe stack layout]");
+ values.print();
+ }
+}
+
+
void JavaThread::trace_stack_from(vframe* start_vf) {
ResourceMark rm;
int vframe_no = 1;
diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp
index 73e0fda02..eefe93bc7 100644
--- a/src/share/vm/runtime/thread.hpp
+++ b/src/share/vm/runtime/thread.hpp
@@ -1380,6 +1380,12 @@ public:
void trace_stack_from(vframe* start_vf) PRODUCT_RETURN;
void trace_frames() PRODUCT_RETURN;
+ // Print an annotated view of the stack frames
+ void print_frame_layout(int depth = 0, bool validate_only = false) PRODUCT_RETURN;
+ void validate_frame_layout() {
+ print_frame_layout(0, true);
+ }
+
// Returns the number of stack frames on the stack
int depth() const;
diff --git a/src/share/vm/utilities/debug.cpp b/src/share/vm/utilities/debug.cpp
index cb5efc08d..27eaea8b4 100644
--- a/src/share/vm/utilities/debug.cpp
+++ b/src/share/vm/utilities/debug.cpp
@@ -469,6 +469,7 @@ extern "C" void verify() {
extern "C" void pp(void* p) {
Command c("pp");
FlagSetting fl(PrintVMMessages, true);
+ FlagSetting f2(DisplayVMOutput, true);
if (Universe::heap()->is_in(p)) {
oop obj = oop(p);
obj->print();
@@ -507,6 +508,17 @@ extern "C" void ps() { // print stack
}
+extern "C" void pfl() {
+ // print frame layout
+ Command c("pfl");
+ JavaThread* p = JavaThread::active();
+ tty->print(" for thread: ");
+ p->print();
+ tty->cr();
+ if (p->has_last_Java_frame()) {
+ p->print_frame_layout();
+ }
+}
extern "C" void psf() { // print stack frames
{