Improve stores to global variables.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Feb 2010 15:04:16 +0000 (15:04 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Feb 2010 15:04:16 +0000 (15:04 +0000)
Review URL: http://codereview.chromium.org/650028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3921 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h
src/ia32/virtual-frame-ia32.cc
src/ia32/virtual-frame-ia32.h

index 1882ac59e1fc06c31ac05e86a26a7c003746ee33..85d8ed9bc02541567c433983fad6a7cbcd3362f7 100644 (file)
@@ -695,8 +695,10 @@ void CodeGenerator::LoadReference(Reference* ref) {
     // 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 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
 
   // 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 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
           // 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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
   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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
   }
 
   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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
   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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
 
   // 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 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
     Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
   }
 
-  ASSERT(frame()->height() == original_height + 1);
+  ASSERT_EQ(frame()->height(), original_height + 1);
 }
 
 
@@ -4861,7 +4874,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
 #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::EmitNamedLoad(Handle<String> name, bool is_contextual) {
 }
 
 
-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();
+  Result result = frame()->CallStoreIC(name, is_contextual);
 
-  ASSERT(frame()->height() == original_height - 2);
+  ASSERT_EQ(expected_height, frame()->height());
   return result;
 }
 
@@ -7103,7 +7115,7 @@ void Reference::SetValue(InitState init_state) {
 
     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;
index cd7a7bbb26bc5f02a8dbbf75774a660060849d18..99dc340b64d1904caee63277b885a9450b258344 100644 (file)
@@ -438,8 +438,9 @@ class CodeGenerator: public AstVisitor {
   // 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();
index 5e44f94d0c1404528d798325b5372fbad59b170a..7df028e946bdfc7bc175ed0593648c258635ec53 100644 (file)
@@ -948,47 +948,38 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
 }
 
 
-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);
+  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);
 
-  // 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);
-    } 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);
+    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 {
-      // 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);
+      value.ToRegister(eax);
     }
-  } 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();
+  __ mov(ecx, name);
   value.Unuse();
-  receiver.Unuse();
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
index 59142b40e2834d4100ce4a034eb330dbf59cc992..7be593cc58f934ef46d6189046c3507a6f246ca5 100644 (file)
@@ -339,12 +339,12 @@ class VirtualFrame: public ZoneObject {
   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.