Revision: 3455
Author: [email protected]
Date: Fri Dec 11 08:09:16 2009
Log: Adding compound assignments to the top-level compiler.

Review URL: http://codereview.chromium.org/486008
http://code.google.com/p/v8/source/detail?r=3455

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/ast.h
  /branches/bleeding_edge/src/compiler.cc
  /branches/bleeding_edge/src/fast-codegen.cc
  /branches/bleeding_edge/src/fast-codegen.h
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/token.h
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Thu Dec 10 06:06:08  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Fri Dec 11 08:09:16  
2009
@@ -541,18 +541,24 @@

  void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
    Comment cmnt(masm_, "[ VariableProxy");
-  Expression* rewrite = expr->var()->rewrite();
+  EmitVariableLoad(expr->var(), expr->context());
+}
+
+
+void FastCodeGenerator::EmitVariableLoad(Variable* var,
+                                         Expression::Context context) {
+  Expression* rewrite = var->rewrite();
    if (rewrite == NULL) {
-    ASSERT(expr->var()->is_global());
+    ASSERT(var->is_global());
      Comment cmnt(masm_, "Global variable");
      // Use inline caching. Variable name is passed in r2 and the global
      // object on the stack.
      __ ldr(ip, CodeGenerator::GlobalObject());
      __ push(ip);
-    __ mov(r2, Operand(expr->name()));
+    __ mov(r2, Operand(var->name()));
      Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
      __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
-    DropAndMove(expr->context(), r0);
+    DropAndMove(context, r0);
    } else if (rewrite->AsSlot() != NULL) {
      Slot* slot = rewrite->AsSlot();
      if (FLAG_debug_code) {
@@ -573,7 +579,7 @@
            UNREACHABLE();
        }
      }
-    Move(expr->context(), slot, r0);
+    Move(context, slot, r0);
    } else {
      // A variable has been rewritten into an explicit access to
      // an object property.
@@ -608,7 +614,7 @@
      __ Call(ic, RelocInfo::CODE_TARGET);

      // Drop key and object left on the stack by IC, and push the result.
-    DropAndMove(expr->context(), r0, 2);
+    DropAndMove(context, r0, 2);
    }
  }

@@ -829,6 +835,34 @@
      }
    }
  }
+
+
+void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
+                                              Expression::Context context)  
{
+  Literal* key = prop->key()->AsLiteral();
+  __ mov(r2, Operand(key->handle()));
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  Move(context, r0);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyLoad(Expression::Context context)  
{
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  Move(context, r0);
+}
+
+
+void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
+                                                 Expression::Context  
context) {
+  __ pop(r0);
+  __ pop(r1);
+  GenericBinaryOpStub stub(op,
+                           NO_OVERWRITE);
+  __ CallStub(&stub);
+  Move(context, r0);
+}


  void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
=======================================
--- /branches/bleeding_edge/src/ast.h   Thu Nov 26 16:28:06 2009
+++ /branches/bleeding_edge/src/ast.h   Fri Dec 11 08:09:16 2009
@@ -1241,6 +1241,8 @@
    Expression* target() const { return target_; }
    Expression* value() const { return value_; }
    int position() { return pos_; }
+  // This check relies on the definition order of token in token.h.
+  bool is_compound() const { return op() > Token::ASSIGN; }

    // An initialization block is a series of statments of the form
    // x.y.z.a = ...; x.y.z.b = ...; etc. The parser marks the beginning and
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Thu Dec 10 06:06:08 2009
+++ /branches/bleeding_edge/src/compiler.cc     Fri Dec 11 08:09:16 2009
@@ -883,9 +883,6 @@
    // non-context (stack-allocated) locals, and global variables.
    Token::Value op = expr->op();
    if (op == Token::INIT_CONST) BAILOUT("initialize constant");
-  if (op != Token::ASSIGN && op != Token::INIT_VAR) {
-    BAILOUT("compound assignment");
-  }

    Variable* var = expr->target()->AsVariableProxy()->AsVariable();
    Property* prop = expr->target()->AsProperty();
=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Thu Dec 10 06:06:08 2009
+++ /branches/bleeding_edge/src/fast-codegen.cc Fri Dec 11 08:09:16 2009
@@ -512,7 +512,6 @@

  void FastCodeGenerator::VisitAssignment(Assignment* expr) {
    Comment cmnt(masm_, "[ Assignment");
-  ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);

    // Record source code position of the (possible) IC call.
    SetSourcePosition(expr->position());
@@ -530,26 +529,60 @@
          : KEYED_PROPERTY;
    }

