diff a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp
--- a/src/hotspot/share/opto/macro.cpp
+++ b/src/hotspot/share/opto/macro.cpp
@@ -301,10 +301,17 @@
       } else {
         assert(adr_idx == Compile::AliasIdxRaw, "address must match or be raw");
       }
       mem = mem->in(MemNode::Memory);
     } else if (mem->is_ClearArray()) {
+      intptr_t offset;
+      AllocateNode* alloc = AllocateNode::Ideal_allocation(mem->in(3), phase, offset);
+
+      if (alloc == NULL) {
+        return start_mem;
+      }
+
       if (!ClearArrayNode::step_through(&mem, alloc->_idx, phase)) {
         // Can not bypass initialization of the instance
         // we are looking.
         debug_only(intptr_t offset;)
         assert(alloc == AllocateNode::Ideal_allocation(mem->in(3), phase, offset), "sanity");
@@ -725,11 +732,11 @@
       }
     }
   }
 
 #ifndef PRODUCT
-  if (PrintEliminateAllocations) {
+  if (print_eliminate_allocations()) {
     if (can_eliminate) {
       tty->print("Scalar ");
       if (res == NULL)
         alloc->dump();
       else
@@ -750,10 +757,22 @@
   }
 #endif
   return can_eliminate;
 }
 
+void PhaseMacroExpand::adjust_safepoint_jvms(SafePointNode* sfpt, Node* res, SafePointScalarObjectNode* sobj) {
+  JVMState *jvms = sfpt->jvms();
+  jvms->set_endoff(sfpt->req());
+
+  // Now make a pass over the debug information replacing any references
+  // to the allocated object with "sobj"
+  int start = jvms->debug_start();
+  int end   = jvms->debug_end();
+  sfpt->replace_edges_in_range(res, sobj, start, end);
+  _igvn._worklist.push(sfpt);
+}
+
 // Do scalar replacement.
 bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) {
   GrowableArray <SafePointNode *> safepoints_done;
 
   ciKlass* klass = NULL;
@@ -882,11 +901,11 @@
             }
           }
           _igvn._worklist.push(sfpt_done);
         }
 #ifndef PRODUCT
-        if (PrintEliminateAllocations) {
+        if (print_eliminate_allocations()) {
           if (field != NULL) {
             tty->print("=== At SafePoint node %d can't find value of Field: ",
                        sfpt->_idx);
             field->print();
             int field_idx = C->get_alias_index(field_addr_type);
@@ -913,18 +932,11 @@
           field_val = transform_later(new DecodeNNode(field_val, field_val->get_ptr_type()));
         }
       }
       sfpt->add_req(field_val);
     }
-    JVMState *jvms = sfpt->jvms();
-    jvms->set_endoff(sfpt->req());
-    // Now make a pass over the debug information replacing any references
-    // to the allocated object with "sobj"
-    int start = jvms->debug_start();
-    int end   = jvms->debug_end();
-    sfpt->replace_edges_in_range(res, sobj, start, end);
-    _igvn._worklist.push(sfpt);
+    adjust_safepoint_jvms(sfpt, res, sobj);
     safepoints_done.append_if_missing(sfpt); // keep it for rollback
   }
   return true;
 }
 
@@ -1016,10 +1028,14 @@
     }
     assert(res->outcnt() == 0, "all uses of allocated objects must be deleted");
     _igvn.remove_dead_node(res);
   }
 
