StoreIC interface changed on ia32 to take receiver in edx, not on stack.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 1 Feb 2010 08:35:38 +0000 (08:35 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 1 Feb 2010 08:35:38 +0000 (08:35 +0000)
Review URL: http://codereview.chromium.org/555162

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

src/ia32/codegen-ia32.cc
src/ia32/full-codegen-ia32.cc
src/ia32/ic-ia32.cc
src/ia32/stub-cache-ia32.cc
src/ia32/virtual-frame-ia32.cc

index 326d609605f3831ec6cfc50ce094f8447b690390..8691dd4eac419a8aa990d6bf82f3dd344e1a3cf3 100644 (file)
@@ -4472,8 +4472,6 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
           Load(property->value());
           frame_->Push(key);
           Result ignored = frame_->CallStoreIC();
-          // Drop the duplicated receiver and ignore the result.
-          frame_->Drop();
           break;
         }
         // Fall through
@@ -6715,7 +6713,7 @@ void Reference::SetValue(InitState init_state) {
       cgen_->frame()->Push(GetName());
       Result answer = cgen_->frame()->CallStoreIC();
       cgen_->frame()->Push(&answer);
-      cgen_->UnloadReference(this);
+      set_unloaded();
       break;
     }
 
index 6b610609fb07bc1b6b7509c11a0c65a317e5a848..5fd594cbe9eb8dd8d7e1f868df07a3d943bbb12f 100644 (file)
@@ -917,10 +917,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
         if (key->handle()->IsSymbol()) {
           VisitForValue(value, kAccumulator);
           __ mov(ecx, Immediate(key->handle()));
+          __ mov(edx, Operand(esp, 0));
           Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
           __ call(ic, RelocInfo::CODE_TARGET);
           __ nop();
-          // StoreIC leaves the receiver on the stack.
           break;
         }
         // Fall through.
@@ -1046,12 +1046,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     // assignment.  Right-hand-side value is passed in eax, variable name in
     // ecx, and the global object on the stack.
     __ mov(ecx, var->name());
-    __ push(CodeGenerator::GlobalObject());
+    __ mov(edx, CodeGenerator::GlobalObject());
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
     __ nop();
-    // Overwrite the receiver on the stack with the result if needed.
-    DropAndApply(1, context, eax);
+    Apply(context, eax);
 
   } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
     __ push(result_register());  // Value.
@@ -1111,6 +1110,11 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
   __ mov(ecx, prop->key()->AsLiteral()->handle());
+  if (expr->ends_initialization_block()) {
+    __ mov(edx, Operand(esp, 0));
+  } else {
+    __ pop(edx);
+  }
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
   __ nop();
@@ -1121,9 +1125,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ push(Operand(esp, kPointerSize));  // Receiver is under value.
     __ CallRuntime(Runtime::kToFastProperties, 1);
     __ pop(eax);
+    DropAndApply(1, context_, eax);
+  } else {
+    Apply(context_, eax);
   }
-
-  DropAndApply(1, context_, eax);
 }
 
 
@@ -1642,18 +1647,18 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       break;
     case NAMED_PROPERTY: {
       __ mov(ecx, prop->key()->AsLiteral()->handle());
+      __ pop(edx);
       Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_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 (expr->is_postfix()) {
-        __ Drop(1);  // Result is on the stack under the receiver.
         if (context_ != Expression::kEffect) {
           ApplyTOS(context_);
         }
       } else {
-        DropAndApply(1, context_, eax);
+        Apply(context_, eax);
       }
       break;
     }
index 7f7e73140a67b2e49a6614e3697ce66e33702933..307a82bbbdc6340eba5f92545f851fd9da34d12e 100644 (file)
@@ -1379,12 +1379,10 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
 
-  // Get the receiver from the stack and probe the stub cache.
-  __ mov(edx, Operand(esp, 4));
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
@@ -1399,12 +1397,12 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : transition map
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
 
   __ pop(ebx);
-  __ push(Operand(esp, 0));  // receiver
+  __ push(edx);  // receiver
   __ push(ecx);  // transition map
   __ push(eax);  // value
   __ push(ebx);  // return address
@@ -1419,12 +1417,12 @@ void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
 
   __ pop(ebx);
