Merge
authoranoll
Thu, 11 Dec 2014 16:22:47 -0800
changeset 28048 a4c961114655
parent 28035 3ca6beb406ca (current diff)
parent 28047 c0e7a15c458f (diff)
child 28049 62648789b8ba
Merge
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -675,7 +675,7 @@
   case handle_exception_nofpu_id:
   case handle_exception_id:
     // At this point all registers MAY be live.
-    oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id);
+    oop_map = save_live_registers(sasm, 1 /*thread*/, id != handle_exception_nofpu_id);
     break;
   case handle_exception_from_callee_id: {
     // At this point all registers except exception oop (RAX) and
@@ -748,7 +748,7 @@
   case handle_exception_nofpu_id:
   case handle_exception_id:
     // Restore the registers that were saved at the beginning.
-    restore_live_registers(sasm, id == handle_exception_nofpu_id);
+    restore_live_registers(sasm, id != handle_exception_nofpu_id);
     break;
   case handle_exception_from_callee_id:
     // WIN64_ONLY: No need to add frame::arg_reg_save_area_bytes to SP
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -385,6 +385,18 @@
   int                handler_bci;
   int                current_bci = bci(thread);
 
+  if (thread->frames_to_pop_failed_realloc() > 0) {
+    // Allocation of scalar replaced object used in this frame
+    // failed. Unconditionally pop the frame.
+    thread->dec_frames_to_pop_failed_realloc();
+    thread->set_vm_result(h_exception());
+    // If the method is synchronized we already unlocked the monitor
+    // during deoptimization so the interpreter needs to skip it when
+    // the frame is popped.
+    thread->set_do_not_unlock_if_synchronized(true);
+    return Interpreter::remove_activation_entry();
+  }
+
   // Need to do this check first since when _do_not_unlock_if_synchronized
   // is set, we don't want to trigger any classloading which may make calls
   // into java, or surprisingly find a matching exception handler for bci 0
--- a/hotspot/src/share/vm/memory/universe.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/memory/universe.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -120,6 +120,7 @@
 oop Universe::_out_of_memory_error_class_metaspace    = NULL;
 oop Universe::_out_of_memory_error_array_size         = NULL;
 oop Universe::_out_of_memory_error_gc_overhead_limit  = NULL;
+oop Universe::_out_of_memory_error_realloc_objects    = NULL;
 objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL;
 volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0;
 bool Universe::_verify_in_progress                    = false;
@@ -191,6 +192,7 @@
   f->do_oop((oop*)&_out_of_memory_error_class_metaspace);
   f->do_oop((oop*)&_out_of_memory_error_array_size);
   f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit);
+  f->do_oop((oop*)&_out_of_memory_error_realloc_objects);
     f->do_oop((oop*)&_preallocated_out_of_memory_error_array);
   f->do_oop((oop*)&_null_ptr_exception_instance);
   f->do_oop((oop*)&_arithmetic_exception_instance);
@@ -575,7 +577,8 @@
           (throwable() != Universe::_out_of_memory_error_metaspace)  &&
           (throwable() != Universe::_out_of_memory_error_class_metaspace)  &&
           (throwable() != Universe::_out_of_memory_error_array_size) &&
-          (throwable() != Universe::_out_of_memory_error_gc_overhead_limit));
+          (throwable() != Universe::_out_of_memory_error_gc_overhead_limit) &&
+          (throwable() != Universe::_out_of_memory_error_realloc_objects));
 }
 
 
@@ -1039,6 +1042,7 @@
     Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false);
     Universe::_out_of_memory_error_gc_overhead_limit =
       k_h->allocate_instance(CHECK_false);
+    Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);
 
     // Setup preallocated NullPointerException
     // (this is currently used for a cheap & dirty solution in compiler exception handling)
@@ -1078,6 +1082,9 @@
     msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false);
     java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg());
 
+    msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false);
+    java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg());
+
     msg = java_lang_String::create_from_str("/ by zero", CHECK_false);
     java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg());
 
--- a/hotspot/src/share/vm/memory/universe.hpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/memory/universe.hpp	Thu Dec 11 16:22:47 2014 -0800
@@ -157,6 +157,7 @@
   static oop          _out_of_memory_error_class_metaspace;
   static oop          _out_of_memory_error_array_size;
   static oop          _out_of_memory_error_gc_overhead_limit;
+  static oop          _out_of_memory_error_realloc_objects;
 
   static Array<int>*       _the_empty_int_array;    // Canonicalized int array
   static Array<u2>*        _the_empty_short_array;  // Canonicalized short array
@@ -328,6 +329,7 @@
   static oop out_of_memory_error_class_metaspace()    { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace);   }
   static oop out_of_memory_error_array_size()         { return gen_out_of_memory_error(_out_of_memory_error_array_size); }
   static oop out_of_memory_error_gc_overhead_limit()  { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit);  }
+  static oop out_of_memory_error_realloc_objects()    { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects);  }
 
   // Accessors needed for fast allocation
   static Klass** boolArrayKlassObj_addr()           { return &_boolArrayKlassObj;   }
