Merge
authoradlertz
Thu, 25 Sep 2014 23:37:41 +0200
changeset 26822 70aa736ff6aa
parent 26818 3b18f9dd1a31 (current diff)
parent 26821 ce9f82507dc2 (diff)
child 26853 a6be7aadcf53
Merge
--- a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -308,3 +308,10 @@
   // unused... but returns fp() to minimize changes introduced by 7087445
   return fp();
 }
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp), _unextended_sp((intptr_t*)sp) {
+  find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp
+}
+#endif
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -343,7 +343,7 @@
 // constructors
 
 // Construct an unpatchable, deficient frame
-frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) {
+void frame::init(intptr_t* sp, address pc, CodeBlob* cb) {
 #ifdef _LP64
   assert( (((intptr_t)sp & (wordSize-1)) == 0), "frame constructor passed an invalid sp");
 #endif
@@ -365,6 +365,10 @@
 #endif // ASSERT
 }
 
+frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) {
+  init(sp, pc, cb);
+}
+
 frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpreted) :
   _sp(sp),
   _younger_sp(younger_sp),
@@ -419,6 +423,13 @@
   }
 }
 
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  init((intptr_t*)sp, (address)pc, NULL);
+}
+#endif
+
 bool frame::is_interpreted_frame() const  {
   return Interpreter::contains(pc());
 }
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp	Thu Sep 25 23:37:41 2014 +0200
@@ -163,6 +163,8 @@
   enum unpatchable_t { unpatchable };
   frame(intptr_t* sp, unpatchable_t, address pc = NULL, CodeBlob* cb = NULL);
 
+  void init(intptr_t* sp, address pc, CodeBlob* cb);
+
   // Walk from sp outward looking for old_sp, and return old_sp's predecessor
   // (i.e. return the sp from the frame where old_sp is the fp).
   // Register windows are assumed to be flushed for the stack in question.
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -715,3 +715,10 @@
   assert(! is_compiled_frame(), "unknown compiled frame size");
   return fp();
 }
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
+}
+#endif
--- a/hotspot/src/cpu/x86/vm/frame_x86.hpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp	Thu Sep 25 23:37:41 2014 +0200
@@ -187,6 +187,8 @@
 
   frame(intptr_t* sp, intptr_t* fp);
 
+  void init(intptr_t* sp, intptr_t* fp, address pc);
+
   // accessors for the instance variables
   // Note: not necessarily the real 'frame pointer' (see real_fp)
   intptr_t*   fp() const { return _fp; }
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp	Thu Sep 25 23:37:41 2014 +0200
@@ -41,7 +41,7 @@
   _deopt_state = unknown;
 }
 
-inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
+inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
   _sp = sp;
   _unextended_sp = sp;
   _fp = fp;
@@ -59,6 +59,10 @@
   }
 }
 
+inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
+  init(sp, fp, pc);
+}
+
 inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
   _sp = sp;
   _unextended_sp = unextended_sp;
--- a/hotspot/src/cpu/zero/vm/frame_zero.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -438,3 +438,10 @@
   // unused... but returns fp() to minimize changes introduced by 7087445
   return fp();
 }
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  Unimplemented();
+}
+#endif
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -265,7 +265,7 @@
                 CAST_FROM_FN_PTR(address, os::current_frame));
   if (os::is_first_C_frame(&myframe)) {
     // stack is not walkable
-    return frame(NULL, NULL, NULL);
+    return frame(NULL, NULL, false);
   } else {
     return os::get_sender_for_C_frame(&myframe);
   }
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -327,7 +327,7 @@
   if (t2->is_constant()) {
     switch (t2->tag()) {
       case intTag   : if (t2->as_IntConstant()->value() == 0)  set_canonical(x->x()); return;
-      case longTag  : if (t2->as_IntConstant()->value() == 0)  set_canonical(x->x()); return;
+      case longTag  : if (t2->as_LongConstant()->value() == (jlong)0)  set_canonical(x->x()); return;
       default       : ShouldNotReachHere();
     }
   }
