From 735aee05f01438b7523998387a1e03021b936de2 Mon Sep 17 00:00:00 2001 From: "fschneider@chromium.org" Date: Tue, 22 Dec 2009 12:41:45 +0000 Subject: [PATCH] Use one runtime call for creating object/array literals in the code generator. The runtime function checks if it needs to create a boilerplate object or if it can clone from an existing boilerplate. This is already done in the top-level compiler. Review URL: http://codereview.chromium.org/507036 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3516 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 158 ++++++------------------------------ src/arm/fast-codegen-arm.cc | 2 +- src/arm/virtual-frame-arm.cc | 7 ++ src/arm/virtual-frame-arm.h | 5 ++ src/ast.h | 8 +- src/ia32/codegen-ia32.cc | 181 ++++++++++-------------------------------- src/ia32/fast-codegen-ia32.cc | 2 +- src/parser.cc | 2 +- src/x64/codegen-x64.cc | 147 ++++++---------------------------- src/x64/fast-codegen-x64.cc | 2 +- 10 files changed, 113 insertions(+), 401 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 2309ea7..c8b62e5 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -2601,42 +2601,6 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { } -// This deferred code stub will be used for creating the boilerplate -// by calling Runtime_CreateObjectLiteralBoilerplate. -// Each created boilerplate is stored in the JSFunction and they are -// therefore context dependent. -class DeferredObjectLiteral: public DeferredCode { - public: - explicit DeferredObjectLiteral(ObjectLiteral* node) : node_(node) { - set_comment("[ DeferredObjectLiteral"); - } - - virtual void Generate(); - - private: - ObjectLiteral* node_; -}; - - -void DeferredObjectLiteral::Generate() { - // Argument is passed in r1. - - // If the entry is undefined we call the runtime system to compute - // the literal. - // Literal array (0). - __ push(r1); - // Literal index (1). - __ mov(r0, Operand(Smi::FromInt(node_->literal_index()))); - __ push(r0); - // Constant properties (2). - __ mov(r0, Operand(node_->constant_properties())); - __ push(r0); - __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); - __ mov(r2, Operand(r0)); - // Result is returned in r2. -} - - void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { #ifdef DEBUG int original_height = frame_->height(); @@ -2644,39 +2608,22 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { VirtualFrame::SpilledScope spilled_scope; Comment cmnt(masm_, "[ ObjectLiteral"); - DeferredObjectLiteral* deferred = new DeferredObjectLiteral(node); - - // Retrieve the literal array and check the allocated entry. - // Load the function of this activation. - __ ldr(r1, frame_->Function()); - - // Load the literals array of the function. - __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); - - // Load the literal at the ast saved index. - int literal_offset = - FixedArray::kHeaderSize + node->literal_index() * kPointerSize; - __ ldr(r2, FieldMemOperand(r1, literal_offset)); - - // Check whether we need to materialize the object literal boilerplate. - // If so, jump to the deferred code. - __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); - __ cmp(r2, Operand(ip)); - deferred->Branch(eq); - deferred->BindExit(); - - // Push the object literal boilerplate. - frame_->EmitPush(r2); - - // Clone the boilerplate object. - Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; - if (node->depth() == 1) { - clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; + __ ldr(r2, frame_->Function()); + // Literal array. + __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); + // Literal index. + __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); + // Constant properties. + __ mov(r0, Operand(node->constant_properties())); + frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); + if (node->depth() > 1) { + frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3); + } else { + frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); } - frame_->CallRuntime(clone_function_id, 1); frame_->EmitPush(r0); // save the result - // r0: cloned object literal + // r0: created object literal for (int i = 0; i < node->properties()->length(); i++) { ObjectLiteral::Property* property = node->properties()->at(i); @@ -2724,42 +2671,6 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { } -// This deferred code stub will be used for creating the boilerplate -// by calling Runtime_CreateArrayLiteralBoilerplate. -// Each created boilerplate is stored in the JSFunction and they are -// therefore context dependent. -class DeferredArrayLiteral: public DeferredCode { - public: - explicit DeferredArrayLiteral(ArrayLiteral* node) : node_(node) { - set_comment("[ DeferredArrayLiteral"); - } - - virtual void Generate(); - - private: - ArrayLiteral* node_; -}; - - -void DeferredArrayLiteral::Generate() { - // Argument is passed in r1. - - // If the entry is undefined we call the runtime system to computed - // the literal. - // Literal array (0). - __ push(r1); - // Literal index (1). - __ mov(r0, Operand(Smi::FromInt(node_->literal_index()))); - __ push(r0); - // Constant properties (2). - __ mov(r0, Operand(node_->literals())); - __ push(r0); - __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); - __ mov(r2, Operand(r0)); - // Result is returned in r2. -} - - void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { #ifdef DEBUG int original_height = frame_->height(); @@ -2767,39 +2678,22 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { VirtualFrame::SpilledScope spilled_scope; Comment cmnt(masm_, "[ ArrayLiteral"); - DeferredArrayLiteral* deferred = new DeferredArrayLiteral(node); - - // Retrieve the literal array and check the allocated entry. - // Load the function of this activation. - __ ldr(r1, frame_->Function()); - - // Load the literals array of the function. - __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); - - // Load the literal at the ast saved index. - int literal_offset = - FixedArray::kHeaderSize + node->literal_index() * kPointerSize; - __ ldr(r2, FieldMemOperand(r1, literal_offset)); - - // Check whether we need to materialize the object literal boilerplate. - // If so, jump to the deferred code. - __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); - __ cmp(r2, Operand(ip)); - deferred->Branch(eq); - deferred->BindExit(); - - // Push the object literal boilerplate. - frame_->EmitPush(r2); - - // Clone the boilerplate object. - Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; - if (node->depth() == 1) { - clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; + __ ldr(r2, frame_->Function()); + // Literals array. + __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); + // Literal index. + __ mov(r1, Operand(Smi::FromInt(node->literal_index()))); + // Constant elements. + __ mov(r0, Operand(node->constant_elements())); + frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit()); + if (node->depth() > 1) { + frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); + } else { + frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } - frame_->CallRuntime(clone_function_id, 1); frame_->EmitPush(r0); // save the result - // r0: cloned object literal + // r0: created object literal // Generate code to set the elements in the array that are not // literals. diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index 0983a63..657f0a6 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -760,7 +760,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); - __ mov(r1, Operand(expr->literals())); + __ mov(r1, Operand(expr->constant_elements())); __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); if (expr->depth() > 1) { __ CallRuntime(Runtime::kCreateArrayLiteral, 3); diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc index 132c8ae..e8403f7 100644 --- a/src/arm/virtual-frame-arm.cc +++ b/src/arm/virtual-frame-arm.cc @@ -387,6 +387,13 @@ void VirtualFrame::EmitPush(Register reg) { } +void VirtualFrame::EmitPushMultiple(int count, int src_regs) { + ASSERT(stack_pointer_ == element_count() - 1); + Adjust(count); + __ stm(db_w, sp, src_regs); +} + + #undef __ } } // namespace v8::internal diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h index d523000..39be1bc 100644 --- a/src/arm/virtual-frame-arm.h +++ b/src/arm/virtual-frame-arm.h @@ -346,6 +346,11 @@ class VirtualFrame : public ZoneObject { // corresponding push instruction. void EmitPush(Register reg); + // Push multiple registers on the stack and the virtual frame + // Register are selected by setting bit in src_regs and + // are pushed in decreasing order: r15 .. r0. + void EmitPushMultiple(int count, int src_regs); + // Push an element on the virtual frame. void Push(Register reg); void Push(Handle value); diff --git a/src/ast.h b/src/ast.h index 195fc14..3a710ab 100644 --- a/src/ast.h +++ b/src/ast.h @@ -827,24 +827,24 @@ class RegExpLiteral: public MaterializedLiteral { // for minimizing the work when constructing it at runtime. class ArrayLiteral: public MaterializedLiteral { public: - ArrayLiteral(Handle literals, + ArrayLiteral(Handle constant_elements, ZoneList* values, int literal_index, bool is_simple, int depth) : MaterializedLiteral(literal_index, is_simple, depth), - literals_(literals), + constant_elements_(constant_elements), values_(values) {} virtual void Accept(AstVisitor* v); virtual ArrayLiteral* AsArrayLiteral() { return this; } virtual bool IsValidJSON(); - Handle literals() const { return literals_; } + Handle constant_elements() const { return constant_elements_; } ZoneList* values() const { return values_; } private: - Handle literals_; + Handle constant_elements_; ZoneList* values_; }; diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index bc7fccf..4343a4c 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -4269,46 +4269,10 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { } -// Materialize the object literal 'node' in the literals array -// 'literals' of the function. Leave the object boilerplate in -// 'boilerplate'. -class DeferredObjectLiteral: public DeferredCode { - public: - DeferredObjectLiteral(Register boilerplate, - Register literals, - ObjectLiteral* node) - : boilerplate_(boilerplate), literals_(literals), node_(node) { - set_comment("[ DeferredObjectLiteral"); - } - - void Generate(); - - private: - Register boilerplate_; - Register literals_; - ObjectLiteral* node_; -}; - - -void DeferredObjectLiteral::Generate() { - // Since the entry is undefined we call the runtime system to - // compute the literal. - // Literal array (0). - __ push(literals_); - // Literal index (1). - __ push(Immediate(Smi::FromInt(node_->literal_index()))); - // Constant properties (2). - __ push(Immediate(node_->constant_properties())); - __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); - if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); -} - - void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { Comment cmnt(masm_, "[ ObjectLiteral"); - // Retrieve the literals array and check the allocated entry. Begin - // with a writable copy of the function of this activation in a + // Load a writable copy of the function of this activation in a // register. frame_->PushFunction(); Result literals = frame_->Pop(); @@ -4318,32 +4282,18 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { // Load the literals array of the function. __ mov(literals.reg(), FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); - - // Load the literal at the ast saved index. - Result boilerplate = allocator_->Allocate(); - ASSERT(boilerplate.is_valid()); - int literal_offset = - FixedArray::kHeaderSize + node->literal_index() * kPointerSize; - __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset)); - - // Check whether we need to materialize the object literal boilerplate. - // If so, jump to the deferred code passing the literals array. - DeferredObjectLiteral* deferred = - new DeferredObjectLiteral(boilerplate.reg(), literals.reg(), node); - __ cmp(boilerplate.reg(), Factory::undefined_value()); - deferred->Branch(equal); - deferred->BindExit(); - literals.Unuse(); - - // Push the boilerplate object. - frame_->Push(&boilerplate); - // Clone the boilerplate object. - Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; - if (node->depth() == 1) { - clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; + // Literal array. + frame_->Push(&literals); + // Literal index. + frame_->Push(Smi::FromInt(node->literal_index())); + // Constant properties. + frame_->Push(node->constant_properties()); + Result clone; + if (node->depth() > 1) { + clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3); + } else { + clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); } - Result clone = frame_->CallRuntime(clone_function_id, 1); - // Push the newly cloned literal object as the result. frame_->Push(&clone); for (int i = 0; i < node->properties()->length(); i++) { @@ -4403,45 +4353,10 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { } -// Materialize the array literal 'node' in the literals array 'literals' -// of the function. Leave the array boilerplate in 'boilerplate'. -class DeferredArrayLiteral: public DeferredCode { - public: - DeferredArrayLiteral(Register boilerplate, - Register literals, - ArrayLiteral* node) - : boilerplate_(boilerplate), literals_(literals), node_(node) { - set_comment("[ DeferredArrayLiteral"); - } - - void Generate(); - - private: - Register boilerplate_; - Register literals_; - ArrayLiteral* node_; -}; - - -void DeferredArrayLiteral::Generate() { - // Since the entry is undefined we call the runtime system to - // compute the literal. - // Literal array (0). - __ push(literals_); - // Literal index (1). - __ push(Immediate(Smi::FromInt(node_->literal_index()))); - // Constant properties (2). - __ push(Immediate(node_->literals())); - __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); - if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); -} - - void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { Comment cmnt(masm_, "[ ArrayLiteral"); - // Retrieve the literals array and check the allocated entry. Begin - // with a writable copy of the function of this activation in a + // Load a writable copy of the function of this activation in a // register. frame_->PushFunction(); Result literals = frame_->Pop(); @@ -4452,39 +4367,19 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { __ mov(literals.reg(), FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); - // Load the literal at the ast saved index. - Result boilerplate = allocator_->Allocate(); - ASSERT(boilerplate.is_valid()); - int literal_offset = - FixedArray::kHeaderSize + node->literal_index() * kPointerSize; - __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset)); - - // Check whether we need to materialize the object literal boilerplate. - // If so, jump to the deferred code passing the literals array. - DeferredArrayLiteral* deferred = - new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node); - __ cmp(boilerplate.reg(), Factory::undefined_value()); - deferred->Branch(equal); - deferred->BindExit(); - literals.Unuse(); - - // Push the resulting array literal boilerplate on the stack. - frame_->Push(&boilerplate); - - // Clone the boilerplate object. + frame_->Push(&literals); + frame_->Push(Smi::FromInt(node->literal_index())); + frame_->Push(node->constant_elements()); int length = node->values()->length(); Result clone; - if (node->depth() == 1) { - if (length <= FastCloneShallowArrayStub::kMaximumLength) { - FastCloneShallowArrayStub stub(length); - clone = frame_->CallStub(&stub, 1); - } else { - clone = frame_->CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); - } + if (node->depth() > 1) { + clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); + } else if (length > FastCloneShallowArrayStub::kMaximumLength) { + clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } else { - clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); + FastCloneShallowArrayStub stub(length); + clone = frame_->CallStub(&stub, 3); } - // Push the newly cloned literal object as the result. frame_->Push(&clone); // Generate code to set the elements in the array that are not @@ -6765,13 +6660,23 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; int size = JSArray::kSize + elements_size; - // Allocate both the JS array and the elements array in one big - // allocation. This avoid multiple limit checks. - Label gc; - __ AllocateInNewSpace(size, eax, ebx, ecx, &gc, TAG_OBJECT); + // Load boilerplate object into ecx and check if we need to create a + // boilerplate. + __ mov(ecx, Operand(esp, 3 * kPointerSize)); + __ mov(eax, Operand(esp, 2 * kPointerSize)); + ASSERT(kPointerSize == 4); + __ mov(ecx, FieldOperand(ecx, + eax, + times_2, + FixedArray::kHeaderSize)); + __ cmp(ecx, Factory::undefined_value()); + Label slow_case; + __ j(equal, &slow_case); - // Get the boilerplate from the stack. - __ mov(ecx, Operand(esp, 1 * kPointerSize)); + + // Allocate both the JS array and the elements array in one big + // allocation. This avoids multiple limit checks. + __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT); // Copy the JS array part. for (int i = 0; i < JSArray::kSize; i += kPointerSize) { @@ -6795,12 +6700,12 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { } } - // Return and remove the on-stack parameter. - __ ret(1 * kPointerSize); + // Return and remove the on-stack parameters. + __ ret(3 * kPointerSize); - __ bind(&gc); - ExternalReference runtime(Runtime::kCloneShallowLiteralBoilerplate); - __ TailCallRuntime(runtime, 1, 1); + __ bind(&slow_case); + ExternalReference runtime(Runtime::kCreateArrayLiteralShallow); + __ TailCallRuntime(runtime, 3, 1); } diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index 4bccd5d..eac50f0 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -752,7 +752,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); __ push(Immediate(Smi::FromInt(expr->literal_index()))); - __ push(Immediate(expr->literals())); + __ push(Immediate(expr->constant_elements())); if (expr->depth() > 1) { __ CallRuntime(Runtime::kCreateArrayLiteral, 3); } else { diff --git a/src/parser.cc b/src/parser.cc index a3bc6da..819b9b9 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -3332,7 +3332,7 @@ Handle CompileTimeValue::GetValue(Expression* expression) { ArrayLiteral* array_literal = expression->AsArrayLiteral(); ASSERT(array_literal != NULL && array_literal->is_simple()); result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL)); - result->set(kElementsSlot, *array_literal->literals()); + result->set(kElementsSlot, *array_literal->constant_elements()); } return result; } diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 8eb4015..d9ebeea 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -2362,46 +2362,10 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { } -// Materialize the object literal 'node' in the literals array -// 'literals' of the function. Leave the object boilerplate in -// 'boilerplate'. -class DeferredObjectLiteral: public DeferredCode { - public: - DeferredObjectLiteral(Register boilerplate, - Register literals, - ObjectLiteral* node) - : boilerplate_(boilerplate), literals_(literals), node_(node) { - set_comment("[ DeferredObjectLiteral"); - } - - void Generate(); - - private: - Register boilerplate_; - Register literals_; - ObjectLiteral* node_; -}; - - -void DeferredObjectLiteral::Generate() { - // Since the entry is undefined we call the runtime system to - // compute the literal. - // Literal array (0). - __ push(literals_); - // Literal index (1). - __ Push(Smi::FromInt(node_->literal_index())); - // Constant properties (2). - __ Push(node_->constant_properties()); - __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); - if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); -} - - void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { Comment cmnt(masm_, "[ ObjectLiteral"); - // Retrieve the literals array and check the allocated entry. Begin - // with a writable copy of the function of this activation in a + // Load a writable copy of the function of this activation in a // register. frame_->PushFunction(); Result literals = frame_->Pop(); @@ -2411,32 +2375,18 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { // Load the literals array of the function. __ movq(literals.reg(), FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); - - // Load the literal at the ast saved index. - Result boilerplate = allocator_->Allocate(); - ASSERT(boilerplate.is_valid()); - int literal_offset = - FixedArray::kHeaderSize + node->literal_index() * kPointerSize; - __ movq(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset)); - - // Check whether we need to materialize the object literal boilerplate. - // If so, jump to the deferred code passing the literals array. - DeferredObjectLiteral* deferred = - new DeferredObjectLiteral(boilerplate.reg(), literals.reg(), node); - __ CompareRoot(boilerplate.reg(), Heap::kUndefinedValueRootIndex); - deferred->Branch(equal); - deferred->BindExit(); - literals.Unuse(); - - // Push the boilerplate object. - frame_->Push(&boilerplate); - // Clone the boilerplate object. - Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; - if (node->depth() == 1) { - clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; + // Literal array. + frame_->Push(&literals); + // Literal index. + frame_->Push(Smi::FromInt(node->literal_index())); + // Constant properties. + frame_->Push(node->constant_properties()); + Result clone; + if (node->depth() > 1) { + clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3); + } else { + clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); } - Result clone = frame_->CallRuntime(clone_function_id, 1); - // Push the newly cloned literal object as the result. frame_->Push(&clone); for (int i = 0; i < node->properties()->length(); i++) { @@ -2496,45 +2446,10 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { } -// Materialize the array literal 'node' in the literals array 'literals' -// of the function. Leave the array boilerplate in 'boilerplate'. -class DeferredArrayLiteral: public DeferredCode { - public: - DeferredArrayLiteral(Register boilerplate, - Register literals, - ArrayLiteral* node) - : boilerplate_(boilerplate), literals_(literals), node_(node) { - set_comment("[ DeferredArrayLiteral"); - } - - void Generate(); - - private: - Register boilerplate_; - Register literals_; - ArrayLiteral* node_; -}; - - -void DeferredArrayLiteral::Generate() { - // Since the entry is undefined we call the runtime system to - // compute the literal. - // Literal array (0). - __ push(literals_); - // Literal index (1). - __ Push(Smi::FromInt(node_->literal_index())); - // Constant properties (2). - __ Push(node_->literals()); - __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); - if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); -} - - void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { Comment cmnt(masm_, "[ ArrayLiteral"); - // Retrieve the literals array and check the allocated entry. Begin - // with a writable copy of the function of this activation in a + // Load a writable copy of the function of this activation in a // register. frame_->PushFunction(); Result literals = frame_->Pop(); @@ -2544,32 +2459,18 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { // Load the literals array of the function. __ movq(literals.reg(), FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); - - // Load the literal at the ast saved index. - Result boilerplate = allocator_->Allocate(); - ASSERT(boilerplate.is_valid()); - int literal_offset = - FixedArray::kHeaderSize + node->literal_index() * kPointerSize; - __ movq(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset)); - - // Check whether we need to materialize the object literal boilerplate. - // If so, jump to the deferred code passing the literals array. - DeferredArrayLiteral* deferred = - new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node); - __ CompareRoot(boilerplate.reg(), Heap::kUndefinedValueRootIndex); - deferred->Branch(equal); - deferred->BindExit(); - literals.Unuse(); - - // Push the resulting array literal boilerplate on the stack. - frame_->Push(&boilerplate); - // Clone the boilerplate object. - Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; - if (node->depth() == 1) { - clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; + // Literal array. + frame_->Push(&literals); + // Literal index. + frame_->Push(Smi::FromInt(node->literal_index())); + // Constant elements. + frame_->Push(node->constant_elements()); + Result clone; + if (node->depth() > 1) { + clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); + } else { + clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } - Result clone = frame_->CallRuntime(clone_function_id, 1); - // Push the newly cloned literal object as the result. frame_->Push(&clone); // Generate code to set the elements in the array that are not diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index c40ee53..ba22135 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -761,7 +761,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); __ Push(Smi::FromInt(expr->literal_index())); - __ Push(expr->literals()); + __ Push(expr->constant_elements()); if (expr->depth() > 1) { __ CallRuntime(Runtime::kCreateArrayLiteral, 3); } else { -- 2.7.4