Revision: 3516
Author: [email protected]
Date: Tue Dec 22 04:41:45 2009
Log: 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
http://code.google.com/p/v8/source/detail?r=3516

Modified:
  /branches/bleeding_edge/src/arm/codegen-arm.cc
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/arm/virtual-frame-arm.cc
  /branches/bleeding_edge/src/arm/virtual-frame-arm.h
  /branches/bleeding_edge/src/ast.h
  /branches/bleeding_edge/src/ia32/codegen-ia32.cc
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/parser.cc
  /branches/bleeding_edge/src/x64/codegen-x64.cc
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Tue Dec 22 02:16:27 2009
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Tue Dec 22 04:41:45 2009
@@ -2599,42 +2599,6 @@
    frame_->EmitPush(r2);
    ASSERT(frame_->height() == original_height + 1);
  }
-
-
-// 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) {
@@ -2644,39 +2608,22 @@
    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;
-  }
-  frame_->CallRuntime(clone_function_id, 1);
+  __ 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_->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);
@@ -2722,42 +2669,6 @@
    }
    ASSERT(frame_->height() == original_height + 1);
  }
-
-
-// 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) {
@@ -2767,39 +2678,22 @@
    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;
-  }
-  frame_->CallRuntime(clone_function_id, 1);
+  __ 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_->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.
=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Fri Dec 18 05:38:28  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Dec 22 04:41:45  
2009
@@ -760,7 +760,7 @@
    __ 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);
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.cc        Fri Dec  4  
04:17:02 2009
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.cc        Tue Dec 22  
04:41:45 2009
@@ -385,6 +385,13 @@
    stack_pointer_++;
    __ push(reg);
  }
+
+
+void VirtualFrame::EmitPushMultiple(int count, int src_regs) {
+  ASSERT(stack_pointer_ == element_count() - 1);
+  Adjust(count);
+  __ stm(db_w, sp, src_regs);
+}


  #undef __
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.h Fri Dec  4 04:17:02  
2009
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.h Tue Dec 22 04:41:45  
2009
@@ -346,6 +346,11 @@
    // 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<Object> value);
=======================================
--- /branches/bleeding_edge/src/ast.h   Thu Dec 17 22:38:12 2009
+++ /branches/bleeding_edge/src/ast.h   Tue Dec 22 04:41:45 2009
@@ -827,24 +827,24 @@
  // for minimizing the work when constructing it at runtime.
  class ArrayLiteral: public MaterializedLiteral {
   public:
-  ArrayLiteral(Handle<FixedArray> literals,
+  ArrayLiteral(Handle<FixedArray> constant_elements,
                 ZoneList<Expression*>* 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<FixedArray> literals() const { return literals_; }
+  Handle<FixedArray> constant_elements() const { return  
constant_elements_; }
    ZoneList<Expression*>* values() const { return values_; }

   private:
-  Handle<FixedArray> literals_;
+  Handle<FixedArray> constant_elements_;
    ZoneList<Expression*>* values_;
  };

=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc    Tue Dec 22 02:16:27  
2009
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc    Tue Dec 22 04:41:45  
2009
@@ -4267,48 +4267,12 @@
    // Push the boilerplate object.
    frame_->Push(&boilerplate);
  }
-
-
-// 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 @@
    // 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;
-  }
-  Result clone = frame_->CallRuntime(clone_function_id, 1);
-  // Push the newly cloned literal object as the result.
+  // 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);
+  }
    frame_->Push(&clone);

    for (int i = 0; i < node->properties()->length(); i++) {
@@ -4401,47 +4351,12 @@
      }
    }
  }
-
-
-// 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 @@
    __ 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);
-  }
-  // Push the newly cloned literal object as the result.
+    FastCloneShallowArrayStub stub(length);
+    clone = frame_->CallStub(&stub, 3);
+  }
    frame_->Push(&clone);

    // Generate code to set the elements in the array that are not
@@ -6765,13 +6660,23 @@
    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);
-
-  // Get the boilerplate from the stack.
-  __ mov(ecx, Operand(esp, 1 * kPointerSize));
+  // 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);
+
+
+  // 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 @@
      }
    }

-  // Return and remove the on-stack parameter.
-  __ ret(1 * kPointerSize);
-
-  __ bind(&gc);
-  ExternalReference runtime(Runtime::kCloneShallowLiteralBoilerplate);
-  __ TailCallRuntime(runtime, 1, 1);
+  // Return and remove the on-stack parameters.
+  __ ret(3 * kPointerSize);
+
+  __ bind(&slow_case);
+  ExternalReference runtime(Runtime::kCreateArrayLiteralShallow);
+  __ TailCallRuntime(runtime, 3, 1);
  }


=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Fri Dec 18  
05:38:28 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Tue Dec 22  
04:41:45 2009
@@ -752,7 +752,7 @@
    __ 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 {
=======================================
--- /branches/bleeding_edge/src/parser.cc       Thu Dec 17 22:38:12 2009
+++ /branches/bleeding_edge/src/parser.cc       Tue Dec 22 04:41:45 2009
@@ -3332,7 +3332,7 @@
      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;
  }
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Tue Dec 22 02:16:27 2009
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Tue Dec 22 04:41:45 2009
@@ -2360,48 +2360,12 @@
    // Push the boilerplate object.
    frame_->Push(&boilerplate);
  }
-
-
-// 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 @@
    // 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;
-  }
-  Result clone = frame_->CallRuntime(clone_function_id, 1);
-  // Push the newly cloned literal object as the result.
+  // 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);
+  }
    frame_->Push(&clone);

    for (int i = 0; i < node->properties()->length(); i++) {
@@ -2494,47 +2444,12 @@
      }
    }
  }
-
-
-// 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 @@
    // 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;
-  }
-  Result clone = frame_->CallRuntime(clone_function_id, 1);
-  // Push the newly cloned literal object as the result.
+  // 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);
+  }
    frame_->Push(&clone);

    // Generate code to set the elements in the array that are not
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Fri Dec 18 05:38:28  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Dec 22 04:41:45  
2009
@@ -761,7 +761,7 @@
    __ 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 {

-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to