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.
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.
};
+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; }
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);
}
KeyedAccessStoreMode store_mode() const {
- return StoreModeBits::decode(sub_minor_key());
+ return CommonStoreModeBits::decode(sub_minor_key());
}
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
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);
};
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 {
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);
};
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);
};
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());
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);
}
+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) {
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");
}
// 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) {
Handle<Map> ComputeTransitionedMap(Handle<Map> map,
KeyedAccessStoreMode store_mode);
+ void ValidateStoreMode(Handle<Code> stub);
+
friend class IC;
};