--- a/hotspot/src/share/vm/opto/castnode.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/opto/castnode.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -104,7 +104,8 @@
   // Try to improve the type of the CastII if we recognize a CmpI/If
   // pattern.
   if (_carry_dependency) {
-    if (in(0) != NULL && (in(0)->is_IfFalse() || in(0)->is_IfTrue())) {
+    if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) {
+      assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj");
       Node* proj = in(0);
       if (proj->in(0)->in(1)->is_Bool()) {
         Node* b = proj->in(0)->in(1);
--- a/hotspot/src/share/vm/opto/ifnode.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/opto/ifnode.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -820,6 +820,11 @@
 
 static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff);
 
+struct RangeCheck {
+  Node* ctl;
+  jint off;
+};
+
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Strip out
 // control copies
@@ -861,83 +866,141 @@
   jint offset1;
   int flip1 = is_range_check(range1, index1, offset1);
   if( flip1 ) {
-    Node *first_prev_dom = NULL;
-
     // Try to remove extra range checks.  All 'up_one_dom' gives up at merges
     // so all checks we inspect post-dominate the top-most check we find.
     // If we are going to fail the current check and we reach the top check
     // then we are guaranteed to fail, so just start interpreting there.
-    // We 'expand' the top 2 range checks to include all post-dominating
+    // We 'expand' the top 3 range checks to include all post-dominating
     // checks.
 
-    // The top 2 range checks seen
-    Node *prev_chk1 = NULL;
-    Node *prev_chk2 = NULL;
+    // The top 3 range checks seen
+    const int NRC =3;
+    RangeCheck prev_checks[NRC];
+    int nb_checks = 0;
+
     // Low and high offsets seen so far
     jint off_lo = offset1;
     jint off_hi = offset1;
 
-    // Scan for the top 2 checks and collect range of offsets
-    for( int dist = 0; dist < 999; dist++ ) { // Range-Check scan limit
-      if( dom->Opcode() == Op_If &&  // Not same opcode?
-          prev_dom->in(0) == dom ) { // One path of test does dominate?
-        if( dom == this ) return NULL; // dead loop
+    bool found_immediate_dominator = false;
+
+    // Scan for the top checks and collect range of offsets
+    for (int dist = 0; dist < 999; dist++) { // Range-Check scan limit
+      if (dom->Opcode() == Op_If &&  // Not same opcode?
+          prev_dom->in(0) == dom) { // One path of test does dominate?
+        if (dom == this) return NULL; // dead loop
         // See if this is a range check
         Node *index2, *range2;
         jint offset2;
         int flip2 = dom->as_If()->is_range_check(range2, index2, offset2);
         // See if this is a _matching_ range check, checking against
         // the same array bounds.
-        if( flip2 == flip1 && range2 == range1 && index2 == index1 &&
-            dom->outcnt() == 2 ) {
+        if (flip2 == flip1 && range2 == range1 && index2 == index1 &&
+            dom->outcnt() == 2) {
+          if (nb_checks == 0 && dom->in(1) == in(1)) {
+            // Found an immediately dominating test at the same offset.
+            // This kind of back-to-back test can be eliminated locally,
+            // and there is no need to search further for dominating tests.
+            assert(offset2 == offset1, "Same test but different offsets");
+            found_immediate_dominator = true;
+            break;
+          }
           // Gather expanded bounds
           off_lo = MIN2(off_lo,offset2);
           off_hi = MAX2(off_hi,offset2);
-          // Record top 2 range checks
-          prev_chk2 = prev_chk1;
-          prev_chk1 = prev_dom;
-          // If we match the test exactly, then the top test covers
-          // both our lower and upper bounds.
-          if( dom->in(1) == in(1) )
-            prev_chk2 = prev_chk1;
+          // Record top NRC range checks
+          prev_checks[nb_checks%NRC].ctl = prev_dom;
+          prev_checks[nb_checks%NRC].off = offset2;
+          nb_checks++;
         }
       }
       prev_dom = dom;
-      dom = up_one_dom( dom );
-      if( !dom ) break;
+      dom = up_one_dom(dom);
+      if (!dom) break;
     }
 
-
-    // Attempt to widen the dominating range check to cover some later
-    // ones.  Since range checks "fail" by uncommon-trapping to the
-    // interpreter, widening a check can make us speculative enter the
-    // interpreter.  If we see range-check deopt's, do not widen!
-    if (!phase->C->allow_range_check_smearing())  return NULL;
+    if (!found_immediate_dominator) {
+      // Attempt to widen the dominating range check to cover some later
+      // ones.  Since range checks "fail" by uncommon-trapping to the
+      // interpreter, widening a check can make us speculatively enter
+      // the interpreter.  If we see range-check deopt's, do not widen!
+      if (!phase->C->allow_range_check_smearing())  return NULL;
 
-    // Constant indices only need to check the upper bound.
-    // Non-constance indices must check both low and high.
-    if( index1 ) {
-      // Didn't find 2 prior covering checks, so cannot remove anything.
-      if( !prev_chk2 ) return NULL;
-      // 'Widen' the offsets of the 1st and 2nd covering check
-      adjust_check( prev_chk1, range1, index1, flip1, off_lo, igvn );
-      // Do not call adjust_check twice on the same projection
-      // as the first call may have transformed the BoolNode to a ConI
-      if( prev_chk1 != prev_chk2 ) {
-        adjust_check( prev_chk2, range1, index1, flip1, off_hi, igvn );
+      // Didn't find prior covering check, so cannot remove anything.
+      if (nb_checks == 0) {
+        return NULL;
       }
-      // Test is now covered by prior checks, dominate it out
-      prev_dom = prev_chk2;
-    } else {
-      // Didn't find prior covering check, so cannot remove anything.
-      if( !prev_chk1 ) return NULL;
-      // 'Widen' the offset of the 1st and only covering check
-      adjust_check( prev_chk1, range1, index1, flip1, off_hi, igvn );
-      // Test is now covered by prior checks, dominate it out
-      prev_dom = prev_chk1;
+      // Constant indices only need to check the upper bound.
+      // Non-constant indices must check both low and high.
+      int chk0 = (nb_checks - 1) % NRC;
+      if (index1) {
+        if (nb_checks == 1) {
+          return NULL;
+        } else {
+          // If the top range check's constant is the min or max of
+          // all constants we widen the next one to cover the whole
+          // range of constants.
+          RangeCheck rc0 = prev_checks[chk0];
+          int chk1 = (nb_checks - 2) % NRC;
+          RangeCheck rc1 = prev_checks[chk1];
+          if (rc0.off == off_lo) {
+            adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn);
+            prev_dom = rc1.ctl;
+          } else if (rc0.off == off_hi) {
+            adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn);
+            prev_dom = rc1.ctl;
+          } else {
+            // If the top test's constant is not the min or max of all
+            // constants, we need 3 range checks. We must leave the
+            // top test unchanged because widening it would allow the
+            // accesses it protects to successfully read/write out of
+            // bounds.
+            if (nb_checks == 2) {
+              return NULL;
+            }
+            int chk2 = (nb_checks - 3) % NRC;
+            RangeCheck rc2 = prev_checks[chk2];
+            // The top range check a+i covers interval: -a <= i < length-a
+            // The second range check b+i covers interval: -b <= i < length-b
+            if (rc1.off <= rc0.off) {
+              // if b <= a, we change the second range check to:
+              // -min_of_all_constants <= i < length-min_of_all_constants
+              // Together top and second range checks now cover:
+              // -min_of_all_constants <= i < length-a
+              // which is more restrictive than -b <= i < length-b:
+              // -b <= -min_of_all_constants <= i < length-a <= length-b
+              // The third check is then changed to:
+              // -max_of_all_constants <= i < length-max_of_all_constants
+              // so 2nd and 3rd checks restrict allowed values of i to:
+              // -min_of_all_constants <= i < length-max_of_all_constants
+              adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn);
+              adjust_check(rc2.ctl, range1, index1, flip1, off_hi, igvn);
+            } else {
+              // if b > a, we change the second range check to:
+              // -max_of_all_constants <= i < length-max_of_all_constants
+              // Together top and second range checks now cover:
+              // -a <= i < length-max_of_all_constants
+              // which is more restrictive than -b <= i < length-b:
+              // -b < -a <= i < length-max_of_all_constants <= length-b
+              // The third check is then changed to:
+              // -max_of_all_constants <= i < length-max_of_all_constants
+              // so 2nd and 3rd checks restrict allowed values of i to:
+              // -min_of_all_constants <= i < length-max_of_all_constants
+              adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn);
+              adjust_check(rc2.ctl, range1, index1, flip1, off_lo, igvn);
+            }
+            prev_dom = rc2.ctl;
+          }
+        }
+      } else {
+        RangeCheck rc0 = prev_checks[chk0];
+        // 'Widen' the offset of the 1st and only covering check
+        adjust_check(rc0.ctl, range1, index1, flip1, off_hi, igvn);
+        // Test is now covered by prior checks, dominate it out
+        prev_dom = rc0.ctl;
+      }
     }
 
-
   } else {                      // Scan for an equivalent test
 
     Node *cmp;
@@ -1019,7 +1082,7 @@
   // for lower and upper bounds.
   ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj();
   if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
-    prev_dom = idom;
+   prev_dom = idom;
 
   // Now walk the current IfNode's projections.
   // Loop ends when 'this' has no more uses.
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -241,8 +241,13 @@
   ProjNode* dp_proj  = dp->as_Proj();
   ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj();
   if (exclude_loop_predicate &&
-      unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
+      (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) ||
+       unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check))) {
+    // If this is a range check (IfNode::is_range_check), do not
+    // reorder because Compile::allow_range_check_smearing might have
+    // changed the check.
     return; // Let IGVN transformation change control dependence.
+  }
 
   IdealLoopTree *old_loop = get_loop(dp);
 
@@ -898,23 +903,23 @@
   int n_op = n->Opcode();
 
   // Check for an IF being dominated by another IF same test
-  if( n_op == Op_If ) {
+  if (n_op == Op_If) {
     Node *bol = n->in(1);
     uint max = bol->outcnt();
     // Check for same test used more than once?
-    if( n_op == Op_If && max > 1 && bol->is_Bool() ) {
+    if (max > 1 && bol->is_Bool()) {
       // Search up IDOMs to see if this IF is dominated.
       Node *cutoff = get_ctrl(bol);
 
       // Now search up IDOMs till cutoff, looking for a dominating test
       Node *prevdom = n;
       Node *dom = idom(prevdom);
-      while( dom != cutoff ) {
-        if( dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom ) {
+      while (dom != cutoff) {
+        if (dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom) {
           // Replace the dominated test with an obvious true or false.
           // Place it on the IGVN worklist for later cleanup.
           C->set_major_progress();
-          dominated_by( prevdom, n, false, true );
+          dominated_by(prevdom, n, false, true);
 #ifndef PRODUCT
           if( VerifyLoopOptimizations ) verify();
 #endif
--- a/hotspot/src/share/vm/opto/macro.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/opto/macro.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -971,7 +971,11 @@
 }
 
 bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
-  if (!EliminateAllocations || !alloc->_is_non_escaping) {
+  // Don't do scalar replacement if the frame can be popped by JVMTI:
+  // if reallocation fails during deoptimization we'll pop all
+  // interpreter frames for this compiled frame and that won't play
+  // nice with JVMTI popframe.
+  if (!EliminateAllocations || JvmtiExport::can_pop_frame() || !alloc->_is_non_escaping) {
     return false;
   }
   Node* klass = alloc->in(AllocateNode::KlassNode);
--- a/hotspot/src/share/vm/prims/whitebox.hpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.hpp	Thu Dec 11 16:22:47 2014 -0800
@@ -74,7 +74,7 @@
   static JavaThread* create_sweeper_thread(TRAPS);
   static int get_blob_type(const CodeBlob* code);
   static CodeHeap* get_code_heap(int blob_type);
-  static CodeBlob* allocate_code_blob(int blob_type, int size);
+  static CodeBlob* allocate_code_blob(int size, int blob_type);
   static int array_bytes_to_length(size_t bytes);
   static void register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread,
     JNINativeMethod* method_array, int method_count);
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -176,6 +176,8 @@
   assert(vf->is_compiled_frame(), "Wrong frame type");
   chunk->push(compiledVFrame::cast(vf));
 
+  bool realloc_failures = false;
+
 #ifdef COMPILER2
   // Reallocate the non-escaping objects and restore their fields. Then
   // relock objects if synchronization on them was eliminated.
@@ -206,19 +208,16 @@
           tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, (void *)result, thread);
         }
       }
-      bool reallocated = false;
       if (objects != NULL) {
         JRT_BLOCK
-          reallocated = realloc_objects(thread, &deoptee, objects, THREAD);
+          realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
         JRT_END
-      }
-      if (reallocated) {
-        reassign_fields(&deoptee, &map, objects);
+        reassign_fields(&deoptee, &map, objects, realloc_failures);
 #ifndef PRODUCT
         if (TraceDeoptimization) {
           ttyLocker ttyl;
           tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
-          print_objects(objects);
+          print_objects(objects, realloc_failures);
         }
 #endif
       }
@@ -236,7 +235,7 @@
         assert (cvf->scope() != NULL,"expect only compiled java frames");
         GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
         if (monitors->is_nonempty()) {
-          relock_objects(monitors, thread);
+          relock_objects(monitors, thread, realloc_failures);
 #ifndef PRODUCT
           if (TraceDeoptimization) {
             ttyLocker ttyl;
@@ -247,7 +246,12 @@
                   first = false;
                   tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
                 }
-                tty->print_cr("     object <" INTPTR_FORMAT "> locked", (void *)mi->owner());
+                if (mi->owner_is_scalar_replaced()) {
+                  Klass* k = java_lang_Class::as_Klass(mi->owner_klass());
+                  tty->print_cr("     failed reallocation for klass %s", k->external_name());
+                } else {
+                  tty->print_cr("     object <" INTPTR_FORMAT "> locked", (void *)mi->owner());
+                }
               }
             }
           }
@@ -262,9 +266,14 @@
   // out the java state residing in the vframeArray will be missed.
   No_Safepoint_Verifier no_safepoint;
 
-  vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk);
+  vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
+#ifdef COMPILER2
+  if (realloc_failures) {
+    pop_frames_failed_reallocs(thread, array);
+  }
+#endif
 
-  assert(thread->vframe_array_head() == NULL, "Pending deopt!");;
+  assert(thread->vframe_array_head() == NULL, "Pending deopt!");
   thread->set_vframe_array_head(array);
 
   // Now that the vframeArray has been created if we have any deferred local writes
@@ -718,6 +727,8 @@
   int exception_line = thread->exception_line();
   thread->clear_pending_exception();
 
+  bool failures = false;
+
   for (int i = 0; i < objects->length(); i++) {
     assert(objects->at(i)->is_object(), "invalid debug information");
     ObjectValue* sv = (ObjectValue*) objects->at(i);
@@ -727,27 +738,34 @@
 
     if (k->oop_is_instance()) {
       InstanceKlass* ik = InstanceKlass::cast(k());
-      obj = ik->allocate_instance(CHECK_(false));
+      obj = ik->allocate_instance(THREAD);
     } else if (k->oop_is_typeArray()) {
       TypeArrayKlass* ak = TypeArrayKlass::cast(k());
       assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length");
       int len = sv->field_size() / type2size[ak->element_type()];
-      obj = ak->allocate(len, CHECK_(false));
+      obj = ak->allocate(len, THREAD);
     } else if (k->oop_is_objArray()) {
       ObjArrayKlass* ak = ObjArrayKlass::cast(k());
-      obj = ak->allocate(sv->field_size(), CHECK_(false));
+      obj = ak->allocate(sv->field_size(), THREAD);
     }
 
-    assert(obj != NULL, "allocation failed");
+    if (obj == NULL) {
+      failures = true;
+    }
+
     assert(sv->value().is_null(), "redundant reallocation");
+    assert(obj != NULL || HAS_PENDING_EXCEPTION, "allocation should succeed or we should get an exception");
+    CLEAR_PENDING_EXCEPTION;
     sv->set_value(obj);
   }
 
-  if (pending_exception.not_null()) {
+  if (failures) {
+    THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), failures);
+  } else if (pending_exception.not_null()) {
     thread->set_pending_exception(pending_exception(), exception_file, exception_line);
   }
 
-  return true;
+  return failures;
 }
 
 // This assumes that the fields are stored in ObjectValue in the same order
@@ -885,12 +903,15 @@
 
 
 // restore fields of all eliminated objects and arrays
-void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects) {
+void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
   for (int i = 0; i < objects->length(); i++) {
     ObjectValue* sv = (ObjectValue*) objects->at(i);
     KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()));
     Handle obj = sv->value();
-    assert(obj.not_null(), "reallocation was missed");
+    assert(obj.not_null() || realloc_failures, "reallocation was missed");
+    if (obj.is_null()) {
+      continue;
+    }
 
     if (k->oop_is_instance()) {
       InstanceKlass* ik = InstanceKlass::cast(k());
@@ -907,34 +928,36 @@
 
 
 // relock objects for which synchronization was eliminated
-void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread) {
+void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures) {
   for (int i = 0; i < monitors->length(); i++) {
     MonitorInfo* mon_info = monitors->at(i);
     if (mon_info->eliminated()) {
-      assert(mon_info->owner() != NULL, "reallocation was missed");
-      Handle obj = Handle(mon_info->owner());
-      markOop mark = obj->mark();
-      if (UseBiasedLocking && mark->has_bias_pattern()) {
-        // New allocated objects may have the mark set to anonymously biased.
-        // Also the deoptimized method may called methods with synchronization
-        // where the thread-local object is bias locked to the current thread.
-        assert(mark->is_biased_anonymously() ||
-               mark->biased_locker() == thread, "should be locked to current thread");
-        // Reset mark word to unbiased prototype.
-        markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
-        obj->set_mark(unbiased_prototype);
+      assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed");
+      if (!mon_info->owner_is_scalar_replaced()) {
+        Handle obj = Handle(mon_info->owner());
+        markOop mark = obj->mark();
+        if (UseBiasedLocking && mark->has_bias_pattern()) {
+          // New allocated objects may have the mark set to anonymously biased.
+          // Also the deoptimized method may called methods with synchronization
+          // where the thread-local object is bias locked to the current thread.
+          assert(mark->is_biased_anonymously() ||
+                 mark->biased_locker() == thread, "should be locked to current thread");
+          // Reset mark word to unbiased prototype.
+          markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
+          obj->set_mark(unbiased_prototype);
+        }
+        BasicLock* lock = mon_info->lock();
+        ObjectSynchronizer::slow_enter(obj, lock, thread);
+        assert(mon_info->owner()->is_locked(), "object must be locked now");
       }
-      BasicLock* lock = mon_info->lock();
-      ObjectSynchronizer::slow_enter(obj, lock, thread);
     }
-    assert(mon_info->owner()->is_locked(), "object must be locked now");
   }
 }
 
 
 #ifndef PRODUCT
 // print information about reallocated objects
-void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects) {
+void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
   fieldDescriptor fd;
 
   for (int i = 0; i < objects->length(); i++) {
@@ -944,10 +967,15 @@
 
     tty->print("     object <" INTPTR_FORMAT "> of type ", (void *)sv->value()());
     k->print_value();
-    tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
+    assert(obj.not_null() || realloc_failures, "reallocation was missed");
+    if (obj.is_null()) {
+      tty->print(" allocation failed");
+    } else {
+      tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
+    }
     tty->cr();
 
-    if (Verbose) {
+    if (Verbose && !obj.is_null()) {
       k->oop_print_on(obj(), tty);
     }
   }
@@ -955,7 +983,7 @@
 #endif
 #endif // COMPILER2
 
-vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk) {
+vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
   Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp());
 
 #ifndef PRODUCT
@@ -998,7 +1026,7 @@
   // Since the Java thread being deoptimized will eventually adjust it's own stack,
   // the vframeArray containing the unpacking information is allocated in the C heap.
   // For Compiler1, the caller of the deoptimized frame is saved for use by unpack_frames().
-  vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr);
+  vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr, realloc_failures);
 
   // Compare the vframeArray to the collected vframes
   assert(array->structural_compare(thread, chunk), "just checking");
