Revision: 22931
Author:   [email protected]
Date:     Wed Aug  6 13:18:36 2014 UTC
Log:      Always use the StoreFieldStub to do the actual storing.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/443963002
http://code.google.com/p/v8/source/detail?r=22931

Modified:
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/arm64/stub-cache-arm64.cc
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/stub-cache.cc
 /branches/bleeding_edge/src/stub-cache.h
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Aug 6 09:31:10 2014 UTC +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Aug 6 13:18:36 2014 UTC
@@ -581,77 +581,28 @@
 }


-// Generate StoreField code, value is passed in r0 register.
-// 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 NamedStoreHandlerCompiler::GenerateStoreField(
-    Handle<JSObject> object, LookupResult* lookup, Register receiver_reg,
- Register name_reg, Register value_reg, Register scratch1, Register scratch2,
-    Label* miss_label) {
-  // r0 : value
-  Label exit;
-
-  // Stub never generated for objects that require access checks.
-  DCHECK(!object->IsAccessCheckNeeded());
-  DCHECK(!object->IsJSGlobalProxy());
-
-  FieldIndex index = lookup->GetFieldIndex();
-
+void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
+                                                   Register value_reg,
+                                                   Label* miss_label) {
   DCHECK(lookup->representation().IsHeapObject());
   __ JumpIfSmi(value_reg, miss_label);
-  HeapType* field_type = lookup->GetFieldType();
-  HeapType::Iterator<Map> it = field_type->Classes();
-  if (!it.Done()) {
-    __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
-    Label do_store;
-    while (true) {
-      __ CompareMap(scratch1, it.Current(), &do_store);
-      it.Advance();
-      if (it.Done()) {
-        __ b(ne, miss_label);
-        break;
-      }
-      __ b(eq, &do_store);
+  HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
+  __ ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset));
+  Label do_store;
+  while (true) {
+    __ CompareMap(scratch1(), it.Current(), &do_store);
+    it.Advance();
+    if (it.Done()) {
+      __ b(ne, miss_label);
+      break;
     }
-    __ bind(&do_store);
+    __ b(eq, &do_store);
   }
+  __ bind(&do_store);

-  if (index.is_inobject()) {
-    // Set the property straight into the object.
-    __ str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
-
-    // Skip updating write barrier if storing a smi.
-    __ JumpIfSmi(value_reg, &exit);
-
-    // Update the write barrier for the array address.
-    // Pass the now unused name_reg as a scratch register.
-    __ mov(name_reg, value_reg);
-    __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
-                        kLRHasNotBeenSaved, kDontSaveFPRegs,
-                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  } else {
-    // Write to the properties array.
-    // Get the properties array
-    __ ldr(scratch1,
-           FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ str(value_reg, FieldMemOperand(scratch1, index.offset()));
-
-    // Skip updating write barrier if storing a smi.
-    __ JumpIfSmi(value_reg, &exit);
-
-    // Update the write barrier for the array address.
-    // Ok to clobber receiver_reg and name_reg, since we return.
-    __ mov(name_reg, value_reg);
-    __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
-                        kLRHasNotBeenSaved, kDontSaveFPRegs,
-                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  }
-
-  // Return the value (register r0).
-  DCHECK(value_reg.is(r0));
-  __ bind(&exit);
-  __ Ret();
+  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+                      lookup->representation());
+  GenerateTailCall(masm(), stub.GetCode());
 }


=======================================
--- /branches/bleeding_edge/src/arm64/stub-cache-arm64.cc Wed Aug 6 09:31:10 2014 UTC +++ /branches/bleeding_edge/src/arm64/stub-cache-arm64.cc Wed Aug 6 13:18:36 2014 UTC
@@ -531,77 +531,28 @@
 }


