src/cpu/sparc/vm/methodHandles_sparc.cpp

changeset 3451
5dbed2f542ff
parent 3445
82e5a84b7436
child 3969
1d7922586cf6
     1.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp	Thu Jan 26 09:38:28 2012 +0100
     1.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp	Thu Jan 26 16:49:22 2012 +0100
     1.3 @@ -177,7 +177,7 @@
     1.4    BLOCK_COMMENT("ricochet_blob.bounce");
     1.5  
     1.6    if (VerifyMethodHandles)  RicochetFrame::verify_clean(_masm);
     1.7 -  trace_method_handle(_masm, "ricochet_blob.bounce");
     1.8 +  trace_method_handle(_masm, "return/ricochet_blob.bounce");
     1.9  
    1.10    __ JMP(L1_continuation, 0);
    1.11    __ delayed()->nop();
    1.12 @@ -268,14 +268,16 @@
    1.13  }
    1.14  
    1.15  // Emit code to verify that FP is pointing at a valid ricochet frame.
    1.16 -#ifdef ASSERT
    1.17 +#ifndef PRODUCT
    1.18  enum {
    1.19    ARG_LIMIT = 255, SLOP = 45,
    1.20    // use this parameter for checking for garbage stack movements:
    1.21    UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
    1.22    // the slop defends against false alarms due to fencepost errors
    1.23  };
    1.24 +#endif
    1.25  
    1.26 +#ifdef ASSERT
    1.27  void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
    1.28    // The stack should look like this:
    1.29    //    ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF]
    1.30 @@ -1000,7 +1002,7 @@
    1.31    BLOCK_COMMENT("} move_return_value");
    1.32  }
    1.33  
    1.34 -#ifdef ASSERT
    1.35 +#ifndef PRODUCT
    1.36  void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no)  {
    1.37      RicochetFrame* rf = new RicochetFrame(*fr);
    1.38  
    1.39 @@ -1022,28 +1024,121 @@
    1.40  extern "C" void print_method_handle(oop mh);
    1.41  void trace_method_handle_stub(const char* adaptername,
    1.42                                oopDesc* mh,
    1.43 -                              intptr_t* saved_sp) {
    1.44 +                              intptr_t* saved_sp,
    1.45 +                              intptr_t* args,
    1.46 +                              intptr_t* tracing_fp) {
    1.47    bool has_mh = (strstr(adaptername, "return/") == NULL);  // return adapters don't have mh
    1.48 -  tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp);
    1.49 -  if (has_mh)
    1.50 +
    1.51 +  tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp, args);
    1.52 +
    1.53 +  if (Verbose) {
    1.54 +    // dumping last frame with frame::describe
    1.55 +
    1.56 +    JavaThread* p = JavaThread::active();
    1.57 +
    1.58 +    ResourceMark rm;
    1.59 +    PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here
    1.60 +    FrameValues values;
    1.61 +
    1.62 +    // Note: We want to allow trace_method_handle from any call site.
    1.63 +    // While trace_method_handle creates a frame, it may be entered
    1.64 +    // without a valid return PC in O7 (e.g. not just after a call).
    1.65 +    // Walking that frame could lead to failures due to that invalid PC.
    1.66 +    // => carefully detect that frame when doing the stack walking
    1.67 +
    1.68 +    // walk up to the right frame using the "tracing_fp" argument
    1.69 +    intptr_t* cur_sp = StubRoutines::Sparc::flush_callers_register_windows_func()();
    1.70 +    frame cur_frame(cur_sp, frame::unpatchable, NULL);
    1.71 +
    1.72 +    while (cur_frame.fp() != (intptr_t *)(STACK_BIAS+(uintptr_t)tracing_fp)) {
    1.73 +      cur_frame = os::get_sender_for_C_frame(&cur_frame);
    1.74 +    }
    1.75 +
    1.76 +    // safely create a frame and call frame::describe
    1.77 +    intptr_t *dump_sp = cur_frame.sender_sp();
    1.78 +    intptr_t *dump_fp = cur_frame.link();
    1.79 +
    1.80 +    bool walkable = has_mh; // whether the traced frame shoud be walkable
    1.81 +
    1.82 +    // the sender for cur_frame is the caller of trace_method_handle
    1.83 +    if (walkable) {
    1.84 +      // The previous definition of walkable may have to be refined
    1.85 +      // if new call sites cause the next frame constructor to start
    1.86 +      // failing. Alternatively, frame constructors could be
    1.87 +      // modified to support the current or future non walkable
    1.88 +      // frames (but this is more intrusive and is not considered as
    1.89 +      // part of this RFE, which will instead use a simpler output).
    1.90 +      frame dump_frame = frame(dump_sp,
    1.91 +                               cur_frame.sp(), // younger_sp
    1.92 +                               false); // no adaptation
    1.93 +      dump_frame.describe(values, 1);
    1.94 +    } else {
    1.95 +      // Robust dump for frames which cannot be constructed from sp/younger_sp
    1.96 +      // Add descriptions without building a Java frame to avoid issues
    1.97 +      values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>");
    1.98 +      values.describe(-1, dump_sp, "sp");
    1.99 +    }
   1.100 +
   1.101 +    bool has_args = has_mh; // whether Gargs is meaningful
   1.102 +
   1.103 +    // mark args, if seems valid (may not be valid for some adapters)
   1.104 +    if (has_args) {
   1.105 +      if ((args >= dump_sp) && (args < dump_fp)) {
   1.106 +        values.describe(-1, args, "*G4_args");
   1.107 +      }
   1.108 +    }
   1.109 +
   1.110 +    // mark saved_sp, if seems valid (may not be valid for some adapters)
   1.111 +    intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp);
   1.112 +    if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) {
   1.113 +      values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS");
   1.114 +    }
   1.115 +
   1.116 +    // Note: the unextended_sp may not be correct
   1.117 +    tty->print_cr("  stack layout:");
   1.118 +    values.print(p);
   1.119 +  }
   1.120 +
   1.121 +  if (has_mh) {
   1.122      print_method_handle(mh);
   1.123 +  }
   1.124  }
   1.125 +
   1.126  void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
   1.127    if (!TraceMethodHandles)  return;
   1.128    BLOCK_COMMENT("trace_method_handle {");
   1.129    // save: Gargs, O5_savedSP
   1.130 -  __ save_frame(16);
   1.131 +  __ save_frame(16); // need space for saving required FPU state
   1.132 +
   1.133    __ set((intptr_t) adaptername, O0);
   1.134    __ mov(G3_method_handle, O1);
   1.135    __ mov(I5_savedSP, O2);
   1.136 +  __ mov(Gargs, O3);
   1.137 +  __ mov(I6, O4); // frame identifier for safe stack walking
   1.138 +
   1.139 +  // Save scratched registers that might be needed. Robustness is more
   1.140 +  // important than optimizing the saves for this debug only code.
   1.141 +
   1.142 +  // save FP result, valid at some call sites (adapter_opt_return_float, ...)
   1.143 +  Address d_save(FP, -sizeof(jdouble) + STACK_BIAS);
   1.144 +  __ stf(FloatRegisterImpl::D, Ftos_d, d_save);
   1.145 +  // Safely save all globals but G2 (handled by call_VM_leaf) and G7
   1.146 +  // (OS reserved).
   1.147    __ mov(G3_method_handle, L3);
   1.148    __ mov(Gargs, L4);
   1.149    __ mov(G5_method_type, L5);
   1.150 -  __ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub));
   1.151 +  __ mov(G6, L6);
   1.152 +  __ mov(G1, L1);
   1.153 +
   1.154 +  __ call_VM_leaf(L2 /* for G2 */, CAST_FROM_FN_PTR(address, trace_method_handle_stub));
   1.155  
   1.156    __ mov(L3, G3_method_handle);
   1.157    __ mov(L4, Gargs);
   1.158    __ mov(L5, G5_method_type);
   1.159 +  __ mov(L6, G6);
   1.160 +  __ mov(L1, G1);
   1.161 +  __ ldf(FloatRegisterImpl::D, d_save, Ftos_d);
   1.162 +
   1.163    __ restore();
   1.164    BLOCK_COMMENT("} trace_method_handle");
   1.165  }
   1.166 @@ -1268,7 +1363,7 @@
   1.167          move_typed_arg(_masm, arg_type, false,
   1.168                         prim_value_addr,
   1.169                         Address(O0_argslot, 0),
   1.170 -                       O2_scratch);  // must be an even register for !_LP64 long moves (uses O2/O3)
   1.171 +                      O2_scratch);  // must be an even register for !_LP64 long moves (uses O2/O3)
   1.172        }
   1.173  
   1.174        if (direct_to_method) {

mercurial