Revision: 3841
Author: [email protected]
Date: Fri Feb 12 02:32:24 2010
Log: Change LoadIC interface on ia32 to take arguments in registers.
Review URL: http://codereview.chromium.org/573009
http://code.google.com/p/v8/source/detail?r=3841

Modified:
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/debug-ia32.cc
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/ic-ia32.cc
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
 /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h

=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Mon Feb  8 05:44:49 2010
+++ /branches/bleeding_edge/src/full-codegen.cc Fri Feb 12 02:32:24 2010
@@ -1050,7 +1050,13 @@
       // Nothing to do here.
       break;
     case NAMED_PROPERTY:
-      VisitForValue(prop->obj(), kStack);
+      if (expr->is_compound()) {
+        // We need the receiver both on the stack and in the accumulator.
+        VisitForValue(prop->obj(), kAccumulator);
+        __ push(result_register());
+      } else {
+        VisitForValue(prop->obj(), kStack);
+      }
       break;
     case KEYED_PROPERTY:
       VisitForValue(prop->obj(), kStack);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 12 02:28:40 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 12 02:32:24 2010
@@ -2327,6 +2327,7 @@
   // Load applicand.apply onto the stack. This will usually
   // give us a megamorphic load site. Not super, but it works.
   Load(applicand);
+  frame()->Dup();
   Handle<String> name = Factory::LookupAsciiSymbol("apply");
   frame()->Push(name);
   Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
@@ -4197,8 +4198,6 @@
   // property case was inlined.  Ensure that there is not a test eax
   // instruction here.
   __ nop();
-  // Discard the global object. The result is in answer.
-  frame_->Drop();
   return answer;
 }

@@ -6276,7 +6275,7 @@


 // Emit a LoadIC call to get the value from receiver and leave it in
-// dst.  The receiver register is restored after the call.
+// dst.
 class DeferredReferenceGetNamedValue: public DeferredCode {
  public:
   DeferredReferenceGetNamedValue(Register dst,
@@ -6299,7 +6298,9 @@


 void DeferredReferenceGetNamedValue::Generate() {
-  __ push(receiver_);
+  if (!receiver_.is(eax)) {
+    __ mov(eax, receiver_);
+  }
   __ Set(ecx, Immediate(name_));
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
@@ -6316,7 +6317,6 @@
   __ IncrementCounter(&Counters::named_load_inline_miss, 1);

   if (!dst_.is(eax)) __ mov(dst_, eax);
-  __ pop(receiver_);
 }


@@ -6570,6 +6570,9 @@
       Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
       ASSERT(slot != NULL);
       cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
+      if (!persist_after_get_) {
+        cgen_->UnloadReference(this);
+      }
       break;
     }

@@ -6578,6 +6581,9 @@
       bool is_global = var != NULL;
       ASSERT(!is_global || var->is_global());

+      if (persist_after_get_) {
+        cgen_->frame()->Dup();
+      }
       // Do not inline the inobject property case for loads from the global
       // object.  Also do not inline for unoptimized code.  This saves time
       // in the code generator.  Unoptimized code is toplevel code or code
@@ -6636,9 +6642,11 @@

         __ IncrementCounter(&Counters::named_load_inline, 1);
         deferred->BindExit();
-        cgen_->frame()->Push(&receiver);
         cgen_->frame()->Push(&value);
       }
+      if (!persist_after_get_) {
+        set_unloaded();
+      }
       break;
     }

@@ -6648,16 +6656,15 @@
       ASSERT(!is_global || var->is_global());
       Result value = cgen_->EmitKeyedLoad(is_global);
       cgen_->frame()->Push(&value);
+      if (!persist_after_get_) {
+        cgen_->UnloadReference(this);
+      }
       break;
     }

-    default:
+      default:
       UNREACHABLE();
   }
-
-  if (!persist_after_get_) {
-    cgen_->UnloadReference(this);
-  }
 }