-  Expression* rhs = expr->value();
-  ASSERT_EQ(Expression::kValue, rhs->context());
-
+  // Evaluate LHS expression.
    switch (assign_type) {
      case VARIABLE:
-      Visit(rhs);
-      EmitVariableAssignment(expr);
+      // Nothing to do here.
        break;
      case NAMED_PROPERTY:
        Visit(prop->obj());
        ASSERT_EQ(Expression::kValue, prop->obj()->context());
-      Visit(rhs);
-      EmitNamedPropertyAssignment(expr);
        break;
      case KEYED_PROPERTY:
        Visit(prop->obj());
        ASSERT_EQ(Expression::kValue, prop->obj()->context());
        Visit(prop->key());
        ASSERT_EQ(Expression::kValue, prop->key()->context());
-      Visit(rhs);
+      break;
+  }
+
+  // If we have a compound assignment: Get value of LHS expression and
+  // store in on top of the stack.
+  // Note: Relies on kValue context being 'stack'.
+  if (expr->is_compound()) {
+    switch (assign_type) {
+      case VARIABLE:
+        EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
+                         Expression::kValue);
+        break;
+      case NAMED_PROPERTY:
+        EmitNamedPropertyLoad(prop, Expression::kValue);
+        break;
+      case KEYED_PROPERTY:
+        EmitKeyedPropertyLoad(Expression::kValue);
+        break;
+    }
+  }
+
+  // Evaluate RHS expression.
+  Expression* rhs = expr->value();
+  ASSERT_EQ(Expression::kValue, rhs->context());
+  Visit(rhs);
+
+  // If we have a compount assignment: Apply operator.
+  if (expr->is_compound()) {
+    EmitCompoundAssignmentOp(expr->binary_op(), Expression::kValue);
+  }
+
+  // Store the value.
+  switch (assign_type) {
+    case VARIABLE:
+      EmitVariableAssignment(expr);
+      break;
+    case NAMED_PROPERTY:
+      EmitNamedPropertyAssignment(expr);
+      break;
+    case KEYED_PROPERTY:
        EmitKeyedPropertyAssignment(expr);
        break;
    }
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Thu Dec 10 06:06:08 2009
+++ /branches/bleeding_edge/src/fast-codegen.h  Fri Dec 11 08:09:16 2009
@@ -242,8 +242,23 @@
    void EmitCallWithStub(Call* expr);
    void EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info);

+  // Platform-specific code for loading variables.
+  void EmitVariableLoad(Variable* expr, Expression::Context context);
+
    // Platform-specific support for compiling assignments.

+  // Load a value from a named property and push the result on the stack.
+  // The receiver is left on the stack by the IC.
+  void EmitNamedPropertyLoad(Property* expr, Expression::Context context);
+
+  // Load a value from a named property and push the result on the stack.
+  // The receiver and the key is left on the stack by the IC.
+  void EmitKeyedPropertyLoad(Expression::Context context);
+
+  // Apply the compound assignment operator. Expects both operands on top
+  // of the stack.
+  void EmitCompoundAssignmentOp(Token::Value op, Expression::Context  
context);
+
    // Complete a variable assignment.  The right-hand-side value is expected
    // on top of the stack.
    void EmitVariableAssignment(Assignment* expr);
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Thu Dec 10  
06:06:08 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Fri Dec 11  
08:09:16 2009
@@ -535,14 +535,20 @@

  void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
    Comment cmnt(masm_, "[ VariableProxy");
-  Expression* rewrite = expr->var()->rewrite();
+  EmitVariableLoad(expr->var(), expr->context());
+}
+
+
+void FastCodeGenerator::EmitVariableLoad(Variable* var,
+                                         Expression::Context context) {
+  Expression* rewrite = var->rewrite();
    if (rewrite == NULL) {
-    ASSERT(expr->var()->is_global());
+    ASSERT(var->is_global());
      Comment cmnt(masm_, "Global variable");
      // Use inline caching. Variable name is passed in ecx and the global
      // object on the stack.
      __ push(CodeGenerator::GlobalObject());
-    __ mov(ecx, expr->name());
+    __ mov(ecx, var->name());
      Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
      // By emitting a nop we make sure that we do not have a test eax
@@ -550,8 +556,7 @@
      // Remember that the assembler may choose to do peephole optimization
      // (eg, push/pop elimination).
      __ nop();
-
-    DropAndMove(expr->context(), eax);
+    DropAndMove(context, eax);
    } else if (rewrite->AsSlot() != NULL) {
      Slot* slot = rewrite->AsSlot();
      if (FLAG_debug_code) {
@@ -572,7 +577,7 @@
            UNREACHABLE();
        }
      }
-    Move(expr->context(), slot, eax);
+    Move(context, slot, eax);
    } else {
      Comment cmnt(masm_, "Variable rewritten to Property");
      // A variable has been rewritten into an explicit access to
@@ -606,9 +611,8 @@
      // Notice: We must not have a "test eax, ..." instruction after
      // the call. It is treated specially by the LoadIC code.
      __ nop();
-
-    // Drop key and object left on the stack by IC, and push the result.
-    DropAndMove(expr->context(), eax, 2);
+    // Drop key and object left on the stack by IC.
+    DropAndMove(context, eax, 2);
    }
  }

