Commit 24921f76 authored by mvstanton's avatar mvstanton Committed by Commit bot

Vector ICs: Ensure KeyedAccessStore mode is encoded in all handlers.

For vector-based keyed store ics, we need to know the current
KeyedAccessStore mode on ic MISS, and to produce optimized code.

We can't store this mode, which can change on any MISS in the IC
without patching. Therefore, this CL makes sure that the information is
redundantly available in the handlers embedded in the IC. This way,
when --vector-stores is turned on, we'll be able to extract that
information from the vector which maintains a list of these handlers.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#30378}
parent bfbcb3d3
......@@ -2234,8 +2234,8 @@ class CountOperation final : public Expression {
class IsPrefixField : public BitField16<bool, 0, 1> {};
class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 4> {};
class TokenField : public BitField16<Token::Value, 6, 8> {};
class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {};
class TokenField : public BitField16<Token::Value, 5, 8> {};
// Starts with 16-bit field, which should get packed together with
// Expression's trailing 16-bit field.
......@@ -2405,8 +2405,8 @@ class Assignment final : public Expression {
class IsUninitializedField : public BitField16<bool, 0, 1> {};
class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 4> {};
class TokenField : public BitField16<Token::Value, 6, 8> {};
class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 3> {};
class TokenField : public BitField16<Token::Value, 5, 8> {};
// Starts with 16-bit field, which should get packed together with
// Expression's trailing 16-bit field.
......
......@@ -1140,10 +1140,15 @@ class KeyedLoadSloppyArgumentsStub : public HandlerStub {
};
class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
class KeyedStoreSloppyArgumentsStub : public HandlerStub {
public:
explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate)
: HandlerStub(isolate) {}
explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
KeyedAccessStoreMode mode)
: HandlerStub(isolate) {
set_sub_minor_key(CommonStoreModeBits::encode(mode));
}
protected:
Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
......@@ -2595,9 +2600,9 @@ class StoreFastElementStub : public HydrogenCodeStub {
StoreFastElementStub(Isolate* isolate, bool is_js_array,
ElementsKind elements_kind, KeyedAccessStoreMode mode)
: HydrogenCodeStub(isolate) {
set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
IsJSArrayBits::encode(is_js_array) |
StoreModeBits::encode(mode));
set_sub_minor_key(CommonStoreModeBits::encode(mode) |
ElementsKindBits::encode(elements_kind) |
IsJSArrayBits::encode(is_js_array));
}
static void GenerateAheadOfTime(Isolate* isolate);
......@@ -2609,7 +2614,7 @@ class StoreFastElementStub : public HydrogenCodeStub {
}
KeyedAccessStoreMode store_mode() const {
return StoreModeBits::decode(sub_minor_key());
return CommonStoreModeBits::decode(sub_minor_key());
}
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
......@@ -2619,10 +2624,11 @@ class StoreFastElementStub : public HydrogenCodeStub {
return StoreDescriptor(isolate());
}
Code::Kind GetCodeKind() const override { return Code::HANDLER; }
private:
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
class IsJSArrayBits: public BitField<bool, 12, 1> {};
class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
class IsJSArrayBits : public BitField<bool, 11, 1> {};
DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
};
......@@ -2836,9 +2842,11 @@ class InternalArrayNArgumentsConstructorStub : public
class StoreElementStub : public PlatformCodeStub {
public:
StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
KeyedAccessStoreMode mode)
: PlatformCodeStub(isolate) {
minor_key_ = ElementsKindBits::encode(elements_kind);
minor_key_ = ElementsKindBits::encode(elements_kind) |
CommonStoreModeBits::encode(mode);
}
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
......@@ -2848,12 +2856,14 @@ class StoreElementStub : public PlatformCodeStub {
return StoreDescriptor(isolate());
}
Code::Kind GetCodeKind() const override { return Code::HANDLER; }
private:
ElementsKind elements_kind() const {
return ElementsKindBits::decode(minor_key_);
}
class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
};
......@@ -2957,25 +2967,25 @@ class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
ElementsKind to_kind, bool is_jsarray,
KeyedAccessStoreMode store_mode)
: HydrogenCodeStub(isolate) {
set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
IsJSArrayBits::encode(is_jsarray) |
StoreModeBits::encode(store_mode));
set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
FromBits::encode(from_kind) | ToBits::encode(to_kind) |
IsJSArrayBits::encode(is_jsarray));
}
ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
KeyedAccessStoreMode store_mode() const {
return StoreModeBits::decode(sub_minor_key());
return CommonStoreModeBits::decode(sub_minor_key());
}
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
Code::Kind GetCodeKind() const override { return Code::HANDLER; }
private:
class FromBits : public BitField<ElementsKind, 0, 8> {};
class ToBits : public BitField<ElementsKind, 8, 8> {};
class IsJSArrayBits : public BitField<bool, 16, 1> {};
class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
class FromBits : public BitField<ElementsKind, 3, 8> {};
class ToBits : public BitField<ElementsKind, 11, 8> {};
class IsJSArrayBits : public BitField<bool, 19, 1> {};
DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
};
......
......@@ -362,16 +362,20 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
transitioned_map->elements_kind(),
is_js_array, store_mode).GetCode();
} else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
// TODO(mvstanton): Consider embedding store_mode in the state of the slow
// keyed store ic for uniformity.
cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
} else {
if (IsSloppyArgumentsElements(elements_kind)) {
cached_stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode();
cached_stub =
KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
} else if (receiver_map->has_fast_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
cached_stub = StoreFastElementStub(isolate(), is_js_array,
elements_kind, store_mode).GetCode();
} else {
cached_stub = StoreElementStub(isolate(), elements_kind).GetCode();
cached_stub =
StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
}
}
DCHECK(!cached_stub.is_null());
......@@ -396,13 +400,13 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub;
if (receiver_map->has_sloppy_arguments_elements()) {
stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode();
stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
} else if (receiver_map->has_fast_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
store_mode).GetCode();
} else {
stub = StoreElementStub(isolate(), elements_kind).GetCode();
stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
}
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
......
......@@ -2059,6 +2059,44 @@ static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
}
void KeyedStoreIC::ValidateStoreMode(Handle<Code> stub) {
#ifdef DEBUG
DCHECK(!FLAG_vector_stores);
if (stub.is_null() || *stub == *megamorphic_stub() || *stub == *slow_stub()) {
return;
}
// Query the keyed store mode.
ExtraICState state = stub->extra_ic_state();
KeyedAccessStoreMode stub_mode = GetKeyedAccessStoreMode(state);
MapHandleList map_list;
stub->FindAllMaps(&map_list);
CodeHandleList list;
stub->FindHandlers(&list, map_list.length());
for (int i = 0; i < list.length(); i++) {
Handle<Code> handler = list.at(i);
CHECK(handler->is_handler());
CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
// Ensure that we only see handlers we know have the store mode embedded.
CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
major_key == CodeStub::StoreFastElement ||
major_key == CodeStub::StoreElement ||
major_key == CodeStub::ElementsTransitionAndStore ||
*handler == *isolate()->builtins()->KeyedStoreIC_Slow());
// Ensure that the store mode matches that of the IC.
CHECK(major_key == CodeStub::NoCache ||
stub_mode == CommonStoreModeBits::decode(minor_key));
// The one exception is the keyed store slow builtin, which doesn't include
// store mode.
CHECK(major_key != CodeStub::NoCache ||
*handler == *isolate()->builtins()->KeyedStoreIC_Slow());
}
#endif // DEBUG
}
MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
Handle<Object> key,
Handle<Object> value) {
......@@ -2139,6 +2177,10 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
KeyedAccessStoreMode store_mode =
GetStoreMode(receiver, index, value);
stub = StoreElementStub(receiver, store_mode);
// Validate that the store_mode in the stub can also be derived
// from peeking in the code bits of the handlers.
ValidateStoreMode(stub);
} else {
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype");
}
......
......@@ -525,9 +525,9 @@ class KeyedStoreIC : public StoreIC {
// When more language modes are added, these BitFields need to move too.
STATIC_ASSERT(i::LANGUAGE_END == 3);
class ExtraICStateKeyedAccessStoreMode
: public BitField<KeyedAccessStoreMode, 3, 4> {}; // NOLINT
: public BitField<KeyedAccessStoreMode, 3, 3> {}; // NOLINT
class IcCheckTypeField : public BitField<IcCheckType, 7, 1> {};
class IcCheckTypeField : public BitField<IcCheckType, 6, 1> {};
static ExtraICState ComputeExtraICState(LanguageMode flag,
KeyedAccessStoreMode mode) {
......@@ -599,6 +599,8 @@ class KeyedStoreIC : public StoreIC {
Handle<Map> ComputeTransitionedMap(Handle<Map> map,
KeyedAccessStoreMode store_mode);
void ValidateStoreMode(Handle<Code> stub);
friend class IC;
};
......
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