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();
|
FieldIndex index = lookup->GetFieldIndex();
|
||||||
|
|
||||||
Representation representation = lookup->representation();
|
DCHECK(lookup->representation().IsHeapObject());
|
||||||
DCHECK(!representation.IsNone());
|
__ JumpIfSmi(value_reg, miss_label);
|
||||||
if (representation.IsSmi()) {
|
HeapType* field_type = lookup->GetFieldType();
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
HeapType::Iterator<Map> it = field_type->Classes();
|
||||||
} else if (representation.IsHeapObject()) {
|
if (!it.Done()) {
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
__ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
||||||
HeapType* field_type = lookup->GetFieldType();
|
Label do_store;
|
||||||
HeapType::Iterator<Map> it = field_type->Classes();
|
while (true) {
|
||||||
if (!it.Done()) {
|
__ CompareMap(scratch1, it.Current(), &do_store);
|
||||||
__ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
it.Advance();
|
||||||
Label do_store;
|
if (it.Done()) {
|
||||||
while (true) {
|
__ b(ne, miss_label);
|
||||||
__ CompareMap(scratch1, it.Current(), &do_store);
|
break;
|
||||||
it.Advance();
|
|
||||||
if (it.Done()) {
|
|
||||||
__ b(ne, miss_label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
__ b(eq, &do_store);
|
|
||||||
}
|
}
|
||||||
__ 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);
|
__ 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()) {
|
if (index.is_inobject()) {
|
||||||
// Set the property straight into the object.
|
// Set the property straight into the object.
|
||||||
__ str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
|
__ str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Skip updating write barrier if storing a smi.
|
||||||
// Skip updating write barrier if storing a smi.
|
__ JumpIfSmi(value_reg, &exit);
|
||||||
__ JumpIfSmi(value_reg, &exit);
|
|
||||||
|
|
||||||
// Update the write barrier for the array address.
|
// Update the write barrier for the array address.
|
||||||
// Pass the now unused name_reg as a scratch register.
|
// Pass the now unused name_reg as a scratch register.
|
||||||
__ mov(name_reg, value_reg);
|
__ mov(name_reg, value_reg);
|
||||||
__ RecordWriteField(receiver_reg,
|
__ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
|
||||||
index.offset(),
|
kLRHasNotBeenSaved, kDontSaveFPRegs,
|
||||||
name_reg,
|
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
scratch1,
|
|
||||||
kLRHasNotBeenSaved,
|
|
||||||
kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET,
|
|
||||||
smi_check);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Write to the properties array.
|
// Write to the properties array.
|
||||||
// Get the properties array
|
// Get the properties array
|
||||||
@ -681,22 +637,15 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
|
|||||||
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
|
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
|
||||||
__ str(value_reg, FieldMemOperand(scratch1, index.offset()));
|
__ str(value_reg, FieldMemOperand(scratch1, index.offset()));
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Skip updating write barrier if storing a smi.
|
||||||
// Skip updating write barrier if storing a smi.
|
__ JumpIfSmi(value_reg, &exit);
|
||||||
__ JumpIfSmi(value_reg, &exit);
|
|
||||||
|
|
||||||
// Update the write barrier for the array address.
|
// Update the write barrier for the array address.
|
||||||
// Ok to clobber receiver_reg and name_reg, since we return.
|
// Ok to clobber receiver_reg and name_reg, since we return.
|
||||||
__ mov(name_reg, value_reg);
|
__ mov(name_reg, value_reg);
|
||||||
__ RecordWriteField(scratch1,
|
__ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
|
||||||
index.offset(),
|
kLRHasNotBeenSaved, kDontSaveFPRegs,
|
||||||
name_reg,
|
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
receiver_reg,
|
|
||||||
kLRHasNotBeenSaved,
|
|
||||||
kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET,
|
|
||||||
smi_check);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the value (register r0).
|
// Return the value (register r0).
|
||||||
|
@ -548,84 +548,38 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
|
|||||||
|
|
||||||
FieldIndex index = lookup->GetFieldIndex();
|
FieldIndex index = lookup->GetFieldIndex();
|
||||||
|
|
||||||
Representation representation = lookup->representation();
|
DCHECK(lookup->representation().IsHeapObject());
|
||||||
DCHECK(!representation.IsNone());
|
__ JumpIfSmi(value_reg, miss_label);
|
||||||
if (representation.IsSmi()) {
|
HeapType* field_type = lookup->GetFieldType();
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
HeapType::Iterator<Map> it = field_type->Classes();
|
||||||
} else if (representation.IsHeapObject()) {
|
if (!it.Done()) {
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
__ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
||||||
HeapType* field_type = lookup->GetFieldType();
|
Label do_store;
|
||||||
HeapType::Iterator<Map> it = field_type->Classes();
|
while (true) {
|
||||||
if (!it.Done()) {
|
__ CompareMap(scratch1, it.Current());
|
||||||
__ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
it.Advance();
|
||||||
Label do_store;
|
if (it.Done()) {
|
||||||
while (true) {
|
__ B(ne, miss_label);
|
||||||
__ CompareMap(scratch1, it.Current());
|
break;
|
||||||
it.Advance();
|
|
||||||
if (it.Done()) {
|
|
||||||
__ B(ne, miss_label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
__ B(eq, &do_store);
|
|
||||||
}
|
}
|
||||||
__ 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);
|
__ 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()) {
|
if (index.is_inobject()) {
|
||||||
// Set the property straight into the object.
|
// Set the property straight into the object.
|
||||||
__ Str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
|
__ Str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Skip updating write barrier if storing a smi.
|
||||||
// Skip updating write barrier if storing a smi.
|
__ JumpIfSmi(value_reg, &exit);
|
||||||
__ JumpIfSmi(value_reg, &exit);
|
|
||||||
|
|
||||||
// Update the write barrier for the array address.
|
// Update the write barrier for the array address.
|
||||||
// Pass the now unused name_reg as a scratch register.
|
// Pass the now unused name_reg as a scratch register.
|
||||||
__ Mov(name_reg, value_reg);
|
__ Mov(name_reg, value_reg);
|
||||||
__ RecordWriteField(receiver_reg,
|
__ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
|
||||||
index.offset(),
|
kLRHasNotBeenSaved, kDontSaveFPRegs,
|
||||||
name_reg,
|
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
scratch1,
|
|
||||||
kLRHasNotBeenSaved,
|
|
||||||
kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET,
|
|
||||||
smi_check);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Write to the properties array.
|
// Write to the properties array.
|
||||||
// Get the properties array
|
// Get the properties array
|
||||||
@ -633,22 +587,15 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
|
|||||||
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
|
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
|
||||||
__ Str(value_reg, FieldMemOperand(scratch1, index.offset()));
|
__ Str(value_reg, FieldMemOperand(scratch1, index.offset()));
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Skip updating write barrier if storing a smi.
|
||||||
// Skip updating write barrier if storing a smi.
|
__ JumpIfSmi(value_reg, &exit);
|
||||||
__ JumpIfSmi(value_reg, &exit);
|
|
||||||
|
|
||||||
// Update the write barrier for the array address.
|
// Update the write barrier for the array address.
|
||||||
// Ok to clobber receiver_reg and name_reg, since we return.
|
// Ok to clobber receiver_reg and name_reg, since we return.
|
||||||
__ Mov(name_reg, value_reg);
|
__ Mov(name_reg, value_reg);
|
||||||
__ RecordWriteField(scratch1,
|
__ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
|
||||||
index.offset(),
|
kLRHasNotBeenSaved, kDontSaveFPRegs,
|
||||||
name_reg,
|
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
receiver_reg,
|
|
||||||
kLRHasNotBeenSaved,
|
|
||||||
kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET,
|
|
||||||
smi_check);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__ Bind(&exit);
|
__ Bind(&exit);
|
||||||
|
@ -62,6 +62,8 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
|
|||||||
|
|
||||||
HLoadNamedField* BuildLoadNamedField(HValue* object,
|
HLoadNamedField* BuildLoadNamedField(HValue* object,
|
||||||
FieldIndex index);
|
FieldIndex index);
|
||||||
|
void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
|
||||||
|
Representation representation);
|
||||||
|
|
||||||
enum ArgumentClass {
|
enum ArgumentClass {
|
||||||
NONE,
|
NONE,
|
||||||
@ -607,6 +609,42 @@ HValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() {
|
|||||||
Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); }
|
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 <>
|
template <>
|
||||||
HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
|
HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
|
||||||
HValue* string = BuildLoadNamedField(GetParameter(0),
|
HValue* string = BuildLoadNamedField(GetParameter(0),
|
||||||
|
@ -76,6 +76,7 @@ namespace internal {
|
|||||||
V(CallApiGetter) \
|
V(CallApiGetter) \
|
||||||
/* IC Handler stubs */ \
|
/* IC Handler stubs */ \
|
||||||
V(LoadField) \
|
V(LoadField) \
|
||||||
|
V(StoreField) \
|
||||||
V(LoadConstant) \
|
V(LoadConstant) \
|
||||||
V(StringLength)
|
V(StringLength)
|
||||||
|
|
||||||
@ -920,19 +921,13 @@ class LoadFieldStub: public HandlerStub {
|
|||||||
public:
|
public:
|
||||||
LoadFieldStub(Isolate* isolate, FieldIndex index)
|
LoadFieldStub(Isolate* isolate, FieldIndex index)
|
||||||
: HandlerStub(isolate), index_(index) {
|
: HandlerStub(isolate), index_(index) {
|
||||||
int property_index_key = index_.GetLoadFieldStubKey();
|
int property_index_key = index_.GetFieldAccessStubKey();
|
||||||
bit_field_ = EncodedLoadFieldByIndexBits::encode(property_index_key);
|
bit_field_ = EncodedLoadFieldByIndexBits::encode(property_index_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
|
||||||
|
|
||||||
Representation representation() {
|
|
||||||
if (unboxed_double()) return Representation::Double();
|
|
||||||
return Representation::Tagged();
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldIndex index() const { return index_; }
|
FieldIndex index() const { return index_; }
|
||||||
bool unboxed_double() { return index_.is_double(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit LoadFieldStub(Isolate* isolate);
|
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 {
|
class StoreGlobalStub : public HandlerStub {
|
||||||
public:
|
public:
|
||||||
StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
|
StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
|
||||||
|
@ -65,7 +65,7 @@ class FieldIndex V8_FINAL {
|
|||||||
|
|
||||||
int GetKeyedLookupCacheIndex() const;
|
int GetKeyedLookupCacheIndex() const;
|
||||||
|
|
||||||
int GetLoadFieldStubKey() const {
|
int GetFieldAccessStubKey() const {
|
||||||
return bit_field_ &
|
return bit_field_ &
|
||||||
(IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask);
|
(IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask);
|
||||||
}
|
}
|
||||||
|
@ -579,94 +579,44 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
|
|||||||
DCHECK(!object->IsJSGlobalProxy());
|
DCHECK(!object->IsJSGlobalProxy());
|
||||||
|
|
||||||
FieldIndex index = lookup->GetFieldIndex();
|
FieldIndex index = lookup->GetFieldIndex();
|
||||||
|
DCHECK(lookup->representation().IsHeapObject());
|
||||||
Representation representation = lookup->representation();
|
__ JumpIfSmi(value_reg, miss_label);
|
||||||
DCHECK(!representation.IsNone());
|
HeapType* field_type = lookup->GetFieldType();
|
||||||
if (representation.IsSmi()) {
|
HeapType::Iterator<Map> it = field_type->Classes();
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
if (!it.Done()) {
|
||||||
} else if (representation.IsHeapObject()) {
|
Label do_store;
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
while (true) {
|
||||||
HeapType* field_type = lookup->GetFieldType();
|
__ CompareMap(value_reg, it.Current());
|
||||||
HeapType::Iterator<Map> it = field_type->Classes();
|
it.Advance();
|
||||||
if (!it.Done()) {
|
if (it.Done()) {
|
||||||
Label do_store;
|
__ j(not_equal, miss_label);
|
||||||
while (true) {
|
break;
|
||||||
__ CompareMap(value_reg, it.Current());
|
|
||||||
it.Advance();
|
|
||||||
if (it.Done()) {
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
__ j(equal, &do_store, Label::kNear);
|
|
||||||
}
|
}
|
||||||
__ 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);
|
__ 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()) {
|
if (index.is_inobject()) {
|
||||||
// Set the property straight into the object.
|
// Set the property straight into the object.
|
||||||
__ mov(FieldOperand(receiver_reg, index.offset()), value_reg);
|
__ mov(FieldOperand(receiver_reg, index.offset()), value_reg);
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Update the write barrier for the array address.
|
||||||
// Update the write barrier for the array address.
|
// Pass the value being stored in the now unused name_reg.
|
||||||
// Pass the value being stored in the now unused name_reg.
|
__ mov(name_reg, value_reg);
|
||||||
__ mov(name_reg, value_reg);
|
__ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
|
||||||
__ RecordWriteField(receiver_reg,
|
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
index.offset(),
|
|
||||||
name_reg,
|
|
||||||
scratch1,
|
|
||||||
kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET,
|
|
||||||
smi_check);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Write to the properties array.
|
// Write to the properties array.
|
||||||
// Get the properties array (optimistically).
|
// Get the properties array (optimistically).
|
||||||
__ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
|
__ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
|
||||||
__ mov(FieldOperand(scratch1, index.offset()), value_reg);
|
__ mov(FieldOperand(scratch1, index.offset()), value_reg);
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Update the write barrier for the array address.
|
||||||
// Update the write barrier for the array address.
|
// Pass the value being stored in the now unused name_reg.
|
||||||
// Pass the value being stored in the now unused name_reg.
|
__ mov(name_reg, value_reg);
|
||||||
__ mov(name_reg, value_reg);
|
__ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
|
||||||
__ RecordWriteField(scratch1,
|
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
index.offset(),
|
|
||||||
name_reg,
|
|
||||||
receiver_reg,
|
|
||||||
kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET,
|
|
||||||
smi_check);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the value (register eax).
|
// Return the value (register eax).
|
||||||
|
@ -1474,6 +1474,11 @@ Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
|
|||||||
} else {
|
} else {
|
||||||
switch (lookup->type()) {
|
switch (lookup->type()) {
|
||||||
case FIELD:
|
case FIELD:
|
||||||
|
if (!lookup->representation().IsHeapObject()) {
|
||||||
|
StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
|
||||||
|
lookup->representation());
|
||||||
|
return stub.GetCode();
|
||||||
|
}
|
||||||
return compiler.CompileStoreField(lookup, name);
|
return compiler.CompileStoreField(lookup, name);
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
|
if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
|
||||||
|
@ -528,85 +528,44 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
|
|||||||
|
|
||||||
FieldIndex index = lookup->GetFieldIndex();
|
FieldIndex index = lookup->GetFieldIndex();
|
||||||
|
|
||||||
Representation representation = lookup->representation();
|
DCHECK(lookup->representation().IsHeapObject());
|
||||||
DCHECK(!representation.IsNone());
|
__ JumpIfSmi(value_reg, miss_label);
|
||||||
if (representation.IsSmi()) {
|
HeapType* field_type = lookup->GetFieldType();
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
HeapType::Iterator<Map> it = field_type->Classes();
|
||||||
} else if (representation.IsHeapObject()) {
|
if (!it.Done()) {
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
Label do_store;
|
||||||
HeapType* field_type = lookup->GetFieldType();
|
while (true) {
|
||||||
HeapType::Iterator<Map> it = field_type->Classes();
|
__ CompareMap(value_reg, it.Current());
|
||||||
if (!it.Done()) {
|
it.Advance();
|
||||||
Label do_store;
|
if (it.Done()) {
|
||||||
while (true) {
|
__ j(not_equal, miss_label);
|
||||||
__ CompareMap(value_reg, it.Current());
|
break;
|
||||||
it.Advance();
|
|
||||||
if (it.Done()) {
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
__ j(equal, &do_store, Label::kNear);
|
|
||||||
}
|
}
|
||||||
__ 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);
|
__ 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()) {
|
if (index.is_inobject()) {
|
||||||
// Set the property straight into the object.
|
// Set the property straight into the object.
|
||||||
__ movp(FieldOperand(receiver_reg, index.offset()), value_reg);
|
__ movp(FieldOperand(receiver_reg, index.offset()), value_reg);
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Update the write barrier for the array address.
|
||||||
// Update the write barrier for the array address.
|
// Pass the value being stored in the now unused name_reg.
|
||||||
// Pass the value being stored in the now unused name_reg.
|
__ movp(name_reg, value_reg);
|
||||||
__ movp(name_reg, value_reg);
|
__ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
|
||||||
__ RecordWriteField(
|
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
receiver_reg, index.offset(), name_reg, scratch1, kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET, smi_check);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Write to the properties array.
|
// Write to the properties array.
|
||||||
// Get the properties array (optimistically).
|
// Get the properties array (optimistically).
|
||||||
__ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
|
__ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
|
||||||
__ movp(FieldOperand(scratch1, index.offset()), value_reg);
|
__ movp(FieldOperand(scratch1, index.offset()), value_reg);
|
||||||
|
|
||||||
if (!representation.IsSmi()) {
|
// Update the write barrier for the array address.
|
||||||
// Update the write barrier for the array address.
|
// Pass the value being stored in the now unused name_reg.
|
||||||
// Pass the value being stored in the now unused name_reg.
|
__ movp(name_reg, value_reg);
|
||||||
__ movp(name_reg, value_reg);
|
__ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
|
||||||
__ RecordWriteField(
|
kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||||
scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs,
|
|
||||||
EMIT_REMEMBERED_SET, smi_check);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the value (register rax).
|
// Return the value (register rax).
|
||||||
|
Loading…
Reference in New Issue
Block a user