ExtendStorageStub added, it is aimed for extending objects backing store when it runs out of space.

R=yangguo@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24286 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ishell@chromium.org 2014-09-29 13:11:27 +00:00
parent 24d1ef4868
commit 171e62e589
25 changed files with 254 additions and 126 deletions

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return r2; }
const Register StoreDescriptor::ValueRegister() { return r0; }
const Register ExtendStorageDescriptor::MapRegister() { return r3; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() { return r3; }

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return x2; }
const Register StoreDescriptor::ValueRegister() { return x0; }
const Register ExtendStorageDescriptor::MapRegister() { return x3; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() { return x3; }

View File

@ -64,7 +64,8 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
HLoadNamedField* BuildLoadNamedField(HValue* object,
FieldIndex index);
void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
Representation representation);
Representation representation,
bool transition_to_field);
enum ArgumentClass {
NONE,
@ -721,7 +722,7 @@ Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() {
void CodeStubGraphBuilderBase::BuildStoreNamedField(
HValue* object, HValue* value, FieldIndex index,
Representation representation) {
Representation representation, bool transition_to_field) {
DCHECK(!index.is_double() || representation.IsDouble());
int offset = index.offset();
HObjectAccess access =
@ -730,12 +731,31 @@ void CodeStubGraphBuilderBase::BuildStoreNamedField(
: 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();
HObjectAccess heap_number_access =
access.WithRepresentation(Representation::Tagged());
if (transition_to_field) {
// The store requires a mutable HeapNumber to be allocated.
NoObservableSideEffectsScope no_side_effects(this);
HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
// TODO(hpayer): Allocation site pretenuring support.
HInstruction* heap_number =
Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
MUTABLE_HEAP_NUMBER_TYPE);
AddStoreMapConstant(heap_number,
isolate()->factory()->mutable_heap_number_map());
Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
value);
// Store the new mutable heap number into the object.
access = heap_number_access;
value = heap_number;
} else {
// Load the heap number.
object = Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
heap_number_access);
// Store the double value into it.
access = HObjectAccess::ForHeapNumberValue();
}
} else if (representation.IsHeapObject()) {
BuildCheckHeapObject(value);
}
@ -747,7 +767,7 @@ void CodeStubGraphBuilderBase::BuildStoreNamedField(
template <>
HValue* CodeStubGraphBuilder<StoreFieldStub>::BuildCodeStub() {
BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(),
casted_stub()->representation());
casted_stub()->representation(), false);
return GetParameter(2);
}
@ -755,6 +775,47 @@ HValue* CodeStubGraphBuilder<StoreFieldStub>::BuildCodeStub() {
Handle<Code> StoreFieldStub::GenerateCode() { return DoGenerateCode(this); }
template <>
HValue* CodeStubGraphBuilder<ExtendStorageStub>::BuildCodeStub() {
HValue* object = GetParameter(ExtendStorageDescriptor::kReceiverIndex);
HValue* properties =
Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
HObjectAccess::ForPropertiesPointer());
HValue* length = AddLoadFixedArrayLength(properties);
HValue* delta = Add<HConstant>(static_cast<int32_t>(JSObject::kFieldsAdded));
HValue* new_capacity = AddUncasted<HAdd>(length, delta);
// Grow properties array.
ElementsKind kind = FAST_ELEMENTS;
Add<HBoundsCheck>(new_capacity,
Add<HConstant>((Page::kMaxRegularHeapObjectSize -
FixedArray::kHeaderSize) >>
ElementsKindToShiftSize(kind)));
// Reuse this code for properties backing store allocation.
HValue* new_properties = BuildAllocateAndInitializeArray(kind, new_capacity);
BuildCopyProperties(properties, new_properties, length, new_capacity);
// Store the new value into the "extended" object.
Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(),
new_properties);
BuildStoreNamedField(
object, GetParameter(ExtendStorageDescriptor::kValueIndex),
casted_stub()->index(), casted_stub()->representation(), true);
// And finally update the map after the new field is added.
Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
GetParameter(ExtendStorageDescriptor::kMapIndex));
return GetParameter(ExtendStorageDescriptor::kValueIndex);
}
Handle<Code> ExtendStorageStub::GenerateCode() { return DoGenerateCode(this); }
template <>
HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
HValue* string = BuildLoadNamedField(GetParameter(0),

View File

@ -614,6 +614,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor(
}
CallInterfaceDescriptor ExtendStorageStub::GetCallInterfaceDescriptor() {
return ExtendStorageDescriptor(isolate());
}
static void InitializeVectorLoadStub(Isolate* isolate,
CodeStubDescriptor* descriptor,
Address deoptimization_handler) {

View File

@ -80,6 +80,7 @@ namespace internal {
V(VectorKeyedLoad) \
V(VectorLoad) \
/* IC Handler stubs */ \
V(ExtendStorage) \
V(LoadConstant) \
V(LoadField) \
V(KeyedLoadSloppyArguments) \
@ -998,6 +999,44 @@ class StoreFieldStub : public HandlerStub {
};
// Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a
// JSObject.
class ExtendStorageStub : public HandlerStub {
public:
ExtendStorageStub(Isolate* isolate, FieldIndex index,
Representation representation)
: HandlerStub(isolate) {
int property_index_key = index.GetFieldAccessStubKey();
uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
RepresentationBits::encode(repr));
}
FieldIndex index() const {
int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
return FieldIndex::FromFieldAccessStubKey(property_index_key);
}
Representation representation() {
uint8_t repr = RepresentationBits::decode(sub_minor_key());
return PropertyDetails::DecodeRepresentation(repr);
}
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
protected:
virtual Code::Kind kind() const { return Code::STORE_IC; }
virtual Code::StubType GetStubType() { return Code::FAST; }
private:
class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
class RepresentationBits : public BitField<uint8_t, 13, 4> {};
DEFINE_HANDLER_CODE_STUB(ExtendStorage, HandlerStub);
};
class StoreGlobalStub : public HandlerStub {
public:
StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)

View File

@ -2626,16 +2626,15 @@ void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
}
HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
ElementsKind kind,
HValue* capacity) {
HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
HValue* capacity) {
// The HForceRepresentation is to prevent possible deopt on int-smi
// conversion after allocation but before the new object fields are set.
capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
HValue* new_elements = BuildAllocateElements(kind, size_in_bytes);
BuildInitializeElementsHeader(new_elements, kind, capacity);
return new_elements;
HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
BuildInitializeElementsHeader(new_array, kind, capacity);
return new_array;
}
@ -2754,8 +2753,8 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
(Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
ElementsKindToShiftSize(new_kind)));
HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
new_kind, new_capacity);
HValue* new_elements =
BuildAllocateAndInitializeArray(new_kind, new_capacity);
BuildCopyElements(elements, kind, new_elements,
new_kind, length, new_capacity);
@ -2789,12 +2788,6 @@ void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
}
}
// Since we're about to store a hole value, the store instruction below must
// assume an elements kind that supports heap object values.
if (IsFastSmiOrObjectElementsKind(elements_kind)) {
elements_kind = FAST_HOLEY_ELEMENTS;
}
if (initial_capacity >= 0) {
for (int i = 0; i < initial_capacity; i++) {
HInstruction* key = Add<HConstant>(i);
@ -2832,10 +2825,40 @@ void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
? Add<HConstant>(factory->the_hole_value())
: Add<HConstant>(nan_double);
// Since we're about to store a hole value, the store instruction below must
// assume an elements kind that supports heap object values.
if (IsFastSmiOrObjectElementsKind(elements_kind)) {
elements_kind = FAST_HOLEY_ELEMENTS;
}
BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
}
void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
HValue* to_properties, HValue* length,
HValue* capacity) {
ElementsKind kind = FAST_ELEMENTS;
BuildFillElementsWithValue(to_properties, kind, length, capacity,
graph()->GetConstantUndefined());
LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
key = AddUncasted<HSub>(key, graph()->GetConstant1());
key->ClearFlag(HValue::kCanOverflow);
HValue* element =
Add<HLoadKeyed>(from_properties, key, static_cast<HValue*>(NULL), kind);
Add<HStoreKeyed>(to_properties, key, element, kind);
builder.EndBody();
}
void HGraphBuilder::BuildCopyElements(HValue* from_elements,
ElementsKind from_elements_kind,
HValue* to_elements,

View File

@ -1805,8 +1805,9 @@ class HGraphBuilder {
ElementsKind kind,
HValue* capacity);
HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind,
HValue* capacity);
// Build allocation and header initialization code for respective successor
// of FixedArrayBase.
HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity);
// |array| must have been allocated with enough room for
// 1) the JSArray and 2) an AllocationMemento if mode requires it.
@ -1838,6 +1839,9 @@ class HGraphBuilder {
HValue* from,
HValue* to);
void BuildCopyProperties(HValue* from_properties, HValue* to_properties,
HValue* length, HValue* capacity);
void BuildCopyElements(HValue* from_elements,
ElementsKind from_elements_kind,
HValue* to_elements,

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return ecx; }
const Register StoreDescriptor::ValueRegister() { return eax; }
const Register ExtendStorageDescriptor::MapRegister() { return ebx; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() {
return ebx;
}

View File

@ -396,14 +396,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ push(receiver_reg);
__ mov(r2, Operand(transition));
__ Push(r2, r0);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ mov(ExtendStorageDescriptor::NameRegister(), Operand(name));
__ mov(ExtendStorageDescriptor::MapRegister(), Operand(transition));
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -441,13 +441,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ Mov(scratch1, Operand(transition));
__ Push(receiver_reg, scratch1, value_reg);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ Mov(ExtendStorageDescriptor::NameRegister(), Operand(name));
__ Mov(ExtendStorageDescriptor::MapRegister(), Operand(transition));
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -390,16 +390,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ pop(scratch1); // Return address.
__ push(receiver_reg);
__ push(Immediate(transition));
__ push(value_reg);
__ push(scratch1);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ mov(ExtendStorageDescriptor::NameRegister(), Immediate(name));
__ mov(ExtendStorageDescriptor::MapRegister(), Immediate(transition));
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -2094,7 +2094,7 @@ RUNTIME_FUNCTION(StoreIC_Miss) {
RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK(args.length() == 3);
DCHECK(args.length() == 3 || args.length() == 4);
StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
Handle<Object> receiver = args.at<Object>(0);
Handle<String> key = args.at<String>(1);
@ -2106,30 +2106,6 @@ RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
}
// Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a
// JSObject.
RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope shs(isolate);
DCHECK(args.length() == 3);
// Convert the parameters
Handle<JSObject> object = args.at<JSObject>(0);
Handle<Map> transition = args.at<Map>(1);
Handle<Object> value = args.at<Object>(2);
// Check the object has run out out property space.
DCHECK(object->HasFastProperties());
DCHECK(object->map()->unused_property_fields() == 0);
JSObject::MigrateToNewProperty(object, transition, value);
// Return the stored value.
return *value;
}
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);

View File

@ -21,7 +21,6 @@ namespace internal {
ICU(CallIC_Customization_Miss) \
ICU(StoreIC_Miss) \
ICU(StoreIC_Slow) \
ICU(SharedStoreIC_ExtendStorage) \
ICU(KeyedStoreIC_Miss) \
ICU(KeyedStoreIC_Slow) \
/* Utilities for IC stubs. */ \

View File

@ -391,14 +391,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ push(receiver_reg);
__ li(a2, Operand(transition));
__ Push(a2, a0);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ mov(ExtendStorageDescriptor::NameRegister(), Operand(name));
__ mov(ExtendStorageDescriptor::MapRegister(), Operand(transition));
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -391,14 +391,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ push(receiver_reg);
__ li(a2, Operand(transition));
__ Push(a2, a0);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ Mov(ExtendStorageDescriptor::NameRegister(), Operand(name));
__ Mov(ExtendStorageDescriptor::MapRegister(), Operand(transition));
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -384,16 +384,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ PopReturnAddressTo(scratch1);
__ Push(receiver_reg);
__ Push(transition);
__ Push(value_reg);
__ PushReturnAddressFrom(scratch1);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ Move(ExtendStorageDescriptor::NameRegister(), name);
__ Move(ExtendStorageDescriptor::MapRegister(), transition);
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -392,16 +392,13 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
if (details.type() == FIELD &&
Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the properties array.
__ pop(scratch1); // Return address.
__ push(receiver_reg);
__ push(Immediate(transition));
__ push(value_reg);
__ push(scratch1);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
isolate()),
3, 1);
__ mov(ExtendStorageDescriptor::NameRegister(), Immediate(name));
__ mov(ExtendStorageDescriptor::MapRegister(), Immediate(transition));
ExtendStorageStub stub(isolate(),
FieldIndex::ForDescriptor(*transition, descriptor),
representation);
GenerateTailCall(masm(), stub.GetCode());
return;
}