+  eliminate_unused_allocation_edges(alloc);
+}
+
+void PhaseMacroExpand::eliminate_unused_allocation_edges(CallNode* alloc) {
   //
   // Process other users of allocation's projections
   //
   if (_resproj != NULL && _resproj->outcnt() != 0) {
     // First disconnect stores captured by Initialize node.
@@ -1084,10 +1100,492 @@
   if (_catchallcatchproj != NULL) {
     _igvn.replace_node(_catchallcatchproj, C->top());
   }
 }
 
+#define STACK_REG_BUFFER 4
+
+bool PhaseMacroExpand::stack_allocation_location_representable(int slot_location) {
+  // TODO This is likely not enough as there are values on the stack above the fixed slots
+  // Revist to see if there is a better check
+  OptoReg::Name stack_reg = OptoReg::stack2reg(slot_location + STACK_REG_BUFFER);
+  if (RegMask::can_represent(stack_reg)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+#undef STACK_REG_BUFFER
+
+int PhaseMacroExpand::next_stack_allocated_object(int num_slots) {
+  int current = C->fixed_slots();
+  int next    = current + num_slots;
+  if (!stack_allocation_location_representable(next)) {
+    return -1;
+  }
+  // Keep the toplevel high water mark current:
+  if (C->fixed_slots() < next) C->set_fixed_slots(next);
+  return current;
+}
+
+bool PhaseMacroExpand::process_write_barriers_on_stack_allocated_objects(AllocateNode* alloc) {
+  GrowableArray<Node*> barriers;
+  Node *res = alloc->result_cast();
+  assert(res != NULL, "result node must not be null");
+
+  // Find direct barriers on the stack allocated objects.
+  // Those we can simply eliminate.
+  for (DUIterator_Fast imax, i = res->fast_outs(imax); i < imax; i++) {
+    Node *use = res->fast_out(i);
+    if (use->Opcode() == Op_CastP2X) {
+      barriers.append_if_missing(use);
+    } else if (use->is_AddP()) {
+      for (DUIterator_Fast jmax, j = use->fast_outs(jmax); j < jmax; j++) {
+        Node *addp_out = use->fast_out(j);
+        if (addp_out->Opcode() == Op_CastP2X) {
+          barriers.append_if_missing(addp_out);
+        }
+      }
+    }
+  }
+
+  while (barriers.length() != 0) {
+    eliminate_gc_barrier(barriers.pop());
+  }
+
+  // After removing the direct barriers result may no longer be used
+  if (alloc->result_cast() == NULL) {
+    return true;
+  }
+
+  // Next walk all uses of the allocate to discover the barriers that
+  // might be reachable from our allocate. If the barrier is reachable
+  // from stack allocated object, we unregister it, so that the check
+  // elimination code doesn't run on it.
+  VectorSet visited(Thread::current()->resource_area());
+  GrowableArray<Node*> node_worklist;
+
+  BarrierSetC2 *bs = BarrierSet::barrier_set()->barrier_set_c2();
+
+  node_worklist.push(res);
+
+  while(node_worklist.length() != 0) {
+    Node* n = node_worklist.pop();
+
+    if (visited.test_set(n->_idx)) {
+      continue;  // already processed
+    }
+
+    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+      Node *use = n->fast_out(i);
+      if (use->Opcode() == Op_CastP2X) {
+        bs->unregister_potential_barrier_node(use);
+      } else if (use->is_Phi() ||
+                 use->is_CheckCastPP() ||
+                 use->is_EncodeP() ||
+                 use->is_DecodeN() ||
+                 use->is_SafePoint() ||
+                 use->is_Proj() ||
+                 (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
+        // Find barriers beyond our current result
+        node_worklist.push(use);
+      } else if (use->is_Store() && use->Opcode() == Op_StoreP) {
+        if (n != use->in(MemNode::ValueIn)) {
+          continue;
+        }
+        // TODO code copied from escape.cpp::ConnectionGraph::get_addp_base.
+        // Common up this code into a helper
+        Node *memory = use->in(MemNode::Address);
+        if (memory->is_AddP()) {
+          Node *base = memory->in(AddPNode::Base);
+          if (base->uncast()->is_top()) { // The AddP case #3 and #6 and #9.
+            base = memory->in(AddPNode::Address);
+            while (base->is_AddP()) {
+              // Case #6 (unsafe access) may have several chained AddP nodes.
+              assert(base->in(AddPNode::Base)->uncast()->is_top(), "expected unsafe access address only");
+              base = base->in(AddPNode::Address);
+            }
+            if (base->Opcode() == Op_CheckCastPP &&
+                base->bottom_type()->isa_rawptr() &&
+                _igvn.type(base->in(1))->isa_oopptr()) {
+              base = base->in(1); // Case #9
+            }
+          }
+          node_worklist.push(base);
+        }
+      } else if (use->is_AddP() ||
+           (use->is_Load() && use->Opcode() == Op_LoadP)) {
+        // Find barriers for loads
+        node_worklist.push(use);
+      }
+    }
+  }
+  return false;
+}
+
+bool PhaseMacroExpand::register_stack_allocated_object_with_safepoints(AllocateNode* alloc, Node* stack_oop) {
+  VectorSet visited(Thread::current()->resource_area());
+  GrowableArray<Node*> node_worklist;
+  GrowableArray<SafePointNode*> temp;
+  Dict* safepoint_map = new Dict(cmpkey, hashkey);
+  bool found_non_direct_safepoint = false;
+  Node *res = alloc->result_cast();
+
+  assert(res != NULL, "result node must not be null");
+
+  node_worklist.push(res);
+
+  while(node_worklist.length() != 0) {
+    Node* n = node_worklist.pop();
+
+    if (visited.test_set(n->_idx)) {
+      continue;  // already processed
+    }
+
+    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+      Node *use = n->fast_out(i);
+      if (use->is_SafePoint()) {
+        SafePointNode* sfpt = use->as_SafePoint();
+        if (sfpt->jvms() != NULL) {
+          temp.push(sfpt);
+        }
+      } else if (use->is_Phi() ||
+          use->is_CheckCastPP() ||
+          use->is_EncodeP() ||
+          use->is_DecodeN() ||
+          use->is_Proj() ||
+          (use->Opcode() == Op_CastP2X) ||
+          use->is_MergeMem() ||
+          use->is_MemBar() ||
+          (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
+        // Find safepoints beyond our current result
+        node_worklist.push(use);
+      } else if (use->is_Store() && use->Opcode() == Op_StoreP) {
+        node_worklist.push(use);
+        if (n != use->in(MemNode::ValueIn)) {
+          continue;
+        }
+        // TODO code copied from escape.cpp::ConnectionGraph::get_addp_base.
+        // Common up this code into a helper
+        Node *memory = use->in(MemNode::Address);
+        if (memory->is_AddP()) {
+          Node *base = memory->in(AddPNode::Base);
+          if (base->uncast()->is_top()) { // The AddP case #3 and #6 and #9.
+            base = memory->in(AddPNode::Address);
+            while (base->is_AddP()) {
+              // Case #6 (unsafe access) may have several chained AddP nodes.
+              assert(base->in(AddPNode::Base)->uncast()->is_top(), "expected unsafe access address only");
+              base = base->in(AddPNode::Address);
+            }
+            if (base->Opcode() == Op_CheckCastPP &&
+                base->bottom_type()->isa_rawptr() &&
+                _igvn.type(base->in(1))->isa_oopptr()) {
+              base = base->in(1); // Case #9
+            }
+          }
+          node_worklist.push(base);
+        }
+      } else if (use->is_AddP() ||
+        (use->is_Load() && use->Opcode() == Op_LoadP)) {
+        // Find safepoints for arrays
+        node_worklist.push(use);
+      }
+    }
+
+    while (temp.length() != 0) {
+      SafePointNode* sfpt = temp.pop();
+      if (res != n) {
+        found_non_direct_safepoint = true;
+      }
+      handle_safepoint_for_stack_allocation(safepoint_map, alloc, stack_oop, n, sfpt);
+    }
+  }
+
+  return found_non_direct_safepoint;
+}
+
+void PhaseMacroExpand::handle_safepoint_for_stack_allocation(Dict* safepoint_map, AllocateNode* alloc, Node* oop_node, Node* parent, SafePointNode* sfpt) {
+  Node* res = alloc->result_cast();
+  assert(res->is_CheckCastPP(), "unexpected AllocateNode result");
+  const TypeOopPtr* res_type = _igvn.type(res)->isa_oopptr();
+  ciKlass* klass = res_type->klass();
+  int nfields = 0;
+  if (res_type->isa_instptr()) {
+    // find the fields of the class which will be needed for safepoint debug information
+    assert(klass->is_instance_klass(), "must be an instance klass.");
+    ciInstanceKlass* iklass = klass->as_instance_klass();
+    nfields = iklass->nof_nonstatic_fields();
+  } else {
+    // find the array's elements which will be needed for safepoint debug information
+    nfields = alloc->in(AllocateNode::ALength)->find_int_con(-1);
+  }
+
+  assert(nfields >= 0, "Sanity");
+
+  SafePointScalarObjectNode* sobj = NULL;
+  Node *result = (Node *)(*safepoint_map)[sfpt];
+  if (result != NULL) {
+    assert(result->is_SafePointScalarObject(), "Has to be a safepointscalarobject");
+    sobj = result->as_SafePointScalarObject();
+  } else {
+    //
+    // Process the safepoint uses
+    //
+    Node* mem = sfpt->memory();
+    Node* ctl = sfpt->control();
+    assert(sfpt->jvms() != NULL, "missed JVMS");
+    // Fields of scalar objs are referenced only at the end
+    // of regular debuginfo at the last (youngest) JVMS.
+    // Record relative start index.
+    uint first_ind = (sfpt->req() - sfpt->jvms()->scloff());
+    sobj = new SafePointScalarObjectNode(res_type,
+#ifdef ASSERT
+                                                alloc,
+#endif
+                                                first_ind, nfields);
+    sobj->init_req(0, C->root());
+    sobj->add_req(oop_node);
+    transform_later(sobj);
+    sobj->set_stack_allocated(true);
+
+    JVMState *jvms = sfpt->jvms();
+    sfpt->add_req(sobj);
+    jvms->set_endoff(sfpt->req());
+    _igvn._worklist.push(sfpt);
+    safepoint_map->Insert(sfpt, sobj);
+  }
+
+  if (parent == res) {
+    adjust_safepoint_jvms(sfpt, parent, sobj);
+  }
+}
+
+bool PhaseMacroExpand::can_stack_allocate(AllocateNode* alloc, Node* res, intptr_t size_of_object) {
+  return ((res != NULL) && alloc->_is_stack_allocateable && (size_of_object != -1) && should_stack_allocate());
+}
+
+void PhaseMacroExpand::estimate_stack_allocation_size(AllocateNode* alloc) {
+  Node* res                  = alloc->result_cast();
+  Node* size_in_bytes        = alloc->in(AllocateNode::AllocSize);
+  intptr_t size_of_object    = _igvn.find_intptr_t_con(size_in_bytes, -1);
+
+  if (alloc->_is_scalar_replaceable && !alloc->_is_stack_allocateable) {
+    C->set_fail_stack_allocation_with_references(true);
+    return;
+  }
+
+  bool can_sa = can_stack_allocate(alloc, res, size_of_object);
+  if (alloc->_is_stack_allocateable && !can_sa) {
+    // If we marked the object as SA in EA and now we can not fail
+    C->set_fail_stack_allocation_with_references(true);
+    return;
+  }
+
+  if (!alloc->_is_stack_allocateable) {
+    // If we can not SA because EA said no then no need to count the size
+    return;
+  }
+
+  int current = C->stack_allocated_slots();
+  C->set_stack_allocated_slots(current + (size_of_object >> LogBytesPerInt));
+}
+
+// Do stack allocation
+bool PhaseMacroExpand::stack_allocation(AllocateNode* alloc) {
+  Node* klass                = alloc->in(AllocateNode::KlassNode);
+  const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr();
+  Node *length               = (alloc->is_AllocateArray()) ? alloc->in(AllocateNode::ALength) : NULL;
+  Node* size_in_bytes        = alloc->in(AllocateNode::AllocSize);
+  Node* res                  = alloc->result_cast();
+  Node* ctrl                 = alloc->in(TypeFunc::Control);
+  Node* mem                  = alloc->in(TypeFunc::Memory);
+
+  intptr_t size_of_object = _igvn.find_intptr_t_con(size_in_bytes, -1);
+
+  if (!can_stack_allocate(alloc, res, size_of_object)) {
+    return false;
+  }
+
+  if (C->fail_stack_allocation_with_references()) {
+    if (alloc->_is_referenced_stack_allocation) {
+#ifndef PRODUCT
+      if (print_stack_allocation()) {
+        tty->print_cr("---- Avoiding stack allocation on node %d because it is referenced by another alloc and SCR/SA failed in method %s", alloc->_idx, _igvn.C->method()->get_Method()->name_and_sig_as_C_string());
+      }
+#endif
+    return false;
+    }
+  }
+
+  int next_stack_allocation_slot = next_stack_allocated_object(size_of_object >> LogBytesPerInt);
+  if (next_stack_allocation_slot < 0) {
+#ifndef PRODUCT
+    if (print_stack_allocation()) {
+      tty->print_cr("---- Avoiding stack allocation on node %d with size %ld for method %s because of insufficient stack space", alloc->_idx, size_of_object, _igvn.C->method()->get_Method()->name_and_sig_as_C_string());
+    }
+#endif
+    return false;
+  }
+
+  if (mem->is_MergeMem()) {
+    mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw);
+  }
+
+  extract_call_projections(alloc);
+
+  // Process barriers as this may result in result_cast() becoming NULL
+  if (process_write_barriers_on_stack_allocated_objects(alloc)) {
+#ifndef PRODUCT
+    if (print_stack_allocation()) {
+      tty->print_cr("---- Allocation %d result_cast is no longer used so yank the alloc instead", alloc->_idx);
+    }
+#endif
+    InitializeNode* init = alloc->initialization();
+    if (init != NULL) {
+      init->remove(&_igvn);
+    }
+    yank_alloc_node(alloc);
+    return true;
+  }
+
+  assert(res == alloc->result_cast(), "values much match");
+
+  Node* stack_oop = transform_later(new BoxLockNode(next_stack_allocation_slot));
+  Node* new_raw_mem = initialize_object(alloc, ctrl, mem, stack_oop, klass, length, size_in_bytes);
+
+  bool non_direct_safepoints = register_stack_allocated_object_with_safepoints(alloc, stack_oop);
+  if (non_direct_safepoints) {
+    if (length != NULL) {
+      stack_allocation_init_array_length_on_entry(alloc, length, stack_oop);
+    }
+#ifndef PRODUCT
+    stack_allocation_clear_object_data(alloc, stack_oop);
+#endif
+  }
+
+  _igvn.replace_node(_resproj, stack_oop);
+
+  for (DUIterator_Fast imax, i = _memproj_fallthrough->fast_outs(imax); i < imax; i++) {
+    Node *use = _memproj_fallthrough->fast_out(i);
+    _igvn.rehash_node_delayed(use);
+    imax -= replace_input(use, _memproj_fallthrough, new_raw_mem);
+    // back up iterator
+    --i;
+  }
+
+  eliminate_unused_allocation_edges(alloc);
+
+  assert(_resproj->outcnt() == 0, "all uses of the original allocate result projection must be deleted");
+  _igvn.remove_dead_node(_resproj);
+
+#ifndef PRODUCT
+  if (print_stack_allocation()) {
+    tty->print_cr("++++ Performing stack allocation on node %d with size %ld for method %s", alloc->_idx, size_of_object, _igvn.C->method()->get_Method()->name_and_sig_as_C_string());
+  }
+#endif
+
+  return true;
+}
+
+/*
+  Initialize stack allocated array length on entry to the method.
+  This is required for de-opt so it can verify array lengths and so
+  that GCs that happen after deopt will not crash for uninitialized
+  arrays.
+*/
+void PhaseMacroExpand::stack_allocation_init_array_length_on_entry(AllocateNode *alloc, Node *length, Node *stack_oop) {
+  Node* start_mem = C->start()->proj_out_or_null(TypeFunc::Memory);
+  assert(length != NULL, "Length can not be NULL");
+
+  if (C->is_osr_compilation()) {
+    for (DUIterator_Fast imax, i = start_mem->fast_outs(imax); i < imax; i++) {
+      Node *child = start_mem->fast_out(i);
+      if (child->is_CallLeaf() && child->as_CallLeaf()->is_call_to_osr_migration_end()) {
+        CallLeafNode* call_leaf = child->as_CallLeaf();
+        start_mem = call_leaf->proj_out_or_null(TypeFunc::Memory);
+        break;
+      }
+    }
+  }
+  assert(start_mem != NULL, "Must find start mem");
+  Node* init_mem = start_mem;
+
+  // need to set the length field for arrays for deopt
+  init_mem = make_store(C->start()->proj_out_or_null(TypeFunc::Control),
+                        init_mem, stack_oop, arrayOopDesc::length_offset_in_bytes(),
+                        length, T_INT);
+
+
+  if (init_mem != start_mem) {
+    for (DUIterator_Fast imax, i = start_mem->fast_outs(imax); i < imax; i++) {
+      Node *use = start_mem->fast_out(i);
+      // Compressed refs can make a new store which adjusts the start
+      // offet and it's sourced by start_mem. Make sure we don't make cycle.
+      if (use == init_mem || (init_mem->find_edge(use) >= 0)) {
+        continue;
+      }
+      _igvn.rehash_node_delayed(use);
+      imax -= replace_input(use, start_mem, init_mem);
+      // back up iterator
+      --i;
+    }
+  }
+}
+
+#ifndef PRODUCT
+/*
+  Initialize SA object on entry to the method to ensure it is initialized
+  before safepoints which may only be reachable through phis and the object
+  may not actually have been initialized.
+*/
+void PhaseMacroExpand::stack_allocation_clear_object_data(AllocateNode *alloc, Node *stack_oop) {
+  Node* klass                = alloc->in(AllocateNode::KlassNode);
+  Node *length               = (alloc->is_AllocateArray()) ? alloc->in(AllocateNode::ALength) : NULL;
+  Node* size_in_bytes        = alloc->in(AllocateNode::AllocSize);
+  Node* start_mem            = C->start()->proj_out_or_null(TypeFunc::Memory);
+  if (C->is_osr_compilation()) {
+    for (DUIterator_Fast imax, i = start_mem->fast_outs(imax); i < imax; i++) {
+      Node *child = start_mem->fast_out(i);
+      if (child->is_CallLeaf() && child->as_CallLeaf()->is_call_to_osr_migration_end()) {
+        CallLeafNode* call_leaf = child->as_CallLeaf();
+        start_mem = call_leaf->proj_out_or_null(TypeFunc::Memory);
+        break;
+      }
+    }
+  }
+  assert(start_mem != NULL, "Must find start mem");
+  int header_size = alloc->minimum_header_size();
+  Node* init_mem = start_mem;
+  if (length != NULL) {
+    // conservatively small header size:
+    header_size = arrayOopDesc::base_offset_in_bytes(T_BYTE);
+    ciKlass* k = _igvn.type(klass)->is_klassptr()->klass();
+    if (k->is_array_klass()) {   // we know the exact header size in most cases:
+      header_size = Klass::layout_helper_header_size(k->layout_helper());
+    }
+  }
+  init_mem = ClearArrayNode::clear_memory(C->start()->proj_out_or_null(TypeFunc::Control),
+                                          init_mem, stack_oop, header_size, size_in_bytes,
+                                          &_igvn);
+  if (init_mem != start_mem) {
+    for (DUIterator_Fast imax, i = start_mem->fast_outs(imax); i < imax; i++) {
+      Node *use = start_mem->fast_out(i);
+      // Compressed refs can make a new store which adjusts the start
+      // offet and it's sourced by start_mem. Make sure we don't make cycle.
+      if (use == init_mem || (init_mem->find_edge(use) >= 0)) {
+        continue;
+      }
+      _igvn.rehash_node_delayed(use);
+      imax -= replace_input(use, start_mem, init_mem);
+      // back up iterator
+      --i;
+    }
+  }
+}
+#endif
+
 bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
   // 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.
@@ -1140,11 +1638,11 @@
   }
 
   process_users_of_allocation(alloc);
 
 #ifndef PRODUCT
-  if (PrintEliminateAllocations) {
+  if (print_eliminate_allocations()) {
     if (alloc->is_AllocateArray())
       tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx);
     else
       tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx);
   }