@@ -1013,6 +1041,33 @@
   return array;
 }
 
+#ifdef COMPILER2
+void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
+  // Reallocation of some scalar replaced objects failed. Record
+  // that we need to pop all the interpreter frames for the
+  // deoptimized compiled frame.
+  assert(thread->frames_to_pop_failed_realloc() == 0, "missed frames to pop?");
+  thread->set_frames_to_pop_failed_realloc(array->frames());
+  // Unlock all monitors here otherwise the interpreter will see a
+  // mix of locked and unlocked monitors (because of failed
+  // reallocations of synchronized objects) and be confused.
+  for (int i = 0; i < array->frames(); i++) {
+    MonitorChunk* monitors = array->element(i)->monitors();
+    if (monitors != NULL) {
+      for (int j = 0; j < monitors->number_of_monitors(); j++) {
+        BasicObjectLock* src = monitors->at(j);
+        if (src->obj() != NULL) {
+          ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread);
+        }
+      }
+      array->element(i)->free_monitors(thread);
+#ifdef ASSERT
+      array->element(i)->set_removed_monitors();
+#endif
+    }
+  }
+}
+#endif
 
 static void collect_monitors(compiledVFrame* cvf, GrowableArray<Handle>* objects_to_revoke) {
   GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp	Thu Dec 11 16:22:47 2014 -0800
@@ -125,13 +125,14 @@
   static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
   static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
   static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj);
-  static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
-  static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
-  NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
+  static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures);
+  static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
+  static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
+  NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
 #endif // COMPILER2
 
   public:
-  static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk);
+  static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);
 
   // Interface used for unpacking deoptimized frames
 
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -456,6 +456,7 @@
 
 address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) {
   assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address));
+  assert(thread->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?");
 
   // Reset method handle flag.
   thread->set_is_method_handle_return(false);
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -1448,6 +1448,7 @@
   _popframe_condition = popframe_inactive;
   _popframe_preserved_args = NULL;
   _popframe_preserved_args_size = 0;
+  _frames_to_pop_failed_realloc = 0;
 
   pd_initialize();
 }
--- a/hotspot/src/share/vm/runtime/thread.hpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Thu Dec 11 16:22:47 2014 -0800
@@ -908,6 +908,12 @@
   // This is set to popframe_pending to signal that top Java frame should be popped immediately
   int _popframe_condition;
 
+  // If reallocation of scalar replaced objects fails, we throw OOM
+  // and during exception propagation, pop the top
+  // _frames_to_pop_failed_realloc frames, the ones that reference
+  // failed reallocations.
+  int _frames_to_pop_failed_realloc;
+
 #ifndef PRODUCT
   int _jmp_ring_index;
   struct {
@@ -1567,6 +1573,10 @@
   void clr_pop_frame_in_process(void)                 { _popframe_condition &= ~popframe_processing_bit; }
 #endif
 
+  int frames_to_pop_failed_realloc() const            { return _frames_to_pop_failed_realloc; }
+  void set_frames_to_pop_failed_realloc(int nb)       { _frames_to_pop_failed_realloc = nb; }
+  void dec_frames_to_pop_failed_realloc()             { _frames_to_pop_failed_realloc--; }
+
  private:
   // Saved incoming arguments to popped frame.
   // Used only when popped interpreted frame returns to deoptimized frame.
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp	Thu Dec 11 16:22:47 2014 -0800
@@ -57,7 +57,7 @@
   }
 }
 
-void vframeArrayElement::fill_in(compiledVFrame* vf) {
+void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
 
 // Copy the information from the compiled vframe to the
 // interpreter frame we will be creating to replace vf
@@ -65,6 +65,9 @@
   _method = vf->method();
   _bci    = vf->raw_bci();
   _reexecute = vf->should_reexecute();
+#ifdef ASSERT
+  _removed_monitors = false;
+#endif
 
   int index;
 
@@ -82,11 +85,15 @@
     // Migrate the BasicLocks from the stack to the monitor chunk
     for (index = 0; index < list->length(); index++) {
       MonitorInfo* monitor = list->at(index);
-      assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already");
-      assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
+      assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
       BasicObjectLock* dest = _monitors->at(index);
-      dest->set_obj(monitor->owner());
-      monitor->lock()->move_to(monitor->owner(), dest->lock());
+      if (monitor->owner_is_scalar_replaced()) {
+        dest->set_obj(NULL);
+      } else {
+        assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
+        dest->set_obj(monitor->owner());
+        monitor->lock()->move_to(monitor->owner(), dest->lock());
+      }
     }
   }
 
@@ -111,7 +118,7 @@
     StackValue* value = locs->at(index);
     switch(value->type()) {
       case T_OBJECT:
-        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
+        assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
         // preserve object type
         _locals->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
         break;
@@ -136,7 +143,7 @@
     StackValue* value = exprs->at(index);
     switch(value->type()) {
       case T_OBJECT:
-        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
+        assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
         // preserve object type
         _expressions->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
         break;
@@ -287,7 +294,7 @@
 
   _frame.patch_pc(thread, pc);
 
-  assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors");
+  assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
 
   BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
   for (int index = 0; index < locks; index++) {
@@ -439,7 +446,8 @@
 
 
 vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
-                                   RegisterMap *reg_map, frame sender, frame caller, frame self) {
+                                   RegisterMap *reg_map, frame sender, frame caller, frame self,
+                                   bool realloc_failures) {
 
   // Allocate the vframeArray
   vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part
@@ -451,19 +459,20 @@
   result->_caller = caller;
   result->_original = self;
   result->set_unroll_block(NULL); // initialize it
-  result->fill_in(thread, frame_size, chunk, reg_map);
+  result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures);
   return result;
 }
 
 void vframeArray::fill_in(JavaThread* thread,
                           int frame_size,
                           GrowableArray<compiledVFrame*>* chunk,
-                          const RegisterMap *reg_map) {
+                          const RegisterMap *reg_map,
+                          bool realloc_failures) {
   // Set owner first, it is used when adding monitor chunks
 
   _frame_size = frame_size;
   for(int i = 0; i < chunk->length(); i++) {
-    element(i)->fill_in(chunk->at(i));
+    element(i)->fill_in(chunk->at(i), realloc_failures);
   }
 
   // Copy registers for callee-saved registers
--- a/hotspot/src/share/vm/runtime/vframeArray.hpp	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/src/share/vm/runtime/vframeArray.hpp	Thu Dec 11 16:22:47 2014 -0800
@@ -58,6 +58,9 @@
     MonitorChunk* _monitors;                                     // active monitors for this vframe
     StackValueCollection* _locals;
     StackValueCollection* _expressions;
+#ifdef ASSERT
+    bool _removed_monitors;
+#endif
 
   public:
 
@@ -78,7 +81,7 @@
 
   StackValueCollection* expressions(void) const        { return _expressions; }
 
-  void fill_in(compiledVFrame* vf);
+  void fill_in(compiledVFrame* vf, bool realloc_failures);
 
   // Formerly part of deoptimizedVFrame
 
@@ -99,6 +102,12 @@
                        bool is_bottom_frame,
                        int exec_mode);
 
+#ifdef ASSERT
+  void set_removed_monitors() {
+    _removed_monitors = true;
+  }
+#endif
+
 #ifndef PRODUCT
   void print(outputStream* st);
 #endif /* PRODUCT */
@@ -160,13 +169,14 @@
   int frames() const                            { return _frames;   }
 
   static vframeArray* allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
-                               RegisterMap* reg_map, frame sender, frame caller, frame self);
+                               RegisterMap* reg_map, frame sender, frame caller, frame self,
+                               bool realloc_failures);
 
 
   vframeArrayElement* element(int index)        { assert(is_within_bounds(index), "Bad index"); return &_elements[index]; }
 
   // Allocates a new vframe in the array and fills the array with vframe information in chunk
