Turn FastNewContextStub into a HydrogenCodeStub.

R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/145513002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18764 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
bmeurer@chromium.org 2014-01-23 08:36:22 +00:00
parent 02c02fe567
commit 5e0f020d3a
14 changed files with 139 additions and 163 deletions

View File

@ -49,6 +49,16 @@ void FastNewClosureStub::InitializeInterfaceDescriptor(
}
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) {
@ -461,48 +471,6 @@ void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
}
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:
//

View File

@ -202,20 +202,22 @@ void FullCodeGenerator::Generate() {
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++) {

View File

@ -207,17 +207,18 @@ bool LCodeGen::GeneratePrologue() {
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++) {

View File

@ -1329,6 +1329,60 @@ Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) {
}
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);

View File

@ -766,6 +766,12 @@ void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
}
void FastNewContextStub::InstallDescriptors(Isolate* isolate) {
FastNewContextStub stub(FastNewContextStub::kMaximumSlots);
InstallDescriptor(isolate, &stub);
}
// static
void BinaryOpICStub::InstallDescriptors(Isolate* isolate) {
BinaryOpICStub stub(Token::ADD, NO_OVERWRITE);

View File

@ -556,7 +556,7 @@ class FastNewClosureStub : public HydrogenCodeStub {
};
class FastNewContextStub : public PlatformCodeStub {
class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
public:
static const int kMaximumSlots = 64;
@ -564,13 +564,24 @@ class FastNewContextStub : public PlatformCodeStub {
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_; }
};

View File

@ -54,6 +54,16 @@ void FastNewClosureStub::InitializeInterfaceDescriptor(
}
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) {
@ -441,49 +451,6 @@ void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
}
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:
//

View File

@ -182,20 +182,22 @@ void FullCodeGenerator::Generate() {
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();

View File

@ -292,17 +292,18 @@ bool LCodeGen::GeneratePrologue() {
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();

View File

@ -2111,6 +2111,7 @@ bool Isolate::Init(Deserializer* des) {
ArrayConstructorStubBase::InstallDescriptors(this);
InternalArrayConstructorStubBase::InstallDescriptors(this);
FastNewClosureStub::InstallDescriptors(this);
FastNewContextStub::InstallDescriptors(this);
NumberToStringStub::InstallDescriptors(this);
StringAddStub::InstallDescriptors(this);
}

View File

@ -8869,7 +8869,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
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
@ -8882,14 +8881,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
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);
}

View File

@ -50,6 +50,16 @@ void FastNewClosureStub::InitializeInterfaceDescriptor(
}
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) {
@ -438,48 +448,6 @@ void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
}
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:
//

View File

@ -182,20 +182,22 @@ void FullCodeGenerator::Generate() {
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();

View File

@ -218,17 +218,18 @@ bool LCodeGen::GeneratePrologue() {
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();