=======================================
--- /branches/bleeding_edge/src/ia32/debug-ia32.cc      Tue Feb  2 10:35:53 2010
+++ /branches/bleeding_edge/src/ia32/debug-ia32.cc      Fri Feb 12 02:32:24 2010
@@ -125,9 +125,10 @@
 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
   // Register state for IC load call (from ic-ia32.cc).
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, ecx.bit(), false);
+  Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);
 }


=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Feb 3 08:12:55 2010 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Feb 12 02:32:24 2010
@@ -808,7 +808,7 @@
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in ecx and the global
     // object on the stack.
-    __ push(CodeGenerator::GlobalObject());
+    __ mov(eax, CodeGenerator::GlobalObject());
     __ mov(ecx, var->name());
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
@@ -817,7 +817,7 @@
     // Remember that the assembler may choose to do peephole optimization
     // (eg, push/pop elimination).
     __ nop();
-    DropAndApply(1, context, eax);
+    Apply(context, eax);

   } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
     Comment cmnt(masm_, "Lookup slot");
@@ -1183,14 +1183,12 @@
   Comment cmnt(masm_, "[ Property");
   Expression* key = expr->key();

-  // Evaluate the receiver.
-  VisitForValue(expr->obj(), kStack);
-
   if (key->IsPropertyName()) {
+    VisitForValue(expr->obj(), kAccumulator);
     EmitNamedPropertyLoad(expr);
-    // Drop receiver left on the stack by IC.
-    DropAndApply(1, context_, eax);
+    Apply(context_, eax);
   } else {
+    VisitForValue(expr->obj(), kStack);
     VisitForValue(expr->key(), kStack);
     EmitKeyedPropertyLoad(expr);
     // Drop key and receiver left on the stack by IC.
@@ -1455,13 +1453,13 @@
           !proxy->var()->is_this() &&
           proxy->var()->is_global()) {
         Comment cmnt(masm_, "Global variable");
-        __ push(CodeGenerator::GlobalObject());
+        __ mov(eax, CodeGenerator::GlobalObject());
         __ mov(ecx, Immediate(proxy->name()));
         Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
         // Use a regular load, not a contextual load, to avoid a reference
         // error.
         __ call(ic, RelocInfo::CODE_TARGET);
-        __ mov(Operand(esp, 0), eax);
+        __ push(eax);
       } else if (proxy != NULL &&
                  proxy->var()->slot() != NULL &&
                  proxy->var()->slot()->type() == Slot::LOOKUP) {
@@ -1565,10 +1563,13 @@
     if (expr->is_postfix() && context_ != Expression::kEffect) {
       __ push(Immediate(Smi::FromInt(0)));
     }
-    VisitForValue(prop->obj(), kStack);
     if (assign_type == NAMED_PROPERTY) {
+      // Put the object both on the stack and in the accumulator.
+      VisitForValue(prop->obj(), kAccumulator);
+      __ push(eax);
       EmitNamedPropertyLoad(prop);
     } else {
+      VisitForValue(prop->obj(), kStack);
       VisitForValue(prop->key(), kStack);
       EmitKeyedPropertyLoad(prop);
     }
=======================================
--- /branches/bleeding_edge/src/ia32/ic-ia32.cc Tue Feb  9 07:18:37 2010
+++ /branches/bleeding_edge/src/ia32/ic-ia32.cc Fri Feb 12 02:32:24 2010
@@ -50,28 +50,29 @@
// or if name is not a symbol, and will jump to the miss_label in that case.
 static void GenerateDictionaryLoad(MacroAssembler* masm,
                                    Label* miss_label,
+                                   Register receiver,
+                                   Register name,
                                    Register r0,
                                    Register r1,
                                    Register r2,
-                                   Register name,
                                    DictionaryCheck check_dictionary) {
   // Register use:
   //
+  // name - holds the name of the property and is unchanged.
+  // receiver - holds the receiver and is unchanged.
+  // Scratch registers:
   // r0   - used to hold the property dictionary.
   //
-  // r1   - initially the receiver
-  //      - used for the index into the property dictionary
+  // r1   - used for the index into the property dictionary
   //      - holds the result on exit.
   //
   // r2   - used to hold the capacity of the property dictionary.
-  //
-  // name - holds the name of the property and is unchanged.

   Label done;

   // Check for the absence of an interceptor.
   // Load the map into r0.
-  __ mov(r0, FieldOperand(r1, JSObject::kMapOffset));
+  __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset));
   // Test the has_named_interceptor bit in the map.
   __ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
           Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
