src/cpu/x86/vm/methodHandles_x86.cpp

changeset 3451
5dbed2f542ff
parent 3445
82e5a84b7436
child 3501
392a3f07d567
     1.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Jan 26 09:38:28 2012 +0100
     1.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Jan 26 16:49:22 2012 +0100
     1.3 @@ -279,14 +279,16 @@
     1.4  }
     1.5  
     1.6  // Emit code to verify that RBP is pointing at a valid ricochet frame.
     1.7 -#ifdef ASSERT
     1.8 +#ifndef PRODUCT
     1.9  enum {
    1.10    ARG_LIMIT = 255, SLOP = 4,
    1.11    // use this parameter for checking for garbage stack movements:
    1.12    UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
    1.13    // the slop defends against false alarms due to fencepost errors
    1.14  };
    1.15 +#endif
    1.16  
    1.17 +#ifdef ASSERT
    1.18  void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
    1.19    // The stack should look like this:
    1.20    //    ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args |
    1.21 @@ -990,7 +992,7 @@
    1.22    BLOCK_COMMENT("} move_return_value");
    1.23  }
    1.24  
    1.25 -#ifdef ASSERT
    1.26 +#ifndef PRODUCT
    1.27  #define DESCRIBE_RICOCHET_OFFSET(rf, name) \
    1.28    values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name)
    1.29  
    1.30 @@ -1021,6 +1023,7 @@
    1.31                                intptr_t* saved_bp) {
    1.32    // called as a leaf from native code: do not block the JVM!
    1.33    bool has_mh = (strstr(adaptername, "return/") == NULL);  // return adapters don't have rcx_mh
    1.34 +
    1.35    intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
    1.36    intptr_t* base_sp = last_sp;
    1.37    typedef MethodHandles::RicochetFrame RicochetFrame;
    1.38 @@ -1050,13 +1053,64 @@
    1.39      tty->cr();
    1.40      if (last_sp != saved_sp && last_sp != NULL)
    1.41        tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp);
    1.42 -    int stack_dump_count = 16;
    1.43 -    if (stack_dump_count < (int)(saved_bp + 2 - saved_sp))
    1.44 -      stack_dump_count = (int)(saved_bp + 2 - saved_sp);
    1.45 -    if (stack_dump_count > 64)  stack_dump_count = 48;
    1.46 -    for (i = 0; i < stack_dump_count; i += 4) {
    1.47 -      tty->print_cr(" dump at SP[%d] "PTR_FORMAT": "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT,
    1.48 -                    i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]);
    1.49 +
    1.50 +    {
    1.51 +     // dumping last frame with frame::describe
    1.52 +
    1.53 +      JavaThread* p = JavaThread::active();
    1.54 +
    1.55 +      ResourceMark rm;
    1.56 +      PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here
    1.57 +      FrameValues values;
    1.58 +
    1.59 +      // Note: We want to allow trace_method_handle from any call site.
    1.60 +      // While trace_method_handle creates a frame, it may be entered
    1.61 +      // without a PC on the stack top (e.g. not just after a call).
    1.62 +      // Walking that frame could lead to failures due to that invalid PC.
    1.63 +      // => carefully detect that frame when doing the stack walking
    1.64 +
    1.65 +      // Current C frame
    1.66 +      frame cur_frame = os::current_frame();
    1.67 +
    1.68 +      // Robust search of trace_calling_frame (independant of inlining).
    1.69 +      // Assumes saved_regs comes from a pusha in the trace_calling_frame.
    1.70 +      assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?");
    1.71 +      frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame);
    1.72 +      while (trace_calling_frame.fp() < saved_regs) {
    1.73 +        trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame);
    1.74 +      }
    1.75 +
    1.76 +      // safely create a frame and call frame::describe
    1.77 +      intptr_t *dump_sp = trace_calling_frame.sender_sp();
    1.78 +      intptr_t *dump_fp = trace_calling_frame.link();
    1.79 +
    1.80 +      bool walkable = has_mh; // whether the traced frame shoud be walkable
    1.81 +
    1.82 +      if (walkable) {
    1.83 +        // The previous definition of walkable may have to be refined
    1.84 +        // if new call sites cause the next frame constructor to start
    1.85 +        // failing. Alternatively, frame constructors could be
    1.86 +        // modified to support the current or future non walkable
    1.87 +        // frames (but this is more intrusive and is not considered as
    1.88 +        // part of this RFE, which will instead use a simpler output).
    1.89 +        frame dump_frame = frame(dump_sp, dump_fp);
    1.90 +        dump_frame.describe(values, 1);
    1.91 +      } else {
    1.92 +        // Stack may not be walkable (invalid PC above FP):
    1.93 +        // Add descriptions without building a Java frame to avoid issues
    1.94 +        values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>");
    1.95 +        values.describe(-1, dump_sp, "sp for #1");
    1.96 +      }
    1.97 +
    1.98 +      // mark saved_sp if seems valid
    1.99 +      if (has_mh) {
   1.100 +        if ((saved_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (saved_sp < dump_fp)) {
   1.101 +          values.describe(-1, saved_sp, "*saved_sp");
   1.102 +        }
   1.103 +      }
   1.104 +
   1.105 +      tty->print_cr("  stack layout:");
   1.106 +      values.print(p);
   1.107      }
   1.108      if (has_mh)
   1.109        print_method_handle(mh);
   1.110 @@ -1086,26 +1140,49 @@
   1.111  void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
   1.112    if (!TraceMethodHandles)  return;
   1.113    BLOCK_COMMENT("trace_method_handle {");
   1.114 -  __ push(rax);
   1.115 -  __ lea(rax, Address(rsp, wordSize * NOT_LP64(6) LP64_ONLY(14))); // entry_sp  __ pusha();
   1.116 +  __ enter();
   1.117 +  __ andptr(rsp, -16); // align stack if needed for FPU state
   1.118    __ pusha();
   1.119 -  __ mov(rbx, rsp);
   1.120 -  __ enter();
   1.121 +  __ mov(rbx, rsp); // for retreiving saved_regs
   1.122 +  // Note: saved_regs must be in the entered frame for the
   1.123 +  // robust stack walking implemented in trace_method_handle_stub.
   1.124 +
   1.125 +  // save FP result, valid at some call sites (adapter_opt_return_float, ...)
   1.126 +  __ increment(rsp, -2 * wordSize);
   1.127 +  if  (UseSSE >= 2) {
   1.128 +    __ movdbl(Address(rsp, 0), xmm0);
   1.129 +  } else if (UseSSE == 1) {
   1.130 +    __ movflt(Address(rsp, 0), xmm0);
   1.131 +  } else {
   1.132 +    __ fst_d(Address(rsp, 0));
   1.133 +  }
   1.134 +
   1.135    // incoming state:
   1.136    // rcx: method handle
   1.137    // r13 or rsi: saved sp
   1.138    // To avoid calling convention issues, build a record on the stack and pass the pointer to that instead.
   1.139 +  // Note: fix the increment below if pushing more arguments
   1.140    __ push(rbp);               // saved_bp
   1.141 -  __ push(rsi);               // saved_sp
   1.142 -  __ push(rax);               // entry_sp
   1.143 +  __ push(saved_last_sp_register()); // saved_sp
   1.144 +  __ push(rbp);               // entry_sp (with extra align space)
   1.145    __ push(rbx);               // pusha saved_regs
   1.146    __ push(rcx);               // mh
   1.147 -  __ push(rcx);               // adaptername
   1.148 +  __ push(rcx);               // slot for adaptername
   1.149    __ movptr(Address(rsp, 0), (intptr_t) adaptername);
   1.150    __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp);
   1.151 +  __ increment(rsp, 6 * wordSize); // MethodHandleStubArguments
   1.152 +
   1.153 +  if  (UseSSE >= 2) {
   1.154 +    __ movdbl(xmm0, Address(rsp, 0));
   1.155 +  } else if (UseSSE == 1) {
   1.156 +    __ movflt(xmm0, Address(rsp, 0));
   1.157 +  } else {
   1.158 +    __ fld_d(Address(rsp, 0));
   1.159 +  }
   1.160 +  __ increment(rsp, 2 * wordSize);
   1.161 +
   1.162 +  __ popa();
   1.163    __ leave();
   1.164 -  __ popa();
   1.165 -  __ pop(rax);
   1.166    BLOCK_COMMENT("} trace_method_handle");
   1.167  }
   1.168  #endif //PRODUCT

mercurial