@@ -808,28 +808,41 @@
 
 static bool match_index_and_scale(Instruction*  instr,
                                   Instruction** index,
-                                  int*          log2_scale,
-                                  Instruction** instr_to_unpin) {
-  *instr_to_unpin = NULL;
-
-  // Skip conversion ops
+                                  int*          log2_scale) {
+  // Skip conversion ops. This works only on 32bit because of the implicit l2i that the
+  // unsafe performs.
+#ifndef _LP64
   Convert* convert = instr->as_Convert();
-  if (convert != NULL) {
+  if (convert != NULL && convert->op() == Bytecodes::_i2l) {
+    assert(convert->value()->type() == intType, "invalid input type");
     instr = convert->value();
   }
+#endif
 
   ShiftOp* shift = instr->as_ShiftOp();
   if (shift != NULL) {
-    if (shift->is_pinned()) {
-      *instr_to_unpin = shift;
+    if (shift->op() == Bytecodes::_lshl) {
+      assert(shift->x()->type() == longType, "invalid input type");
+    } else {
+#ifndef _LP64
+      if (shift->op() == Bytecodes::_ishl) {
+        assert(shift->x()->type() == intType, "invalid input type");
+      } else {
+        return false;
+      }
+#else
+      return false;
+#endif
     }
+
+
     // Constant shift value?
     Constant* con = shift->y()->as_Constant();
     if (con == NULL) return false;
     // Well-known type and value?
     IntConstant* val = con->type()->as_IntConstant();
-    if (val == NULL) return false;
-    if (shift->x()->type() != intType) return false;
+    assert(val != NULL, "Should be an int constant");
+
     *index = shift->x();
     int tmp_scale = val->value();
     if (tmp_scale >= 0 && tmp_scale < 4) {
@@ -842,31 +855,42 @@
 
   ArithmeticOp* arith = instr->as_ArithmeticOp();
   if (arith != NULL) {
-    if (arith->is_pinned()) {
-      *instr_to_unpin = arith;
+    // See if either arg is a known constant
+    Constant* con = arith->x()->as_Constant();
+    if (con != NULL) {
+      *index = arith->y();
+    } else {
+      con = arith->y()->as_Constant();
+      if (con == NULL) return false;
+      *index = arith->x();
     }
+    long const_value;
     // Check for integer multiply
-    if (arith->op() == Bytecodes::_imul) {
-      // See if either arg is a known constant
-      Constant* con = arith->x()->as_Constant();
-      if (con != NULL) {
-        *index = arith->y();
+    if (arith->op() == Bytecodes::_lmul) {
+      assert((*index)->type() == longType, "invalid input type");
+      LongConstant* val = con->type()->as_LongConstant();
+      assert(val != NULL, "expecting a long constant");
+      const_value = val->value();
+    } else {
+#ifndef _LP64
+      if (arith->op() == Bytecodes::_imul) {
+        assert((*index)->type() == intType, "invalid input type");
+        IntConstant* val = con->type()->as_IntConstant();
+        assert(val != NULL, "expecting an int constant");
+        const_value = val->value();
       } else {
-        con = arith->y()->as_Constant();
-        if (con == NULL) return false;
-        *index = arith->x();
+        return false;
       }
-      if ((*index)->type() != intType) return false;
-      // Well-known type and value?
-      IntConstant* val = con->type()->as_IntConstant();
-      if (val == NULL) return false;
-      switch (val->value()) {
-      case 1: *log2_scale = 0; return true;
-      case 2: *log2_scale = 1; return true;
-      case 4: *log2_scale = 2; return true;
-      case 8: *log2_scale = 3; return true;
-      default:            return false;
-      }
+#else
+      return false;
+#endif
+    }
+    switch (const_value) {
+    case 1: *log2_scale = 0; return true;
+    case 2: *log2_scale = 1; return true;
+    case 4: *log2_scale = 2; return true;
+    case 8: *log2_scale = 3; return true;
+    default:            return false;
     }
   }
 
@@ -879,29 +903,37 @@
                   Instruction** base,
                   Instruction** index,
                   int*          log2_scale) {
-  Instruction* instr_to_unpin = NULL;
   ArithmeticOp* root = x->base()->as_ArithmeticOp();
   if (root == NULL) return false;
   // Limit ourselves to addition for now
   if (root->op() != Bytecodes::_ladd) return false;
+
+  bool match_found = false;
   // Try to find shift or scale op
-  if (match_index_and_scale(root->y(), index, log2_scale, &instr_to_unpin)) {
+  if (match_index_and_scale(root->y(), index, log2_scale)) {
     *base = root->x();
-  } else if (match_index_and_scale(root->x(), index, log2_scale, &instr_to_unpin)) {
+    match_found = true;
+  } else if (match_index_and_scale(root->x(), index, log2_scale)) {
     *base = root->y();
-  } else if (root->y()->as_Convert() != NULL) {
+    match_found = true;
+  } else if (NOT_LP64(root->y()->as_Convert() != NULL) LP64_ONLY(false)) {
+    // Skipping i2l works only on 32bit because of the implicit l2i that the unsafe performs.
+    // 64bit needs a real sign-extending conversion.
     Convert* convert = root->y()->as_Convert();
-    if (convert->op() == Bytecodes::_i2l && convert->value()->type() == intType) {
+    if (convert->op() == Bytecodes::_i2l) {
+      assert(convert->value()->type() == intType, "should be an int");
       // pick base and index, setting scale at 1
       *base  = root->x();
       *index = convert->value();
       *log2_scale = 0;
-    } else {
-      return false;
+      match_found = true;
     }
-  } else {
-    // doesn't match any expected sequences
-    return false;
+  }
+  // The default solution
+  if (!match_found) {
+    *base = root->x();
+    *index = root->y();
+    *log2_scale = 0;
   }
 
   // If the value is pinned then it will be always be computed so
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -2045,6 +2045,8 @@
   }
 }
 
+// Here UnsafeGetRaw may have x->base() and x->index() be int or long
+// on both 64 and 32 bits. Expecting x->base() to be always long on 64bit.
 void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) {
   LIRItem base(x->base(), this);
   LIRItem idx(this);
@@ -2059,50 +2061,73 @@
 
   int   log2_scale = 0;
   if (x->has_index()) {
-    assert(x->index()->type()->tag() == intTag, "should not find non-int index");
     log2_scale = x->log2_scale();
   }
 
   assert(!x->has_index() || idx.value() == x->index(), "should match");
 
   LIR_Opr base_op = base.result();
+  LIR_Opr index_op = idx.result();
 #ifndef _LP64
   if (x->base()->type()->tag() == longTag) {
     base_op = new_register(T_INT);
     __ convert(Bytecodes::_l2i, base.result(), base_op);
-  } else {
-    assert(x->base()->type()->tag() == intTag, "must be");
+  }
+  if (x->has_index()) {
+    if (x->index()->type()->tag() == longTag) {
+      LIR_Opr long_index_op = index_op;
+      if (x->index()->type()->is_constant()) {
+        long_index_op = new_register(T_LONG);
+        __ move(index_op, long_index_op);
+      }
+      index_op = new_register(T_INT);
+      __ convert(Bytecodes::_l2i, long_index_op, index_op);
+    } else {
+      assert(x->index()->type()->tag() == intTag, "must be");
+    }
   }
+  // At this point base and index should be all ints.
+  assert(base_op->type() == T_INT && !base_op->is_constant(), "base should be an non-constant int");
+  assert(!x->has_index() || index_op->type() == T_INT, "index should be an int");
+#else
+  if (x->has_index()) {
+    if (x->index()->type()->tag() == intTag) {
+      if (!x->index()->type()->is_constant()) {
+        index_op = new_register(T_LONG);
+        __ convert(Bytecodes::_i2l, idx.result(), index_op);
+      }
+    } else {
+      assert(x->index()->type()->tag() == longTag, "must be");
+      if (x->index()->type()->is_constant()) {
+        index_op = new_register(T_LONG);
+        __ move(idx.result(), index_op);
+      }
+    }
+  }
+  // At this point base is a long non-constant
+  // Index is a long register or a int constant.
+  // We allow the constant to stay an int because that would allow us a more compact encoding by
+  // embedding an immediate offset in the address expression. If we have a long constant, we have to
+  // move it into a register first.
+  assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a long non-constant");
+  assert(!x->has_index() || (index_op->type() == T_INT && index_op->is_constant()) ||
+                            (index_op->type() == T_LONG && !index_op->is_constant()), "unexpected index type");
 #endif
 
   BasicType dst_type = x->basic_type();
-  LIR_Opr index_op = idx.result();
 
   LIR_Address* addr;
   if (index_op->is_constant()) {
     assert(log2_scale == 0, "must not have a scale");
+    assert(index_op->type() == T_INT, "only int constants supported");
     addr = new LIR_Address(base_op, index_op->as_jint(), dst_type);
   } else {
 #ifdef X86
-#ifdef _LP64
-    if (!index_op->is_illegal() && index_op->type() == T_INT) {
-      LIR_Opr tmp = new_pointer_register();
-      __ convert(Bytecodes::_i2l, index_op, tmp);
-      index_op = tmp;
-    }
-#endif
     addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type);
 #elif defined(ARM)
     addr = generate_address(base_op, index_op, log2_scale, 0, dst_type);
 #else
     if (index_op->is_illegal() || log2_scale == 0) {
-#ifdef _LP64
-      if (!index_op->is_illegal() && index_op->type() == T_INT) {
-        LIR_Opr tmp = new_pointer_register();
-        __ convert(Bytecodes::_i2l, index_op, tmp);
-        index_op = tmp;
-      }
-#endif
       addr = new LIR_Address(base_op, index_op, dst_type);
     } else {
       LIR_Opr tmp = new_pointer_register();
@@ -2129,7 +2154,6 @@
   BasicType type = x->basic_type();
 
   if (x->has_index()) {
-    assert(x->index()->type()->tag() == intTag, "should not find non-int index");
     log2_scale = x->log2_scale();
   }
 
@@ -2152,38 +2176,39 @@
   set_no_result(x);
 
   LIR_Opr base_op = base.result();
+  LIR_Opr index_op = idx.result();
+
 #ifndef _LP64
   if (x->base()->type()->tag() == longTag) {
     base_op = new_register(T_INT);
     __ convert(Bytecodes::_l2i, base.result(), base_op);
-  } else {
-    assert(x->base()->type()->tag() == intTag, "must be");
+  }
+  if (x->has_index()) {
+    if (x->index()->type()->tag() == longTag) {
+      index_op = new_register(T_INT);
+      __ convert(Bytecodes::_l2i, idx.result(), index_op);
+    }
   }
+  // At this point base and index should be all ints and not constants
+  assert(base_op->type() == T_INT && !base_op->is_constant(), "base should be an non-constant int");
+  assert(!x->has_index() || (index_op->type() == T_INT && !index_op->is_constant()), "index should be an non-constant int");
+#else
+  if (x->has_index()) {
+    if (x->index()->type()->tag() == intTag) {
+      index_op = new_register(T_LONG);
+      __ convert(Bytecodes::_i2l, idx.result(), index_op);
+    }
+  }
+  // At this point base and index are long and non-constant
+  assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a non-constant long");
+  assert(!x->has_index() || (index_op->type() == T_LONG && !index_op->is_constant()), "index must be a non-constant long");
 #endif
 
-  LIR_Opr index_op = idx.result();
   if (log2_scale != 0) {
     // temporary fix (platform dependent code without shift on Intel would be better)
-    index_op = new_pointer_register();
-#ifdef _LP64
-    if(idx.result()->type() == T_INT) {
-      __ convert(Bytecodes::_i2l, idx.result(), index_op);
-    } else {
-#endif
-      // TODO: ARM also allows embedded shift in the address
-      __ move(idx.result(), index_op);
-#ifdef _LP64
-    }
-#endif
+    // TODO: ARM also allows embedded shift in the address
     __ shift_left(index_op, log2_scale, index_op);
   }
-#ifdef _LP64
-  else if(!index_op->is_illegal() && index_op->type() == T_INT) {
-    LIR_Opr tmp = new_pointer_register();
-    __ convert(Bytecodes::_i2l, index_op, tmp);
-    index_op = tmp;
-  }
-#endif
 
   LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());
   __ move(value.result(), addr);
--- a/hotspot/src/share/vm/runtime/frame.hpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/share/vm/runtime/frame.hpp	Thu Sep 25 23:37:41 2014 +0200
@@ -68,6 +68,15 @@
   // Constructors
   frame();
 
+#ifndef PRODUCT
+  // This is a generic constructor which is only used by pns() in debug.cpp.
+  // pns (i.e. print native stack) uses this constructor to create a starting
+  // frame for stack walking. The implementation of this constructor is platform
+  // dependent (i.e. SPARC doesn't need an 'fp' argument an will ignore it) but
+  // we want to keep the signature generic because pns() is shared code.
+  frame(void* sp, void* fp, void* pc);
+#endif
+
   // Accessors
 
   // pc: Returns the pc at which this frame will continue normally.
--- a/hotspot/src/share/vm/utilities/debug.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/share/vm/utilities/debug.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -653,6 +653,13 @@
   tty->print_cr("  pm(int pc)    - print Method* given compiled PC");
   tty->print_cr("  findm(intptr_t pc) - finds Method*");
   tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
+  tty->print_cr("  pns(void* sp, void* fp, void* pc)  - print native (i.e. mixed) stack trace. E.g.");
+  tty->print_cr("                   pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or");
+  tty->print_cr("                   pns($sp, $ebp, $pc) on Linux/x86 or");
+  tty->print_cr("                   pns($sp, 0, $pc)    on Linux/ppc64 or");
+  tty->print_cr("                   pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC");
+  tty->print_cr("                 - in gdb do 'set overload-resolution off' before calling pns()");
+  tty->print_cr("                 - in dbx do 'frame 1' before calling pns()");
 
   tty->print_cr("misc.");
   tty->print_cr("  flush()       - flushes the log file");
@@ -665,3 +672,56 @@
 }
 
 #endif // !PRODUCT
+
+void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size) {
+
+  // see if it's a valid frame
+  if (fr.pc()) {
+    st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
+
+    int count = 0;
+    while (count++ < StackPrintLimit) {
+      fr.print_on_error(st, buf, buf_size);
+      st->cr();
+      // Compiled code may use EBP register on x86 so it looks like
+      // non-walkable C frame. Use frame.sender() for java frames.
+      if (t && t->is_Java_thread()) {
+        // Catch very first native frame by using stack address.
+        // For JavaThread stack_base and stack_size should be set.
+        if (!t->on_local_stack((address)(fr.real_fp() + 1))) {
+          break;
+        }
+        if (fr.is_java_frame() || fr.is_native_frame() || fr.is_runtime_frame()) {
+          RegisterMap map((JavaThread*)t, false); // No update
+          fr = fr.sender(&map);
+        } else {
+          fr = os::get_sender_for_C_frame(&fr);
+        }
+      } else {
+        // is_first_C_frame() does only simple checks for frame pointer,
+        // it will pass if java compiled code has a pointer in EBP.
+        if (os::is_first_C_frame(&fr)) break;
+        fr = os::get_sender_for_C_frame(&fr);
+      }
+    }
+
+    if (count > StackPrintLimit) {
+      st->print_cr("...<more frames>...");
+    }
+
+    st->cr();
+  }
+}
+
+#ifndef PRODUCT
+
+extern "C" void pns(void* sp, void* fp, void* pc) { // print native stack
+  Command c("pns");
+  static char buf[O_BUFLEN];
+  Thread* t = ThreadLocalStorage::get_thread_slow();
+  // Call generic frame constructor (certain arguments may be ignored)
+  frame fr(sp, fp, pc);
+  print_native_stack(tty, fr, t, buf, sizeof(buf));
+}
+
+#endif // !PRODUCT
--- a/hotspot/src/share/vm/utilities/debug.hpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp	Thu Sep 25 23:37:41 2014 +0200
@@ -263,4 +263,7 @@
 void pd_ps(frame f);
 void pd_obfuscate_location(char *buf, size_t buflen);
 
+class outputStream;
+void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size);
+
 #endif // SHARE_VM_UTILITIES_DEBUG_HPP
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Wed Sep 24 09:48:15 2014 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Thu Sep 25 23:37:41 2014 +0200
@@ -577,7 +577,7 @@
 
   STEP(120, "(printing native stack)" )
 
-     if (_verbose) {
+   if (_verbose) {
      if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
        // We have printed the native stack in platform-specific code
        // Windows/x64 needs special handling.
@@ -585,43 +585,7 @@
        frame fr = _context ? os::fetch_frame_from_context(_context)
                            : os::current_frame();
 
-       // see if it's a valid frame
-       if (fr.pc()) {
-          st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
-
-
-          int count = 0;
-          while (count++ < StackPrintLimit) {
-             fr.print_on_error(st, buf, sizeof(buf));
-             st->cr();
-             // Compiled code may use EBP register on x86 so it looks like
-             // non-walkable C frame. Use frame.sender() for java frames.
-             if (_thread && _thread->is_Java_thread()) {
-               // Catch very first native frame by using stack address.
-               // For JavaThread stack_base and stack_size should be set.
-               if (!_thread->on_local_stack((address)(fr.sender_sp() + 1))) {
-                 break;
-               }
-               if (fr.is_java_frame()) {
-                 RegisterMap map((JavaThread*)_thread, false); // No update
-                 fr = fr.sender(&map);
-               } else {
-                 fr = os::get_sender_for_C_frame(&fr);
-               }
-             } else {
-               // is_first_C_frame() does only simple checks for frame pointer,
-               // it will pass if java compiled code has a pointer in EBP.
-               if (os::is_first_C_frame(&fr)) break;
-               fr = os::get_sender_for_C_frame(&fr);
-             }
-          }
-
-          if (count > StackPrintLimit) {
-             st->print_cr("...<more frames>...");
-          }
-
-          st->cr();
-       }
+       print_native_stack(st, fr, _thread, buf, sizeof(buf));
      }
    }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/UnsafeRaw.java	Thu Sep 25 23:37:41 2014 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8058744
+ * @summary Invalid pattern-matching of address computations in raw unsafe
+ * @library /testlibrary
+ * @run main/othervm -Xbatch UnsafeRaw
+ */
+
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
+
+public class UnsafeRaw {
+  public static class Tests {
+    public static int int_index(sun.misc.Unsafe unsafe, long base, int index) throws Exception {
+      return unsafe.getInt(base + (index << 2));
+    }
+    public static int long_index(sun.misc.Unsafe unsafe, long base, long index) throws Exception {
+      return unsafe.getInt(base + (index << 2));
+    }
+    public static int int_index_back_ashift(sun.misc.Unsafe unsafe, long base, int index) throws Exception {
+      return unsafe.getInt(base + (index >> 2));
+    }
+    public static int int_index_back_lshift(sun.misc.Unsafe unsafe, long base, int index) throws Exception {
+      return unsafe.getInt(base + (index >>> 2));
+    }
+    public static int long_index_back_ashift(sun.misc.Unsafe unsafe, long base, long index) throws Exception {
+      return unsafe.getInt(base + (index >> 2));
+    }
+    public static int long_index_back_lshift(sun.misc.Unsafe unsafe, long base, long index) throws Exception {
+      return unsafe.getInt(base + (index >>> 2));
+    }
+    public static int int_const_12345678_index(sun.misc.Unsafe unsafe, long base) throws Exception {
+      int idx4 = 0x12345678;
+      return unsafe.getInt(base + idx4);
+    }
+    public static int long_const_1234567890abcdef_index(sun.misc.Unsafe unsafe, long base) throws Exception {
+      long idx5 = 0x1234567890abcdefL;
+      return unsafe.getInt(base + idx5);
+    }
+    public static int int_index_mul(sun.misc.Unsafe unsafe, long base, int index) throws Exception {
+      return unsafe.getInt(base + (index * 4));
+    }
+    public static int long_index_mul(sun.misc.Unsafe unsafe, long base, long index) throws Exception {
+      return unsafe.getInt(base + (index * 4));
+    }
+    public static int int_index_mul_scale_16(sun.misc.Unsafe unsafe, long base, int index) throws Exception {
+      return unsafe.getInt(base + (index * 16));
+    }
+    public static int long_index_mul_scale_16(sun.misc.Unsafe unsafe, long base, long index) throws Exception {
+      return unsafe.getInt(base + (index * 16));
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    sun.misc.Unsafe unsafe = Utils.getUnsafe();
+    final int array_size = 128;
+    final int element_size = 4;
+    final int magic = 0x12345678;
+
+    Random rnd = new Random();
+
+    long array = unsafe.allocateMemory(array_size * element_size); // 128 ints
+    long addr = array + array_size * element_size / 2; // something in the middle to work with
+    unsafe.putInt(addr, magic);
+    for (int j = 0; j < 100000; j++) {
+       if (Tests.int_index(unsafe, addr, 0) != magic) throw new Exception();
+       if (Tests.long_index(unsafe, addr, 0) != magic) throw new Exception();
+       if (Tests.int_index_mul(unsafe, addr, 0) != magic) throw new Exception();
+       if (Tests.long_index_mul(unsafe, addr, 0) != magic) throw new Exception();
+       {
+         long idx1 = rnd.nextLong();
+         long addr1 = addr - (idx1 << 2);
+         if (Tests.long_index(unsafe, addr1, idx1) != magic) throw new Exception();
+       }
+       {
+         long idx2 = rnd.nextLong();
+         long addr2 = addr - (idx2 >> 2);
+         if (Tests.long_index_back_ashift(unsafe, addr2, idx2) != magic) throw new Exception();
+       }
+       {
+         long idx3 = rnd.nextLong();
+         long addr3 = addr - (idx3 >>> 2);
+         if (Tests.long_index_back_lshift(unsafe, addr3, idx3) != magic) throw new Exception();
+       }
+       {
+         long idx4 = 0x12345678;
+         long addr4 = addr - idx4;
+         if (Tests.int_const_12345678_index(unsafe, addr4) != magic) throw new Exception();
+       }
+       {
+         long idx5 = 0x1234567890abcdefL;
+         long addr5 = addr - idx5;
+         if (Tests.long_const_1234567890abcdef_index(unsafe, addr5) != magic) throw new Exception();
+       }
+       {
+         int idx6 = rnd.nextInt();
+         long addr6 = addr - (idx6 >> 2);
+         if (Tests.int_index_back_ashift(unsafe, addr6, idx6) != magic) throw new Exception();
+       }
+       {
+         int idx7 = rnd.nextInt();
+         long addr7 = addr - (idx7 >>> 2);
+         if (Tests.int_index_back_lshift(unsafe, addr7, idx7) != magic) throw new Exception();
+       }
+       {
+         int idx8 = rnd.nextInt();
+         long addr8 = addr - (idx8 * 16);
+         if (Tests.int_index_mul_scale_16(unsafe, addr8, idx8) != magic) throw new Exception();
+       }
+       {
+         long idx9 = rnd.nextLong();
+         long addr9 = addr - (idx9 * 16);
+         if (Tests.long_index_mul_scale_16(unsafe, addr9, idx9) != magic) throw new Exception();
+       }
+    }
+  }
+}