}
+void FastNewContextStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { r1 };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ = NULL;
+}
+
+
void ToNumberStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
}
-void FastNewContextStub::Generate(MacroAssembler* masm) {
- // Try to allocate the context in new space.
- Label gc;
- int length = slots_ + Context::MIN_CONTEXT_SLOTS;
-
- // Attempt to allocate the context in new space.
- __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT);
-
- // Load the function from the stack.
- __ ldr(r3, MemOperand(sp, 0));
-
- // Set up the object header.
- __ LoadRoot(r1, Heap::kFunctionContextMapRootIndex);
- __ mov(r2, Operand(Smi::FromInt(length)));
- __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset));
- __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-
- // Set up the fixed slots, copy the global object from the previous context.
- __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ mov(r1, Operand(Smi::FromInt(0)));
- __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX)));
- __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
- __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX)));
- __ str(r2, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_OBJECT_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)));
- }
-
- // Remove the on-stack argument and return.
- __ mov(cp, r0);
- __ pop();
- __ Ret();
-
- // Need to collect. Call into runtime system.
- __ bind(&gc);
- __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
-}
-
-
void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
// Stack layout on entry:
//
if (heap_slots > 0) {
// Argument to NewContext is the function, which is still in r1.
Comment cmnt(masm_, "[ Allocate context");
- __ push(r1);
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
+ __ push(r1);
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {
+ __ push(r1);
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
function_in_register = false;
- // Context is returned in both r0 and cp. It replaces the context
- // passed to us. It's saved in the stack and kept live in cp.
- __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ // Context is returned in r0. It replaces the context passed to us.
+ // It's saved in the stack and kept live in cp.
+ __ mov(cp, r0);
+ __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
if (heap_slots > 0) {
Comment(";;; Allocate local context");
// Argument to NewContext is the function, which is in r1.
- __ push(r1);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {
+ __ push(r1);
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
RecordSafepoint(Safepoint::kNoLazyDeopt);
// Context is returned in both r0 and cp. It replaces the context
// passed to us. It's saved in the stack and kept live in cp.
- __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ mov(cp, r0);
+ __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
template<>
+HValue* CodeStubGraphBuilder<FastNewContextStub>::BuildCodeStub() {
+ int length = casted_stub()->slots() + Context::MIN_CONTEXT_SLOTS;
+
+ // Get the function.
+ HParameter* function = GetParameter(FastNewContextStub::kFunction);
+
+ // Allocate the context in new space.
+ HAllocate* function_context = Add<HAllocate>(
+ Add<HConstant>(length * kPointerSize + FixedArray::kHeaderSize),
+ HType::Tagged(), NOT_TENURED, FIXED_ARRAY_TYPE);
+
+ // Set up the object header.
+ AddStoreMapConstant(function_context,
+ isolate()->factory()->function_context_map());
+ Add<HStoreNamedField>(function_context,
+ HObjectAccess::ForFixedArrayLength(),
+ Add<HConstant>(length));
+
+ // Set up the fixed slots.
+ Add<HStoreNamedField>(function_context,
+ HObjectAccess::ForContextSlot(Context::CLOSURE_INDEX),
+ function);
+ Add<HStoreNamedField>(function_context,
+ HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX),
+ context());
+ Add<HStoreNamedField>(function_context,
+ HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX),
+ graph()->GetConstant0());
+
+ // Copy the global object from the previous context.
+ HValue* global_object = Add<HLoadNamedField>(
+ context(), HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
+ Add<HStoreNamedField>(function_context,
+ HObjectAccess::ForContextSlot(
+ Context::GLOBAL_OBJECT_INDEX),
+ global_object);
+
+ // Initialize the rest of the slots to undefined.
+ for (int i = Context::MIN_CONTEXT_SLOTS; i < length; ++i) {
+ Add<HStoreNamedField>(function_context,
+ HObjectAccess::ForContextSlot(i),
+ graph()->GetConstantUndefined());
+ }
+
+ return function_context;
+}
+
+
+Handle<Code> FastNewContextStub::GenerateCode(Isolate* isolate) {
+ return DoGenerateCode(isolate, this);
+}
+
+
+template<>
HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() {
HValue* receiver = GetParameter(0);
HValue* key = GetParameter(1);
}
+void FastNewContextStub::InstallDescriptors(Isolate* isolate) {
+ FastNewContextStub stub(FastNewContextStub::kMaximumSlots);
+ InstallDescriptor(isolate, &stub);
+}
+
+
// static
void BinaryOpICStub::InstallDescriptors(Isolate* isolate) {
BinaryOpICStub stub(Token::ADD, NO_OVERWRITE);
};
-class FastNewContextStub : public PlatformCodeStub {
+class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
public:
static const int kMaximumSlots = 64;
ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
}
- void Generate(MacroAssembler* masm);
+ virtual Handle<Code> GenerateCode(Isolate* isolate);
+
+ virtual void InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor);
+
+ static void InstallDescriptors(Isolate* isolate);
+
+ int slots() const { return slots_; }
+
+ virtual Major MajorKey() V8_OVERRIDE { return FastNewContext; }
+ virtual int NotMissMinorKey() V8_OVERRIDE { return slots_; }
+
+ // Parameters accessed via CodeStubGraphBuilder::GetParameter()
+ static const int kFunction = 0;
private:
int slots_;
-
- Major MajorKey() { return FastNewContext; }
- int MinorKey() { return slots_; }
};
}
+void FastNewContextStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { edi };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ = NULL;
+}
+
+
void ToNumberStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
}
-void FastNewContextStub::Generate(MacroAssembler* masm) {
- // Try to allocate the context in new space.
- Label gc;
- int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
- eax, ebx, ecx, &gc, TAG_OBJECT);
-
- // Get the function from the stack.
- __ mov(ecx, Operand(esp, 1 * kPointerSize));
-
- // Set up the object header.
- Factory* factory = masm->isolate()->factory();
- __ mov(FieldOperand(eax, HeapObject::kMapOffset),
- factory->function_context_map());
- __ mov(FieldOperand(eax, Context::kLengthOffset),
- Immediate(Smi::FromInt(length)));
-
- // Set up the fixed slots.
- __ Set(ebx, Immediate(0)); // Set to NULL.
- __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
- __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi);
- __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx);
-
- // Copy the global object from the previous context.
- __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), ebx);
-
- // Initialize the rest of the slots to undefined.
- __ mov(ebx, factory->undefined_value());
- for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
- __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
- }
-
- // Return and remove the on-stack parameter.
- __ mov(esi, eax);
- __ ret(1 * kPointerSize);
-
- // Need to collect. Call into runtime system.
- __ bind(&gc);
- __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
-}
-
-
void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
// Stack layout on entry:
//
if (heap_slots > 0) {
Comment cmnt(masm_, "[ Allocate context");
// Argument to NewContext is the function, which is still in edi.
- __ push(edi);
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
+ __ push(edi);
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {
+ __ push(edi);
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
function_in_register = false;
- // Context is returned in both eax and esi. It replaces the context
- // passed to us. It's saved in the stack and kept live in esi.
- __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
+ // Context is returned in eax. It replaces the context passed to us.
+ // It's saved in the stack and kept live in esi.
+ __ mov(esi, eax);
+ __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
// Copy parameters into context if necessary.
int num_parameters = info->scope()->num_parameters();
if (heap_slots > 0) {
Comment(";;; Allocate local context");
// Argument to NewContext is the function, which is still in edi.
- __ push(edi);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {
+ __ push(edi);
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
RecordSafepoint(Safepoint::kNoLazyDeopt);
- // Context is returned in both eax and esi. It replaces the context
- // passed to us. It's saved in the stack and kept live in esi.
- __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
+ // Context is returned in eax. It replaces the context passed to us.
+ // It's saved in the stack and kept live in esi.
+ __ mov(esi, eax);
+ __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
// Copy parameters into context if necessary.
int num_parameters = scope()->num_parameters();
ArrayConstructorStubBase::InstallDescriptors(this);
InternalArrayConstructorStubBase::InstallDescriptors(this);
FastNewClosureStub::InstallDescriptors(this);
+ FastNewContextStub::InstallDescriptors(this);
NumberToStringStub::InstallDescriptors(this);
StringAddStub::InstallDescriptors(this);
}
ASSERT(function->context() == isolate->context());
ASSERT(function->context()->global_object() == result->global_object());
- isolate->set_context(result);
result->global_object()->set_global_context(result);
return result; // non-failure
CONVERT_ARG_CHECKED(JSFunction, function, 0);
int length = function->shared()->scope_info()->ContextLength();
- Context* result;
- MaybeObject* maybe_result =
- isolate->heap()->AllocateFunctionContext(length, function);
- if (!maybe_result->To(&result)) return maybe_result;
-
- isolate->set_context(result);
-
- return result; // non-failure
+ return isolate->heap()->AllocateFunctionContext(length, function);
}
}
+void FastNewContextStub::InitializeInterfaceDescriptor(
+ Isolate* isolate,
+ CodeStubInterfaceDescriptor* descriptor) {
+ static Register registers[] = { rdi };
+ descriptor->register_param_count_ = 1;
+ descriptor->register_params_ = registers;
+ descriptor->deoptimization_handler_ = NULL;
+}
+
+
void ToNumberStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
}
-void FastNewContextStub::Generate(MacroAssembler* masm) {
- // Try to allocate the context in new space.
- Label gc;
- int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
- rax, rbx, rcx, &gc, TAG_OBJECT);
-
- // Get the function from the stack.
- StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
- __ movp(rcx, args.GetArgumentOperand(0));
-
- // Set up the object header.
- __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex);
- __ movp(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
- __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
-
- // Set up the fixed slots.
- __ Set(rbx, 0); // Set to NULL.
- __ movp(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
- __ movp(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi);
- __ movp(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx);
-
- // Copy the global object from the previous context.
- __ movp(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ movp(Operand(rax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), rbx);
-
- // Initialize the rest of the slots to undefined.
- __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
- for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
- __ movp(Operand(rax, Context::SlotOffset(i)), rbx);
- }
-
- // Return and remove the on-stack parameter.
- __ movp(rsi, rax);
- __ ret(1 * kPointerSize);
-
- // Need to collect. Call into runtime system.
- __ bind(&gc);
- __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
-}
-
-
void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
// Stack layout on entry:
//
if (heap_slots > 0) {
Comment cmnt(masm_, "[ Allocate context");
// Argument to NewContext is the function, which is still in rdi.
- __ push(rdi);
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
+ __ push(rdi);
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {
+ __ push(rdi);
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
function_in_register = false;
- // Context is returned in both rax and rsi. It replaces the context
- // passed to us. It's saved in the stack and kept live in rsi.
- __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
+ // Context is returned in rax. It replaces the context passed to us.
+ // It's saved in the stack and kept live in rsi.
+ __ movp(rsi, rax);
+ __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
// Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters();
if (heap_slots > 0) {
Comment(";;; Allocate local context");
// Argument to NewContext is the function, which is still in rdi.
- __ push(rdi);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {
+ __ push(rdi);
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
RecordSafepoint(Safepoint::kNoLazyDeopt);
- // Context is returned in both rax and rsi. It replaces the context
- // passed to us. It's saved in the stack and kept live in rsi.
- __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
+ // Context is returned in rax. It replaces the context passed to us.
+ // It's saved in the stack and kept live in rsi.
+ __ movp(rsi, rax);
+ __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
// Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters();