Hydrogenize (and share) StoreField except heapobject (for now).
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 6 Aug 2014 09:31:10 +0000 (09:31 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 6 Aug 2014 09:31:10 +0000 (09:31 +0000)
BUG=
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/443873002

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

src/arm/stub-cache-arm.cc
src/arm64/stub-cache-arm64.cc
src/code-stubs-hydrogen.cc
src/code-stubs.h
src/field-index.h
src/ia32/stub-cache-ia32.cc
src/ic.cc
src/x64/stub-cache-x64.cc

index e37ff60b0f9710e065fb18aa3f7ddbffb8a05a71..f8dfe26e8c29cb62409097ef5896729422254859 100644 (file)
@@ -598,82 +598,38 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
 
   FieldIndex index = lookup->GetFieldIndex();
 
-  Representation representation = lookup->representation();
-  DCHECK(!representation.IsNone());
-  if (representation.IsSmi()) {
-    __ JumpIfNotSmi(value_reg, miss_label);
-  } else if (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);
+  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;
       }
-      __ bind(&do_store);
+      __ b(eq, &do_store);
     }
-  } else if (representation.IsDouble()) {
-    // Load the double storage.
-    if (index.is_inobject()) {
-      __ ldr(scratch1, FieldMemOperand(receiver_reg, index.offset()));
-    } else {
-      __ ldr(scratch1,
-             FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ ldr(scratch1, FieldMemOperand(scratch1, index.offset()));
-    }
-
-    // Store the value into the storage.
-    Label do_store, heap_number;
-    __ JumpIfNotSmi(value_reg, &heap_number);
-    __ SmiUntag(scratch2, value_reg);
-    __ vmov(s0, scratch2);
-    __ vcvt_f64_s32(d0, s0);
-    __ jmp(&do_store);
-
-    __ bind(&heap_number);
-    __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex,
-                miss_label, DONT_DO_SMI_CHECK);
-    __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
-
     __ bind(&do_store);
-    __ vstr(d0, FieldMemOperand(scratch1, HeapNumber::kValueOffset));
-    // Return the value (register r0).
-    DCHECK(value_reg.is(r0));
-    __ Ret();
-    return;
   }
 
-  // TODO(verwaest): Share this code as a code stub.
-  SmiCheck smi_check = representation.IsTagged()
-      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index.is_inobject()) {
     // Set the property straight into the object.
     __ str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
 
-    if (!representation.IsSmi()) {
-      // Skip updating write barrier if storing a smi.
-      __ JumpIfSmi(value_reg, &exit);
+    // 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,
-                          smi_check);
-    }
+    // 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
@@ -681,22 +637,15 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
            FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
     __ str(value_reg, FieldMemOperand(scratch1, index.offset()));
 
-    if (!representation.IsSmi()) {
-      // Skip updating write barrier if storing a smi.
-      __ JumpIfSmi(value_reg, &exit);
+    // 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,
-                          smi_check);
-    }
+    // 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).
index 7ac68e79a5b1c3eebc1b27e8006f586563bc7b50..92fbecf7524e90d881f6d3dcba9c4ae72c9127ed 100644 (file)
@@ -548,84 +548,38 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
 
   FieldIndex index = lookup->GetFieldIndex();
 
-  Representation representation = lookup->representation();
-  DCHECK(!representation.IsNone());
-  if (representation.IsSmi()) {
-    __ JumpIfNotSmi(value_reg, miss_label);
-  } else if (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);
+  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;
       }
-      __ Bind(&do_store);
-    }
-  } else if (representation.IsDouble()) {
-    UseScratchRegisterScope temps(masm());
-    DoubleRegister temp_double = temps.AcquireD();
-
-    __ SmiUntagToDouble(temp_double, value_reg, kSpeculativeUntag);
-
-    // Load the double storage.
-    if (index.is_inobject()) {
-      __ Ldr(scratch1, FieldMemOperand(receiver_reg, index.offset()));
-    } else {
-      __ Ldr(scratch1,
-             FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ Ldr(scratch1, FieldMemOperand(scratch1, index.offset()));
+      __ B(eq, &do_store);
     }
-
-    // Store the value into the storage.
-    Label do_store, heap_number;
-
-    __ JumpIfSmi(value_reg, &do_store);
-
-    __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex,
-                miss_label, DONT_DO_SMI_CHECK);
-    __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
-
     __ Bind(&do_store);
-    __ Str(temp_double, FieldMemOperand(scratch1, HeapNumber::kValueOffset));
-
-    // Return the value (register x0).
-    DCHECK(value_reg.is(x0));
-    __ Ret();
-    return;
   }
 
-  // TODO(verwaest): Share this code as a code stub.
-  SmiCheck smi_check = representation.IsTagged()
-      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index.is_inobject()) {
     // Set the property straight into the object.
     __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
 
-    if (!representation.IsSmi()) {
-      // Skip updating write barrier if storing a smi.
-      __ JumpIfSmi(value_reg, &exit);
+    // 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,
-                          smi_check);
-    }
+    // 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
@@ -633,22 +587,15 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
            FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
     __ Str(value_reg, FieldMemOperand(scratch1, index.offset()));
 
-    if (!representation.IsSmi()) {
-      // Skip updating write barrier if storing a smi.
-      __ JumpIfSmi(value_reg, &exit);
+    // 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,
-                          smi_check);
-    }
+    // 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);
index 2306da6db7e84af9e6342db942a04b777eb9768f..ba647bab8487caf3545888dc74776e57036afc0a 100644 (file)
@@ -62,6 +62,8 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
 
   HLoadNamedField* BuildLoadNamedField(HValue* object,
                                        FieldIndex index);
+  void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
+                            Representation representation);
 
   enum ArgumentClass {
     NONE,
@@ -607,6 +609,42 @@ HValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() {
 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); }
 
 
+void CodeStubGraphBuilderBase::BuildStoreNamedField(
+    HValue* object, HValue* value, FieldIndex index,
+    Representation representation) {
+  DCHECK(!index.is_double() || representation.IsDouble());
+  int offset = index.offset();
+  HObjectAccess access =
+      index.is_inobject()
+          ? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
+          : HObjectAccess::ForBackingStoreOffset(offset, representation);
+
+  if (representation.IsDouble()) {
+    // Load the heap number.
+    object = Add<HLoadNamedField>(
+        object, static_cast<HValue*>(NULL),
+        access.WithRepresentation(Representation::Tagged()));
+    // Store the double value into it.
+    access = HObjectAccess::ForHeapNumberValue();
+  } else if (representation.IsHeapObject()) {
+    BuildCheckHeapObject(value);
+  }
+
+  Add<HStoreNamedField>(object, access, value, STORE_TO_INITIALIZED_ENTRY);
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<StoreFieldStub>::BuildCodeStub() {
+  BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(),
+                       casted_stub()->representation());
+  return GetParameter(2);
+}
+
+
+Handle<Code> StoreFieldStub::GenerateCode() { return DoGenerateCode(this); }
+
+
 template <>
 HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
   HValue* string = BuildLoadNamedField(GetParameter(0),
index 01f83ed54f5f7afa5274919620643b7521458fca..e9378de5bb8988f095f005f5691d1164a2f897ca 100644 (file)
@@ -76,6 +76,7 @@ namespace internal {
   V(CallApiGetter)                          \
   /* IC Handler stubs */                    \
   V(LoadField)                              \
+  V(StoreField)                             \
   V(LoadConstant)                           \
   V(StringLength)
 
@@ -920,19 +921,13 @@ class LoadFieldStub: public HandlerStub {
  public:
   LoadFieldStub(Isolate* isolate, FieldIndex index)
     : HandlerStub(isolate), index_(index) {
-    int property_index_key = index_.GetLoadFieldStubKey();
+    int property_index_key = index_.GetFieldAccessStubKey();
     bit_field_ = EncodedLoadFieldByIndexBits::encode(property_index_key);
   }
 
   virtual Handle<Code> GenerateCode() V8_OVERRIDE;
 
-  Representation representation() {
-    if (unboxed_double()) return Representation::Double();
-    return Representation::Tagged();
-  }
-
   FieldIndex index() const { return index_; }
-  bool unboxed_double() { return index_.is_double(); }
 
  protected:
   explicit LoadFieldStub(Isolate* isolate);
@@ -980,6 +975,36 @@ class StringLengthStub: public HandlerStub {
 };
 
 
+class StoreFieldStub : public HandlerStub {
+ public:
+  StoreFieldStub(Isolate* isolate, FieldIndex index,
+                 Representation representation)
+      : HandlerStub(isolate), index_(index), representation_(representation) {
+    int property_index_key = index_.GetFieldAccessStubKey();
+    bit_field_ = EncodedStoreFieldByIndexBits::encode(property_index_key) |
+                 RepresentationBits::encode(
+                     PropertyDetails::EncodeRepresentation(representation));
+  }
+
+  virtual Handle<Code> GenerateCode() V8_OVERRIDE;
+
+  FieldIndex index() const { return index_; }
+  Representation representation() { return representation_; }
+
+ protected:
+  explicit StoreFieldStub(Isolate* isolate);
+  virtual Code::Kind kind() const { return Code::STORE_IC; }
+  virtual Code::StubType GetStubType() { return Code::FAST; }
+
+ private:
+  class EncodedStoreFieldByIndexBits : public BitField<int, 0, 13> {};
+  class RepresentationBits : public BitField<int, 13, 4> {};
+  virtual CodeStub::Major MajorKey() const { return StoreField; }
+  FieldIndex index_;
+  Representation representation_;
+};
+
+
 class StoreGlobalStub : public HandlerStub {
  public:
   StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
index 56df7ec758a025ccae8c24c2ea9c26859e31250b..8650c8fb8fdeb4dadbb1fb75463f8b09b5fe8914 100644 (file)
@@ -65,7 +65,7 @@ class FieldIndex V8_FINAL {
 
   int GetKeyedLookupCacheIndex() const;
 
-  int GetLoadFieldStubKey() const {
+  int GetFieldAccessStubKey() const {
     return bit_field_ &
         (IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask);
   }
index 0d74009a8bc65dcc9a162a978294e1471ecbe405..2720711e2b701f47a822a559d4ac45eb886a8630 100644 (file)
@@ -579,94 +579,44 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
   DCHECK(!object->IsJSGlobalProxy());
 
   FieldIndex index = lookup->GetFieldIndex();
-
-  Representation representation = lookup->representation();
-  DCHECK(!representation.IsNone());
-  if (representation.IsSmi()) {
-    __ JumpIfNotSmi(value_reg, miss_label);
-  } else if (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);
+  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;
       }
-      __ bind(&do_store);
+      __ j(equal, &do_store, Label::kNear);
     }
-  } else if (representation.IsDouble()) {
-    // Load the double storage.
-    if (index.is_inobject()) {
-      __ mov(scratch1, FieldOperand(receiver_reg, index.offset()));
-    } else {
-      __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ mov(scratch1, FieldOperand(scratch1, index.offset()));
-    }
-
-    // Store the value into the storage.
-    Label do_store, heap_number;
-    __ JumpIfNotSmi(value_reg, &heap_number);
-    __ SmiUntag(value_reg);
-    __ Cvtsi2sd(xmm0, value_reg);
-    __ SmiTag(value_reg);
-    __ jmp(&do_store);
-    __ bind(&heap_number);
-    __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label,
-                DONT_DO_SMI_CHECK);
-    __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
     __ bind(&do_store);
-    __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0);
-    // Return the value (register eax).
-    DCHECK(value_reg.is(eax));
-    __ ret(0);
-    return;
   }
 
-  DCHECK(!representation.IsDouble());
-  // TODO(verwaest): Share this code as a code stub.
-  SmiCheck smi_check = representation.IsTagged()
-      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index.is_inobject()) {
     // Set the property straight into the object.
     __ mov(FieldOperand(receiver_reg, index.offset()), value_reg);
 
-    if (!representation.IsSmi()) {
-      // 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,
-                          smi_check);
-    }
+    // 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);
 
