Change StoreIC interface on x64 to pass receiver in rdx, not on stack.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 2 Feb 2010 09:20:19 +0000 (09:20 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 2 Feb 2010 09:20:19 +0000 (09:20 +0000)
Review URL: http://codereview.chromium.org/558069

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

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

index 2f1470fd51632acc779880109f8fe0fd2abd4b44..d6851a9c7ea23669223b1103f368ed73100ae53a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -132,12 +132,13 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
 
 
 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
-  // REgister state for IC store call (from ic-ia32.cc).
+  // Register state for IC store call (from ic-ia32.cc).
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
+  //  -- edx    : receiver
   // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
+  Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit() | edx.bit(), false);
 }
 
 
index b56d991b85071bd0b26fa9329335ac3ea6499a8c..9b5f160e8f39e796ab8036c470366a7011bd808c 100644 (file)
@@ -2439,8 +2439,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
@@ -6021,7 +6019,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 b3e1b2e78701e20029c4c878d9faadc13e76b822..019e558b2024a1ff988f7a348deb04c1dafdf595 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -158,12 +158,13 @@ void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
 
 
 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
-  // REgister state for IC store call (from ic-x64.cc).
+  // Register state for IC store call (from ic-x64.cc).
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false);
+  Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit() | rdx.bit(), false);
 }
 
 
index 688bfba7c86ad08790188c847d456b369f406fc9..f5bbfafe6268308bc0a9898a280f571ef9d08832 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -929,10 +929,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
         if (key->handle()->IsSymbol()) {
           VisitForValue(value, kAccumulator);
           __ Move(rcx, key->handle());
+          __ movq(rdx, Operand(rsp, 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.
@@ -1054,13 +1054,12 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     ASSERT(!var->is_this());
     // 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.
+    // rcx, and the global object in rdx.
     __ Move(rcx, var->name());
-    __ push(CodeGenerator::GlobalObject());
+    __ movq(rdx, 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.
-    DropAndApply(1, context, rax);
+    Apply(context, rax);
 
   } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
     __ push(result_register());  // Value.
@@ -1120,6 +1119,11 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
   __ Move(rcx, prop->key()->AsLiteral()->handle());
+  if (expr->ends_initialization_block()) {
+    __ movq(rdx, Operand(rsp, 0));
+  } else {
+    __ pop(rdx);
+  }
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
   __ nop();
@@ -1130,9 +1134,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
     __ CallRuntime(Runtime::kToFastProperties, 1);
     __ pop(rax);
+    DropAndApply(1, context_, rax);
+  } else {
+    Apply(context_, rax);
   }
-
-  DropAndApply(1, context_, rax);
 }
 
 
@@ -1658,18 +1663,18 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       break;
     case NAMED_PROPERTY: {
       __ Move(rcx, prop->key()->AsLiteral()->handle());
+      __ pop(rdx);
       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_, rax);
+        Apply(context_, rax);
       }
       break;
     }
index b1bc213ef309083af4c36489ee6aeda479197018..28bfd2ee6b315b99ad72df56eea741498efd4175 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1330,12 +1330,12 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
 
   __ pop(rbx);
-  __ push(Operand(rsp, 0));  // receiver
+  __ push(rdx);  // receiver
   __ push(rcx);  // name
   __ push(rax);  // value
   __ push(rbx);  // return address
@@ -1348,12 +1348,12 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : Map (target of map transition)
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
 
   __ pop(rbx);
-  __ push(Operand(rsp, 0));  // receiver
+  __ push(rdx);  // receiver
   __ push(rcx);  // transition map
   __ push(rax);  // value
   __ push(rbx);  // return address
@@ -1367,12 +1367,11 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
 
   // Get the receiver from the stack and probe the stub cache.
-  __ movq(rdx, Operand(rsp, kPointerSize));
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
index 7982d52ebcd4888113755e9e3f449dbf42f22215..64d0532bf328bc5304a57a09b739e33186144171 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1354,25 +1354,22 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ movq(rbx, Operand(rsp, 1 * kPointerSize));
-
   // Check that the object isn't a smi.
-  __ JumpIfSmi(rbx, &miss);
+  __ JumpIfSmi(rdx, &miss);
 
   // Check that the map of the object hasn't changed.