@@ -1181,11 +1679,11 @@
   }
 
   process_users_of_allocation(boxing);
 
 #ifndef PRODUCT
-  if (PrintEliminateAllocations) {
+  if (print_eliminate_allocations()) {
     tty->print("++++ Eliminated: %d ", boxing->_idx);
     boxing->method()->print_short_name(tty);
     tty->cr();
   }
 #endif
@@ -2777,10 +3275,30 @@
     _igvn.optimize();
     if (C->failing())  return true;
     _igvn.set_delay_transform(true);
   }
 
+  for (int i = C->macro_count(); i > 0; i --) {
+    Node * n = C->macro_node(i-1);
+    assert(n->is_macro(), "only macro nodes expected here");
+
+    switch (n->class_id()) {
+    case Node::Class_Allocate:
+    case Node::Class_AllocateArray:
+      estimate_stack_allocation_size(n->as_Allocate());
+      break;
+    default:
+      assert(false, "unknown node type in macro list");
+    }
+  }
+
+  // Check to see if stack allocation size is too large before macro expansion
+  // so we can reject required stack allocations
+  if (!stack_allocation_location_representable(C->fixed_slots() + C->stack_allocated_slots())) {
+    C->set_fail_stack_allocation_with_references(true);
+  }
+
   // All nodes except Allocate nodes are expanded now. There could be
   // new optimization opportunities (such as folding newly created
   // load from a just allocated object). Run IGVN.
 
   // expand "macro" nodes
@@ -2800,14 +3318,18 @@
     if (C->check_node_count(300, "out of nodes before macro expansion")) {
       return true;
     }
     switch (n->class_id()) {
     case Node::Class_Allocate:
-      expand_allocate(n->as_Allocate());
+      if (!stack_allocation(n->as_Allocate())) {
+        expand_allocate(n->as_Allocate());
+      }
       break;
     case Node::Class_AllocateArray:
-      expand_allocate_array(n->as_AllocateArray());
+      if (!stack_allocation(n->as_AllocateArray())) {
+        expand_allocate_array(n->as_AllocateArray());
+      }
       break;
     default:
       assert(false, "unknown node type in macro list");
     }
     assert(C->macro_count() < macro_count, "must have deleted a node from macro list");