View File

@ -74,6 +74,13 @@ void StoreDescriptor::Initialize(CallInterfaceDescriptorData* data) {
}
void ExtendStorageDescriptor::Initialize(CallInterfaceDescriptorData* data) {
Register registers[] = {ContextRegister(), ReceiverRegister(), NameRegister(),
ValueRegister(), MapRegister()};
data->Initialize(arraysize(registers), registers, NULL);
}
void ElementTransitionAndStoreDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
Register registers[] = {ContextRegister(), ValueRegister(), MapRegister(),

View File

@ -16,6 +16,7 @@ class PlatformInterfaceDescriptor;
#define INTERFACE_DESCRIPTOR_LIST(V) \
V(Load) \
V(Store) \
V(ExtendStorage) \
V(ElementTransitionAndStore) \
V(Instanceof) \
V(VectorLoadICTrampoline) \
@ -213,6 +214,22 @@ class StoreDescriptor : public CallInterfaceDescriptor {
};
class ExtendStorageDescriptor : public StoreDescriptor {
public:
DECLARE_DESCRIPTOR(ExtendStorageDescriptor, StoreDescriptor)
// Extends StoreDescriptor with Map parameter.
enum ParameterIndices {
kReceiverIndex,
kNameIndex,
kValueIndex,
kMapIndex,
kParameterCount
};
static const Register MapRegister();
};
class ElementTransitionAndStoreDescriptor : public StoreDescriptor {
public:
DECLARE_DESCRIPTOR(ElementTransitionAndStoreDescriptor, StoreDescriptor)

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return a2; }
const Register StoreDescriptor::ValueRegister() { return a0; }
const Register ExtendStorageDescriptor::MapRegister() { return a3; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() { return a3; }

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return a2; }
const Register StoreDescriptor::ValueRegister() { return a0; }
const Register ExtendStorageDescriptor::MapRegister() { return a3; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() { return a3; }

View File

@ -1962,7 +1962,7 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
}
DCHECK(number_of_fields == old_number_of_fields + 1);
// This migration is a transition from a map that has run out out property
// This migration is a transition from a map that has run out of property
// space. Therefore it could be done by extending the backing store.
Handle<FixedArray> old_storage = handle(object->properties(), isolate);
Handle<FixedArray> new_storage =
@ -3753,15 +3753,6 @@ bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
}
void JSObject::MigrateToNewProperty(Handle<JSObject> object,
Handle<Map> map,
Handle<Object> value) {
JSObject::MigrateToMap(object, map);
if (map->GetLastDescriptorDetails().type() != FIELD) return;
object->WriteToField(map->LastAdded(), *value);
}
void JSObject::WriteToField(int descriptor, Object* value) {
DisallowHeapAllocation no_gc;

View File

@ -2209,10 +2209,6 @@ class JSObject: public JSReceiver {
Handle<Name> name,
Handle<Object> old_value);
static void MigrateToNewProperty(Handle<JSObject> object,
Handle<Map> transition,
Handle<Object> value);
private:
friend class DictionaryElementsAccessor;
friend class JSReceiver;

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return rcx; }
const Register StoreDescriptor::ValueRegister() { return rax; }
const Register ExtendStorageDescriptor::MapRegister() { return rbx; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() {
return rbx;
}

View File

@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return ecx; }
const Register StoreDescriptor::ValueRegister() { return eax; }
const Register ExtendStorageDescriptor::MapRegister() { return ebx; }
const Register ElementTransitionAndStoreDescriptor::MapRegister() {
return ebx;
}