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:
verwaest@chromium.org 2014-08-06 09:31:10 +00:00
parent df7057b3ce
commit b8ab822040
8 changed files with 182 additions and 309 deletions

View File

@ -598,11 +598,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
FieldIndex index = lookup->GetFieldIndex(); FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation(); DCHECK(lookup->representation().IsHeapObject());
DCHECK(!representation.IsNone());
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label); __ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType(); HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes(); HeapType::Iterator<Map> it = field_type->Classes();
@ -620,60 +616,20 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
} }
__ bind(&do_store); __ bind(&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()) { 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).

View File

@ -548,11 +548,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
FieldIndex index = lookup->GetFieldIndex(); FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation(); DCHECK(lookup->representation().IsHeapObject());
DCHECK(!representation.IsNone());
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label); __ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType(); HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes(); HeapType::Iterator<Map> it = field_type->Classes();
@ -570,62 +566,20 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
} }
__ Bind(&do_store); __ 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()));
}
// 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()) { 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);

View File

@ -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),

View File

@ -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)

View File

@ -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);
} }

View File

@ -579,12 +579,7 @@ 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();
DCHECK(!representation.IsNone());
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label); __ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType(); HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes(); HeapType::Iterator<Map> it = field_type->Classes();
@ -601,72 +596,27 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
} }
__ bind(&do_store); __ bind(&do_store);
} }
} 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()) { 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, __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
index.offset(), kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
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, __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
index.offset(), kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
name_reg,
receiver_reg,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
smi_check);
}
} }
// Return the value (register eax). // Return the value (register eax).

View File

@ -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()) {

View File

@ -528,11 +528,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
FieldIndex index = lookup->GetFieldIndex(); FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation(); DCHECK(lookup->representation().IsHeapObject());
DCHECK(!representation.IsNone());
if (representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label); __ JumpIfSmi(value_reg, miss_label);
HeapType* field_type = lookup->GetFieldType(); HeapType* field_type = lookup->GetFieldType();
HeapType::Iterator<Map> it = field_type->Classes(); HeapType::Iterator<Map> it = field_type->Classes();
@ -549,64 +545,27 @@ void NamedStoreHandlerCompiler::GenerateStoreField(
} }
__ bind(&do_store); __ bind(&do_store);
} }
} 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()) { 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( __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1,
receiver_reg, index.offset(), name_reg, scratch1, kDontSaveFPRegs, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
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( __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg,
scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
EMIT_REMEMBERED_SET, smi_check);
}
} }
// Return the value (register rax). // Return the value (register rax).