@@ -820,6 +824,32 @@
      }
    }
  }
+
+
+void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,  
Expression::Context context) {
+  Literal* key = prop->key()->AsLiteral();
+  __ mov(ecx, Immediate(key->handle()));
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  Move(context, eax);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyLoad(Expression::Context context)  
{
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  Move(context, eax);
+}
+
+
+void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
+                                                 Expression::Context  
context) {
+  GenericBinaryOpStub stub(op,
+                           NO_OVERWRITE,
+                           NO_GENERIC_BINARY_FLAGS);
+  __ CallStub(&stub);
+  Move(context, eax);
+}


  void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
=======================================
--- /branches/bleeding_edge/src/token.h Fri Dec 11 02:40:01 2009
+++ /branches/bleeding_edge/src/token.h Fri Dec 11 08:09:16 2009
@@ -66,8 +66,9 @@
    T(DEC, "--", 0)                                                       \
                                                                          \
    /* Assignment operators. */                                           \
-  /* IsAssignmentOp() relies on this block of enum values */            \
-  /* being contiguous and sorted in the same order! */                  \
+  /* IsAssignmentOp() and Assignment::is_compound() relies on */        \
+  /* this block of enum values being contiguous and sorted in the */    \
+  /* same order! */                                                     \
    T(INIT_VAR, "=init_var", 2)  /* AST-use only. */                      \
    T(INIT_CONST, "=init_const", 2)  /* AST-use only. */                  \
    T(ASSIGN, "=", 2)                                                     \
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Thu Dec 10 06:06:08  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Fri Dec 11 08:09:16  
2009
@@ -545,14 +545,20 @@

  void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
    Comment cmnt(masm_, "[ VariableProxy");
-  Expression* rewrite = expr->var()->rewrite();
+  EmitVariableLoad(expr->var(), expr->context());
+}
+
+
+void FastCodeGenerator::EmitVariableLoad(Variable* var,
+                                          Expression::Context context) {
+  Expression* rewrite = var->rewrite();
    if (rewrite == NULL) {
-    ASSERT(expr->var()->is_global());
+    ASSERT(var->is_global());
      Comment cmnt(masm_, "Global variable");
      // Use inline caching. Variable name is passed in rcx and the global
      // object on the stack.
      __ push(CodeGenerator::GlobalObject());
-    __ Move(rcx, expr->name());
+    __ Move(rcx, var->name());
      Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
      __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
      // A test rax instruction following the call is used by the IC to
@@ -560,7 +566,7 @@
      // is no test rax instruction here.
      __ nop();

-    DropAndMove(expr->context(), rax);
+    DropAndMove(context, rax);
    } else if (rewrite->AsSlot() != NULL) {
      Slot* slot = rewrite->AsSlot();
      if (FLAG_debug_code) {
@@ -581,7 +587,7 @@
            UNREACHABLE();
        }
      }
-    Move(expr->context(), slot, rax);
+    Move(context, slot, rax);
    } else {
      // A variable has been rewritten into an explicit access to
      // an object property.
@@ -615,7 +621,7 @@
      // the call. It is treated specially by the LoadIC code.

      // Drop key and object left on the stack by IC, and push the result.
-    DropAndMove(expr->context(), rax, 2);
+    DropAndMove(context, rax, 2);
    }
  }

@@ -827,6 +833,33 @@
      }
    }
  }
+
+
+void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
+                                              Expression::Context context)  
{
+  Literal* key = prop->key()->AsLiteral();
+  __ Move(rcx, key->handle());
+  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  Move(context, rax);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyLoad(Expression::Context context)  
{
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  Move(context, rax);
+}
+
+
+void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
+                                                 Expression::Context  
context) {
+  GenericBinaryOpStub stub(op,
+                           NO_OVERWRITE,
+                           NO_GENERIC_BINARY_FLAGS);
+  __ CallStub(&stub);
+  Move(context, rax);
+}


  void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {

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

Reply via email to