-  void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map);
+  void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map, bool realloc_failures);
 
   // Returns the owner of this vframeArray
   JavaThread* owner_thread() const           { return _owner_thread; }
--- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java	Thu Dec 11 16:22:47 2014 -0800
@@ -61,6 +61,7 @@
         String[] vmOpts = new String[] {
                 "-Xbootclasspath/p:" + testClasses,
                 "-Xcomp",
+                "-XX:+IgnoreUnrecognizedVMOptions",
                 "-XX:-VerifyDependencies",
                 "-XX:CompileOnly=TestMonomorphicObjectCall::callFinalize",
                 "-XX:CompileOnly=Object::finalizeObject",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/exceptions/SumTest.java	Thu Dec 11 16:22:47 2014 -0800
@@ -0,0 +1,86 @@
+/*
+ * 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 8066900
+ * @summary FP registers are not properly restored by C1 when handling exceptions
+ * @run main/othervm -Xbatch SumTest
+ *
+ */
+public class SumTest {
+    private static class Sum {
+
+        double[] sums;
+
+        /**
+         * Construct empty Sum
+         */
+        public Sum() {
+            sums = new double[0];
+        }
+
+        /**
+         * Return the sum of all numbers added to this Sum
+         *
+         * @return the sum
+         */
+        final public double getSum() {
+            double sum = 0;
+            for (final double s : sums) {
+                sum += s;
+            }
+
+            return sum;
+        }
+
+        /**
+         * Add a new number to this Sum
+         *
+         * @param a number to be added.
+         */
+        final public void add(double a) {
+            try {
+                sums[sums.length] = -1; // Cause IndexOutOfBoundsException
+            } catch (final IndexOutOfBoundsException e) {
+                final double[] oldSums = sums;
+                sums = new double[oldSums.length + 1]; // Extend sums
+                System.arraycopy(oldSums, 0, sums, 0, oldSums.length);
+                sums[oldSums.length] = a; // Append a
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        final Sum sum = new Sum();
+        for (int i = 1; i <= 10000; ++i) {
+            sum.add(1);
+            double ii = sum.getSum();
+            if (i != ii) {
+                throw new Exception("Failure: computed = " + ii + ", expected = " + i);
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java	Thu Dec 11 16:22:47 2014 -0800
@@ -0,0 +1,436 @@
+/*
+ * 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 8066103
+ * @summary C2's range check smearing allows out of bound array accesses
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox /testlibrary/com/oracle/java/testlibrary
+ * @build TestRangeCheckSmearing
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
+ * @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing
+ *
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import sun.hotspot.WhiteBox;
+import sun.hotspot.code.NMethod;
+import com.oracle.java.testlibrary.Platform;
+
+public class TestRangeCheckSmearing {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Args { int[] value(); }
+
+    // first range check is i + max of all constants
+    @Args({0, 8})
+    static int m1(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+9];
+        if (allaccesses) {
+            res += array[i+8];
+            res += array[i+7];
+            res += array[i+6];
+            res += array[i+5];
+            res += array[i+4];
+            res += array[i+3];
+            res += array[i+2];
+            res += array[i+1];
+        }
+        return res;
+    }
+
+    // first range check is i + min of all constants
+    @Args({0, -9})
+    static int m2(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+1];
+        if (allaccesses) {
+            res += array[i+2];
+            res += array[i+3];
+            res += array[i+4];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    // first range check is not i + min/max of all constants
+    @Args({0, 8})
+    static int m3(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        if (allaccesses) {
+            res += array[i+2];
+            res += array[i+1];
+            res += array[i+4];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    @Args({0, -9})
+    static int m4(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        if (allaccesses) {
+            res += array[i+4];
+            res += array[i+1];
+            res += array[i+2];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    @Args({0, -3})
+    static int m5(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i+2];
+        if (allaccesses) {
+            res += array[i+1];
+            res += array[i+4];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    @Args({0, 6})
+    static int m6(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i+4];
+        if (allaccesses) {
+            res += array[i+2];
+            res += array[i+1];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    @Args({0, 6})
+    static int m7(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i+2];
+        res += array[i+4];
+        if (allaccesses) {
+            res += array[i+1];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    @Args({0, -3})
+    static int m8(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i+4];
+        res += array[i+2];
+        if (allaccesses) {
+            res += array[i+1];
+            res += array[i+5];
+            res += array[i+6];
+            res += array[i+7];
+            res += array[i+8];
+            res += array[i+9];
+        }
+        return res;
+    }
+
+    @Args({6, 15})
+    static int m9(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        if (allaccesses) {
+            res += array[i-2];
+            res += array[i-1];
+            res += array[i-4];
+            res += array[i-5];
+            res += array[i-6];
+        }
+        return res;
+    }
+
+    @Args({3, 12})
+    static int m10(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        if (allaccesses) {
+            res += array[i-2];
+            res += array[i-1];
+            res += array[i-3];
+            res += array[i+4];
+            res += array[i+5];
+            res += array[i+6];
+        }
+        return res;
+    }
+
+    @Args({3, -3})
+    static int m11(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i-2];
+        if (allaccesses) {
+            res += array[i+5];
+            res += array[i+6];
+        }
+        return res;
+    }
+
+    @Args({3, 6})
+    static int m12(int[] array, int i, boolean allaccesses) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i+6];
+        if (allaccesses) {
+            res += array[i-2];
+            res += array[i-3];
+        }
+        return res;
+    }
+
+    // check that identical range check is replaced by dominating one
+    // only when correct
+    @Args({0})
+    static int m13(int[] array, int i, boolean ignore) {
+        int res = 0;
+        res += array[i+3];
+        res += array[i+3];
+        return res;
+    }
+
+    @Args({2, 0})
+    static int m14(int[] array, int i, boolean ignore) {
+        int res = 0;
+
+        res += array[i];
+        res += array[i-2];
+        res += array[i]; // If range check below were to be removed first this cannot be considered identical to first range check
+        res += array[i-1]; // range check removed so i-1 array access depends on previous check
+
+        return res;
+    }
+
+    static int[] m15_dummy = new int[10];
+    @Args({2, 0})
+    static int m15(int[] array, int i, boolean ignore) {
+        int res = 0;
+        res += array[i];
+
+        // When the loop is optimized out we don't want the
+        // array[i-1] access which is dependent on array[i]'s
+        // range check to become dependent on the identical range
+        // check above.
+
+        int[] array2 = m15_dummy;
+        int j = 0;
+        for (; j < 10; j++);
+        if (j == 10) {
+            array2 = array;
+        }
+
+        res += array2[i-2];
+        res += array2[i];
+        res += array2[i-1]; // range check removed so i-1 array access depends on previous check
+
+        return res;
+    }
+
+    @Args({2, 0})
+    static int m16(int[] array, int i, boolean ignore) {
+        int res = 0;
+
+        res += array[i];
+        res += array[i-1];
+        res += array[i-1];
+        res += array[i-2];
+
+        return res;
+    }
+
+    @Args({2, 0})
+    static int m17(int[] array, int i, boolean ignore) {
+        int res = 0;
+
+        res += array[i];
+        res += array[i-2];
+        res += array[i-2];
+        res += array[i+2];
+        res += array[i+2];
+        res += array[i-1];
+        res += array[i-1];
+
+        return res;
+    }
+
+    static public void main(String[] args) {
+        if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
+            throw new AssertionError("Background compilation enabled");
+        }
+        new TestRangeCheckSmearing().doTests();
+    }
+    boolean success = true;
+    boolean exception = false;
+    final int[] array = new int[10];
+    final HashMap<String,Method> tests = new HashMap<>();
+    {
+        final Class<?> TEST_PARAM_TYPES[] = { int[].class, int.class, boolean.class };
+        for (Method m : this.getClass().getDeclaredMethods()) {
+            if (m.getName().matches("m[0-9]+")) {
+                assert(Modifier.isStatic(m.getModifiers())) : m;
+                assert(m.getReturnType() == int.class) : m;
+                assert(Arrays.equals(m.getParameterTypes(), TEST_PARAM_TYPES)) : m;
+                tests.put(m.getName(), m);
+            }
+        }
+    }
+
+    void invokeTest(Method m, int[] array, int index, boolean z) {
+        try {
+            m.invoke(null, array, index, z);
+        } catch (ReflectiveOperationException roe) {
+            Throwable ex = roe.getCause();
+            if (ex instanceof ArrayIndexOutOfBoundsException)
+                throw (ArrayIndexOutOfBoundsException) ex;
+            throw new AssertionError(roe);
+        }
+    }
+
+    void doTest(String name) {
+        Method m = tests.get(name);
+        tests.remove(name);
+        int[] args = m.getAnnotation(Args.class).value();
+        int index0 = args[0], index1;
+        boolean exceptionRequired = true;
+        if (args.length == 2) {
+            index1 = args[1];
+        } else {
+            // no negative test for this one
+            assert(args.length == 1);
+            assert(name.equals("m13"));
+            exceptionRequired = false;
+            index1 = index0;
+        }
+        // Get the method compiled.
+        if (!WHITE_BOX.isMethodCompiled(m)) {
+            // If not, try to compile it with C2
+            if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
+                // C2 compiler not available, try to compile with C1
+                WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
+            }
+        }
+        if (!WHITE_BOX.isMethodCompiled(m)) {
+            throw new RuntimeException(m + " not compiled");
+        }
+
+        // valid access
+        invokeTest(m, array, index0, true);
+
+        if (!WHITE_BOX.isMethodCompiled(m)) {
+            throw new RuntimeException(m + " deoptimized on valid array access");
+        }
+
+        exception = false;
+        boolean test_success = true;
+        try {
+            invokeTest(m, array, index1, false);
+        } catch(ArrayIndexOutOfBoundsException aioob) {
+            exception = true;
+            System.out.println("ArrayIndexOutOfBoundsException thrown in "+name);
+        }
+        if (!exception) {
+            System.out.println("ArrayIndexOutOfBoundsException was not thrown in "+name);
+        }
+
+        if (Platform.isServer()) {
+            if (exceptionRequired == WHITE_BOX.isMethodCompiled(m)) {
+                System.out.println((exceptionRequired?"Didn't deoptimized":"deoptimized") + " in "+name);
+                test_success = false;
+            }
+        }
+
+        if (exception != exceptionRequired) {
+            System.out.println((exceptionRequired?"exception required but not thrown":"not exception required but thrown") + " in "+name);
+            test_success = false;
+        }
+
+        if (!test_success) {
+            success = false;
+            System.out.println("TEST FAILED: "+name);
+        }
+
+    }
+    void doTests() {
+        doTest("m1");
+        doTest("m2");
+        doTest("m3");
+        doTest("m4");
+        doTest("m5");
+        doTest("m6");
+        doTest("m7");
+        doTest("m8");
+        doTest("m9");
+        doTest("m10");
+        doTest("m11");
+        doTest("m12");
+        doTest("m13");
+        doTest("m14");
+        doTest("m15");
+        doTest("m16");
+        doTest("m17");
+        if (!success) {
+            throw new RuntimeException("Some tests failed");
+        }
+        assert(tests.isEmpty()) : tests;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearingLoopOpts.java	Thu Dec 11 16:22:47 2014 -0800
@@ -0,0 +1,76 @@
+/*
+ * 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 8048170
+ * @summary Following range check smearing, range check cannot be replaced by dominating identical test.
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearingLoopOpts
+ *
+ */
+public class TestRangeCheckSmearingLoopOpts {
+
+    static int dummy;
+
+    static int m1(int[] array, int i) {
+        for (;;) {
+            for (;;) {
+                if (array[i] < 0) { // range check (i+0) dominates equivalent check below
+                    break;
+                }
+                i++;
+            }
+
+            // A control flow that stops IfNode::up_one_dom()
+            if ((i % 2)== 0) {
+                if ((array[i] % 2) == 0) {
+                    dummy = i;
+                }
+            }
+
+            // IfNode::Ideal will rewrite some range checks if Compile::allow_range_check_smearing
+            if (array[i-1] == 9) {    // range check (i-1) unchanged
+                int res = array[i-3]; // range check (i-3) unchanged
+                res += array[i];      // range check (i+0) unchanged
+                res += array[i-2];    // removed redundant range check
+                // the previous access might be hoisted by
+                // PhaseIdealLoop::split_if_with_blocks_post because
+                // it appears to have the same guard, but it also
+                // depends on the previous guards
+                return res;
+            }
+            i++;
+        }
+    }
+
+    static public void main(String[] args) {
+        int[] array = { 0, 1, 2, -3, 4, 5, -2, 7, 8, 9, -1 };
+        for (int i = 0; i < 20000; i++) {
+            m1(array, 0);
+        }
+        array[0] = -1;
+        try {
+            m1(array, 0);
+        } catch(ArrayIndexOutOfBoundsException aioobe) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/uncommontrap/TestDeoptOOM.java	Thu Dec 11 16:22:47 2014 -0800
@@ -0,0 +1,426 @@
+/*
+ * 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 6898462
+ * @summary failed reallocations of scalar replaced objects during deoptimization causes crash
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=exclude,TestDeoptOOM::main -XX:CompileCommand=exclude,TestDeoptOOM::m9_1 -Xmx128M TestDeoptOOM
+ *
+ */
+
+public class TestDeoptOOM {
+
+    long f1;
+    long f2;
+    long f3;
+    long f4;
+    long f5;
+
+    static class LinkedList {
+        LinkedList l;
+        long[] array;
+        LinkedList(LinkedList l, int size) {
+            array = new long[size];
+            this.l = l;
+        }
+    }
+
+    static LinkedList ll;
+
+    static void consume_all_memory() {
+        int size = 128 * 1024 * 1024;
+        while(size > 0) {
+            try {
+                while(true) {
+                    ll = new LinkedList(ll, size);
+                }
+            } catch(OutOfMemoryError oom) {
+            }
+            size = size / 2;
+        }
+    }
+
+    static void free_memory() {
+        ll = null;
+    }
+
+    static TestDeoptOOM m1(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            if (deopt) {
+                return tdoom;
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m1");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m2_1(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            if (deopt) {
+                return tdoom;
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m2_1");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m2(boolean deopt) {
+        try {
+            return m2_1(deopt);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m2");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m3_3(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            if (deopt) {
+                return tdoom;
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m3_3");
+        }
+        return null;
+    }
+
+    static boolean m3_2(boolean deopt) {
+        try {
+            return m3_3(deopt) != null;
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m3_2");
+        }
+        return false;
+    }
+
+    static TestDeoptOOM m3_1(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            if (m3_2(deopt)) {
+                return tdoom;
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m3_1");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m3(boolean deopt) {
+        try {
+            return m3_1(deopt);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m3");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m4(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            if (deopt) {
+                tdoom.f1 = 1l;
+                tdoom.f2 = 2l;
+                tdoom.f3 = 3l;
+                return tdoom;
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m4");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m5(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            synchronized(tdoom) {
+                if (deopt) {
+                    return tdoom;
+                }
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m5");
+        }
+        return null;
+    }
+
+    synchronized TestDeoptOOM m6_1(boolean deopt) {
+        if (deopt) {
+            return this;
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m6(boolean deopt) {
+        try {
+            TestDeoptOOM tdoom = new TestDeoptOOM();
+            return tdoom.m6_1(deopt);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m6");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m7_1(boolean deopt, Object lock) {
+        try {
+            synchronized(lock) {
+                TestDeoptOOM tdoom = new TestDeoptOOM();
+                if (deopt) {
+                    return tdoom;
+                }
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m7_1");
+        }
+        return null;
+    }
+
+    static TestDeoptOOM m7(boolean deopt, Object lock) {
+        try {
+            return m7_1(deopt, lock);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m7");
+        }
+        return null;
+    }
+
+    static class A {
+        long f1;
+        long f2;
+        long f3;
+        long f4;
+        long f5;
+    }
+
+    static class B {
+        long f1;
+        long f2;
+        long f3;
+        long f4;
+        long f5;
+
+        A a;
+    }
+
+    static B m8(boolean deopt) {
+        try {
+            A a = new A();
+            B b = new B();
+            b.a = a;
+            if (deopt) {
+                return b;
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m8");
+        }
+        return null;
+    }
+
+    static void m9_1(int i) {
+        if (i > 90000) {
+            consume_all_memory();
+        }
+    }
+
+    static TestDeoptOOM m9() {
+        try {
+            for (int i = 0; i < 100000; i++) {
+                TestDeoptOOM tdoom = new TestDeoptOOM();
+                m9_1(i);
+                if (i > 90000) {
+                    return tdoom;
+                }
+            }
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in m1");
+        }
+        return null;
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 20000; i++) {
+            m1(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m1(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main " + oom.getMessage());
+        }
+
+        free_memory();
+
+        for (int i = 0; i < 20000; i++) {
+            m2(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m2(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        for (int i = 0; i < 20000; i++) {
+            m3(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m3(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        for (int i = 0; i < 20000; i++) {
+            m4(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m4(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        for (int i = 0; i < 20000; i++) {
+            m5(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m5(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        for (int i = 0; i < 20000; i++) {
+            m6(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m6(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        final Object lock = new Object();
+
+        for (int i = 0; i < 20000; i++) {
+            m7(false, lock);
+        }
+
+        consume_all_memory();
+
+        try {
+            m7(true, lock);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        Thread thread = new Thread() {
+                public void run() {
+                    System.out.println("Acquiring lock");
+                    synchronized(lock) {
+                        System.out.println("Lock acquired");
+                    }
+                    System.out.println("Lock released");
+                }
+            };
+        thread.start();
+        try {
+            thread.join();
+        } catch(InterruptedException ie) {
+        }
+
+        for (int i = 0; i < 20000; i++) {
+            m8(false);
+        }
+
+        consume_all_memory();
+
+        try {
+            m8(true);
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+
+        try {
+            m9();
+        } catch(OutOfMemoryError oom) {
+            free_memory();
+            System.out.println("OOM caught in main");
+        }
+
+        free_memory();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java	Thu Dec 11 16:22:47 2014 -0800
@@ -0,0 +1,47 @@
+/*
+ * 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 8067144
+ * @summary -XX:+TraceDeoptimization tries to print realloc'ed objects even when there are none
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceDeoptimization TraceDeoptimizationNoRealloc
+ *
+ */
+
+public class TraceDeoptimizationNoRealloc {
+
+    static void m(boolean some_condition) {
+        if (some_condition) {
+            return;
+        }
+    }
+
+
+    static public void main(String[] args) {
+        for (int i = 0; i < 20000; i++) {
+            m(false);
+        }
+        m(true);
+    }
+}
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu Dec 11 20:39:25 2014 +0100
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu Dec 11 16:22:47 2014 -0800
@@ -153,6 +153,14 @@
   public native int     getMethodEntryBci(Executable method);
   public native Object[] getNMethod(Executable method, boolean isOsr);
   public native long    allocateCodeBlob(int size, int type);
+  public        long    allocateCodeBlob(long size, int type) {
+      int intSize = (int) size;
+      if ((long) intSize != size || size < 0) {
+          throw new IllegalArgumentException(
+                "size argument has illegal value " + size);
+      }
+      return allocateCodeBlob( intSize, type);
+  }
   public native void    freeCodeBlob(long addr);
   public        void    forceNMethodSweep() {
     try {