Revision: 3921
Author: [email protected]
Date: Fri Feb 19 07:04:16 2010
Log: Improve stores to global variables.
Review URL: http://codereview.chromium.org/650028
http://code.google.com/p/v8/source/detail?r=3921

Modified:
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.h
 /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
 /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h

=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 19 06:52:39 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 19 07:04:16 2010
@@ -695,8 +695,10 @@
     // The expression is a variable proxy that does not rewrite to a
// property. Global variables are treated as named property references.
     if (var->is_global()) {
- // Named loads require object in eax. Named stores don't use references.
-      // Spilling eax makes it free, so LoadGlobal loads directly into eax.
+      // If eax is free, the register allocator prefers it.  Thus the code
+      // generator will load the global object into eax, which is where
+      // LoadIC wants it.  Most uses of Reference call LoadIC directly
+      // after the reference is created.
       frame_->Spill(eax);
       LoadGlobal();
       ref->set_type(Reference::NAMED);
@@ -4316,6 +4318,10 @@

   // All extension objects were empty and it is safe to use a global
   // load IC call.
+ // The register allocator prefers eax if it is free, so the code generator + // will load the global object directly into eax, which is where the LoadIC
+  // expects it.
+  frame_->Spill(eax);
   LoadGlobal();
   frame_->Push(slot->var()->name());
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
@@ -4601,8 +4607,8 @@
           // Duplicate the object as the IC receiver.
           frame_->Dup();
           Load(property->value());
-          frame_->Push(key);
-          Result ignored = frame_->CallStoreIC();
+ Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false);
+          dummy.Unuse();
           break;
         }
         // Fall through
