Author: [email protected]
Date: Tue Feb 17 00:08:26 2009
New Revision: 1283

Modified:
    branches/experimental/toiger/src/codegen-arm.cc
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/virtual-frame-arm.cc
    branches/experimental/toiger/src/virtual-frame-arm.h

Log:
Experimental: more stuff to get ARM to work.  Stubbed out frame merge
code (frames are always spilled on ARM).  Threaded frame to deferred
code.

Renamed some functions for uniformity.

Review URL: http://codereview.chromium.org/20408

Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc     (original)
+++ branches/experimental/toiger/src/codegen-arm.cc     Tue Feb 17 00:08:26 2009
@@ -668,14 +668,18 @@
      }

      case Token::DIV: {
-      __ mov(r0, Operand(1));
-      frame_->InvokeBuiltin(Builtins::DIV, CALL_JS, 2);
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));
+      frame_->InvokeBuiltin(Builtins::DIV, CALL_JS, &arg_count, 2);
        break;
      }

      case Token::MOD: {
-      __ mov(r0, Operand(1));
-      frame_->InvokeBuiltin(Builtins::MOD, CALL_JS, 2);
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));
+      frame_->InvokeBuiltin(Builtins::MOD, CALL_JS, &arg_count, 2);
        break;
      }

@@ -693,80 +697,96 @@
  }