-// Generate StoreField code, value is passed in x0 register.
-// 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 NamedStoreHandlerCompiler::GenerateStoreField(
-    Handle<JSObject> object, LookupResult* lookup, Register receiver_reg,
- Register name_reg, Register value_reg, Register scratch1, Register scratch2,
-    Label* miss_label) {
-  // x0 : value
-  Label exit;
-
-  // Stub never generated for objects that require access checks.
-  DCHECK(!object->IsAccessCheckNeeded());
-  DCHECK(!object->IsJSGlobalProxy());
-
-  FieldIndex index = lookup->GetFieldIndex();
-
+void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
+                                                   Register value_reg,
+                                                   Label* miss_label) {
   DCHECK(lookup->representation().IsHeapObject());
   __ JumpIfSmi(value_reg, miss_label);
-  HeapType* field_type = lookup->GetFieldType();
-  HeapType::Iterator<Map> it = field_type->Classes();
-  if (!it.Done()) {
-    __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
-    Label do_store;
-    while (true) {
-      __ CompareMap(scratch1, it.Current());
-      it.Advance();
-      if (it.Done()) {
-        __ B(ne, miss_label);
-        break;
-      }
-      __ B(eq, &do_store);
+  HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
+  __ Ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset));
+  Label do_store;
+  while (true) {
+    __ CompareMap(scratch1(), it.Current());
+    it.Advance();
+    if (it.Done()) {
+      __ B(ne, miss_label);
+      break;
     }
-    __ Bind(&do_store);
+    __ B(eq, &do_store);
   }
+  __ Bind(&do_store);

-  if (index.is_inobject()) {
-    // Set the property straight into the object.
-    __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
-
-    // Skip updating write barrier if storing a smi.
-    __ JumpIfSmi(value_reg, &exit);
-
-    // Update the write barrier for the array address.
-    // Pass the now unused name_reg as a scratch register.
-    __ Mov(name_reg, value_reg);
-    __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
-                        kLRHasNotBeenSaved, kDontSaveFPRegs,
-                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  } else {
-    // Write to the properties array.
-    // Get the properties array
-    __ Ldr(scratch1,
-           FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ Str(value_reg, FieldMemOperand(scratch1, index.offset()));
-
-    // Skip updating write barrier if storing a smi.
-    __ JumpIfSmi(value_reg, &exit);
-
-    // Update the write barrier for the array address.
-    // Ok to clobber receiver_reg and name_reg, since we return.
-    __ Mov(name_reg, value_reg);
-    __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
-                        kLRHasNotBeenSaved, kDontSaveFPRegs,
-                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  }
-
-  __ Bind(&exit);
-  // Return the value (register x0).
-  DCHECK(value_reg.is(x0));
-  __ Ret();
+  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+                      lookup->representation());
+  GenerateTailCall(masm(), stub.GetCode());
 }


=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Wed Aug  6 08:02:21 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.cc   Wed Aug  6 13:18:36 2014 UTC
@@ -935,6 +935,14 @@
   KeyedLoadGenericStub stub(isolate);
   InstallDescriptor(isolate, &stub);
 }
+
+
+// static
+void StoreFieldStub::InstallDescriptors(Isolate* isolate) {
+  StoreFieldStub stub(isolate, FieldIndex::ForInObjectOffset(0),
+                      Representation::None());
+  InstallDescriptor(isolate, &stub);
+}


 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Wed Aug  6 09:31:10 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.h    Wed Aug  6 13:18:36 2014 UTC
@@ -990,6 +990,7 @@

   FieldIndex index() const { return index_; }
   Representation representation() { return representation_; }
+  static void InstallDescriptors(Isolate* isolate);

  protected:
   explicit StoreFieldStub(Isolate* isolate);
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Aug 6 09:31:10 2014 UTC +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Aug 6 13:18:36 2014 UTC
@@ -568,60 +568,27 @@
 }


