Revision: 3198
Author: [email protected]
Date: Mon Nov  2 05:30:24 2009
Log: Add support for initialization block assignments in the toplevel code
generator, mimicing the behavior of the optimizing compiler.

Initialization blocks can only contain (thus begin and end) with a
property assignment in toplevel code.

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

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

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov  2 04:04:35  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov  2 05:30:24  
2009
@@ -572,12 +572,14 @@
  }


-void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
-                                               Variable* var) {
+void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
+  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+  ASSERT(var != NULL);
+
    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.
+    // Assignment to a global variable.  Use inline caching for the
+    // assignment.  Right-hand-side 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());
@@ -585,9 +587,10 @@
      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(context, r0);
+    DropAndMove(expr->context(), r0);
+
    } else {
-    switch (context) {
+    switch (expr->context()) {
        case Expression::kUninitialized:
          UNREACHABLE();
        case Expression::kEffect:
@@ -631,25 +634,69 @@
  }


-void FastCodeGenerator::EmitNamedPropertyAssignment(
-    Expression::Context context,
-    Handle<Object> name) {
+void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a named store IC.
+  Property* prop = expr->target()->AsProperty();
+  ASSERT(prop != NULL);
+  ASSERT(prop->key()->AsLiteral() != NULL);
+
+  // If the assignment starts a block of assignments to the same object,
+  // change to slow case to avoid the quadratic behavior of repeatedly
+  // adding fast properties.
+  if (expr->starts_initialization_block()) {
+    __ ldr(ip, MemOperand(sp, kPointerSize));  // Receiver is under value.
+    __ push(ip);
+    __ CallRuntime(Runtime::kToSlowProperties, 1);
+  }
+
    __ pop(r0);
-  __ mov(r2, Operand(name));
+  __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
    __ Call(ic, RelocInfo::CODE_TARGET);
-  DropAndMove(context, r0);
+
+  // If the assignment ends an initialization block, revert to fast case.
+  if (expr->ends_initialization_block()) {
+    __ push(r0);  // Result of assignment, saved even if not needed.
+    __ ldr(ip, MemOperand(sp, kPointerSize));  // Receiver is under value.
+    __ push(ip);
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+    __ pop(r0);
+  }
+
+  DropAndMove(expr->context(), r0);
  }


-void FastCodeGenerator::EmitKeyedPropertyAssignment(
-    Expression::Context context) {
+void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a keyed store IC.
+
+  // If the assignment starts a block of assignments to the same object,
+  // change to slow case to avoid the quadratic behavior of repeatedly
+  // adding fast properties.
+  if (expr->starts_initialization_block()) {
+    // Reciever is under the key and value.
+    __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
+    __ push(ip);
+    __ CallRuntime(Runtime::kToSlowProperties, 1);
+  }
+
    __ pop(r0);
    Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
    __ Call(ic, RelocInfo::CODE_TARGET);
+
+  // If the assignment ends an initialization block, revert to fast case.
+  if (expr->ends_initialization_block()) {
+    __ push(r0);  // Result of assignment, saved even if not needed.
+    // Reciever is under the key and value.
+    __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
+    __ push(ip);
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+    __ pop(r0);
+  }
+
    // Receiver and key are still on stack.
    __ add(sp, sp, Operand(2 * kPointerSize));
-  Move(context, r0);
+  Move(expr->context(), r0);
  }


=======================================
--- /branches/bleeding_edge/src/compiler.cc     Mon Nov  2 04:04:35 2009
+++ /branches/bleeding_edge/src/compiler.cc     Mon Nov  2 05:30:24 2009
@@ -724,11 +724,6 @@
  void CodeGenSelector::VisitAssignment(Assignment* expr) {
    // 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");
-  }
-
    Token::Value op = expr->op();
    if (op == Token::INIT_CONST) BAILOUT("initialize constant");
    if (op != Token::ASSIGN && op != Token::INIT_VAR) {
=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Mon Nov  2 03:01:47 2009
+++ /branches/bleeding_edge/src/fast-codegen.cc Mon Nov  2 05:30:24 2009
@@ -439,7 +439,7 @@
    if (var != NULL) {
      Visit(rhs);
      ASSERT_EQ(Expression::kValue, rhs->context());
-    EmitVariableAssignment(expr->context(), var);
+    EmitVariableAssignment(expr);
    } else if (prop != NULL) {
      // Assignment to a property.
      Visit(prop->obj());
@@ -450,14 +450,13 @@
        ASSERT(prop->key()->AsLiteral() != NULL);
        Visit(rhs);
        ASSERT_EQ(Expression::kValue, rhs->context());
-      EmitNamedPropertyAssignment(expr->context(),
-                                  prop->key()->AsLiteral()->handle());
+      EmitNamedPropertyAssignment(expr);
      } else {
        Visit(prop->key());
        ASSERT_EQ(Expression::kValue, prop->key()->context());
        Visit(rhs);
        ASSERT_EQ(Expression::kValue, rhs->context());
-      EmitKeyedPropertyAssignment(expr->context());
+      EmitKeyedPropertyAssignment(expr);
      }
    } else {
      UNREACHABLE();
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Mon Nov  2 03:01:47 2009
+++ /branches/bleeding_edge/src/fast-codegen.h  Mon Nov  2 05:30:24 2009
@@ -77,18 +77,17 @@

    // Platform-specific support for compiling assignments.

-  // Complete a variable assignment.  The right-hand-side value are  
expected
+  // Complete a variable assignment.  The right-hand-side value is expected
    // on top of the stack.
-  void EmitVariableAssignment(Expression::Context context, Variable* var);
+  void EmitVariableAssignment(Assignment* expr);

    // 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);
+  void EmitNamedPropertyAssignment(Assignment* expr);

    // 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 EmitKeyedPropertyAssignment(Assignment* expr);

    void SetFunctionPosition(FunctionLiteral* fun);
    void SetReturnPosition(FunctionLiteral* fun);
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Mon Nov  2  
04:04:35 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Mon Nov  2  
05:30:24 2009
@@ -586,21 +586,24 @@
  }


-void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
-                                               Variable* var) {
+void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
+  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+  ASSERT(var != NULL);
+
    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.
+    // Assignment to a global variable.  Use inline caching for the
+    // assignment.  Right-hand-side value is passed in eax, variable name  
in
+    // ecx, and the global object on the stack.
      __ 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(context, eax);
+    // Overwrite the receiver on the stack with the result if needed.
+    DropAndMove(expr->context(), eax);
+
    } else {
-    switch (context) {
+    switch (expr->context()) {
        case Expression::kUninitialized:
          UNREACHABLE();
        case Expression::kEffect:
@@ -643,28 +646,68 @@
  }


-void FastCodeGenerator::EmitNamedPropertyAssignment(
-    Expression::Context context,
-    Handle<Object> name) {
+void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a named store IC.
+  Property* prop = expr->target()->AsProperty();
+  ASSERT(prop != NULL);
+  ASSERT(prop->key()->AsLiteral() != NULL);
+
+  // If the assignment starts a block of assignments to the same object,
+  // change to slow case to avoid the quadratic behavior of repeatedly
+  // adding fast properties.
+  if (expr->starts_initialization_block()) {
+    __ push(Operand(esp, kPointerSize));  // Receiver is under value.
+    __ CallRuntime(Runtime::kToSlowProperties, 1);
+  }
+
    __ pop(eax);
-  __ mov(ecx, name);
+  __ mov(ecx, prop->key()->AsLiteral()->handle());
    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
    __ call(ic, RelocInfo::CODE_TARGET);
-  DropAndMove(context, eax);
+
+  // If the assignment ends an initialization block, revert to fast case.
+  if (expr->ends_initialization_block()) {
+    __ push(eax);  // Result of assignment, saved even if not needed.
+    __ push(Operand(esp, kPointerSize));  // Receiver is under value.
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+    __ pop(eax);
+  }
+
+  DropAndMove(expr->context(), eax);
  }


-void FastCodeGenerator::EmitKeyedPropertyAssignment(
-    Expression::Context context) {
+void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a keyed store IC.
+
+  // If the assignment starts a block of assignments to the same object,
+  // change to slow case to avoid the quadratic behavior of repeatedly
+  // adding fast properties.
+  if (expr->starts_initialization_block()) {
+    // Reciever is under the key and value.
+    __ push(Operand(esp, 2 * kPointerSize));
+    __ CallRuntime(Runtime::kToSlowProperties, 1);
+  }
+
    __ 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();
+
+  // If the assignment ends an initialization block, revert to fast case.
+  if (expr->ends_initialization_block()) {
+    __ push(eax);  // Result of assignment, saved even if not needed.
+    // Reciever is under the key and value.
+    __ push(Operand(esp, 2 * kPointerSize));
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+    __ pop(eax);
+  }
+
    // Receiver and key are still on stack.
    __ add(Operand(esp), Immediate(2 * kPointerSize));
-  Move(context, eax);
+  Move(expr->context(), eax);
  }


=======================================
--- /branches/bleeding_edge/src/parser.cc       Tue Oct 13 02:37:17 2009
+++ /branches/bleeding_edge/src/parser.cc       Mon Nov  2 05:30:24 2009
@@ -1339,7 +1339,7 @@


  // An InitializationBlockFinder finds and marks sequences of statements of  
the
-// form x.y.z.a = ...; x.y.z.b = ...; etc.
+// form expr.a = ...; expr.b = ...; etc.
  class InitializationBlockFinder : public ParserFinder {
   public:
    InitializationBlockFinder()
@@ -1367,7 +1367,7 @@
   private:
    // Returns true if the expressions appear to denote the same object.
    // In the context of initialization blocks, we only consider expressions
-  // of the form 'x.y.z'.
+  // of the form 'expr.x' or expr["x"].
    static bool SameObject(Expression* e1, Expression* e2) {
      VariableProxy* v1 = e1->AsVariableProxy();
      VariableProxy* v2 = e2->AsVariableProxy();
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov  2 04:04:35  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov  2 05:30:24  
2009
@@ -600,21 +600,24 @@
  }


-void FastCodeGenerator::EmitVariableAssignment(Expression::Context context,
-                                               Variable* var) {
+void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
+  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+  ASSERT(var != NULL);
+
    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.
+    // Assignment to a global variable.  Use inline caching for the
+    // assignment.  Right-hand-side value is passed in rax, variable name  
in
+    // rcx, and the global object on the stack.
      __ 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(context, rax);
+    DropAndMove(expr->context(), rax);
+
    } else {
-    switch (context) {
+    switch (expr->context()) {
        case Expression::kUninitialized:
          UNREACHABLE();
        case Expression::kEffect:
@@ -657,28 +660,68 @@
  }


-void FastCodeGenerator::EmitNamedPropertyAssignment(
-    Expression::Context context,
-    Handle<Object> name) {
+void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a named store IC.
+  Property* prop = expr->target()->AsProperty();
+  ASSERT(prop != NULL);
+  ASSERT(prop->key()->AsLiteral() != NULL);
+
+  // If the assignment starts a block of assignments to the same object,
+  // change to slow case to avoid the quadratic behavior of repeatedly
+  // adding fast properties.
+  if (expr->starts_initialization_block()) {
+    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
+    __ CallRuntime(Runtime::kToSlowProperties, 1);
+  }
+
    __ pop(rax);
-  __ Move(rcx, name);
+  __ Move(rcx, prop->key()->AsLiteral()->handle());
    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
    __ Call(ic, RelocInfo::CODE_TARGET);
-  DropAndMove(context, rax);
+
+  // If the assignment ends an initialization block, revert to fast case.
+  if (expr->ends_initialization_block()) {
+    __ push(rax);  // Result of assignment, saved even if not needed.
+    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+    __ pop(rax);
+  }
+
+  DropAndMove(expr->context(), rax);
  }


-void FastCodeGenerator::EmitKeyedPropertyAssignment(
-    Expression::Context context) {
+void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a keyed store IC.
+
+  // If the assignment starts a block of assignments to the same object,
+  // change to slow case to avoid the quadratic behavior of repeatedly
+  // adding fast properties.
+  if (expr->starts_initialization_block()) {
+    // Reciever is under the key and value.
+    __ push(Operand(rsp, 2 * kPointerSize));
+    __ CallRuntime(Runtime::kToSlowProperties, 1);
+  }
+
    __ 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();
+
+  // If the assignment ends an initialization block, revert to fast case.
+  if (expr->ends_initialization_block()) {
+    __ push(rax);  // Result of assignment, saved even if not needed.
+    // Reciever is under the key and value.
+    __ push(Operand(rsp, 2 * kPointerSize));
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+    __ pop(rax);
+  }
+
    // Receiver and key are still on stack.
    __ addq(rsp, Immediate(2 * kPointerSize));
-  Move(context, rax);
+  Move(expr->context(), rax);
  }



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

Reply via email to