Hydrogenize (and share) StoreField except heapobject (for now).
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
This commit is contained in:
parent
df7057b3ce
commit
b8ab822040
@ -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).
|
||||
|
@ -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);
|
||||
__ B(eq, &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()));
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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).
|
||||
|
@ -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()) {
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user