-class DeferredInlinedSmiOperation: public DeferredCode {
+class DeferredInlineSmiOperation: public DeferredCode {
   public:
-  DeferredInlinedSmiOperation(CodeGenerator* generator, Token::Value op,
-                              int value, bool reversed) :
-      DeferredCode(generator), op_(op), value_(value), reversed_(reversed)  
{
+  DeferredInlineSmiOperation(CodeGenerator* generator,
+                             Token::Value op,
+                             int value,
+                             bool reversed)
+      : DeferredCode(generator),
+        op_(op),
+        value_(value),
+        reversed_(reversed) {
      set_comment("[ DeferredInlinedSmiOperation");
    }

-  virtual void Generate() {
-    switch (op_) {
-      case Token::ADD: {
-        if (reversed_) {
-          // revert optimistic add
-          __ sub(r0, r0, Operand(Smi::FromInt(value_)));
-          __ mov(r1, Operand(Smi::FromInt(value_)));  // x
-        } else {
-          // revert optimistic add
-          __ sub(r1, r0, Operand(Smi::FromInt(value_)));
-          __ mov(r0, Operand(Smi::FromInt(value_)));
-        }
-        break;
-      }
+  virtual void Generate();

-      case Token::SUB: {
-        if (reversed_) {
-          // revert optimistic sub
-          __ rsb(r0, r0, Operand(Smi::FromInt(value_)));
-          __ mov(r1, Operand(Smi::FromInt(value_)));
-        } else {
-          __ add(r1, r0, Operand(Smi::FromInt(value_)));
-          __ mov(r0, Operand(Smi::FromInt(value_)));
-        }
-        break;
+ private:
+  Token::Value op_;
+  int value_;
+  bool reversed_;
+};
+
+
+void DeferredInlineSmiOperation::Generate() {
+  enter()->Bind();
+  VirtualFrame::SpilledScope spilled_scope(generator());
+
+  switch (op_) {
+    case Token::ADD: {
+      if (reversed_) {
+        // revert optimistic add
+        __ sub(r0, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r1, Operand(Smi::FromInt(value_)));
+      } else {
+        // revert optimistic add
+        __ sub(r1, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
        }
+      break;
+    }

-      case Token::BIT_OR:
-      case Token::BIT_XOR:
-      case Token::BIT_AND: {
-        if (reversed_) {
-          __ mov(r1, Operand(Smi::FromInt(value_)));
-        } else {
-          __ mov(r1, Operand(r0));
-          __ mov(r0, Operand(Smi::FromInt(value_)));
-        }
-        break;
+    case Token::SUB: {
+      if (reversed_) {
+        // revert optimistic sub
+        __ rsb(r0, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r1, Operand(Smi::FromInt(value_)));
+      } else {
+        __ add(r1, r0, Operand(Smi::FromInt(value_)));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
        }
+      break;
+    }

-      case Token::SHL:
-      case Token::SHR:
-      case Token::SAR: {
-        if (!reversed_) {
-          __ mov(r1, Operand(r0));
-          __ mov(r0, Operand(Smi::FromInt(value_)));
-        } else {
-          UNREACHABLE();  // should have been handled in SmiOperation
-        }
-        break;
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND: {
+      if (reversed_) {
+        __ mov(r1, Operand(Smi::FromInt(value_)));
+      } else {
+        __ mov(r1, Operand(r0));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
        }
+      break;
+    }

-      default:
-        // other cases should have been handled before this point.
-        UNREACHABLE();
-        break;
+    case Token::SHL:
+    case Token::SHR:
+    case Token::SAR: {
+      if (!reversed_) {
+        __ mov(r1, Operand(r0));
+        __ mov(r0, Operand(Smi::FromInt(value_)));
+      } else {
+        UNREACHABLE();  // should have been handled in SmiOperation
+      }
+      break;
      }

-    GenericBinaryOpStub igostub(op_);
-    __ CallStub(&igostub);
+    default:
+      // other cases should have been handled before this point.
+      UNREACHABLE();
+      break;
    }

- private:
-  Token::Value op_;
-  int value_;
-  bool reversed_;
-};
+  GenericBinaryOpStub igostub(op_);
+  Result arg0 = generator()->allocator()->Allocate(r0);
+  ASSERT(arg0.is_valid());
+  Result arg1 = generator()->allocator()->Allocate(r1);
+  ASSERT(arg1.is_valid());
+  generator()->frame()->CallStub(&igostub, &arg0, &arg1, 0);
+  exit()->Jump();
+}


  void CodeGenerator::SmiOperation(Token::Value op,
@@ -790,7 +810,7 @@
    switch (op) {
      case Token::ADD: {
        DeferredCode* deferred =
-        new DeferredInlinedSmiOperation(this, op, int_value, reversed);
+        new DeferredInlineSmiOperation(this, op, int_value, reversed);

        __ add(r0, r0, Operand(value), SetCC);
        deferred->enter()->Branch(vs);
@@ -802,7 +822,7 @@

      case Token::SUB: {
        DeferredCode* deferred =
-        new DeferredInlinedSmiOperation(this, op, int_value, reversed);
+        new DeferredInlineSmiOperation(this, op, int_value, reversed);

        if (!reversed) {
          __ sub(r0, r0, Operand(value), SetCC);
@@ -820,7 +840,7 @@
      case Token::BIT_XOR:
      case Token::BIT_AND: {
        DeferredCode* deferred =
-        new DeferredInlinedSmiOperation(this, op, int_value, reversed);
+        new DeferredInlineSmiOperation(this, op, int_value, reversed);
        __ tst(r0, Operand(kSmiTagMask));
        deferred->enter()->Branch(ne);
        switch (op) {
@@ -845,7 +865,7 @@
        } else {
          int shift_value = int_value & 0x1f;  // least significant 5 bits
          DeferredCode* deferred =
-          new DeferredInlinedSmiOperation(this, op, shift_value, false);
+          new DeferredInlineSmiOperation(this, op, shift_value, false);
          __ tst(r0, Operand(kSmiTagMask));
          deferred->enter()->Branch(ne);
          __ mov(r2, Operand(r0, ASR, kSmiTagSize));  // remove tags
@@ -954,9 +974,15 @@
    // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
    // tagged as a small integer.
    frame_->EmitPush(r0);
-  __ mov(r0, Operand(arg_count));
-  frame_->InvokeBuiltin(native, CALL_JS, arg_count + 1);
-  __ cmp(r0, Operand(0));
+  Result arg_count_register = allocator_->Allocate(r0);
+  ASSERT(arg_count_register.is_valid());
+  __ mov(arg_count_register.reg(), Operand(arg_count));
+  Result result = frame_->InvokeBuiltin(native,
+                                        CALL_JS,
+                                        &arg_count_register,
+                                        arg_count + 1);
+  __ cmp(result.reg(), Operand(0));
+  result.Unuse();
    exit.Jump();

    // test smi equality by pointer comparison.
@@ -1043,7 +1069,9 @@
    node->set_break_stack_height(break_stack_height_);
    node->break_target()->Initialize(this);
    VisitStatementsAndSpill(node->statements());
-  node->break_target()->Bind();
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
  }


@@ -1462,7 +1490,6 @@
    CodeForStatementPosition(node);
    node->set_break_stack_height(break_stack_height_);
    node->break_target()->Initialize(this);
-  node->continue_target()->Initialize(this);

    // Simple condition analysis.  ALWAYS_TRUE and ALWAYS_FALSE represent a
    // known result for the test expression, with no side effects.
@@ -1483,22 +1510,28 @@

    switch (node->type()) {
      case LoopStatement::DO_LOOP: {
-      JumpTarget body(this);
-      // Label the body.
+      JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
+
+      // Label the top of the loop for the backward CFG edge.  If the test
+      // is always true we can use the continue target, and if the test is
+      // always false there is no need.
        if (info == ALWAYS_TRUE) {
+        node->continue_target()->Initialize(this,  
JumpTarget::BIDIRECTIONAL);
          node->continue_target()->Bind();
        } else if (info == ALWAYS_FALSE) {
-        // There is no need, we will never jump back.
+        node->continue_target()->Initialize(this);
        } else {
          ASSERT(info == DONT_KNOW);
+        node->continue_target()->Initialize(this);
          body.Bind();
        }
+
        CheckStack();  // TODO(1222600): ignore if body contains calls.
        VisitAndSpill(node->body());

-      // Compile the "test".
+      // Compile the test.
        if (info == ALWAYS_TRUE) {
-        if (frame_ != NULL) {
+        if (has_valid_frame()) {
            // If control can fall off the end of the body, jump back to the
            // top.
            node->continue_target()->Jump();
@@ -1513,13 +1546,15 @@
          ASSERT(info == DONT_KNOW);
          // We have to compile the test expression if it can be reached by
          // control flow falling out of the body or via continue.
-        if (frame_ != NULL || node->continue_target()->is_linked()) {
+        if (node->continue_target()->is_linked()) {
            node->continue_target()->Bind();
+        }
+        if (has_valid_frame()) {
            LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
                                  &body, node->break_target(), true);
-          if (frame_ != NULL) {
-            // A NULL frame here indicates that control did not fall out of
-            // the test expression.
+          if (has_valid_frame()) {
+            // A invalid frame here indicates that control did not
+            // fall out of the test expression.
              Branch(true, &body);
            }
          }
@@ -1528,36 +1563,35 @@
      }

      case LoopStatement::WHILE_LOOP: {
-      JumpTarget body(this);
-      // Generate the loop header.
-      if (info == ALWAYS_TRUE) {
-        // Merely label the body with the continue target.
-        node->continue_target()->Bind();
-      } else if (info == ALWAYS_FALSE) {
-        // There is no need to even compile the test or body.
-        break;
-      } else {
-        // Compile the test labeled with the continue target and label the
-        // body with the body target.
-        ASSERT(info == DONT_KNOW);
-        node->continue_target()->Bind();
+      // If the test is never true and has no side effects there is no need
+      // to compile the test or body.
+      if (info == ALWAYS_FALSE) break;
+
+      // Label the top of the loop with the continue target for the  
backward
+      // CFG edge.
+      node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
+      node->continue_target()->Bind();
+
+      if (info == DONT_KNOW) {
+        JumpTarget body(this);
          LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
                                &body, node->break_target(), true);
-        if (frame_ != NULL) {
+        if (has_valid_frame()) {
            // A NULL frame indicates that control did not fall out of the
            // test expression.
            Branch(false, node->break_target());
          }
-        if (frame_ != NULL || body.is_linked()) {
+        if (has_valid_frame() || body.is_linked()) {
            body.Bind();
          }
        }
-      if (frame_ != NULL) {
+
+      if (has_valid_frame()) {
          CheckStack();  // TODO(1222600): ignore if body contains calls.
          VisitAndSpill(node->body());

          // If control flow can fall out of the body, jump back to the top.
-        if (frame_ != NULL) {
+        if (has_valid_frame()) {
            node->continue_target()->Jump();
          }
        }
@@ -1565,8 +1599,8 @@
      }

      case LoopStatement::FOR_LOOP: {
-      JumpTarget loop(this);
-      JumpTarget body(this);
+      JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
+
        if (node->init() != NULL) {
          VisitAndSpill(node->init());
        }
@@ -1577,44 +1611,48 @@
        // If there is no update statement, label the top of the loop with  
the
        // continue target, otherwise with the loop target.
        if (node->next() == NULL) {
+        node->continue_target()->Initialize(this,  
JumpTarget::BIDIRECTIONAL);
          node->continue_target()->Bind();
        } else {
+        node->continue_target()->Initialize(this);
          loop.Bind();
        }

        // If the test is always true, there is no need to compile it.
        if (info == DONT_KNOW) {
+        JumpTarget body(this);
          LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
                                &body, node->break_target(), true);
-        if (frame_ != NULL) {
+        if (has_valid_frame()) {
            Branch(false, node->break_target());
          }
-        if (frame_ != NULL || body.is_linked()) {
+        if (has_valid_frame() || body.is_linked()) {
            body.Bind();
          }
        }

-      if (frame_ != NULL) {
+      if (has_valid_frame()) {
          CheckStack();  // TODO(1222600): ignore if body contains calls.
          VisitAndSpill(node->body());

          if (node->next() == NULL) {
            // If there is no update statement and control flow can fall out
            // of the loop, jump directly to the continue label.
-          if (frame_ != NULL) {
+          if (has_valid_frame()) {
              node->continue_target()->Jump();
            }
          } else {
            // If there is an update statement and control flow can reach it
            // via falling out of the body of the loop or continuing, we
            // compile the update statement.
-          if (frame_ != NULL || node->continue_target()->is_linked()) {
+          if (node->continue_target()->is_linked()) {
              node->continue_target()->Bind();
+          }
+          if (has_valid_frame()) {
              // Record source position of the statement as this code which  
is
              // after the code for the body actually belongs to the loop
              // statement and not the body.
              CodeForStatementPosition(node);
-
              VisitAndSpill(node->next());
              loop.Jump();
            }
@@ -1680,8 +1718,10 @@

    primitive.Bind();
    frame_->EmitPush(r0);
-  __ mov(r0, Operand(0));
-  frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, 1);
+  Result arg_count = allocator_->Allocate(r0);
+  ASSERT(arg_count.is_valid());
+  __ mov(arg_count.reg(), Operand(0));
+  frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1);


    jsobject.Bind();
@@ -1761,9 +1801,15 @@
    __ ldr(r0, frame_->ElementAt(4));  // push enumerable
    frame_->EmitPush(r0);
    frame_->EmitPush(r3);  // push entry
-  __ mov(r0, Operand(1));
-  frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2);
-  __ mov(r3, Operand(r0));
+  Result arg_count_register = allocator_->Allocate(r0);
+  ASSERT(arg_count_register.is_valid());
+  __ mov(arg_count_register.reg(), Operand(1));
+  Result result = frame_->InvokeBuiltin(Builtins::FILTER_KEY,
+                                        CALL_JS,
+                                        &arg_count_register,
+                                        2);
+  __ mov(r3, Operand(result.reg()));
+  result.Unuse();

    // If the property has been removed while iterating, we just skip it.
    __ cmp(r3, Operand(Factory::null_value()));
@@ -2271,26 +2317,36 @@
        : DeferredCode(generator), node_(node) {
      set_comment("[ ObjectLiteralDeferred");
    }
+
    virtual void Generate();
+
   private:
    ObjectLiteral* node_;
  };


  void ObjectLiteralDeferred::Generate() {
+  // Argument is passed in r1.
+  enter()->Bind();
+  VirtualFrame::SpilledScope spilled_scope(generator());
+
    // If the entry is undefined we call the runtime system to computed
    // the literal.

+  VirtualFrame* frame = generator()->frame();
    // Literal array (0).
-  __ push(r1);
+  frame->Push(r1);
    // Literal index (1).
    __ mov(r0, Operand(Smi::FromInt(node_->literal_index())));
-  __ push(r0);
+  frame->Push(r0);
    // Constant properties (2).
    __ mov(r0, Operand(node_->constant_properties()));
-  __ push(r0);
-  __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
-  __ mov(r2, Operand(r0));
+  frame->Push(r0);
+  Result boilerplate =
+      frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
+  __ mov(r2, Operand(boilerplate.reg()));
+  // Result is returned in r2.
+  exit()->Jump();
  }


@@ -2716,16 +2772,24 @@
    }

    // r0: the number of arguments.
-  __ mov(r0, Operand(arg_count));
+  Result num_args = allocator_->Allocate(r0);
+  ASSERT(num_args.is_valid());
+  __ mov(num_args.reg(), Operand(arg_count));

    // Load the function into r1 as per calling convention.
-  __ ldr(r1, frame_->ElementAt(arg_count + 1));
+  Result function = allocator_->Allocate(r1);
+  ASSERT(function.is_valid());
+  __ ldr(function.reg(), frame_->ElementAt(arg_count + 1));

    // Call the construct call builtin that handles allocation and
    // constructor invocation.
    CodeForSourcePosition(node->position());
    Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
-  frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1);
+  Result result = frame_->CallCodeObject(ic,
+                                         RelocInfo::CONSTRUCT_CALL,
+                                         &num_args,
+                                         &function,
+                                         arg_count + 1);

    // Discard old TOS value and push r0 on the stack (same as Pop(),  
push(r0)).
    __ str(r0, frame_->Top());
@@ -2962,8 +3026,10 @@
      if (property != NULL) {
        LoadAndSpill(property->obj());
        LoadAndSpill(property->key());
-      __ mov(r0, Operand(1));  // not counting receiver
-      frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+      frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);

      } else if (variable != NULL) {
        Slot* slot = variable->slot();
@@ -2971,8 +3037,10 @@
          LoadGlobal();
          __ mov(r0, Operand(variable->name()));
          frame_->EmitPush(r0);
-        __ mov(r0, Operand(1));  // not counting receiver
-        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);

        } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
          // lookup the context holding the named variable
@@ -2984,8 +3052,10 @@
          frame_->EmitPush(r0);
          __ mov(r0, Operand(variable->name()));
          frame_->EmitPush(r0);
-        __ mov(r0, Operand(1));  // not counting receiver
-        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);

        } else {
          // Default: Result of deleting non-global, not dynamically
@@ -3032,8 +3102,10 @@
          smi_label.Branch(eq);

          frame_->EmitPush(r0);
-        __ mov(r0, Operand(0));  // not counting receiver
-        frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, 1);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(0));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1);

          continue_label.Jump();
          smi_label.Bind();
@@ -3055,8 +3127,10 @@
          __ tst(r0, Operand(kSmiTagMask));
          continue_label.Branch(eq);
          frame_->EmitPush(r0);
-        __ mov(r0, Operand(0));  // not counting receiver
-        frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
+        Result arg_count = allocator_->Allocate(r0);
+        ASSERT(arg_count.is_valid());
+        __ mov(arg_count.reg(), Operand(0));  // not counting receiver
+        frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1);
          continue_label.Bind();
          break;
        }
@@ -3460,18 +3534,30 @@
        Comparison(eq, true);
        break;

-    case Token::IN:
-      __ mov(r0, Operand(1));  // not counting receiver
-      frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2);
-      frame_->EmitPush(r0);
+    case Token::IN: {
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+      Result result = frame_->InvokeBuiltin(Builtins::IN,
+                                            CALL_JS,
+                                            &arg_count,
+                                            2);
+      frame_->EmitPush(result.reg());
        break;
+    }

-    case Token::INSTANCEOF:
-      __ mov(r0, Operand(1));  // not counting receiver
-      frame_->InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS, 2);
-      __ tst(r0, Operand(r0));
+    case Token::INSTANCEOF: {
+      Result arg_count = allocator_->Allocate(r0);
+      ASSERT(arg_count.is_valid());
+      __ mov(arg_count.reg(), Operand(1));  // not counting receiver
+      Result result = frame_->InvokeBuiltin(Builtins::INSTANCE_OF,
+                                            CALL_JS,
+                                            &arg_count,
+                                            2);
+      __ tst(result.reg(), Operand(result.reg()));
        cc_reg_ = eq;
        break;
+    }

      default:
        UNREACHABLE();
@@ -3676,12 +3762,22 @@
        Comment cmnt(masm, "[ Store to named Property");
        // Call the appropriate IC code.
        Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-      frame->EmitPop(r0);  // value
-      // Setup the name register.
        Handle<String> name(GetName());
-      __ mov(r2, Operand(name));
-      frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
-      frame->EmitPush(r0);
+
+      Result value = cgen_->allocator()->Allocate(r0);
+      ASSERT(value.is_valid());
+      frame->EmitPop(value.reg());
+
+      // Setup the name register.
+      Result property_name = cgen_->allocator()->Allocate(r2);
+      ASSERT(property_name.is_valid());
+      __ mov(property_name.reg(), Operand(name));
+      Result answer = frame->CallCodeObject(ic,
+                                            RelocInfo::CODE_TARGET,
+                                            &value,
+                                            &property_name,
+                                            0);
+      frame->EmitPush(answer.reg());
        break;
      }

@@ -3694,9 +3790,12 @@
        // Call IC code.
        Handle<Code>  
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
        // TODO(1222589): Make the IC grab the values from the stack.
-      frame->EmitPop(r0);  // value
-      frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
-      frame->EmitPush(r0);
+      Result value = cgen_->allocator()->Allocate(r0);
+      ASSERT(value.is_valid());
+      frame->EmitPop(value.reg());  // value
+      Result result =
+          frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, &value, 0);
+      frame->EmitPush(result.reg());
        break;
      }


Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Tue Feb 17 00:08:26  
2009
@@ -786,9 +786,9 @@
  }


-class DeferredInlinedSmiOperation: public DeferredCode {
+class DeferredInlineSmiOperation: public DeferredCode {
   public:
-  DeferredInlinedSmiOperation(CodeGenerator* generator,
+  DeferredInlineSmiOperation(CodeGenerator* generator,
                                Token::Value op,
                                Smi* value,
                                OverwriteMode overwrite_mode)
@@ -796,7 +796,7 @@
          op_(op),
          value_(value),
          overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlinedSmiOperation");
+    set_comment("[ DeferredInlineSmiOperation");
    }

    virtual void Generate();
@@ -808,7 +808,7 @@
  };


-void DeferredInlinedSmiOperation::Generate() {
+void DeferredInlineSmiOperation::Generate() {
    Result left(generator());
    enter()->Bind(&left);
    generator()->frame()->Push(&left);
@@ -819,17 +819,17 @@
  }


-class DeferredInlinedSmiOperationReversed: public DeferredCode {
+class DeferredInlineSmiOperationReversed: public DeferredCode {
   public:
-  DeferredInlinedSmiOperationReversed(CodeGenerator* generator,
-                                      Token::Value op,
-                                      Smi* value,
-                                      OverwriteMode overwrite_mode)
+  DeferredInlineSmiOperationReversed(CodeGenerator* generator,
+                                     Token::Value op,
+                                     Smi* value,
+                                     OverwriteMode overwrite_mode)
        : DeferredCode(generator),
          op_(op),
          value_(value),
          overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlinedSmiOperationReversed");
+    set_comment("[ DeferredInlineSmiOperationReversed");
    }

    virtual void Generate();
@@ -841,7 +841,7 @@
  };


-void DeferredInlinedSmiOperationReversed::Generate() {
+void DeferredInlineSmiOperationReversed::Generate() {
    Result right(generator());
    enter()->Bind(&right);
    generator()->frame()->Push(value_);
@@ -852,15 +852,15 @@
  }


-class DeferredInlinedSmiAdd: public DeferredCode {
+class DeferredInlineSmiAdd: public DeferredCode {
   public:
-  DeferredInlinedSmiAdd(CodeGenerator* generator,
-                        Smi* value,
-                        OverwriteMode overwrite_mode)
+  DeferredInlineSmiAdd(CodeGenerator* generator,
+                       Smi* value,
+                       OverwriteMode overwrite_mode)
        : DeferredCode(generator),
          value_(value),
          overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlinedSmiAdd");
+    set_comment("[ DeferredInlineSmiAdd");
    }

    virtual void Generate();
@@ -871,7 +871,7 @@
  };


-void DeferredInlinedSmiAdd::Generate() {
+void DeferredInlineSmiAdd::Generate() {
    // Undo the optimistic add operation and call the shared stub.
    Result left(generator());  // Initially left + value_.
    enter()->Bind(&left);
@@ -886,15 +886,15 @@
  }


-class DeferredInlinedSmiAddReversed: public DeferredCode {
+class DeferredInlineSmiAddReversed: public DeferredCode {
   public:
-  DeferredInlinedSmiAddReversed(CodeGenerator* generator,
-                                Smi* value,
-                                OverwriteMode overwrite_mode)
+  DeferredInlineSmiAddReversed(CodeGenerator* generator,
+                               Smi* value,
+                               OverwriteMode overwrite_mode)
        : DeferredCode(generator),
          value_(value),
          overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlinedSmiAddReversed");
+    set_comment("[ DeferredInlineSmiAddReversed");
    }

    virtual void Generate();
@@ -905,7 +905,7 @@
  };


-void DeferredInlinedSmiAddReversed::Generate() {
+void DeferredInlineSmiAddReversed::Generate() {
    // Undo the optimistic add operation and call the shared stub.
    Result right(generator());  // Initially value_ + right.
    enter()->Bind(&right);
@@ -920,15 +920,15 @@
  }


-class DeferredInlinedSmiSub: public DeferredCode {
+class DeferredInlineSmiSub: public DeferredCode {
   public:
-  DeferredInlinedSmiSub(CodeGenerator* generator,
-                        Smi* value,
-                        OverwriteMode overwrite_mode)
+  DeferredInlineSmiSub(CodeGenerator* generator,
+                       Smi* value,
+                       OverwriteMode overwrite_mode)
        : DeferredCode(generator),
          value_(value),
          overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlinedSmiSub");
+    set_comment("[ DeferredInlineSmiSub");
    }

    virtual void Generate();
@@ -939,7 +939,7 @@
  };


-void DeferredInlinedSmiSub::Generate() {
+void DeferredInlineSmiSub::Generate() {
    // Undo the optimistic sub operation and call the shared stub.
    Result left(generator());  // Initially left - value_.
    enter()->Bind(&left);
@@ -954,15 +954,15 @@
  }


-class DeferredInlinedSmiSubReversed: public DeferredCode {
+class DeferredInlineSmiSubReversed: public DeferredCode {
   public:
-  DeferredInlinedSmiSubReversed(CodeGenerator* generator,
-                                Smi* value,
-                                OverwriteMode overwrite_mode)
+  DeferredInlineSmiSubReversed(CodeGenerator* generator,
+                               Smi* value,
+                               OverwriteMode overwrite_mode)
        : DeferredCode(generator),
          value_(value),
          overwrite_mode_(overwrite_mode) {
-    set_comment("[ DeferredInlinedSmiSubReversed");
+    set_comment("[ DeferredInlineSmiSubReversed");
    }

    virtual void Generate();
@@ -973,7 +973,7 @@
  };


-void DeferredInlinedSmiSubReversed::Generate() {
+void DeferredInlineSmiSubReversed::Generate() {
    // Call the shared stub.
    Result right(generator());
    enter()->Bind(&right);
@@ -1009,10 +1009,10 @@
      case Token::ADD: {
        DeferredCode* deferred = NULL;
        if (!reversed) {
-        deferred = new DeferredInlinedSmiAdd(this, smi_value,  
overwrite_mode);
+        deferred = new DeferredInlineSmiAdd(this, smi_value,  
overwrite_mode);
        } else {
-        deferred = new DeferredInlinedSmiAddReversed(this, smi_value,
-                                                     overwrite_mode);
+        deferred = new DeferredInlineSmiAddReversed(this, smi_value,
+                                                    overwrite_mode);
        }
        Result operand = frame_->Pop();
        operand.ToRegister();
@@ -1033,17 +1033,17 @@
        if (!reversed) {
          operand.ToRegister();
          frame_->Spill(operand.reg());
-        deferred = new DeferredInlinedSmiSub(this,
-                                             smi_value,
-                                             overwrite_mode);
+        deferred = new DeferredInlineSmiSub(this,
+                                            smi_value,
+                                            overwrite_mode);
          __ sub(Operand(operand.reg()), Immediate(value));
          answer = operand;
        } else {
          answer = allocator()->Allocate();
          ASSERT(answer.is_valid());
-        deferred = new DeferredInlinedSmiSubReversed(this,
-                                                     smi_value,
-                                                     overwrite_mode);
+        deferred = new DeferredInlineSmiSubReversed(this,
+                                                    smi_value,
+                                                    overwrite_mode);
          __ mov(answer.reg(), Immediate(value));
          if (operand.is_register()) {
            __ sub(answer.reg(), Operand(operand.reg()));
@@ -1072,8 +1072,8 @@
          // In the slow case, this masking is done inside the runtime call.
          int shift_value = int_value & 0x1f;
          DeferredCode* deferred =
-          new DeferredInlinedSmiOperation(this, Token::SAR, smi_value,
-                                          overwrite_mode);
+          new DeferredInlineSmiOperation(this, Token::SAR, smi_value,
+                                         overwrite_mode);
          Result result = frame_->Pop();
          result.ToRegister();
          __ test(result.reg(), Immediate(kSmiTagMask));
@@ -1098,8 +1098,8 @@
          // In the slow case, this masking is done inside the runtime call.
          int shift_value = int_value & 0x1f;
          DeferredCode* deferred =
-        new DeferredInlinedSmiOperation(this, Token::SHR, smi_value,
-                                        overwrite_mode);
+        new DeferredInlineSmiOperation(this, Token::SHR, smi_value,
+                                       overwrite_mode);
          Result operand = frame_->Pop();
          operand.ToRegister();
          __ test(operand.reg(), Immediate(kSmiTagMask));
@@ -1135,8 +1135,8 @@
          // In the slow case, this masking is done inside the runtime call.
          int shift_value = int_value & 0x1f;
          DeferredCode* deferred =
-        new DeferredInlinedSmiOperation(this, Token::SHL, smi_value,
-                                        overwrite_mode);
+        new DeferredInlineSmiOperation(this, Token::SHL, smi_value,
+                                       overwrite_mode);
          Result operand = frame_->Pop();
          operand.ToRegister();
          __ test(operand.reg(), Immediate(kSmiTagMask));
@@ -1167,11 +1167,11 @@
      case Token::BIT_AND: {
        DeferredCode* deferred = NULL;
        if (!reversed) {
-        deferred =  new DeferredInlinedSmiOperation(this, op, smi_value,
-                                                    overwrite_mode);
+        deferred =  new DeferredInlineSmiOperation(this, op, smi_value,
+                                                   overwrite_mode);
        } else {
-        deferred = new DeferredInlinedSmiOperationReversed(this, op,  
smi_value,
-                                                           overwrite_mode);
+        deferred = new DeferredInlineSmiOperationReversed(this, op,  
smi_value,
+                                                          overwrite_mode);
        }
        Result operand = frame_->Pop();
        operand.ToRegister();
@@ -2156,7 +2156,7 @@
          // We have to compile the test expression if it can be reached by
          // control flow falling out of the body or via continue.
          if (node->continue_target()->is_linked()) {
-        node->continue_target()->Bind();
+          node->continue_target()->Bind();
          }
          if (has_valid_frame()) {
            ControlDestination dest(&body, node->break_target(), false);
@@ -3595,7 +3595,7 @@
                                           RelocInfo::CONSTRUCT_CALL,
                                           &num_args,
                                           &function,
-                                         args->length() + 1);
+                                         arg_count + 1);

    // Replace the function on the stack with the result.
    frame_->SetElementAt(0, &result);

Modified: branches/experimental/toiger/src/virtual-frame-arm.cc
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-arm.cc       (original)
+++ branches/experimental/toiger/src/virtual-frame-arm.cc       Tue Feb 17  
00:08:26 2009
@@ -151,22 +151,71 @@


  void VirtualFrame::MergeTo(VirtualFrame* expected) {
-  UNIMPLEMENTED();
+  Comment cmnt(masm_, "[ Merge frame");
+  // We should always be merging the code generator's current frame to an
+  // expected frame.
+  ASSERT(cgen_->frame() == this);
+
+  // Adjust the stack pointer upward (toward the top of the virtual
+  // frame) if necessary.
+  if (stack_pointer_ < expected->stack_pointer_) {
+    int difference = expected->stack_pointer_ - stack_pointer_;
+    stack_pointer_ = expected->stack_pointer_;
+    __ sub(sp, sp, Operand(difference * kPointerSize));
+  }
+
+  MergeMoveRegistersToMemory(expected);
+  MergeMoveRegistersToRegisters(expected);
+  MergeMoveMemoryToRegisters(expected);
+
+  // Fix any sync bit problems.
+  for (int i = 0; i <= stack_pointer_; i++) {
+    FrameElement source = elements_[i];
+    FrameElement target = expected->elements_[i];
+    if (source.is_synced() && !target.is_synced()) {
+      elements_[i].clear_sync();
+    } else if (!source.is_synced() && target.is_synced()) {
+      SyncElementAt(i);
+    }
+  }
+
+  // Adjust the stack point downard if necessary.
+  if (stack_pointer_ > expected->stack_pointer_) {
+    int difference = stack_pointer_ - expected->stack_pointer_;
+    stack_pointer_ = expected->stack_pointer_;
+    __ add(sp, sp, Operand(difference * kPointerSize));
+  }
+
+  // At this point, the frames should be identical.
+  ASSERT(Equals(expected));
  }


  void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
-  UNIMPLEMENTED();
+  ASSERT(stack_pointer_ >= expected->stack_pointer_);
+
+  // Move registers, constants, and copies to memory.  Perform moves
+  // from the top downward in the frame in order to leave the backing
+  // stores of copies in registers.
+  //
+  // Moving memory-backed copies to memory requires a spare register
+  // for the memory-to-memory moves.  Since we are performing a merge,
+  // we use esi (which is already saved in the frame).  We keep track
+  // of the index of the frame element esi is caching or kIllegalIndex
+  // if esi has not been disturbed.
+
+  for (int i = 0; i < elements_.length(); i++) {
+    ASSERT(elements_[i].is_memory());
+    ASSERT(expected->elements_[i].is_memory());
+  }
  }


  void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
-  UNIMPLEMENTED();
  }


  void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
-  UNIMPLEMENTED();
  }


@@ -192,6 +241,8 @@
    // Adjust FP to point to saved FP.
    frame_pointer_ = elements_.length() - 2;
    __ add(fp, sp, Operand(2 * kPointerSize));
+  cgen_->allocator()->Unuse(r1);
+  cgen_->allocator()->Unuse(lr);
  }


@@ -296,10 +347,14 @@

  Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
                                     InvokeJSFlags flags,
+                                   Result* arg_count_register,
                                     int frame_arg_count) {
-  UNIMPLEMENTED();
-  Result invalid(cgen_);
-  return invalid;
+  ASSERT(arg_count_register->reg().is(r0));
+  PrepareForCall(frame_arg_count, frame_arg_count);
+  arg_count_register->Unuse();
+  __ InvokeBuiltin(id, flags);
+  Result result = cgen_->allocator()->Allocate(r0);
+  return result;
  }


@@ -346,9 +401,30 @@
                                      Result* arg0,
                                      Result* arg1,
                                      int dropped_args) {
-  UNIMPLEMENTED();
-  Result invalid(cgen_);
-  return invalid;
+  int spilled_args = 1;
+  switch (code->kind()) {
+    case Code::STORE_IC:
+      ASSERT(arg0->reg().is(r0));
+      ASSERT(arg1->reg().is(r2));
+      ASSERT(dropped_args == 0);
+      spilled_args = 1;
+      break;
+    case Code::BUILTIN:
+      ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall));
+      ASSERT(arg0->reg().is(r0));
+      ASSERT(arg1->reg().is(r1));
+      spilled_args = dropped_args + 1;
+      break;
+    default:
+      // No other types of code objects are called with values
+      // in exactly two registers.
+      UNREACHABLE();
+      break;
+  }
+  PrepareForCall(spilled_args, dropped_args);
+  arg0->Unuse();
+  arg1->Unuse();
+  return RawCallCodeObject(code, rmode);
  }



Modified: branches/experimental/toiger/src/virtual-frame-arm.h
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-arm.h        (original)
+++ branches/experimental/toiger/src/virtual-frame-arm.h        Tue Feb 17  
00:08:26 2009
@@ -243,6 +243,7 @@
    // removes from) the top of the physical frame.
    Result InvokeBuiltin(Builtins::JavaScript id,
                         InvokeJSFlags flag,
+                       Result* arg_count_register,
                         int frame_arg_count);

    // Call into a JS code object, given the number of arguments it

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

Reply via email to