Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 3582) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -187,12 +187,18 @@ |
function_return_is_shadowed_ = false; |
VirtualFrame::SpilledScope spilled_scope; |
- if (scope_->num_heap_slots() > 0) { |
+ int heap_slots = scope_->num_heap_slots(); |
+ if (heap_slots > 0) { |
// Allocate local context. |
// Get outer context and create a new context based on it. |
__ ldr(r0, frame_->Function()); |
frame_->EmitPush(r0); |
- frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result |
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
+ FastNewContextStub stub(heap_slots); |
+ frame_->CallStub(&stub, 1); |
+ } else { |
+ frame_->CallRuntime(Runtime::kNewContext, 1); |
+ } |
#ifdef DEBUG |
JumpTarget verified_true; |
@@ -4432,6 +4438,55 @@ |
} |
+void FastNewContextStub::Generate(MacroAssembler* masm) { |
+ // Try to allocate the context in new space. |
+ Label gc; |
+ int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
+ |
+ // Pop the function from the stack. |
+ __ pop(r3); |
+ |
+ // Attempt to allocate the context in new space. |
+ __ AllocateInNewSpace(length + (FixedArray::kHeaderSize / kPointerSize), |
+ r0, |
+ r1, |
+ r2, |
+ &gc, |
+ TAG_OBJECT); |
+ |
+ // Setup the object header. |
+ __ LoadRoot(r2, Heap::kContextMapRootIndex); |
+ __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
+ __ mov(r2, Operand(length)); |
+ __ str(r2, FieldMemOperand(r0, Array::kLengthOffset)); |
+ |
+ // Setup the fixed slots. |
+ __ mov(r1, Operand(Smi::FromInt(0))); |
+ __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); |
+ __ str(r0, MemOperand(r0, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
+ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
+ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX))); |
+ |
+ // Copy the global object from the surrounding context. |
+ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
+ __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); |
+ |
+ // Initialize the rest of the slots to undefined. |
+ __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
+ for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { |
+ __ str(r1, MemOperand(r0, Context::SlotOffset(i))); |
+ } |
+ |
+ // Return. The on-stack parameter has already been popped. |
+ __ mov(cp, r0); |
+ __ Ret(); |
+ |
+ // Need to collect. Call into runtime system. |
+ __ bind(&gc); |
+ __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); |
+} |
+ |
+ |
// Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz |
// instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0 |
// (31 instead of 32). |