| 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).
|
|
|