-// Both name_reg and receiver_reg are preserved on jumps to miss_label,
-// but may be destroyed if store is successful.
-void NamedStoreHandlerCompiler::GenerateStoreField(
-    Handle<JSObject> object, LookupResult* lookup, Register receiver_reg,
- Register name_reg, Register value_reg, Register scratch1, Register scratch2,
-    Label* miss_label) {
-  // Stub never generated for objects that require access checks.
-  DCHECK(!object->IsAccessCheckNeeded());
-  DCHECK(!object->IsJSGlobalProxy());
-
-  FieldIndex index = lookup->GetFieldIndex();
+void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
+                                                   Register value_reg,
+                                                   Label* miss_label) {
   DCHECK(lookup->representation().IsHeapObject());
   __ JumpIfSmi(value_reg, miss_label);
-  HeapType* field_type = lookup->GetFieldType();
-  HeapType::Iterator<Map> it = field_type->Classes();
-  if (!it.Done()) {
-    Label do_store;
-    while (true) {
-      __ CompareMap(value_reg, it.Current());
-      it.Advance();
-      if (it.Done()) {
-        __ j(not_equal, miss_label);
-        break;
-      }
-      __ j(equal, &do_store, Label::kNear);
+  HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
+  Label do_store;
+  while (true) {
+    __ CompareMap(value_reg, it.Current());
+    it.Advance();
+    if (it.Done()) {
+      __ j(not_equal, miss_label);
+      break;
     }
-    __ bind(&do_store);
+    __ j(equal, &do_store, Label::kNear);
   }
+  __ bind(&do_store);

-  if (index.is_inobject()) {
-    // Set the property straight into the object.
-    __ mov(FieldOperand(receiver_reg, index.offset()), value_reg);
-
-    // Update the write barrier for the array address.
-    // Pass the value being stored in the now unused name_reg.
-    __ mov(name_reg, value_reg);
-    __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  } else {
-    // Write to the properties array.
-    // Get the properties array (optimistically).
- __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ mov(FieldOperand(scratch1, index.offset()), value_reg);
-
-    // Update the write barrier for the array address.
-    // Pass the value being stored in the now unused name_reg.
-    __ mov(name_reg, value_reg);
-    __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  }
-
-  // Return the value (register eax).
-  DCHECK(value_reg.is(eax));
-  __ ret(0);
+  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+                      lookup->representation());
+  GenerateTailCall(masm(), stub.GetCode());
 }


=======================================
--- /branches/bleeding_edge/src/ic.cc   Wed Aug  6 09:31:10 2014 UTC
+++ /branches/bleeding_edge/src/ic.cc   Wed Aug  6 13:18:36 2014 UTC
@@ -1473,13 +1473,21 @@
     }
   } else {
     switch (lookup->type()) {
-      case FIELD:
-        if (!lookup->representation().IsHeapObject()) {
+      case FIELD: {
+        bool use_stub = true;
+        if (lookup->representation().IsHeapObject()) {
+          // Only use a generic stub if no types need to be tracked.
+          HeapType* field_type = lookup->GetFieldType();
+          HeapType::Iterator<Map> it = field_type->Classes();
+          use_stub = it.Done();
+        }
+        if (use_stub) {
           StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
                               lookup->representation());
           return stub.GetCode();
         }
         return compiler.CompileStoreField(lookup, name);
+      }
       case NORMAL:
         if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
// The stub generated for the global object picks the value directly
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Wed Aug  6 09:41:52 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc      Wed Aug  6 13:18:36 2014 UTC
@@ -2003,6 +2003,7 @@
     StringAddStub::InstallDescriptors(this);
     RegExpConstructResultStub::InstallDescriptors(this);
     KeyedLoadGenericStub::InstallDescriptors(this);
+    StoreFieldStub::InstallDescriptors(this);
   }

   CallDescriptors::InitializeForIsolate(this);
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc   Wed Aug  6 08:02:21 2014 UTC
+++ /branches/bleeding_edge/src/stub-cache.cc   Wed Aug  6 13:18:36 2014 UTC
@@ -995,14 +995,7 @@
Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupResult* lookup, Handle<Name> name) {
   Label miss;
-
-  FrontendHeader(receiver(), name, &miss);
-
-  // Generate store field code.
-  GenerateStoreField(holder(), lookup, receiver(), this->name(), value(),
-                     scratch1(), scratch2(), &miss);
-
-  // Handle store cache miss.
+  GenerateStoreField(lookup, value(), &miss);
   __ bind(&miss);
   TailCallBuiltin(masm(), MissBuiltin(kind()));
   return GetCode(kind(), Code::FAST, name);
=======================================
--- /branches/bleeding_edge/src/stub-cache.h    Wed Aug  6 08:02:21 2014 UTC
+++ /branches/bleeding_edge/src/stub-cache.h    Wed Aug  6 13:18:36 2014 UTC
@@ -589,10 +589,8 @@
                                Register scratch2, Register scratch3,
                                Label* miss_label, Label* slow);

-  void GenerateStoreField(Handle<JSObject> object, LookupResult* lookup,
-                          Register receiver_reg, Register name_reg,
-                          Register value_reg, Register scratch1,
-                          Register scratch2, Label* miss_label);
+  void GenerateStoreField(LookupResult* lookup, Register value_reg,
+                          Label* miss_label);

   static Builtins::Name SlowBuiltin(Code::Kind kind) {
     switch (kind) {
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Aug 6 09:31:10 2014 UTC +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Aug 6 13:18:36 2014 UTC
@@ -516,61 +516,27 @@
 }


-// Both name_reg and receiver_reg are preserved on jumps to miss_label,
-// but may be destroyed if store is successful.
-void NamedStoreHandlerCompiler::GenerateStoreField(
-    Handle<JSObject> object, LookupResult* lookup, Register receiver_reg,
- Register name_reg, Register value_reg, Register scratch1, Register scratch2,
-    Label* miss_label) {
-  // Stub never generated for objects that require access checks.
-  DCHECK(!object->IsAccessCheckNeeded());
-  DCHECK(!object->IsJSGlobalProxy());
-
-  FieldIndex index = lookup->GetFieldIndex();
-
+void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
+                                                   Register value_reg,
+                                                   Label* miss_label) {
   DCHECK(lookup->representation().IsHeapObject());
   __ JumpIfSmi(value_reg, miss_label);
-  HeapType* field_type = lookup->GetFieldType();
-  HeapType::Iterator<Map> it = field_type->Classes();
-  if (!it.Done()) {
-    Label do_store;
-    while (true) {
-      __ CompareMap(value_reg, it.Current());
-      it.Advance();
-      if (it.Done()) {
-        __ j(not_equal, miss_label);
-        break;
-      }
-      __ j(equal, &do_store, Label::kNear);
+  HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
+  Label do_store;
+  while (true) {
+    __ CompareMap(value_reg, it.Current());
+    it.Advance();
+    if (it.Done()) {
+      __ j(not_equal, miss_label);
+      break;
     }
-    __ bind(&do_store);
+    __ j(equal, &do_store, Label::kNear);
   }
+  __ bind(&do_store);

-  if (index.is_inobject()) {
-    // Set the property straight into the object.
-    __ movp(FieldOperand(receiver_reg, index.offset()), value_reg);
-
-    // Update the write barrier for the array address.
-    // Pass the value being stored in the now unused name_reg.
-    __ movp(name_reg, value_reg);
-    __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  } else {
-    // Write to the properties array.
-    // Get the properties array (optimistically).
- __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ movp(FieldOperand(scratch1, index.offset()), value_reg);
-
-    // Update the write barrier for the array address.
-    // Pass the value being stored in the now unused name_reg.
-    __ movp(name_reg, value_reg);
-    __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
- kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-  }
-
-  // Return the value (register rax).
-  DCHECK(value_reg.is(rax));
-  __ ret(0);
+  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+                      lookup->representation());
+  GenerateTailCall(masm(), stub.GetCode());
 }


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to