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) {
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) {
typedef LoadWithVectorDescriptor Descriptor;
......@@ -221,43 +191,6 @@ TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) {
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) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
......
......@@ -244,11 +244,9 @@ class Isolate;
TFS(LoadIC_FunctionPrototype, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \
ASH(LoadIC_Getter_ForDeopt, BUILTIN, kNoExtraICState) \
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_Uninitialized, BUILTIN, kNoExtraICState, LoadWithVector, 1) \
TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector, 1) \
TFS(StoreIC_Normal, HANDLER, Code::STORE_IC, StoreWithVector, 1) \
ASH(StoreIC_Setter_ForDeopt, BUILTIN, kNoExtraICState) \
\
/* Built-in functions for Javascript */ \
......
......@@ -789,7 +789,7 @@ class RuntimeCallTimer final {
V(LoadIC_LoadInterceptor) \
V(LoadIC_LoadNonexistentDH) \
V(LoadIC_LoadNonexistent) \
V(LoadIC_LoadNormal) \
V(LoadIC_LoadNormalDH) \
V(LoadIC_LoadScriptContextFieldStub) \
V(LoadIC_LoadViaGetter) \
V(LoadIC_NonReceiver) \
......@@ -814,7 +814,7 @@ class RuntimeCallTimer final {
V(StoreIC_StoreGlobal) \
V(StoreIC_StoreGlobalTransition) \
V(StoreIC_StoreInterceptorStub) \
V(StoreIC_StoreNormal) \
V(StoreIC_StoreNormalDH) \
V(StoreIC_StoreScriptContextFieldStub) \
V(StoreIC_StoreTransition) \
V(StoreIC_StoreTransitionDH) \
......
This diff is collapsed.
......@@ -89,6 +89,7 @@ class AccessorAssembler : public CodeStubAssembler {
void HandleStoreICHandlerCase(
const StoreICParameters* p, Node* handler, Label* miss,
ElementSupport support_elements = kOnlyProperties);
void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
private:
// Stub generation entry points.
......@@ -136,6 +137,10 @@ class AccessorAssembler : public CodeStubAssembler {
ExitPoint* exit_point,
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* handler_length, Node* handler_flags,
Label* miss,
......
......@@ -13,6 +13,11 @@
namespace v8 {
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,
FieldIndex field_index) {
int config = KindBits::encode(kForFields) |
......@@ -25,16 +30,14 @@ Handle<Object> LoadHandler::LoadField(Isolate* isolate,
Handle<Object> LoadHandler::LoadConstant(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kForConstants) |
IsAccessorInfoBits::encode(false) |
DescriptorValueIndexBits::encode(
DescriptorArray::ToValueIndex(descriptor));
DescriptorBits::encode(descriptor);
return handle(Smi::FromInt(config), isolate);
}
Handle<Object> LoadHandler::LoadApiGetter(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kForConstants) |
IsAccessorInfoBits::encode(true) |
DescriptorValueIndexBits::encode(
DescriptorArray::ToValueIndex(descriptor));
DescriptorBits::encode(descriptor);
return handle(Smi::FromInt(config), isolate);
}
......@@ -79,6 +82,11 @@ Handle<Object> LoadHandler::LoadElement(Isolate* 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,
int descriptor, FieldIndex field_index,
Representation representation,
......@@ -101,7 +109,6 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
UNREACHABLE();
return Handle<Object>::null();
}
int value_index = DescriptorArray::ToValueIndex(descriptor);
DCHECK(kind == kStoreField || kind == kTransitionToField ||
(kind == kStoreConstField && FLAG_track_constant_fields));
......@@ -112,7 +119,7 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
StoreHandler::ExtendStorageBits::encode(extend_storage) |
StoreHandler::IsInobjectBits::encode(field_index.is_inobject()) |
StoreHandler::FieldRepresentationBits::encode(field_rep) |
StoreHandler::DescriptorValueIndexBits::encode(value_index) |
StoreHandler::DescriptorBits::encode(descriptor) |
StoreHandler::FieldOffsetBits::encode(field_index.offset());
return handle(Smi::FromInt(config), isolate);
}
......@@ -138,10 +145,9 @@ Handle<Object> StoreHandler::TransitionToField(Isolate* isolate, int descriptor,
Handle<Object> StoreHandler::TransitionToConstant(Isolate* isolate,
int descriptor) {
DCHECK(!FLAG_track_constant_fields);
int value_index = DescriptorArray::ToValueIndex(descriptor);
int config =
StoreHandler::KindBits::encode(StoreHandler::kTransitionToConstant) |
StoreHandler::DescriptorValueIndexBits::encode(value_index);
StoreHandler::DescriptorBits::encode(descriptor);
return handle(Smi::FromInt(config), isolate);
}
......
......@@ -16,8 +16,14 @@ namespace internal {
// A set of bit fields representing Smi handlers for loads.
class LoadHandler {
public:
enum Kind { kForElements, kForFields, kForConstants, kForNonExistent };
class KindBits : public BitField<Kind, 0, 2> {};
enum Kind {
kForElements,
kForNormal,
kForFields,
kForConstants,
kForNonExistent
};
class KindBits : public BitField<Kind, 0, 3> {};
// Defines whether access rights check should be done on receiver object.
// Applicable to kForFields, kForConstants and kForNonExistent kinds only when
......@@ -38,12 +44,10 @@ class LoadHandler {
class IsAccessorInfoBits
: public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {};
// Index of a value entry in the descriptor array.
// +2 here is because each descriptor entry occupies 3 slots in array.
class DescriptorValueIndexBits
: public BitField<unsigned, IsAccessorInfoBits::kNext,
kDescriptorIndexBitCount + 2> {};
class DescriptorBits : public BitField<unsigned, IsAccessorInfoBits::kNext,
kDescriptorIndexBitCount> {};
// Make sure we don't overflow the smi.
STATIC_ASSERT(DescriptorValueIndexBits::kNext <= kSmiValueSize);
STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize);
//
// Encoding when KindBits contains kForFields.
......@@ -83,6 +87,9 @@ class LoadHandler {
static const int kHolderCellIndex = 2;
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.
static inline Handle<Object> LoadField(Isolate* isolate,
FieldIndex field_index);
......@@ -122,11 +129,12 @@ class StoreHandler {
kStoreElement,
kStoreField,
kStoreConstField,
kStoreNormal,
kTransitionToField,
// TODO(ishell): remove once constant field tracking is done.
kTransitionToConstant = kStoreConstField
};
class KindBits : public BitField<Kind, 0, 2> {};
class KindBits : public BitField<Kind, 0, 3> {};
enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };
......@@ -134,22 +142,19 @@ class StoreHandler {
// kinds.
// Index of a value entry in the descriptor array.
// +2 here is because each descriptor entry occupies 3 slots in array.
class DescriptorValueIndexBits
: public BitField<unsigned, KindBits::kNext,
kDescriptorIndexBitCount + 2> {};
class DescriptorBits
: public BitField<unsigned, KindBits::kNext, kDescriptorIndexBitCount> {};
//
// Encoding when KindBits contains kTransitionToConstant.
//
// 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.
//
class ExtendStorageBits
: public BitField<bool, DescriptorValueIndexBits::kNext, 1> {};
class ExtendStorageBits : public BitField<bool, DescriptorBits::kNext, 1> {};
class IsInobjectBits : public BitField<bool, ExtendStorageBits::kNext, 1> {};
class FieldRepresentationBits
: public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {};
......@@ -180,6 +185,9 @@ class StoreHandler {
PropertyConstness constness,
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.
static inline Handle<Object> TransitionToField(Isolate* isolate,
int descriptor,
......
......@@ -1383,8 +1383,8 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
return slow_stub();
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal);
return isolate()->builtins()->LoadIC_Normal();
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
return LoadHandler::LoadNormal(isolate());
}
// -------------- Fields --------------
......@@ -2005,9 +2005,9 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
if (holder->IsJSGlobalObject()) {
break; // Custom-compiled handler.
}
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal);
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
DCHECK(holder.is_identical_to(receiver));
return isolate()->builtins()->StoreIC_Normal();
return StoreHandler::StoreNormal(isolate());
}
// -------------- Fields --------------
......
......@@ -67,7 +67,6 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
ElementsKind packed_kind,
ElementsKind packed_kind_2, Label* bailout);
void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
void LookupPropertyOnPrototypeChain(Node* receiver_map, Node* name,
Label* accessor,
Variable* var_accessor_pair,
......@@ -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(
Node* receiver_map, Node* name, Label* accessor,
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