-    if (!representation.IsSmi()) {
-      // 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,
-                          smi_check);
-    }
+    // 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).
index bd8db3e01af8bda046cff075238be2c522597304..05b235c79407355d24790e9ba2454556420627a0 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1474,6 +1474,11 @@ Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
   } else {
     switch (lookup->type()) {
       case FIELD:
+        if (!lookup->representation().IsHeapObject()) {
+          StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+                              lookup->representation());
+          return stub.GetCode();
+        }
         return compiler.CompileStoreField(lookup, name);
       case NORMAL:
         if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
index 0bf542e95a03f7160727832ea76f1ccbf9c24c96..7d6dbd20b2befe3b1136449be424e7d0fc41019f 100644 (file)
@@ -528,85 +528,44 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
 
   FieldIndex index = lookup->GetFieldIndex();
 
-  Representation representation = lookup->representation();
-  DCHECK(!representation.IsNone());
-  if (representation.IsSmi()) {
-    __ JumpIfNotSmi(value_reg, miss_label);
-  } else if (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);
+  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;
       }
-      __ bind(&do_store);
+      __ j(equal, &do_store, Label::kNear);
     }
-  } else if (representation.IsDouble()) {
-    // Load the double storage.
-    if (index.is_inobject()) {
-      __ movp(scratch1, FieldOperand(receiver_reg, index.offset()));
-    } else {
-      __ movp(scratch1,
-              FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ movp(scratch1, FieldOperand(scratch1, index.offset()));
-    }
-
-    // Store the value into the storage.
-    Label do_store, heap_number;
-    __ JumpIfNotSmi(value_reg, &heap_number);
-    __ SmiToInteger32(scratch2, value_reg);
-    __ Cvtlsi2sd(xmm0, scratch2);
-    __ jmp(&do_store);
-
-    __ bind(&heap_number);
-    __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label,
-                DONT_DO_SMI_CHECK);
-    __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
     __ bind(&do_store);
-    __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0);
-    // Return the value (register rax).
-    DCHECK(value_reg.is(rax));
-    __ ret(0);
-    return;
   }
 
-  // TODO(verwaest): Share this code as a code stub.
-  SmiCheck smi_check = representation.IsTagged()
-      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index.is_inobject()) {
     // Set the property straight into the object.
     __ movp(FieldOperand(receiver_reg, index.offset()), value_reg);
 
-    if (!representation.IsSmi()) {
-      // 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, smi_check);
-    }
+    // 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);
 
-    if (!representation.IsSmi()) {
-      // 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, smi_check);
-    }
+    // 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).