-  __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
+  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
          Handle<Map>(object->map()));
   __ j(not_equal, &miss);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
-    __ CheckAccessGlobalProxy(rbx, rdx, &miss);
+    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
   }
 
   // Stub never generated for non-global objects that require access
@@ -1380,7 +1377,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
   __ pop(rbx);  // remove the return address
-  __ push(Operand(rsp, 0));  // receiver
+  __ push(rdx);  // receiver
   __ Push(Handle<AccessorInfo>(callback));  // callback info
   __ push(rcx);  // name
   __ push(rax);  // value
@@ -1408,21 +1405,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ movq(rbx, Operand(rsp, 1 * kPointerSize));
-
   // Generate store field code.  Trashes the name register.
   GenerateStoreField(masm(),
                      Builtins::StoreIC_ExtendStorage,
                      object,
                      index,
                      transition,
-                     rbx, rcx, rdx,
+                     rdx, rcx, rbx,
                      &miss);
 
   // Handle store cache miss.
@@ -1441,25 +1435,22 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ movq(rbx, Operand(rsp, 1 * kPointerSize));
-
   // Check that the object isn't a smi.
-  __ JumpIfSmi(rbx, &miss);
+  __ JumpIfSmi(rdx, &miss);
 
   // Check that the map of the object hasn't changed.
-  __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
+  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
          Handle<Map>(receiver->map()));
   __ j(not_equal, &miss);
 
   // Perform global security token check if needed.
   if (receiver->IsJSGlobalProxy()) {
-    __ CheckAccessGlobalProxy(rbx, rdx, &miss);
+    __ CheckAccessGlobalProxy(rdx, rbx, &miss);
   }
 
   // Stub never generated for non-global objects that require access
@@ -1467,7 +1458,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
   ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
 
   __ pop(rbx);  // remove the return address
-  __ push(Operand(rsp, 0));  // receiver
+  __ push(rdx);  // receiver
   __ push(rcx);  // name
   __ push(rax);  // value
   __ push(rbx);  // restore return address
@@ -1493,14 +1484,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
+  //  -- rdx    : receiver
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;
 
   // Check that the map of the global has not changed.
-  __ movq(rbx, Operand(rsp, kPointerSize));
-  __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
+  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
          Handle<Map>(object->map()));
   __ j(not_equal, &miss);
 
index 6e84ed1639ddf76020c6fb1f260cfbbc12c8b224..cb93d5d46704b9bf7e4310a220c03815b7560610 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1046,31 +1046,45 @@ Result VirtualFrame::CallConstructor(int arg_count) {
 
 Result VirtualFrame::CallStoreIC() {
   // Name, value, and receiver are on top of the frame.  The IC
-  // expects name in rcx, value in rax, and receiver on the stack.  It
-  // does not drop the receiver.
+  // expects name in rcx, value in rax, 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(rcx)) {
-    if (name.is_register() && name.reg().is(rax)) {
+  // Optimized for case in which name is a constant value.
+  if (name.is_register() && (name.reg().is(rdx) || name.reg().is(rax))) {
+    if (!is_used(rcx)) {
+      name.ToRegister(rcx);
+    } else if (!is_used(rbx)) {
+      name.ToRegister(rbx);
+    } else {
+      ASSERT(!is_used(rdi));  // Only three results are live, so rdi is free.
+      name.ToRegister(rdi);
+    }
+  }
+  // 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(rdx)) {
+    if (receiver.is_register() && receiver.reg().is(rax)) {
       // Wrong registers.
-      __ xchg(rax, rcx);
+      __ xchg(rax, rdx);
     } else {
-      // Register rax is free for value, which frees rcx for name.
+      // Register rax is free for value, which frees rcx for receiver.
       value.ToRegister(rax);
-      name.ToRegister(rcx);
+      receiver.ToRegister(rdx);
     }
   } else {
-    // Register rcx is free for name, which guarantees rax is free for
+    // Register rcx is free for receiver, which guarantees rax is free for
     // value.
-    name.ToRegister(rcx);
+    receiver.ToRegister(rdx);
     value.ToRegister(rax);
   }
-
+  // Receiver and value are in the right place, so rcx is free for name.
+  name.ToRegister(rcx);
   name.Unuse();
   value.Unuse();
+  receiver.Unuse();
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }