Change StoreIC interface on ARM platform
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 10 Feb 2010 15:06:08 +0000 (15:06 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 10 Feb 2010 15:06:08 +0000 (15:06 +0000)
Review URL: http://codereview.chromium.org/554152

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

src/arm/codegen-arm.cc
src/arm/debug-arm.cc
src/arm/full-codegen-arm.cc
src/arm/ic-arm.cc
src/arm/stub-cache-arm.cc

index 8557808..5b3f836 100644 (file)
@@ -2718,9 +2718,9 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
     frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
   }
   frame_->EmitPush(r0);  // save the result
-  // r0: created object literal
-
   for (int i = 0; i < node->properties()->length(); i++) {
+    // At the start of each iteration, the top of stack contains
+    // the newly created object literal.
     ObjectLiteral::Property* property = node->properties()->at(i);
     Literal* key = property->key();
     Expression* value = property->value();
@@ -2730,34 +2730,43 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
         if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
         // else fall through
-      case ObjectLiteral::Property::COMPUTED:  // fall through
+      case ObjectLiteral::Property::COMPUTED:
+        if (key->handle()->IsSymbol()) {
+          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+          LoadAndSpill(value);
+          frame_->EmitPop(r0);
+          __ mov(r2, Operand(key->handle()));
+          __ ldr(r1, frame_->Top());  // Load the receiver.
+          frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+          break;
+        }
+        // else fall through
       case ObjectLiteral::Property::PROTOTYPE: {
+        __ ldr(r0, frame_->Top());
         frame_->EmitPush(r0);  // dup the result
         LoadAndSpill(key);
         LoadAndSpill(value);
         frame_->CallRuntime(Runtime::kSetProperty, 3);
-        // restore r0
-        __ ldr(r0, frame_->Top());
         break;
       }
       case ObjectLiteral::Property::SETTER: {
+        __ ldr(r0, frame_->Top());
         frame_->EmitPush(r0);
         LoadAndSpill(key);
         __ mov(r0, Operand(Smi::FromInt(1)));
         frame_->EmitPush(r0);
         LoadAndSpill(value);
         frame_->CallRuntime(Runtime::kDefineAccessor, 4);
-        __ ldr(r0, frame_->Top());
         break;
       }
       case ObjectLiteral::Property::GETTER: {
+        __ ldr(r0, frame_->Top());
         frame_->EmitPush(r0);
         LoadAndSpill(key);
         __ mov(r0, Operand(Smi::FromInt(0)));
         frame_->EmitPush(r0);
         LoadAndSpill(value);
         frame_->CallRuntime(Runtime::kDefineAccessor, 4);
-        __ ldr(r0, frame_->Top());
         break;
       }
     }
@@ -4388,11 +4397,11 @@ void Reference::SetValue(InitState init_state) {
       Handle<String> name(GetName());
 
       frame->EmitPop(r0);
-      // Setup the name register.
+      frame->EmitPop(r1);
       __ mov(r2, Operand(name));
       frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
       frame->EmitPush(r0);
-      cgen_->UnloadReference(this);
+      set_unloaded();
       break;
     }
 
index 6eb5239..e6b61b4 100644 (file)
@@ -128,7 +128,7 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
   //  -- lr    : return address
   //  -- [sp]  : receiver
   // -----------------------------------
-  // Registers r0 and r2 contain objects that needs to be pushed on the
+  // Registers r0 and r2 contain objects that need to be pushed on the
   // expression stack of the fake JS frame.
   Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
 }
@@ -137,14 +137,14 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
   // Calling convention for IC store (from ic-arm.cc).
   // ----------- S t a t e -------------
-  //  -- r0    : receiver
+  //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
-  // Registers r0 and r2 contain objects that needs to be pushed on the
+  // Registers r0, r1, and r2 contain objects that need to be pushed on the
   // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
+  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit());
 }
 
 
index 7e048ff..96549f8 100644 (file)
@@ -816,9 +816,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
         if (key->handle()->IsSymbol()) {
           VisitForValue(value, kAccumulator);
           __ mov(r2, Operand(key->handle()));
+          __ ldr(r1, MemOperand(sp));
           Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
           __ Call(ic, RelocInfo::CODE_TARGET);
-          // StoreIC leaves the receiver on the stack.
           break;
         }
         // Fall through.
@@ -945,21 +945,17 @@ 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 r0, variable name in
-    // r2, and the global object on the stack.
+    // r2, and the global object in r1.
     __ mov(r2, Operand(var->name()));
-    __ ldr(ip, CodeGenerator::GlobalObject());
-    __ push(ip);
+    __ ldr(r1, 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, r0);
 
   } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
     __ push(result_register());  // Value.
     __ mov(r1, Operand(var->name()));
     __ stm(db_w, sp, cp.bit() | r1.bit());  // Context and name.
     __ CallRuntime(Runtime::kStoreContextSlot, 3);
-    Apply(context, r0);
 
   } else if (var->slot() != NULL) {
     Slot* slot = var->slot();
@@ -986,13 +982,13 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         UNREACHABLE();
         break;
     }
-    Apply(context, result_register());
 
   } else {
     // Variables rewritten as properties are not treated as variables in
     // assignments.
     UNREACHABLE();
   }
+  Apply(context, result_register());
 }
 
 
@@ -1016,6 +1012,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
   __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
+  if (expr->ends_initialization_block()) {
+    __ ldr(r1, MemOperand(sp));
+  } else {
+    __ pop(r1);
+  }
+
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
 
@@ -1026,9 +1028,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ push(ip);
     __ CallRuntime(Runtime::kToFastProperties, 1);
     __ pop(r0);
+    DropAndApply(1, context_, r0);
+  } else {
+    Apply(context_, r0);
   }
-
-  DropAndApply(1, context_, r0);
 }
 
 
@@ -1548,15 +1551,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
       break;
     case NAMED_PROPERTY: {
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
+      __ pop(r1);
       Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
       __ Call(ic, RelocInfo::CODE_TARGET);
       if (expr->is_postfix()) {
-        __ Drop(1);  // Result is on the stack under the receiver.
         if (context_ != Expression::kEffect) {
           ApplyTOS(context_);
         }
       } else {
-        DropAndApply(1, context_, r0);
+        Apply(context_, r0);
       }
       break;
     }
index 10bc438..b48958a 100644 (file)
@@ -791,13 +791,12 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
 
   // Get the receiver from the stack and probe the stub cache.
-  __ ldr(r1, MemOperand(sp));
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
@@ -811,13 +810,13 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
 
-  __ ldr(r3, MemOperand(sp));  // copy receiver
-  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+  __ push(r1);
+  __ stm(db_w, sp, r2.bit() | r0.bit());
 
   // Perform tail call to the entry.
   __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1);
index 521ecc6..390339b 100644 (file)
@@ -258,8 +258,9 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
 
 
 // Generate StoreField code, value is passed in r0 register.
-// After executing generated code, the receiver_reg and name_reg
-// may be clobbered.
+// When leaving generated code after success, the receiver_reg and name_reg
+// may be clobbered.  Upon branch to miss_label, the receiver and name
+// registers have their original values.
 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
                                       JSObject* object,
                                       int index,
@@ -525,9 +526,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
     // Note: starting a frame here makes GC aware of pointers pushed below.
     __ EnterInternalFrame();
 
-    if (lookup->type() == CALLBACKS) {
-      __ push(receiver);
-    }
+    __ push(receiver);
     __ push(holder);
     __ push(name_);
 
@@ -548,10 +547,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
     __ bind(&interceptor_failed);
     __ pop(name_);
     __ pop(holder);
-
-    if (lookup->type() == CALLBACKS) {
-      __ pop(receiver);
-    }
+    __ pop(receiver);
 
     __ LeaveInternalFrame();
 
@@ -1208,24 +1204,19 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
                                              String* name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the receiver from the stack.
-  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
-
-  // name register might be clobbered.
   GenerateStoreField(masm(),
                      object,
                      index,
                      transition,
-                     r3, r2, r1,
+                     r1, r2, r3,
                      &miss);
   __ bind(&miss);
-  __ mov(r2, Operand(Handle<String>(name)));  // restore name
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
@@ -1239,39 +1230,33 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
                                                 String* name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
-
   // Check that the object isn't a smi.
-  __ tst(r3, Operand(kSmiTagMask));
+  __ tst(r1, Operand(kSmiTagMask));
   __ b(eq, &miss);
 
   // Check that the map of the object hasn't changed.
-  __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ cmp(r1, Operand(Handle<Map>(object->map())));
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ cmp(r3, Operand(Handle<Map>(object->map())));
   __ b(ne, &miss);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
-    __ CheckAccessGlobalProxy(r3, r1, &miss);
+    __ CheckAccessGlobalProxy(r1, r3, &miss);
   }
 
   // Stub never generated for non-global objects that require access
   // checks.
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
-  __ ldr(ip, MemOperand(sp));  // receiver
-  __ push(ip);
+  __ push(r1);  // receiver
   __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback info
-  __ push(ip);
-  __ push(r2);  // name
-  __ push(r0);  // value
+  __ stm(db_w, sp, ip.bit() | r2.bit() | r0.bit());
 
   // Do tail-call to the runtime system.
   ExternalReference store_callback_property =
@@ -1292,37 +1277,33 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
                                                    String* name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
   Label miss;
 
-  // Get the object from the stack.
-  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
-
   // Check that the object isn't a smi.
-  __ tst(r3, Operand(kSmiTagMask));
+  __ tst(r1, Operand(kSmiTagMask));
   __ b(eq, &miss);
 
   // Check that the map of the object hasn't changed.
-  __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
-  __ cmp(r1, Operand(Handle<Map>(receiver->map())));
+  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ cmp(r3, Operand(Handle<Map>(receiver->map())));
   __ b(ne, &miss);
 
   // Perform global security token check if needed.
   if (receiver->IsJSGlobalProxy()) {
-    __ CheckAccessGlobalProxy(r3, r1, &miss);
+    __ CheckAccessGlobalProxy(r1, r3, &miss);
   }
 
-  // Stub never generated for non-global objects that require access
+  // Stub is never generated for non-global objects that require access
   // checks.
   ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
 
-  __ ldr(ip, MemOperand(sp));  // receiver
-  __ push(ip);
-  __ push(r2);  // name
-  __ push(r0);  // value
+  __ push(r1);  // receiver.
+  __ push(r2);  // name.
+  __ push(r0);  // value.
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
@@ -1344,14 +1325,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
                                               String* name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
+  //  -- r1    : receiver
   //  -- r2    : name
   //  -- lr    : return address
-  //  -- [sp]  : receiver
   // -----------------------------------
   Label miss;
 
   // Check that the map of the global has not changed.
-  __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
   __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
   __ cmp(r3, Operand(Handle<Map>(object->map())));
   __ b(ne, &miss);
@@ -1360,12 +1340,12 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
   __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell)));
   __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
 
-  __ IncrementCounter(&Counters::named_store_global_inline, 1, r1, r3);
+  __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3);
   __ Ret();
 
   // Handle store cache miss.
   __ bind(&miss);
-  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r1, r3);
+  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3);
   Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
   __ Jump(ic, RelocInfo::CODE_TARGET);