@@ -91,7 +92,7 @@
   __ j(equal, miss_label, not_taken);

   // Load properties array.
-  __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
+  __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));

   // Check that the properties array is a dictionary.
   if (check_dictionary == CHECK_DICTIONARY) {
@@ -176,14 +177,12 @@

 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  __ mov(eax, Operand(esp, kPointerSize));
-
   StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
   __ bind(&miss);
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@@ -192,14 +191,12 @@

 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  __ mov(eax, Operand(esp, kPointerSize));
-
   StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss);
   __ bind(&miss);
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@@ -208,14 +205,12 @@

 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  __ mov(eax, Operand(esp, kPointerSize));
-
   StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
   __ bind(&miss);
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@@ -364,13 +359,14 @@
   __ bind(&probe_dictionary);
   GenerateDictionaryLoad(masm,
                          &slow,
-                         ebx,
                          ecx,
-                         edx,
                          eax,
+                         ebx,
+                         edx,
+                         edi,
                          DICTIONARY_CHECK_DONE);
-  GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx);
-  __ mov(eax, Operand(ecx));
+  GenerateCheckNonObjectOrLoaded(masm, &slow, edx, ebx);
+  __ mov(eax, Operand(edx));
   __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
   __ ret(0);

@@ -1001,7 +997,7 @@

   // Search dictionary - put result in register edi.
   __ mov(edi, edx);
-  GenerateDictionaryLoad(masm, miss, eax, edi, ebx, ecx, CHECK_DICTIONARY);
+ GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY);

   // Check that the result is not a smi.
   __ test(edi, Immediate(kSmiTagMask));
@@ -1150,13 +1146,11 @@

 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------

-  __ mov(eax, Operand(esp, kPointerSize));
-
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
                                          NOT_IN_LOOP,
@@ -1170,14 +1164,12 @@

 void LoadIC::GenerateNormal(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss, probe, global;

-  __ mov(eax, Operand(esp, kPointerSize));
-
   // Check that the receiver isn't a smi.
   __ test(eax, Immediate(kSmiTagMask));
   __ j(zero, &miss, not_taken);
@@ -1202,8 +1194,16 @@

   // Search the dictionary placing the result in eax.
   __ bind(&probe);
- GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx, CHECK_DICTIONARY);
-  GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx);
+  GenerateDictionaryLoad(masm,
+                         &miss,
+                         eax,
+                         ecx,
+                         edx,
+                         edi,
+                         ebx,
+                         CHECK_DICTIONARY);
+  GenerateCheckNonObjectOrLoaded(masm, &miss, edi, edx);
+  __ mov(eax, edi);
   __ ret(0);

   // Global object access: Check access rights.
@@ -1213,20 +1213,19 @@

   // Cache miss: Restore receiver from stack and jump to runtime.
   __ bind(&miss);
-  __ mov(eax, Operand(esp, 1 * kPointerSize));
   GenerateMiss(masm);
 }


 void LoadIC::GenerateMiss(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------

   __ pop(ebx);
-  __ push(Operand(esp, 0));  // receiver
+  __ push(eax);  // receiver
   __ push(ecx);  // name
   __ push(ebx);  // return address

=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Feb 9 08:14:14 2010 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Feb 12 02:32:24 2010
@@ -1767,13 +1767,12 @@
                                            int index,
                                            String* name) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  __ mov(eax, Operand(esp, kPointerSize));
   GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1788,13 +1787,12 @@
                                               JSObject* holder,
                                               AccessorInfo* callback) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  __ mov(eax, Operand(esp, kPointerSize));
   Failure* failure = Failure::InternalError();
   bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
                                       callback, name, &miss, &failure);
@@ -1813,13 +1811,12 @@
                                               Object* value,
                                               String* name) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  __ mov(eax, Operand(esp, kPointerSize));
   GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1833,16 +1830,15 @@
                                                  JSObject* holder,
                                                  String* name) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

   LookupResult lookup;
   LookupPostInterceptor(holder, name, &lookup);

-  __ mov(eax, Operand(esp, kPointerSize));
   // TODO(368): Compile in the whole chain: all the interceptors in
   // prototypes and ultimate answer.
   GenerateLoadInterceptor(receiver,
@@ -1869,15 +1865,12 @@
                                             String* name,
                                             bool is_dont_delete) {
   // ----------- S t a t e -------------
+  //  -- eax    : receiver
   //  -- ecx    : name
   //  -- esp[0] : return address
-  //  -- esp[4] : receiver
   // -----------------------------------
   Label miss;

-  // Get the receiver from the stack.
-  __ mov(eax, Operand(esp, kPointerSize));
-
   // If the object is the holder then we know that it's a global
   // object which can only happen for contextual loads. In this case,
   // the receiver cannot be a smi.
@@ -1890,19 +1883,20 @@
   CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);

   // Get the value from the cell.
-  __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
-  __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
+  __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
+  __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));

   // Check for deleted property if property can actually be deleted.
   if (!is_dont_delete) {
-    __ cmp(eax, Factory::the_hole_value());
+    __ cmp(ebx, Factory::the_hole_value());
     __ j(equal, &miss, not_taken);
   } else if (FLAG_debug_code) {
-    __ cmp(eax, Factory::the_hole_value());
+    __ cmp(ebx, Factory::the_hole_value());
     __ Check(not_equal, "DontDelete cells can't contain the hole");
   }

   __ IncrementCounter(&Counters::named_load_global_inline, 1);
+  __ mov(eax, ebx);
   __ ret(0);

   __ bind(&miss);
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Mon Feb 8 05:44:49 2010 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Fri Feb 12 02:32:24 2010
@@ -888,13 +888,28 @@

 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
   // Name and receiver are on the top of the frame.  The IC expects
-  // name in ecx and receiver on the stack.  It does not drop the
-  // receiver.
+  // name in ecx and receiver in eax.
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   Result name = Pop();
-  PrepareForCall(1, 0);  // One stack arg, not callee-dropped.
-  name.ToRegister(ecx);
+  Result receiver = Pop();
+  PrepareForCall(0, 0);  // No stack arguments.
+  // Move results to the right registers:
+  if (name.is_register() && name.reg().is(eax)) {
+    if (receiver.is_register() && receiver.reg().is(ecx)) {
+      // Wrong registers.
+      __ xchg(eax, ecx);
+    } else {
+      // Register ecx is free for name, which frees eax for receiver.
+      name.ToRegister(ecx);
+      receiver.ToRegister(eax);
+    }
+  } else {
+    // Register eax is free for receiver, which frees ecx for name.
+    receiver.ToRegister(eax);
+    name.ToRegister(ecx);
+  }
   name.Unuse();
+  receiver.Unuse();
   return RawCallCodeObject(ic, mode);
 }

=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Mon Feb 8 05:44:49 2010 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Fri Feb 12 02:32:24 2010
@@ -333,7 +333,7 @@
Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count);

   // Call load IC.  Name and receiver are found on top of the frame.
-  // Receiver is not dropped.
+  // Both are dropped.
   Result CallLoadIC(RelocInfo::Mode mode);

   // Call keyed load IC.  Key and receiver are found on top of the

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

Reply via email to