# HG changeset patch # User never # Date 1304387617 25200 # Node ID 2e038ad0c1d09407fe8a1627269a5b1c4d163985 # Parent 49d67a090fe24d2695a4cfdb8c4374cfbee4c802 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp Reviewed-by: kvn, twisti diff -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/sparc/vm/frame_sparc.cpp --- a/src/cpu/sparc/vm/frame_sparc.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Mon May 02 18:53:37 2011 -0700 @@ -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 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/sparc/vm/methodHandles_sparc.cpp --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Mon May 02 18:53:37 2011 -0700 @@ -350,8 +350,9 @@ #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 @@ __ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Mon May 02 18:53:37 2011 -0700 @@ -1698,35 +1698,21 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon May 02 18:53:37 2011 -0700 @@ -6039,6 +6039,43 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/assembler_x86.hpp Mon May 02 18:53:37 2011 -0700 @@ -1655,6 +1655,14 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/frame_x86.cpp --- a/src/cpu/x86/vm/frame_x86.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/frame_x86.cpp Mon May 02 18:53:37 2011 -0700 @@ -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 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/interp_masm_x86_32.cpp --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon May 02 18:53:37 2011 -0700 @@ -383,32 +383,6 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/interp_masm_x86_32.hpp --- a/src/cpu/x86/vm/interp_masm_x86_32.hpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp Mon May 02 18:53:37 2011 -0700 @@ -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 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon May 02 18:53:37 2011 -0700 @@ -381,56 +381,6 @@ } -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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/interp_masm_x86_64.hpp --- a/src/cpu/x86/vm/interp_masm_x86_64.hpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp Mon May 02 18:53:37 2011 -0700 @@ -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 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/cpu/x86/vm/methodHandles_x86.cpp --- a/src/cpu/x86/vm/methodHandles_x86.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Mon May 02 18:53:37 2011 -0700 @@ -315,56 +315,38 @@ #ifndef PRODUCT extern "C" void print_method_handle(oop mh); void trace_method_handle_stub(const char* adaptername, + intptr_t* saved_sp, oop mh, - intptr_t* saved_regs, - intptr_t* entry_sp, - intptr_t* saved_sp, - intptr_t* saved_bp) { + 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/opto/loopPredicate.cpp --- a/src/share/vm/opto/loopPredicate.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/opto/loopPredicate.cpp Mon May 02 18:53:37 2011 -0700 @@ -700,32 +700,35 @@ 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* bol = new (C, 2) BoolNode(cmp, BoolTest::lt); register_new_node(bol, ctrl); - if (TraceLoopPredicate) tty->print_cr("print_cr("print(predString->as_string()); + } return bol; } @@ -957,4 +963,3 @@ return hoisted; } - diff -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/runtime/deoptimization.cpp Mon May 02 18:53:37 2011 -0700 @@ -189,6 +189,10 @@ 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 @@ 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 @@ 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 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/runtime/frame.cpp Mon May 02 18:53:37 2011 -0700 @@ -1308,6 +1308,72 @@ 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 @@ _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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/runtime/frame.hpp --- a/src/share/vm/runtime/frame.hpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/runtime/frame.hpp Mon May 02 18:53:37 2011 -0700 @@ -60,6 +60,7 @@ typedef class BytecodeInterpreter* interpreterState; class CodeBlob; +class FrameValues; class vframeArray; @@ -381,6 +382,8 @@ 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 @@ 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 @@ }; +#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 _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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/runtime/thread.cpp Mon May 02 18:53:37 2011 -0700 @@ -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 @@ } +// 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/runtime/thread.hpp Mon May 02 18:53:37 2011 -0700 @@ -1380,6 +1380,12 @@ 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 -r 49d67a090fe2 -r 2e038ad0c1d0 src/share/vm/utilities/debug.cpp --- a/src/share/vm/utilities/debug.cpp Mon May 02 10:51:36 2011 -0700 +++ b/src/share/vm/utilities/debug.cpp Mon May 02 18:53:37 2011 -0700 @@ -469,6 +469,7 @@ 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 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 {