-  __ push(Operand(esp, 0));
+  __ push(edx);
   __ push(ecx);
   __ push(eax);
   __ push(ebx);
index 38498305de8a46f78c21ad538da8e887998b6de9..030c1569fa516d3cc9040809f47c4e1b00bca147 100644 (file)
@@ -1255,21 +1255,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ mov(ebx, Operand(esp, 1 * kPointerSize));
-
   // Generate store field code.  Trashes the name register.
   GenerateStoreField(masm(),
                      Builtins::StoreIC_ExtendStorage,
                      object,
                      index,
                      transition,
-                     ebx, ecx, edx,
+                     edx, ecx, ebx,
                      &miss);
 
   // Handle store cache miss.
@@ -1289,26 +1286,23 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ mov(ebx, Operand(esp, 1 * kPointerSize));
-
   // Check that the object isn't a smi.
-  __ test(ebx, Immediate(kSmiTagMask));
+  __ test(edx, Immediate(kSmiTagMask));
   __ j(zero, &miss, not_taken);
 
   // Check that the map of the object hasn't changed.
-  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
          Immediate(Handle<Map>(object->map())));
   __ j(not_equal, &miss, not_taken);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
-    __ CheckAccessGlobalProxy(ebx, edx, &miss);
+    __ CheckAccessGlobalProxy(edx, ebx, &miss);
   }
 
   // Stub never generated for non-global objects that require access
@@ -1316,7 +1310,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
   __ pop(ebx);  // remove the return address
-  __ push(Operand(esp, 0));  // receiver
+  __ push(edx);  // receiver
   __ push(Immediate(Handle<AccessorInfo>(callback)));  // callback info
   __ push(ecx);  // name
   __ push(eax);  // value
@@ -1342,26 +1336,23 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ mov(ebx, Operand(esp, 1 * kPointerSize));
-
   // Check that the object isn't a smi.
-  __ test(ebx, Immediate(kSmiTagMask));
+  __ test(edx, Immediate(kSmiTagMask));
   __ j(zero, &miss, not_taken);
 
   // Check that the map of the object hasn't changed.
-  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
          Immediate(Handle<Map>(receiver->map())));
   __ j(not_equal, &miss, not_taken);
 
   // Perform global security token check if needed.
   if (receiver->IsJSGlobalProxy()) {
-    __ CheckAccessGlobalProxy(ebx, edx, &miss);
+    __ CheckAccessGlobalProxy(edx, ebx, &miss);
   }
 
   // Stub never generated for non-global objects that require access
@@ -1369,7 +1360,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
   ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
 
   __ pop(ebx);  // remove the return address
-  __ push(Operand(esp, 0));  // receiver
+  __ push(edx);  // receiver
   __ push(ecx);  // name
   __ push(eax);  // value
   __ push(ebx);  // restore return address
@@ -1395,14 +1386,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;
 
   // Check that the map of the global has not changed.
-  __ mov(ebx, Operand(esp, kPointerSize));
-  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
          Immediate(Handle<Map>(object->map())));
   __ j(not_equal, &miss, not_taken);
 
index 104d1875072885e6df9f7e0b943e8a4c8bdcba3e..9267507c7ee932b8f31630cdaa08bd727beb6f53 100644 (file)
@@ -899,31 +899,45 @@ 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 on the stack.  It
-  // does not drop the receiver.
+  // 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();
-  PrepareForCall(1, 0);  // One stack arg, not callee-dropped.
+  Result receiver = Pop();
+  PrepareForCall(0, 0);
 
-  if (value.is_register() && value.reg().is(ecx)) {
-    if (name.is_register() && name.reg().is(eax)) {
+  // 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, ecx);
+      __ xchg(eax, edx);
     } else {
-      // Register eax is free for value, which frees ecx for name.
+      // Register eax is free for value, which frees edx for receiver.
       value.ToRegister(eax);
-      name.ToRegister(ecx);
+      receiver.ToRegister(edx);
     }
   } else {
-    // Register ecx is free for name, which guarantees eax is free for
+    // Register edx is free for receiver, which guarantees eax is free for
     // value.
-    name.ToRegister(ecx);
+    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.Unuse();
+  receiver.Unuse();
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }