Revision: 3195
Author: [email protected]
Date: Mon Nov  2 03:01:47 2009
Log: Refactor the somewhat complicated code generation for assignments into
a platform-independent structure and a few platform-specific helpers
to do the heavy lifting.

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

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /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/x64/fast-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov  2 02:22:22  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov  2 03:01:47  
2009
@@ -572,127 +572,85 @@
  }


-void FastCodeGenerator::VisitAssignment(Assignment* expr) {
-  Comment cmnt(masm_, "[ Assignment");
-  ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
-
-  // Record the source position for the assignment.
-  SetSourcePosition(expr->position());
-
-  // Left-hand side can only be a property, a global or
-  // a (parameter or local) slot.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  Expression* rhs = expr->value();
-  if (var == NULL) {
-    // Assignment to a property.
-    ASSERT(expr->target()->AsProperty() != NULL);
-    Property* prop = expr->target()->AsProperty();
-    Visit(prop->obj());
-    Literal* literal_key = prop->key()->AsLiteral();
-    uint32_t dummy;
-    if (literal_key != NULL &&
-        literal_key->handle()->IsSymbol() &&
-        !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
-      // NAMED property assignment
-      Visit(rhs);
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      __ pop(r0);
-      __ mov(r2, Operand(literal_key->handle()));
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-      __ Call(ic, RelocInfo::CODE_TARGET);
-    } else {
-      // KEYED property assignment
-      Visit(prop->key());
-      Visit(rhs);
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      __ pop(r0);
-      Handle<Code>  
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
-      __ Call(ic, RelocInfo::CODE_TARGET);
-      // Drop key from the stack
-      __ pop();
-    }
-    // Overwrite the receiver on the stack with the result if needed.
-    DropAndMove(expr->context(), r0);
-  } else if (var->is_global()) {
+void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
+                                               Variable* var) {
+  if (var->is_global()) {
      // Assignment to a global variable, use inline caching.   
Right-hand-side
-    // value is passed in r0, variable name in r2, and the global object on
-    // the stack.
-
-    // Code for the right-hand-side expression depends on its type.
-    if (rhs->AsLiteral() != NULL) {
-      __ mov(r0, Operand(rhs->AsLiteral()->handle()));
-    } else {
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      Visit(rhs);
-      __ pop(r0);
-    }
+    // value is passed in r0, variable name in r2, and the global object
+    // on the stack.
+    __ pop(r0);
      __ mov(r2, Operand(var->name()));
      __ ldr(ip, CodeGenerator::GlobalObject());
      __ push(ip);
      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
      __ Call(ic, RelocInfo::CODE_TARGET);
      // Overwrite the global object on the stack with the result if needed.
-    DropAndMove(expr->context(), r0);
+    DropAndMove(context, r0);
    } else {
-    // Local or parameter assignment.
-
-    // Code for the right-hand side expression depends on its type.
-    if (rhs->AsLiteral() != NULL) {
-      // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
-      // discarded result.  Always perform the assignment.
-      __ mov(ip, Operand(rhs->AsLiteral()->handle()));
-      __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
-      Move(expr->context(), ip);
-    } else {
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      Visit(rhs);
-      // Load right-hand side into ip.
-      switch (expr->context()) {
-        case Expression::kUninitialized:
-          UNREACHABLE();
-        case Expression::kEffect:
-          // Case 'var = temp'.  Discard right-hand-side temporary.
-          __ pop(r0);
-          __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
-          break;
-        case Expression::kValue:
-          // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
-          // temporary on the stack.
-          __ ldr(r0, MemOperand(sp));
-          __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
-          break;
-        case Expression::kTest:
-          // Case 'if (var = temp) ...'.
-          __ pop(r0);
-          __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
-          TestAndBranch(r0, true_label_, false_label_);
-          break;
-        case Expression::kValueTest: {
-          // Case '(var = temp) || ...' in value context.
-          Label discard;
-          __ ldr(r0, MemOperand(sp));
-          __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
-          TestAndBranch(r0, true_label_, &discard);
-          __ bind(&discard);
-          __ pop();
-          __ jmp(false_label_);
-          break;
-        }
-        case Expression::kTestValue: {
-          // Case '(var = temp) && ...' in value context.
-          Label discard;
-          __ ldr(r0, MemOperand(sp));
-          __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
-          TestAndBranch(r0, &discard, false_label_);
-          __ bind(&discard);
-          __ pop();
-          __ jmp(true_label_);
-          break;
-        }
+    switch (context) {
+      case Expression::kUninitialized:
+        UNREACHABLE();
+      case Expression::kEffect:
+        // Perform assignment and discard value.
+        __ pop(r0);
+        __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+        break;
+      case Expression::kValue:
+        // Perform assignment and preserve value.
+        __ ldr(r0, MemOperand(sp));
+        __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+        break;
+      case Expression::kTest:
+        // Perform assignment and test (and discard) value.
+        __ pop(r0);
+        __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+        TestAndBranch(r0, true_label_, false_label_);
+        break;
+      case Expression::kValueTest: {
+        Label discard;
+        __ ldr(r0, MemOperand(sp));
+        __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+        TestAndBranch(r0, true_label_, &discard);
+        __ bind(&discard);
+        __ pop();
+        __ jmp(false_label_);
+        break;
+      }
+      case Expression::kTestValue: {
+        Label discard;
+        __ ldr(r0, MemOperand(sp));
+        __ str(r0, MemOperand(fp, SlotOffset(var->slot())));
+        TestAndBranch(r0, &discard, false_label_);
+        __ bind(&discard);
+        __ pop();
+        __ jmp(true_label_);
+        break;
        }
      }
    }
  }
+
+
+void FastCodeGenerator::EmitNamedPropertyAssignment(
+    Expression::Context context,
+    Handle<Object> name) {
+  __ pop(r0);
+  __ mov(r2, Operand(name));
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  DropAndMove(context, r0);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyAssignment(
+    Expression::Context context) {
+  __ pop(r0);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  // Receiver and key are still on stack.
+  __ add(sp, sp, Operand(2 * kPointerSize));
+  Move(context, r0);
+}


  void FastCodeGenerator::VisitProperty(Property* expr) {
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Mon Nov  2 02:22:22 2009
+++ /branches/bleeding_edge/src/compiler.cc     Mon Nov  2 03:01:47 2009
@@ -736,18 +736,36 @@
    }

    Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  if (var == NULL) {
-    Property* prop = expr->target()->AsProperty();
-    if (prop == NULL) BAILOUT("non-variable, non-property assignment");
+  Property* prop = expr->target()->AsProperty();
+  if (var != NULL) {
+    // All global variables are supported.
+    if (!var->is_global()) {
+      if (var->slot() == NULL) {
+        // This is a parameter that has rewritten to an arguments access.
+        BAILOUT("non-global/non-slot assignment");
+      }
+      Slot::Type type = var->slot()->type();
+      if (type != Slot::PARAMETER && type != Slot::LOCAL) {
+        BAILOUT("non-parameter/non-local slot assignment");
+      }
+    }
+  } else if (prop != NULL) {
      ProcessExpression(prop->obj(), Expression::kValue);
      CHECK_BAILOUT;
-    ProcessExpression(prop->key(), Expression::kValue);
-  } else if (!var->is_global()) {
-    if (var->slot() == NULL) BAILOUT("Assigment with an unsupported LHS.");
-    Slot::Type type = var->slot()->type();
-    if (type != Slot::PARAMETER && type != Slot::LOCAL) {
-      BAILOUT("non-parameter/non-local slot assignment");
-    }
+    // We will only visit the key during code generation for keyed property
+    // stores.  Leave its expression context uninitialized for named
+    // property stores.
+    Literal* lit = prop->key()->AsLiteral();
+    uint32_t ignored;
+    if (lit == NULL ||
+        !lit->handle()->IsSymbol() ||
+        String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
+      ProcessExpression(prop->key(), Expression::kValue);
+      CHECK_BAILOUT;
+    }
+  } else {
+    // This is a throw reference error.
+    BAILOUT("non-variable/non-property assignment");
    }

    ProcessExpression(expr->value(), Expression::kValue);
=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Mon Nov  2 02:22:22 2009
+++ /branches/bleeding_edge/src/fast-codegen.cc Mon Nov  2 03:01:47 2009
@@ -422,6 +422,47 @@
  void FastCodeGenerator::VisitLiteral(Literal* expr) {
    Move(expr->context(), expr);
  }
+
+
+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());
+
+  Expression* rhs = expr->value();
+  // Left-hand side can only be a property, a global or a (parameter or
+  // local) slot.
+  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+  Property* prop = expr->target()->AsProperty();
+  if (var != NULL) {
+    Visit(rhs);
+    ASSERT_EQ(Expression::kValue, rhs->context());
+    EmitVariableAssignment(expr->context(), var);
+  } else if (prop != NULL) {
+    // Assignment to a property.
+    Visit(prop->obj());
+    ASSERT_EQ(Expression::kValue, prop->obj()->context());
+    // Use the expression context of the key subexpression to detect  
whether
+    // we have decided to us a named or keyed IC.
+    if (prop->key()->context() == Expression::kUninitialized) {
+      ASSERT(prop->key()->AsLiteral() != NULL);
+      Visit(rhs);
+      ASSERT_EQ(Expression::kValue, rhs->context());
+      EmitNamedPropertyAssignment(expr->context(),
+                                  prop->key()->AsLiteral()->handle());
+    } else {
+      Visit(prop->key());
+      ASSERT_EQ(Expression::kValue, prop->key()->context());
+      Visit(rhs);
+      ASSERT_EQ(Expression::kValue, rhs->context());
+      EmitKeyedPropertyAssignment(expr->context());
+    }
+  } else {
+    UNREACHABLE();
+  }
+}


  void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject*  
expr) {
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Fri Oct 30 07:06:48 2009
+++ /branches/bleeding_edge/src/fast-codegen.h  Mon Nov  2 03:01:47 2009
@@ -75,6 +75,21 @@
    void EmitCallWithStub(Call* expr);
    void EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info);

+  // Platform-specific support for compiling assignments.
+
+  // Complete a variable assignment.  The right-hand-side value are  
expected
+  // on top of the stack.
+  void EmitVariableAssignment(Expression::Context context, Variable* var);
+
+  // Complete a named property assignment.  The receiver and  
right-hand-side
+  // value are expected on top of the stack.
+  void EmitNamedPropertyAssignment(Expression::Context context,
+                                   Handle<Object> name);
+
+  // Complete a keyed property assignment.  The reciever, key, and
+  // right-hand-side value are expected on top of the stack.
+  void EmitKeyedPropertyAssignment(Expression::Context context);
+
    void SetFunctionPosition(FunctionLiteral* fun);
    void SetReturnPosition(FunctionLiteral* fun);
    void SetStatementPosition(Statement* stmt);
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Mon Nov  2  
02:22:22 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Mon Nov  2  
03:01:47 2009
@@ -586,129 +586,86 @@
  }


-void FastCodeGenerator::VisitAssignment(Assignment* expr) {
-  Comment cmnt(masm_, "[ Assignment");
-  ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
-
-  // Record the source position for the assignment.
-  SetSourcePosition(expr->position());
-
-  // Left-hand side can only be a property, a global or
-  // a (parameter or local) slot.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  Expression* rhs = expr->value();
-  if (var == NULL) {
-    // Assignment to a property.
-    ASSERT(expr->target()->AsProperty() != NULL);
-    Property* prop = expr->target()->AsProperty();
-    Visit(prop->obj());
-    Literal* literal_key = prop->key()->AsLiteral();
-    uint32_t dummy;
-    if (literal_key != NULL &&
-        literal_key->handle()->IsSymbol() &&
-        !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
-      // NAMED property assignment
-      Visit(rhs);
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      __ pop(eax);
-      __ mov(ecx, Immediate(literal_key->handle()));
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-      __ call(ic, RelocInfo::CODE_TARGET);
-      __ nop();
-    } else {
-      // KEYED property assignment
-      Visit(prop->key());
-      Visit(rhs);
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      __ pop(eax);
-      Handle<Code>  
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
-      __ call(ic, RelocInfo::CODE_TARGET);
-      __ nop();
-      // Drop key from the stack
-      __ add(Operand(esp), Immediate(kPointerSize));
-    }
-    // Overwrite the receiver on the stack with the result if needed.
-    DropAndMove(expr->context(), eax);
-  } else if (var->is_global()) {
+void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
+                                               Variable* var) {
+  if (var->is_global()) {
      // Assignment to a global variable, use inline caching.   
Right-hand-side
      // value is passed in eax, variable name in ecx, and the global object
      // on the stack.
-
-    // Code for the right-hand-side expression depends on its type.
-    if (rhs->AsLiteral() != NULL) {
-      __ mov(eax, rhs->AsLiteral()->handle());
-    } else {
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      Visit(rhs);
-      __ pop(eax);
-    }
-    // Record position for debugger.
-    SetSourcePosition(expr->position());
+    __ pop(eax);
      __ mov(ecx, var->name());
      __ push(CodeGenerator::GlobalObject());
      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
      __ call(ic, RelocInfo::CODE_TARGET);
      // Overwrite the global object on the stack with the result if needed.
-    DropAndMove(expr->context(), eax);
+    DropAndMove(context, eax);
    } else {
-    // Local or parameter assignment.
-    ASSERT(var->slot() != NULL);
-
-    // Code for the right-hand side expression depends on its type.
-    if (rhs->AsLiteral() != NULL) {
-      // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
-      // discarded result.  Always perform the assignment.
-      __ mov(eax, rhs->AsLiteral()->handle());
-      __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-      Move(expr->context(), eax);
-    } else {
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      Visit(rhs);
-      switch (expr->context()) {
-        case Expression::kUninitialized:
-          UNREACHABLE();
-        case Expression::kEffect:
-          // Case 'var = temp'.  Discard right-hand-side temporary.
-          __ pop(Operand(ebp, SlotOffset(var->slot())));
-          break;
-        case Expression::kValue:
-          // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
-          // temporary on the stack.
-          __ mov(eax, Operand(esp, 0));
-          __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-          break;
-        case Expression::kTest:
-          // Case 'if (var = temp) ...'.
-          __ pop(eax);
-          __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-          TestAndBranch(eax, true_label_, false_label_);
-          break;
-        case Expression::kValueTest: {
-          // Case '(var = temp) || ...' in value context.
-          Label discard;
-          __ mov(eax, Operand(esp, 0));
-          __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-          TestAndBranch(eax, true_label_, &discard);
-          __ bind(&discard);
-          __ add(Operand(esp), Immediate(kPointerSize));
-          __ jmp(false_label_);
-          break;
-        }
-        case Expression::kTestValue: {
-          // Case '(var = temp) && ...' in value context.
-          Label discard;
-          __ mov(eax, Operand(esp, 0));
-          __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-          TestAndBranch(eax, &discard, false_label_);
-          __ bind(&discard);
-          __ add(Operand(esp), Immediate(kPointerSize));
-          __ jmp(true_label_);
-          break;
-        }
+    switch (context) {
+      case Expression::kUninitialized:
+        UNREACHABLE();
+      case Expression::kEffect:
+        // Perform assignment and discard value.
+        __ pop(Operand(ebp, SlotOffset(var->slot())));
+        break;
+      case Expression::kValue:
+        // Perform assignment and preserve value.
+        __ mov(eax, Operand(esp, 0));
+        __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+        break;
+      case Expression::kTest:
+        // Perform assignment and test (and discard) value.
+        __ pop(eax);
+        __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+        TestAndBranch(eax, true_label_, false_label_);
+        break;
+      case Expression::kValueTest: {
+        Label discard;
+        __ mov(eax, Operand(esp, 0));
+        __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+        TestAndBranch(eax, true_label_, &discard);
+        __ bind(&discard);
+        __ add(Operand(esp), Immediate(kPointerSize));
+        __ jmp(false_label_);
+        break;
+      }
+      case Expression::kTestValue: {
+        Label discard;
+        __ mov(eax, Operand(esp, 0));
+        __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+        TestAndBranch(eax, &discard, false_label_);
+        __ bind(&discard);
+        __ add(Operand(esp), Immediate(kPointerSize));
+        __ jmp(true_label_);
+        break;
        }
      }
    }
  }
+
+
+void FastCodeGenerator::EmitNamedPropertyAssignment(
+    Expression::Context context,
+    Handle<Object> name) {
+  __ pop(eax);
+  __ mov(ecx, name);
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  DropAndMove(context, eax);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyAssignment(
+    Expression::Context context) {
+  __ pop(eax);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  // This nop signals to the IC that there is no inlined code at the call
+  // site for it to patch.
+  __ nop();
+  // Receiver and key are still on stack.
+  __ add(Operand(esp), Immediate(2 * kPointerSize));
+  Move(context, eax);
+}


  void FastCodeGenerator::VisitProperty(Property* expr) {
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov  2 02:22:22  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov  2 03:01:47  
2009
@@ -600,128 +600,86 @@
  }


-void FastCodeGenerator::VisitAssignment(Assignment* expr) {
-  Comment cmnt(masm_, "[ Assignment");
-  ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
-
-  // Record the source position for the assignment.
-  SetSourcePosition(expr->position());
-
-  // Left-hand side can only be a property, a global or
-  // a (parameter or local) slot.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  Expression* rhs = expr->value();
-  if (var == NULL) {
-    // Assignment to a property.
-    ASSERT(expr->target()->AsProperty() != NULL);
-    Property* prop = expr->target()->AsProperty();
-    Visit(prop->obj());
-    Literal* literal_key = prop->key()->AsLiteral();
-    uint32_t dummy;
-    if (literal_key != NULL &&
-        literal_key->handle()->IsSymbol() &&
-        !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) {
-      // NAMED property assignment
-      Visit(rhs);
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      __ pop(rax);
-      __ Move(rcx, literal_key->handle());
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-      __ call(ic, RelocInfo::CODE_TARGET);
-      __ nop();
-    } else {
-      // KEYED property assignment
-      Visit(prop->key());
-      Visit(rhs);
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      __ pop(rax);
-      Handle<Code>  
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
-      __ call(ic, RelocInfo::CODE_TARGET);
-      __ nop();
-      // Drop key from the stack
-      __ addq(rsp, Immediate(kPointerSize));
-    }
-    // Overwrite the receiver on the stack with the result if needed.
-    DropAndMove(expr->context(), rax);
-  } else if (var->is_global()) {
+void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
+                                               Variable* var) {
+  if (var->is_global()) {
      // Assignment to a global variable, use inline caching.   
Right-hand-side
      // value is passed in rax, variable name in rcx, and the global object
      // on the stack.
-
-    // Code for the right-hand-side expression depends on its type.
-    if (rhs->AsLiteral() != NULL) {
-      __ Move(rax, rhs->AsLiteral()->handle());
-    } else {
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      Visit(rhs);
-      __ pop(rax);
-    }
-    // Record position for debugger.
-    SetSourcePosition(expr->position());
+    __ pop(rax);
      __ Move(rcx, var->name());
      __ push(CodeGenerator::GlobalObject());
      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
      __ Call(ic, RelocInfo::CODE_TARGET);
      // Overwrite the global object on the stack with the result if needed.
-    DropAndMove(expr->context(), rax);
+    DropAndMove(context, rax);
    } else {
-    // Local or parameter assignment.
-
-    // Code for the right-hand-side expression depends on its type.
-    if (rhs->AsLiteral() != NULL) {
-      // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
-      // discarded result.  Always perform the assignment.
-      __ Move(kScratchRegister, rhs->AsLiteral()->handle());
-      __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
-      Move(expr->context(), kScratchRegister);
-    } else {
-      ASSERT_EQ(Expression::kValue, rhs->context());
-      Visit(rhs);
-      switch (expr->context()) {
-        case Expression::kUninitialized:
-          UNREACHABLE();
-        case Expression::kEffect:
-          // Case 'var = temp'.  Discard right-hand-side temporary.
-          __ pop(Operand(rbp, SlotOffset(var->slot())));
-          break;
-        case Expression::kValue:
-          // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
-          // temporary on the stack.
-          __ movq(kScratchRegister, Operand(rsp, 0));
-          __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
-          break;
-        case Expression::kTest:
-          // Case 'if (var = temp) ...'.
-          __ pop(rax);
-          __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
-          TestAndBranch(rax, true_label_, false_label_);
-          break;
-        case Expression::kValueTest: {
-          // Case '(var = temp) || ...' in value context.
-          Label discard;
-          __ movq(rax, Operand(rsp, 0));
-          __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
-          TestAndBranch(rax, true_label_, &discard);
-          __ bind(&discard);
-          __ addq(rsp, Immediate(kPointerSize));
-          __ jmp(false_label_);
-          break;
-        }
-        case Expression::kTestValue: {
-          // Case '(var = temp) && ...' in value context.
-          Label discard;
-          __ movq(rax, Operand(rsp, 0));
-          __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
-          TestAndBranch(rax, &discard, false_label_);
-          __ bind(&discard);
-          __ addq(rsp, Immediate(kPointerSize));
-          __ jmp(true_label_);
-          break;
-        }
+    switch (context) {
+      case Expression::kUninitialized:
+        UNREACHABLE();
+      case Expression::kEffect:
+        // Perform assignment and discard value.
+        __ pop(Operand(rbp, SlotOffset(var->slot())));
+        break;
+      case Expression::kValue:
+        // Perform assignment and preserve value.
+        __ movq(rax, Operand(rsp, 0));
+        __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+        break;
+      case Expression::kTest:
+        // Perform assignment and test (and discard) value.
+        __ pop(rax);
+        __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+        TestAndBranch(rax, true_label_, false_label_);
+        break;
+      case Expression::kValueTest: {
+        Label discard;
+        __ movq(rax, Operand(rsp, 0));
+        __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+        TestAndBranch(rax, true_label_, &discard);
+        __ bind(&discard);
+        __ addq(rsp, Immediate(kPointerSize));
+        __ jmp(false_label_);
+        break;
+      }
+      case Expression::kTestValue: {
+        Label discard;
+        __ movq(rax, Operand(rsp, 0));
+        __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
+        TestAndBranch(rax, &discard, false_label_);
+        __ bind(&discard);
+        __ addq(rsp, Immediate(kPointerSize));
+        __ jmp(true_label_);
+        break;
        }
      }
    }
  }
+
+
+void FastCodeGenerator::EmitNamedPropertyAssignment(
+    Expression::Context context,
+    Handle<Object> name) {
+  __ pop(rax);
+  __ Move(rcx, name);
+  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  DropAndMove(context, rax);
+}
+
+
+void FastCodeGenerator::EmitKeyedPropertyAssignment(
+    Expression::Context context) {
+  __ pop(rax);
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  __ Call(ic, RelocInfo::CODE_TARGET);
+  // This nop signals to the IC that there is no inlined code at the call
+  // site for it to patch.
+  __ nop();
+  // Receiver and key are still on stack.
+  __ addq(rsp, Immediate(2 * kPointerSize));
+  Move(context, rax);
+}


  void FastCodeGenerator::VisitProperty(Property* expr) {

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

Reply via email to