@@ -4776,10 +4782,9 @@
   bool is_trivial_receiver = false;
   if (var != NULL) {
     name = var->name();
-    LoadGlobal();
   } else {
     Literal* lit = prop->key()->AsLiteral();
-    ASSERT(lit != NULL);
+    ASSERT_NOT_NULL(lit);
     name = Handle<String>::cast(lit->handle());
     // Do not materialize the receiver on the frame if it is trivial.
     is_trivial_receiver = prop->obj()->IsTrivial();
@@ -4787,6 +4792,7 @@
   }

   if (node->starts_initialization_block()) {
+    ASSERT_EQ(NULL, var);
     // Change to slow case in the beginning of an initialization block to
     // avoid the quadratic behavior of repeatedly adding fast properties.
     if (is_trivial_receiver) {
@@ -4807,6 +4813,11 @@
   if (node->is_compound()) {
     if (is_trivial_receiver) {
       frame()->Push(prop->obj());
+    } else if (var != NULL) {
+      // The LoadIC stub expects the object in eax.
+      // Freeing eax causes the code generator to load the global into it.
+      frame_->Spill(eax);
+      LoadGlobal();
     } else {
       frame()->Dup();
     }
@@ -4826,17 +4837,19 @@

   // Perform the assignment.  It is safe to ignore constants here.
   ASSERT(var == NULL || var->mode() != Variable::CONST);
-  ASSERT(node->op() != Token::INIT_CONST);
+  ASSERT_NE(Token::INIT_CONST, node->op());
   if (is_trivial_receiver) {
     Result value = frame()->Pop();
     frame()->Push(prop->obj());
     frame()->Push(&value);
   }
   CodeForSourcePosition(node->position());
-  Result answer = EmitNamedStore(name);
+  bool is_contextual = (var != NULL);
+  Result answer = EmitNamedStore(name, is_contextual);
   frame()->Push(&answer);

   if (node->ends_initialization_block()) {
+    ASSERT_EQ(NULL, var);
     // The argument to the runtime call is the receiver.
     if (is_trivial_receiver) {
       frame()->Push(prop->obj());
@@ -4851,7 +4864,7 @@
     Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
   }

-  ASSERT(frame()->height() == original_height + 1);
+  ASSERT_EQ(frame()->height(), original_height + 1);
 }


@@ -4861,7 +4874,7 @@
 #endif
   Comment cmnt(masm_, "[ Named Property Assignment");
   Property* prop = node->target()->AsProperty();
-  ASSERT(prop != NULL);
+  ASSERT_NOT_NULL(prop);

   // Evaluate the receiver subexpression.
   Load(prop->obj());
@@ -6779,14 +6792,13 @@
 }


-Result CodeGenerator::EmitNamedStore(Handle<String> name) {
+Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
 #ifdef DEBUG
-  int original_height = frame()->height();
+  int expected_height = frame()->height() - (is_contextual ? 1 : 2);
 #endif
-  frame()->Push(name);
-  Result result = frame()->CallStoreIC();
-
-  ASSERT(frame()->height() == original_height - 2);
+  Result result = frame()->CallStoreIC(name, is_contextual);
+
+  ASSERT_EQ(expected_height, frame()->height());
   return result;
 }

@@ -7103,7 +7115,7 @@

     case NAMED: {
       Comment cmnt(masm, "[ Store to named Property");
-      Result answer = cgen_->EmitNamedStore(GetName());
+      Result answer = cgen_->EmitNamedStore(GetName(), false);
       cgen_->frame()->Push(&answer);
       set_unloaded();
       break;
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h     Fri Feb 19 06:52:39 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h     Fri Feb 19 07:04:16 2010
@@ -438,8 +438,9 @@
   // Receiver is passed on the frame and consumed.
   Result EmitNamedLoad(Handle<String> name, bool is_contextual);

-  // Reciever and value are passed on the frame and consumed.
-  Result EmitNamedStore(Handle<String> name);
+  // If the store is contextual, value is passed on the frame and consumed.
+  // Otherwise, receiver and value are passed on the frame and consumed.
+  Result EmitNamedStore(Handle<String> name, bool is_contextual);

   // Receiver and key are passed on the frame and consumed.
   Result EmitKeyedLoad();
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Fri Feb 19 01:01:31 2010 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Fri Feb 19 07:04:16 2010
@@ -948,47 +948,38 @@
 }


-Result VirtualFrame::CallStoreIC() {
-  // Name, value, and receiver are on top of the frame.  The IC
-  // expects name in ecx, value in eax, and receiver in edx.
+Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
+  // Value and (if not contextual) receiver are on top of the frame.
+  //  The IC expects name in ecx, value in eax, and receiver in edx.
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-  Result name = Pop();
   Result value = Pop();
-  Result receiver = Pop();
-  PrepareForCall(0, 0);
-
-  // Optimized for case in which name is a constant value.
-  if (name.is_register() && (name.reg().is(edx) || name.reg().is(eax))) {
-    if (!is_used(ecx)) {
-      name.ToRegister(ecx);
-    } else if (!is_used(ebx)) {
-      name.ToRegister(ebx);
+  if (is_contextual) {
+    PrepareForCall(0, 0);
+    value.ToRegister(eax);
+    __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+    __ mov(ecx, name);
+  } else {
+    Result receiver = Pop();
+    PrepareForCall(0, 0);
+
+    if (value.is_register() && value.reg().is(edx)) {
+      if (receiver.is_register() && receiver.reg().is(eax)) {
+        // Wrong registers.
+        __ xchg(eax, edx);
+      } else {
+        // Register eax is free for value, which frees edx for receiver.
+        value.ToRegister(eax);
+        receiver.ToRegister(edx);
+      }
     } else {
- ASSERT(!is_used(edi)); // Only three results are live, so edi is free.
-      name.ToRegister(edi);
-    }
-  }
- // Now name is not in edx or eax, so we can fix them, then move name to ecx.
-  if (value.is_register() && value.reg().is(edx)) {
-    if (receiver.is_register() && receiver.reg().is(eax)) {
-      // Wrong registers.
-      __ xchg(eax, edx);
-    } else {
-      // Register eax is free for value, which frees edx for receiver.
-      value.ToRegister(eax);
+ // Register edx is free for receiver, which guarantees eax is free for
+      // value.
       receiver.ToRegister(edx);
-    }
-  } else {
-    // Register edx is free for receiver, which guarantees eax is free for
-    // value.
-    receiver.ToRegister(edx);
-    value.ToRegister(eax);
-  }
-  // Receiver and value are in the right place, so ecx is free for name.
-  name.ToRegister(ecx);
-  name.Unuse();
+      value.ToRegister(eax);
+    }
+  }
+  __ mov(ecx, name);
   value.Unuse();
-  receiver.Unuse();
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }

=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Fri Feb 19 01:01:31 2010 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Fri Feb 19 07:04:16 2010
@@ -339,12 +339,12 @@
   Result CallLoadIC(RelocInfo::Mode mode);

   // Call keyed load IC.  Key and receiver are found on top of the
-  // frame.  They are not dropped.
+  // frame.  Both are dropped.
   Result CallKeyedLoadIC(RelocInfo::Mode mode);

-  // Call store IC.  Name, value, and receiver are found on top of the
-  // frame.  Receiver is not dropped.
-  Result CallStoreIC();
+ // Call store IC. If the load is contextual, value is found on top of the + // frame. If not, value and receiver are on the frame. Both are dropped.
+  Result CallStoreIC(Handle<String> name, bool is_contextual);

   // Call keyed store IC.  Value, key, and receiver are found on top
   // of the frame.  Key and receiver are not dropped.

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

Reply via email to