Revision: 3180
Author: [email protected]
Date: Fri Oct 30 00:56:38 2009
Log: Support for property assignment in the fast compiler.

The code for .result = (b.y = 99) where b is a global variable is:

   push [esi+0x17]
   mov ecx,0xf5c229ad          ;; object: 0xf5c229ad <String[1]: b>
   call LoadIC_Initialize
   nop
   mov [esp],eax
   mov eax,0xc6
   mov ecx,0xf5c25c41          ;; object: 0xf5c25c41 <String[1]: y>
   call StoreIC_Initialize
   nop
   mov [esp],eax
   pop [ebp+0xf4]

There is still some room for improvement in the generated code.

Other changes:
  - Replaced switch-statement in FastCodeGenerator::VisitProperty with  
DropAndMove(...)
  - Do not emit nop after IC calls on ARM.

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

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/compiler.cc
  /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 Thu Oct 29 06:58:04  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Fri Oct 30 00:56:38  
2009
@@ -455,14 +455,42 @@
    Comment cmnt(masm_, "[ Assignment");
    ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);

-  // Left-hand side can only be a global or a (parameter or local) slot.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  ASSERT(var != NULL);
-  ASSERT(var->is_global() || var->slot() != NULL);
-
+  // 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();
-  Location destination = expr->location();
-  if (var->is_global()) {
+  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);
+      Move(r0, rhs->location());
+      __ 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);
+      Move(r0, rhs->location());
+      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->location(), r0);
+  } else 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.
@@ -534,29 +562,15 @@
      __ mov(r2, Operand(key->AsLiteral()->handle()));
      Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
      __ Call(ic, RelocInfo::CODE_TARGET);
-    // By emitting a nop we make sure that we do not have a "test eax,..."
-    // instruction after the call it is treated specially by the LoadIC  
code.
-    __ nop();
    } else {
      // Do a KEYED property load.
      Visit(expr->key());
      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
      __ Call(ic, RelocInfo::CODE_TARGET);
-    // By emitting a nop we make sure that we do not have a "test eax,..."
-    // instruction after the call it is treated specially by the LoadIC  
code.
-    __ nop();
      // Drop key and receiver left on the stack by IC.
      __ pop();
    }
-  switch (expr->location().type()) {
-    case Location::kUninitialized:
-      UNREACHABLE();
-    case Location::kValue:
-      __ str(r0, MemOperand(sp));
-      break;
-    case Location::kEffect:
-      __ pop();
-  }
+  DropAndMove(expr->location(), r0);
  }


=======================================
--- /branches/bleeding_edge/src/compiler.cc     Thu Oct 29 04:55:03 2009
+++ /branches/bleeding_edge/src/compiler.cc     Fri Oct 30 00:56:38 2009
@@ -741,8 +741,8 @@


  void CodeGenSelector::VisitAssignment(Assignment* expr) {
-  // We support plain non-compound assignments to parameters and
-  // non-context (stack-allocated) locals.
+  // We support plain non-compound assignments to properties, parameters  
and
+  // non-context (stack-allocated) locals, and global variables.
    if (expr->starts_initialization_block() ||
        expr->ends_initialization_block()) {
      BAILOUT("initialization block start");
@@ -755,10 +755,14 @@
    }

    Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  if (var == NULL) BAILOUT("non-variable assignment");
-
-  if (!var->is_global()) {
-    ASSERT(var->slot() != NULL);
+  if (var == NULL) {
+    Property* prop = expr->target()->AsProperty();
+    if (prop == NULL) BAILOUT("non-variable, non-property assignment");
+    VisitAsValue(prop->obj());
+    CHECK_BAILOUT;
+    VisitAsValue(prop->key());
+  } 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");
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Thu Oct 29  
06:58:04 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Fri Oct 30  
00:56:38 2009
@@ -442,13 +442,44 @@
    Comment cmnt(masm_, "[ Assignment");
    ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);

-  // Left-hand side can only be a global or a (parameter or local) slot.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  ASSERT(var != NULL);
-  ASSERT(var->is_global() || var->slot() != NULL);
-
+  // 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->is_global()) {
+  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);
+      Move(eax, rhs->location());
+      __ 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);
+      Move(eax, rhs->location());
+      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->location(), eax);
+  } else 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.
@@ -469,6 +500,7 @@
      DropAndMove(expr->location(), 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) {
@@ -509,7 +541,6 @@

    // Evaluate receiver.
    Visit(expr->obj());
-
    if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
        !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
      // Do a NAMED property load.
@@ -531,16 +562,7 @@
      // Drop key left on the stack by IC.
      __ add(Operand(esp), Immediate(kPointerSize));
    }
-  switch (expr->location().type()) {
-    case Location::kUninitialized:
-      UNREACHABLE();
-    case Location::kValue:
-      __ mov(Operand(esp, 0), eax);
-      break;
-    case Location::kEffect:
-      __ add(Operand(esp), Immediate(kPointerSize));
-      break;
-  }
+  DropAndMove(expr->location(), eax);
  }


=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Thu Oct 29 06:58:04  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Fri Oct 30 00:56:38  
2009
@@ -454,14 +454,44 @@
    Comment cmnt(masm_, "[ Assignment");
    ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);

-  // Left-hand side can only be a global or a (parameter or local) slot.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
-  ASSERT(var != NULL);
-  ASSERT(var->is_global() || var->slot() != NULL);
-
+  // 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();
-  Location destination = expr->location();
-  if (var->is_global()) {
+  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);
+      Move(rax, rhs->location());
+      __ 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);
+      Move(rax, rhs->location());
+      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->location(), rax);
+  } else 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.
@@ -530,7 +560,7 @@
      __ Move(rcx, key->AsLiteral()->handle());
      Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
      __ call(ic, RelocInfo::CODE_TARGET);
-    // By emitting a nop we make sure that we do not have a "test eax,..."
+    // By emitting a nop we make sure that we do not have a "test rax,..."
      // instruction after the call it is treated specially by the LoadIC  
code.
      __ nop();
    } else {
@@ -538,22 +568,13 @@
      Visit(expr->key());
      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
      __ call(ic, RelocInfo::CODE_TARGET);
-    // By emitting a nop we make sure that we do not have a "test ..."
+    // By emitting a nop we make sure that we do not have a "test rax,..."
      // instruction after the call it is treated specially by the LoadIC  
code.
      __ nop();
      // Drop key left on the stack by IC.
      __ addq(rsp, Immediate(kPointerSize));
    }
-  switch (expr->location().type()) {
-    case Location::kUninitialized:
-      UNREACHABLE();
-    case Location::kValue:
-      __ movq(Operand(rsp, 0), rax);
-      break;
-    case Location::kEffect:
-      __ addq(rsp, Immediate(kPointerSize));
-      break;
-  }
+  DropAndMove(expr->location(), rax);
  }



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

Reply via email to