Commit 0db5bc23 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[ic] Turn LoadIC_Normal and StoreIC_Normal into data handlers

This is mostly prework to also support prototype chain checks using data handlers

BUG=

Change-Id: I70aac1e86e45c78dfdc9f02d06b7e821494a4c9c
Reviewed-on: https://chromium-review.googlesource.com/447679
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43495}
parent 1c7f8398
...@@ -167,36 +167,6 @@ TF_BUILTIN(LoadIC_Miss, CodeStubAssembler) { ...@@ -167,36 +167,6 @@ TF_BUILTIN(LoadIC_Miss, CodeStubAssembler) {
TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector); TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
} }
TF_BUILTIN(LoadIC_Normal, CodeStubAssembler) {
typedef LoadWithVectorDescriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver);
Node* name = Parameter(Descriptor::kName);
Node* context = Parameter(Descriptor::kContext);
Label slow(this);
{
Node* properties = LoadProperties(receiver);
Variable var_name_index(this, MachineType::PointerRepresentation());
Label found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, name, &found,
&var_name_index, &slow);
Bind(&found);
{
Variable var_details(this, MachineRepresentation::kWord32);
Variable var_value(this, MachineRepresentation::kTagged);
LoadPropertyFromNameDictionary(properties, var_name_index.value(),
&var_details, &var_value);
Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
context, receiver, &slow);
Return(value);
}
}
Bind(&slow);
TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
}
TF_BUILTIN(LoadIC_Slow, CodeStubAssembler) { TF_BUILTIN(LoadIC_Slow, CodeStubAssembler) {
typedef LoadWithVectorDescriptor Descriptor; typedef LoadWithVectorDescriptor Descriptor;
...@@ -221,43 +191,6 @@ TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) { ...@@ -221,43 +191,6 @@ TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) {
receiver, name); receiver, name);
} }
TF_BUILTIN(StoreIC_Normal, CodeStubAssembler) {
typedef StoreWithVectorDescriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver);
Node* name = Parameter(Descriptor::kName);
Node* value = Parameter(Descriptor::kValue);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Label slow(this);
{
Node* properties = LoadProperties(receiver);
Variable var_name_index(this, MachineType::PointerRepresentation());
Label found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, name, &found,
&var_name_index, &slow);
Bind(&found);
{
Node* details = LoadDetailsByKeyIndex<NameDictionary>(
properties, var_name_index.value());
// Check that the property is a writable data property (no accessor).
const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
PropertyDetails::kAttributesReadOnlyMask;
STATIC_ASSERT(kData == 0);
GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), &slow);
StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
value);
Return(value);
}
}
Bind(&slow);
TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
receiver, name);
}
void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) { void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm); NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
} }
......
...@@ -244,11 +244,9 @@ class Isolate; ...@@ -244,11 +244,9 @@ class Isolate;
TFS(LoadIC_FunctionPrototype, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \ TFS(LoadIC_FunctionPrototype, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \
ASH(LoadIC_Getter_ForDeopt, BUILTIN, kNoExtraICState) \ ASH(LoadIC_Getter_ForDeopt, BUILTIN, kNoExtraICState) \
TFS(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector, 1) \ TFS(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector, 1) \
TFS(LoadIC_Normal, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \
TFS(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \ TFS(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \
TFS(LoadIC_Uninitialized, BUILTIN, kNoExtraICState, LoadWithVector, 1) \ TFS(LoadIC_Uninitialized, BUILTIN, kNoExtraICState, LoadWithVector, 1) \
TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector, 1) \ TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector, 1) \
TFS(StoreIC_Normal, HANDLER, Code::STORE_IC, StoreWithVector, 1) \
ASH(StoreIC_Setter_ForDeopt, BUILTIN, kNoExtraICState) \ ASH(StoreIC_Setter_ForDeopt, BUILTIN, kNoExtraICState) \
\ \
/* Built-in functions for Javascript */ \ /* Built-in functions for Javascript */ \
......
...@@ -789,7 +789,7 @@ class RuntimeCallTimer final { ...@@ -789,7 +789,7 @@ class RuntimeCallTimer final {
V(LoadIC_LoadInterceptor) \ V(LoadIC_LoadInterceptor) \
V(LoadIC_LoadNonexistentDH) \ V(LoadIC_LoadNonexistentDH) \
V(LoadIC_LoadNonexistent) \ V(LoadIC_LoadNonexistent) \
V(LoadIC_LoadNormal) \ V(LoadIC_LoadNormalDH) \
V(LoadIC_LoadScriptContextFieldStub) \ V(LoadIC_LoadScriptContextFieldStub) \
V(LoadIC_LoadViaGetter) \ V(LoadIC_LoadViaGetter) \
V(LoadIC_NonReceiver) \ V(LoadIC_NonReceiver) \
...@@ -814,7 +814,7 @@ class RuntimeCallTimer final { ...@@ -814,7 +814,7 @@ class RuntimeCallTimer final {
V(StoreIC_StoreGlobal) \ V(StoreIC_StoreGlobal) \
V(StoreIC_StoreGlobalTransition) \ V(StoreIC_StoreGlobalTransition) \
V(StoreIC_StoreInterceptorStub) \ V(StoreIC_StoreInterceptorStub) \
V(StoreIC_StoreNormal) \ V(StoreIC_StoreNormalDH) \
V(StoreIC_StoreScriptContextFieldStub) \ V(StoreIC_StoreScriptContextFieldStub) \
V(StoreIC_StoreTransition) \ V(StoreIC_StoreTransition) \
V(StoreIC_StoreTransitionDH) \ V(StoreIC_StoreTransitionDH) \
......
...@@ -179,6 +179,48 @@ void AccessorAssembler::HandleLoadICHandlerCase( ...@@ -179,6 +179,48 @@ void AccessorAssembler::HandleLoadICHandlerCase(
} }
} }
void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word,
Variable* var_double_value,
Label* rebox_double,
ExitPoint* exit_point) {
Comment("field_load");
Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word);
Label inobject(this), out_of_object(this);
Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject,
&out_of_object);
Bind(&inobject);
{
Label is_double(this);
GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
exit_point->Return(LoadObjectField(holder, offset));
Bind(&is_double);
if (FLAG_unbox_double_fields) {
var_double_value->Bind(
LoadObjectField(holder, offset, MachineType::Float64()));
} else {
Node* mutable_heap_number = LoadObjectField(holder, offset);
var_double_value->Bind(LoadHeapNumberValue(mutable_heap_number));
}
Goto(rebox_double);
}
Bind(&out_of_object);
{
Label is_double(this);
Node* properties = LoadProperties(holder);
Node* value = LoadObjectField(properties, offset);
GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
exit_point->Return(value);
Bind(&is_double);
var_double_value->Bind(LoadHeapNumberValue(value));
Goto(rebox_double);
}
}
void AccessorAssembler::HandleLoadICSmiHandlerCase( void AccessorAssembler::HandleLoadICSmiHandlerCase(
const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss,
ExitPoint* exit_point, ElementSupport support_elements) { ExitPoint* exit_point, ElementSupport support_elements) {
...@@ -232,63 +274,32 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase( ...@@ -232,63 +274,32 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
Comment("property_load"); Comment("property_load");
} }
Label constant(this), field(this); Label constant(this), field(this), normal(this);
Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)),
&field, &constant); &field);
Bind(&field); Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)),
{ &constant, &normal);
Comment("field_load");
Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word);
Label inobject(this), out_of_object(this); Bind(&field);
Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject, HandleLoadField(holder, handler_word, &var_double_value, &rebox_double,
&out_of_object); exit_point);
Bind(&inobject);
{
Label is_double(this);
GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
exit_point->Return(LoadObjectField(holder, offset));
Bind(&is_double);
if (FLAG_unbox_double_fields) {
var_double_value.Bind(
LoadObjectField(holder, offset, MachineType::Float64()));
} else {
Node* mutable_heap_number = LoadObjectField(holder, offset);
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
}
Goto(&rebox_double);
}
Bind(&out_of_object);
{
Label is_double(this);
Node* properties = LoadProperties(holder);
Node* value = LoadObjectField(properties, offset);
GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
exit_point->Return(value);
Bind(&is_double);
var_double_value.Bind(LoadHeapNumberValue(value));
Goto(&rebox_double);
}
Bind(&rebox_double);
exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value()));
}
Bind(&constant); Bind(&constant);
{ {
Comment("constant_load"); Comment("constant_load");
Node* descriptors = LoadMapDescriptors(LoadMap(holder)); Node* descriptors = LoadMapDescriptors(LoadMap(holder));
Node* descriptor = Node* descriptor = DecodeWord<LoadHandler::DescriptorBits>(handler_word);
DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); Node* scaled_descriptor =
IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
Node* value_index =
IntPtrAdd(scaled_descriptor,
IntPtrConstant(DescriptorArray::kFirstIndex +
DescriptorArray::kEntryValueIndex));
CSA_ASSERT(this, CSA_ASSERT(this,
UintPtrLessThan(descriptor, UintPtrLessThan(descriptor,
LoadAndUntagFixedArrayBaseLength(descriptors))); LoadAndUntagFixedArrayBaseLength(descriptors)));
Node* value = LoadFixedArrayElement(descriptors, descriptor); Node* value = LoadFixedArrayElement(descriptors, value_index);
Label if_accessor_info(this); Label if_accessor_info(this);
GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word),
...@@ -300,6 +311,29 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase( ...@@ -300,6 +311,29 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
exit_point->ReturnCallStub(callable, p->context, p->receiver, holder, exit_point->ReturnCallStub(callable, p->context, p->receiver, holder,
value); value);
} }
Bind(&normal);
{
Comment("load_normal");
Node* properties = LoadProperties(holder);
Variable var_name_index(this, MachineType::PointerRepresentation());
Label found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
&var_name_index, miss);
Bind(&found);
{
Variable var_details(this, MachineRepresentation::kWord32);
Variable var_value(this, MachineRepresentation::kTagged);
LoadPropertyFromNameDictionary(properties, var_name_index.value(),
&var_details, &var_value);
Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
p->context, p->receiver, miss);
exit_point->Return(value);
}
}
Bind(&rebox_double);
exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value()));
} }
void AccessorAssembler::HandleLoadICProtoHandlerCase( void AccessorAssembler::HandleLoadICProtoHandlerCase(
...@@ -464,6 +498,16 @@ void AccessorAssembler::HandleLoadGlobalICHandlerCase( ...@@ -464,6 +498,16 @@ void AccessorAssembler::HandleLoadGlobalICHandlerCase(
miss, exit_point, kOnlyProperties); miss, exit_point, kOnlyProperties);
} }
void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable,
Label* readonly) {
// Accessor properties never have the READ_ONLY attribute set.
GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
readonly);
Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
// Fall through if it's an accessor property.
}
void AccessorAssembler::HandleStoreICHandlerCase( void AccessorAssembler::HandleStoreICHandlerCase(
const StoreICParameters* p, Node* handler, Label* miss, const StoreICParameters* p, Node* handler, Label* miss,
ElementSupport support_elements) { ElementSupport support_elements) {
...@@ -479,6 +523,33 @@ void AccessorAssembler::HandleStoreICHandlerCase( ...@@ -479,6 +523,33 @@ void AccessorAssembler::HandleStoreICHandlerCase(
Node* holder = p->receiver; Node* holder = p->receiver;
Node* handler_word = SmiUntag(handler); Node* handler_word = SmiUntag(handler);
Label if_fast_smi(this), slow(this);
GotoIfNot(
WordEqual(handler_word, IntPtrConstant(StoreHandler::kStoreNormal)),
&if_fast_smi);
Node* properties = LoadProperties(holder);
Variable var_name_index(this, MachineType::PointerRepresentation());
Label dictionary_found(this, &var_name_index);
NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found,
&var_name_index, miss);
Bind(&dictionary_found);
{
Node* details = LoadDetailsByKeyIndex<NameDictionary>(
properties, var_name_index.value());
// Check that the property is a writable data property (no accessor).
const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
PropertyDetails::kAttributesReadOnlyMask;
STATIC_ASSERT(kData == 0);
GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
p->value);
Return(p->value);
}
Bind(&if_fast_smi);
// Handle non-transitioning field stores. // Handle non-transitioning field stores.
HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss); HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss);
} }
...@@ -606,11 +677,20 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p, ...@@ -606,11 +677,20 @@ void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p,
Bind(&if_transition_to_constant); Bind(&if_transition_to_constant);
{ {
// Check that constant matches value. // Check that constant matches value.
Node* value_index_in_descriptor = Node* descriptor = DecodeWord<StoreHandler::DescriptorBits>(handler_word);
DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); Node* scaled_descriptor =
IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
Node* value_index =
IntPtrAdd(scaled_descriptor,
IntPtrConstant(DescriptorArray::kFirstIndex +
DescriptorArray::kEntryValueIndex));
Node* descriptors = LoadMapDescriptors(transition); Node* descriptors = LoadMapDescriptors(transition);
Node* constant = CSA_ASSERT(
LoadFixedArrayElement(descriptors, value_index_in_descriptor); this,
UintPtrLessThan(descriptor,
LoadAndUntagFixedArrayBaseLength(descriptors)));
Node* constant = LoadFixedArrayElement(descriptors, value_index);
GotoIf(WordNotEqual(p->value, constant), miss); GotoIf(WordNotEqual(p->value, constant), miss);
StoreMap(p->receiver, transition); StoreMap(p->receiver, transition);
...@@ -761,12 +841,19 @@ Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder, ...@@ -761,12 +841,19 @@ Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder,
IntPtrConstant(StoreHandler::kStoreConstField)), IntPtrConstant(StoreHandler::kStoreConstField)),
&done); &done);
} }
Node* value_index_in_descriptor = Node* descriptor = DecodeWord<StoreHandler::DescriptorBits>(handler_word);
DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); Node* scaled_descriptor =
IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
Node* value_index =
IntPtrAdd(scaled_descriptor,
IntPtrConstant(DescriptorArray::kFirstIndex +
DescriptorArray::kEntryValueIndex));
Node* descriptors = Node* descriptors =
LoadMapDescriptors(transition ? transition : LoadMap(holder)); LoadMapDescriptors(transition ? transition : LoadMap(holder));
Node* maybe_field_type = CSA_ASSERT(this,
LoadFixedArrayElement(descriptors, value_index_in_descriptor); UintPtrLessThan(descriptor,
LoadAndUntagFixedArrayBaseLength(descriptors)));
Node* maybe_field_type = LoadFixedArrayElement(descriptors, value_index);
GotoIf(TaggedIsSmi(maybe_field_type), &done); GotoIf(TaggedIsSmi(maybe_field_type), &done);
// Check that value type matches the field type. // Check that value type matches the field type.
...@@ -1977,8 +2064,16 @@ void AccessorAssembler::GenerateLoadField() { ...@@ -1977,8 +2064,16 @@ void AccessorAssembler::GenerateLoadField() {
ExitPoint direct_exit(this); ExitPoint direct_exit(this);
HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), Variable var_double_value(this, MachineRepresentation::kFloat64);
nullptr, &direct_exit, kOnlyProperties); Label rebox_double(this, &var_double_value);
Node* smi_handler = Parameter(Descriptor::kSmiHandler);
Node* handler_word = SmiUntag(smi_handler);
HandleLoadField(receiver, handler_word, &var_double_value, &rebox_double,
&direct_exit);
Bind(&rebox_double);
Return(AllocateHeapNumberWithValue(var_double_value.value()));
} }
void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) {
......
...@@ -89,6 +89,7 @@ class AccessorAssembler : public CodeStubAssembler { ...@@ -89,6 +89,7 @@ class AccessorAssembler : public CodeStubAssembler {
void HandleStoreICHandlerCase( void HandleStoreICHandlerCase(
const StoreICParameters* p, Node* handler, Label* miss, const StoreICParameters* p, Node* handler, Label* miss,
ElementSupport support_elements = kOnlyProperties); ElementSupport support_elements = kOnlyProperties);
void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
private: private:
// Stub generation entry points. // Stub generation entry points.
...@@ -136,6 +137,10 @@ class AccessorAssembler : public CodeStubAssembler { ...@@ -136,6 +137,10 @@ class AccessorAssembler : public CodeStubAssembler {
ExitPoint* exit_point, ExitPoint* exit_point,
bool throw_reference_error_if_nonexistent); bool throw_reference_error_if_nonexistent);
void HandleLoadField(Node* holder, Node* handler_word,
Variable* var_double_value, Label* rebox_double,
ExitPoint* exit_point);
Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler, Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler,
Node* handler_length, Node* handler_flags, Node* handler_length, Node* handler_flags,
Label* miss, Label* miss,
......
...@@ -13,6 +13,11 @@ ...@@ -13,6 +13,11 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
Handle<Object> LoadHandler::LoadNormal(Isolate* isolate) {
int config = KindBits::encode(kForNormal);
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> LoadHandler::LoadField(Isolate* isolate, Handle<Object> LoadHandler::LoadField(Isolate* isolate,
FieldIndex field_index) { FieldIndex field_index) {
int config = KindBits::encode(kForFields) | int config = KindBits::encode(kForFields) |
...@@ -25,16 +30,14 @@ Handle<Object> LoadHandler::LoadField(Isolate* isolate, ...@@ -25,16 +30,14 @@ Handle<Object> LoadHandler::LoadField(Isolate* isolate,
Handle<Object> LoadHandler::LoadConstant(Isolate* isolate, int descriptor) { Handle<Object> LoadHandler::LoadConstant(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kForConstants) | int config = KindBits::encode(kForConstants) |
IsAccessorInfoBits::encode(false) | IsAccessorInfoBits::encode(false) |
DescriptorValueIndexBits::encode( DescriptorBits::encode(descriptor);
DescriptorArray::ToValueIndex(descriptor));
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
Handle<Object> LoadHandler::LoadApiGetter(Isolate* isolate, int descriptor) { Handle<Object> LoadHandler::LoadApiGetter(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kForConstants) | int config = KindBits::encode(kForConstants) |
IsAccessorInfoBits::encode(true) | IsAccessorInfoBits::encode(true) |
DescriptorValueIndexBits::encode( DescriptorBits::encode(descriptor);
DescriptorArray::ToValueIndex(descriptor));
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
...@@ -79,6 +82,11 @@ Handle<Object> LoadHandler::LoadElement(Isolate* isolate, ...@@ -79,6 +82,11 @@ Handle<Object> LoadHandler::LoadElement(Isolate* isolate,
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
Handle<Object> StoreHandler::StoreNormal(Isolate* isolate) {
int config = KindBits::encode(kStoreNormal);
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind, Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index, int descriptor, FieldIndex field_index,
Representation representation, Representation representation,
...@@ -101,7 +109,6 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind, ...@@ -101,7 +109,6 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
UNREACHABLE(); UNREACHABLE();
return Handle<Object>::null(); return Handle<Object>::null();
} }
int value_index = DescriptorArray::ToValueIndex(descriptor);
DCHECK(kind == kStoreField || kind == kTransitionToField || DCHECK(kind == kStoreField || kind == kTransitionToField ||
(kind == kStoreConstField && FLAG_track_constant_fields)); (kind == kStoreConstField && FLAG_track_constant_fields));
...@@ -112,7 +119,7 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind, ...@@ -112,7 +119,7 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
StoreHandler::ExtendStorageBits::encode(extend_storage) | StoreHandler::ExtendStorageBits::encode(extend_storage) |
StoreHandler::IsInobjectBits::encode(field_index.is_inobject()) | StoreHandler::IsInobjectBits::encode(field_index.is_inobject()) |
StoreHandler::FieldRepresentationBits::encode(field_rep) | StoreHandler::FieldRepresentationBits::encode(field_rep) |
StoreHandler::DescriptorValueIndexBits::encode(value_index) | StoreHandler::DescriptorBits::encode(descriptor) |
StoreHandler::FieldOffsetBits::encode(field_index.offset()); StoreHandler::FieldOffsetBits::encode(field_index.offset());
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
...@@ -138,10 +145,9 @@ Handle<Object> StoreHandler::TransitionToField(Isolate* isolate, int descriptor, ...@@ -138,10 +145,9 @@ Handle<Object> StoreHandler::TransitionToField(Isolate* isolate, int descriptor,
Handle<Object> StoreHandler::TransitionToConstant(Isolate* isolate, Handle<Object> StoreHandler::TransitionToConstant(Isolate* isolate,
int descriptor) { int descriptor) {
DCHECK(!FLAG_track_constant_fields); DCHECK(!FLAG_track_constant_fields);
int value_index = DescriptorArray::ToValueIndex(descriptor);
int config = int config =
StoreHandler::KindBits::encode(StoreHandler::kTransitionToConstant) | StoreHandler::KindBits::encode(StoreHandler::kTransitionToConstant) |
StoreHandler::DescriptorValueIndexBits::encode(value_index); StoreHandler::DescriptorBits::encode(descriptor);
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
......
...@@ -16,8 +16,14 @@ namespace internal { ...@@ -16,8 +16,14 @@ namespace internal {
// A set of bit fields representing Smi handlers for loads. // A set of bit fields representing Smi handlers for loads.
class LoadHandler { class LoadHandler {
public: public:
enum Kind { kForElements, kForFields, kForConstants, kForNonExistent }; enum Kind {
class KindBits : public BitField<Kind, 0, 2> {}; kForElements,
kForNormal,
kForFields,
kForConstants,
kForNonExistent
};
class KindBits : public BitField<Kind, 0, 3> {};
// Defines whether access rights check should be done on receiver object. // Defines whether access rights check should be done on receiver object.
// Applicable to kForFields, kForConstants and kForNonExistent kinds only when // Applicable to kForFields, kForConstants and kForNonExistent kinds only when
...@@ -38,12 +44,10 @@ class LoadHandler { ...@@ -38,12 +44,10 @@ class LoadHandler {
class IsAccessorInfoBits class IsAccessorInfoBits
: public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {}; : public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {};
// Index of a value entry in the descriptor array. // Index of a value entry in the descriptor array.
// +2 here is because each descriptor entry occupies 3 slots in array. class DescriptorBits : public BitField<unsigned, IsAccessorInfoBits::kNext,
class DescriptorValueIndexBits kDescriptorIndexBitCount> {};
: public BitField<unsigned, IsAccessorInfoBits::kNext,
kDescriptorIndexBitCount + 2> {};
// Make sure we don't overflow the smi. // Make sure we don't overflow the smi.
STATIC_ASSERT(DescriptorValueIndexBits::kNext <= kSmiValueSize); STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize);
// //
// Encoding when KindBits contains kForFields. // Encoding when KindBits contains kForFields.
...@@ -83,6 +87,9 @@ class LoadHandler { ...@@ -83,6 +87,9 @@ class LoadHandler {
static const int kHolderCellIndex = 2; static const int kHolderCellIndex = 2;
static const int kFirstPrototypeIndex = 3; static const int kFirstPrototypeIndex = 3;
// Creates a Smi-handler for loading a property from a slow object.
static inline Handle<Object> LoadNormal(Isolate* isolate);
// Creates a Smi-handler for loading a field from fast object. // Creates a Smi-handler for loading a field from fast object.
static inline Handle<Object> LoadField(Isolate* isolate, static inline Handle<Object> LoadField(Isolate* isolate,
FieldIndex field_index); FieldIndex field_index);
...@@ -122,11 +129,12 @@ class StoreHandler { ...@@ -122,11 +129,12 @@ class StoreHandler {
kStoreElement, kStoreElement,
kStoreField, kStoreField,
kStoreConstField, kStoreConstField,
kStoreNormal,
kTransitionToField, kTransitionToField,
// TODO(ishell): remove once constant field tracking is done. // TODO(ishell): remove once constant field tracking is done.
kTransitionToConstant = kStoreConstField kTransitionToConstant = kStoreConstField
}; };
class KindBits : public BitField<Kind, 0, 2> {}; class KindBits : public BitField<Kind, 0, 3> {};
enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged }; enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };
...@@ -134,22 +142,19 @@ class StoreHandler { ...@@ -134,22 +142,19 @@ class StoreHandler {
// kinds. // kinds.
// Index of a value entry in the descriptor array. // Index of a value entry in the descriptor array.
// +2 here is because each descriptor entry occupies 3 slots in array. class DescriptorBits
class DescriptorValueIndexBits : public BitField<unsigned, KindBits::kNext, kDescriptorIndexBitCount> {};
: public BitField<unsigned, KindBits::kNext,
kDescriptorIndexBitCount + 2> {};
// //
// Encoding when KindBits contains kTransitionToConstant. // Encoding when KindBits contains kTransitionToConstant.
// //
// Make sure we don't overflow the smi. // Make sure we don't overflow the smi.
STATIC_ASSERT(DescriptorValueIndexBits::kNext <= kSmiValueSize); STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize);
// //
// Encoding when KindBits contains kStoreField or kTransitionToField. // Encoding when KindBits contains kStoreField or kTransitionToField.
// //
class ExtendStorageBits class ExtendStorageBits : public BitField<bool, DescriptorBits::kNext, 1> {};
: public BitField<bool, DescriptorValueIndexBits::kNext, 1> {};
class IsInobjectBits : public BitField<bool, ExtendStorageBits::kNext, 1> {}; class IsInobjectBits : public BitField<bool, ExtendStorageBits::kNext, 1> {};
class FieldRepresentationBits class FieldRepresentationBits
: public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {}; : public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {};
...@@ -180,6 +185,9 @@ class StoreHandler { ...@@ -180,6 +185,9 @@ class StoreHandler {
PropertyConstness constness, PropertyConstness constness,
Representation representation); Representation representation);
// Creates a Smi-handler for storing a property to a slow object.
static inline Handle<Object> StoreNormal(Isolate* isolate);
// Creates a Smi-handler for transitioning store to a field. // Creates a Smi-handler for transitioning store to a field.
static inline Handle<Object> TransitionToField(Isolate* isolate, static inline Handle<Object> TransitionToField(Isolate* isolate,
int descriptor, int descriptor,
......
...@@ -1383,8 +1383,8 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1383,8 +1383,8 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
return slow_stub(); return slow_stub();
} }
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
return isolate()->builtins()->LoadIC_Normal(); return LoadHandler::LoadNormal(isolate());
} }
// -------------- Fields -------------- // -------------- Fields --------------
...@@ -2005,9 +2005,9 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -2005,9 +2005,9 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
if (holder->IsJSGlobalObject()) { if (holder->IsJSGlobalObject()) {
break; // Custom-compiled handler. break; // Custom-compiled handler.
} }
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
DCHECK(holder.is_identical_to(receiver)); DCHECK(holder.is_identical_to(receiver));
return isolate()->builtins()->StoreIC_Normal(); return StoreHandler::StoreNormal(isolate());
} }
// -------------- Fields -------------- // -------------- Fields --------------
......
...@@ -67,7 +67,6 @@ class KeyedStoreGenericAssembler : public AccessorAssembler { ...@@ -67,7 +67,6 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
ElementsKind packed_kind, ElementsKind packed_kind,
ElementsKind packed_kind_2, Label* bailout); ElementsKind packed_kind_2, Label* bailout);
void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
void LookupPropertyOnPrototypeChain(Node* receiver_map, Node* name, void LookupPropertyOnPrototypeChain(Node* receiver_map, Node* name,
Label* accessor, Label* accessor,
Variable* var_accessor_pair, Variable* var_accessor_pair,
...@@ -506,17 +505,6 @@ void KeyedStoreGenericAssembler::EmitGenericElementStore( ...@@ -506,17 +505,6 @@ void KeyedStoreGenericAssembler::EmitGenericElementStore(
} }
} }
void KeyedStoreGenericAssembler::JumpIfDataProperty(Node* details,
Label* writable,
Label* readonly) {
// Accessor properties never have the READ_ONLY attribute set.
GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
readonly);
Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
// Fall through if it's an accessor property.
}
void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain( void KeyedStoreGenericAssembler::LookupPropertyOnPrototypeChain(
Node* receiver_map, Node* name, Label* accessor, Node* receiver_map, Node* name, Label* accessor,
Variable* var_accessor_pair, Variable* var_accessor_holder, Label* readonly, Variable* var_accessor_pair, Variable* var_accessor_holder, Label* readonly,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment