| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 3581)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -326,12 +326,19 @@
|
| function_return_is_shadowed_ = false;
|
|
|
| // Allocate the local context if needed.
|
| - if (scope_->num_heap_slots() > 0) {
|
| + int heap_slots = scope_->num_heap_slots();
|
| + if (heap_slots > 0) {
|
| Comment cmnt(masm_, "[ allocate local context");
|
| // Allocate local context.
|
| // Get outer context and create a new context based on it.
|
| frame_->PushFunction();
|
| - Result context = frame_->CallRuntime(Runtime::kNewContext, 1);
|
| + Result context;
|
| + if (heap_slots <= FastNewContextStub::kMaximumSlots) {
|
| + FastNewContextStub stub(heap_slots);
|
| + context = frame_->CallStub(&stub, 1);
|
| + } else {
|
| + context = frame_->CallRuntime(Runtime::kNewContext, 1);
|
| + }
|
|
|
| // Update context local.
|
| frame_->SaveContextRegister();
|
| @@ -6110,6 +6117,48 @@
|
| }
|
|
|
|
|
| +void FastNewContextStub::Generate(MacroAssembler* masm) {
|
| + // Try to allocate the context in new space.
|
| + Label gc;
|
| + int length = slots_ + Context::MIN_CONTEXT_SLOTS;
|
| + __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
|
| + rax, rbx, rcx, &gc, TAG_OBJECT);
|
| +
|
| + // Get the function from the stack.
|
| + __ movq(rcx, Operand(rsp, 1 * kPointerSize));
|
| +
|
| + // Setup the object header.
|
| + __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex);
|
| + __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
|
| + __ movl(FieldOperand(rax, Array::kLengthOffset), Immediate(length));
|
| +
|
| + // Setup the fixed slots.
|
| + __ xor_(rbx, rbx); // Set to NULL.
|
| + __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
|
| + __ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax);
|
| + __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx);
|
| + __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx);
|
| +
|
| + // Copy the global object from the surrounding context.
|
| + __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
|
| + __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx);
|
| +
|
| + // Initialize the rest of the slots to undefined.
|
| + __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
|
| + for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
|
| + __ movq(Operand(rax, Context::SlotOffset(i)), rbx);
|
| + }
|
| +
|
| + // Return and remove the on-stack parameter.
|
| + __ movq(rsi, rax);
|
| + __ ret(1 * kPointerSize);
|
| +
|
| + // Need to collect. Call into runtime system.
|
| + __ bind(&gc);
|
| + __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1);
|
| +}
|
| +
|
| +
|
| void ToBooleanStub::Generate(MacroAssembler* masm) {
|
| Label false_result, true_result, not_string;
|
| __ movq(rax, Operand(rsp, 1 * kPointerSize));
|
|
|