diff --git a/src/builtins/base.tq b/src/builtins/base.tq index b2630f0d59..c34d9f6884 100644 --- a/src/builtins/base.tq +++ b/src/builtins/base.tq @@ -672,7 +672,7 @@ extern transitioning builtin SetProperty(implicit context: Context)( JSAny, JSAny, JSAny): JSAny; extern transitioning builtin SetPropertyIgnoreAttributes( implicit context: Context)(JSObject, String, JSAny, Smi): JSAny; -extern transitioning builtin SetPropertyInLiteral(implicit context: Context)( +extern transitioning builtin CreateDataProperty(implicit context: Context)( JSAny, JSAny, JSAny): JSAny; extern transitioning builtin DeleteProperty(implicit context: Context)( JSAny, JSAny | PrivateSymbol, LanguageModeSmi): Boolean; diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h index a75f15c40c..2427e5ccb7 100644 --- a/src/builtins/builtins-definitions.h +++ b/src/builtins/builtins-definitions.h @@ -1062,7 +1062,7 @@ namespace internal { TFC(GetProperty, GetProperty) \ TFS(GetPropertyWithReceiver, kObject, kKey, kReceiver, kOnNonExistent) \ TFS(SetProperty, kReceiver, kKey, kValue) \ - TFS(SetPropertyInLiteral, kReceiver, kKey, kValue) \ + TFS(CreateDataProperty, kReceiver, kKey, kValue) \ ASM(MemCopyUint8Uint8, CCall) \ ASM(MemMove, CCall) \ \ diff --git a/src/builtins/builtins-internal-gen.cc b/src/builtins/builtins-internal-gen.cc index a8b22f243c..f4ab999f44 100644 --- a/src/builtins/builtins-internal-gen.cc +++ b/src/builtins/builtins-internal-gen.cc @@ -839,7 +839,7 @@ class SetOrCopyDataPropertiesAssembler : public CodeStubAssembler { 1, IndexAdvanceMode::kPost); } - CallBuiltin(Builtin::kSetPropertyInLiteral, context, target, key, + CallBuiltin(Builtin::kCreateDataProperty, context, target, key, value); Goto(&skip); Bind(&skip); @@ -1362,14 +1362,14 @@ TF_BUILTIN(SetProperty, CodeStubAssembler) { // being initialized, and have not yet been made accessible to the user. Thus, // any operation here should be unobservable until after the object has been // returned. -TF_BUILTIN(SetPropertyInLiteral, CodeStubAssembler) { +TF_BUILTIN(CreateDataProperty, CodeStubAssembler) { auto context = Parameter(Descriptor::kContext); auto receiver = Parameter(Descriptor::kReceiver); auto key = Parameter(Descriptor::kKey); auto value = Parameter(Descriptor::kValue); - KeyedStoreGenericGenerator::SetPropertyInLiteral(state(), context, receiver, - key, value); + KeyedStoreGenericGenerator::CreateDataProperty(state(), context, receiver, + key, value); } TF_BUILTIN(InstantiateAsmJs, CodeStubAssembler) { diff --git a/src/builtins/object-fromentries.tq b/src/builtins/object-fromentries.tq index cb43a1ea2a..94a723667b 100644 --- a/src/builtins/object-fromentries.tq +++ b/src/builtins/object-fromentries.tq @@ -18,20 +18,20 @@ transitioning macro ObjectFromEntriesFastCase(implicit context: Context)( const pair: KeyValuePair = collections::LoadKeyValuePairNoSideEffects(value) otherwise IfSlow; - // StorePropertyInLiteral only handles Names and Numbers. Bail out if + // CreateDataProperty only handles Names and Numbers. Bail out if // the key is not one of those types. Note that JSReceivers should // always bail to the slow path, as calling Symbol.toPrimitive, // toString, or valueOf could invalidate assumptions about the // iterable. typeswitch (pair.key) { case (Name): { - SetPropertyInLiteral(result, pair.key, pair.value); + CreateDataProperty(result, pair.key, pair.value); } case (Number): { - SetPropertyInLiteral(result, pair.key, pair.value); + CreateDataProperty(result, pair.key, pair.value); } case (oddball: Oddball): { - SetPropertyInLiteral(result, oddball.to_string, pair.value); + CreateDataProperty(result, oddball.to_string, pair.value); } case (JSAny): { goto IfSlow; diff --git a/src/codegen/code-stub-assembler.h b/src/codegen/code-stub-assembler.h index f0bbb3f658..bccdc34b74 100644 --- a/src/codegen/code-stub-assembler.h +++ b/src/codegen/code-stub-assembler.h @@ -3229,10 +3229,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler return CallBuiltin(Builtin::kSetProperty, context, receiver, key, value); } - TNode SetPropertyInLiteral(TNode context, - TNode receiver, - TNode key, TNode value) { - return CallBuiltin(Builtin::kSetPropertyInLiteral, context, receiver, key, + TNode CreateDataProperty(TNode context, + TNode receiver, TNode key, + TNode value) { + return CallBuiltin(Builtin::kCreateDataProperty, context, receiver, key, value); } diff --git a/src/compiler/js-heap-broker.cc b/src/compiler/js-heap-broker.cc index 00bb53d2d8..267890a11c 100644 --- a/src/compiler/js-heap-broker.cc +++ b/src/compiler/js-heap-broker.cc @@ -429,7 +429,7 @@ NamedAccessFeedback::NamedAccessFeedback(NameRef const& name, ZoneVector const& maps, FeedbackSlotKind slot_kind) : ProcessedFeedback(kNamedAccess, slot_kind), name_(name), maps_(maps) { - DCHECK(IsLoadICKind(slot_kind) || IsStoreICKind(slot_kind) || + DCHECK(IsLoadICKind(slot_kind) || IsSetNamedICKind(slot_kind) || IsDefineNamedOwnICKind(slot_kind) || IsKeyedLoadICKind(slot_kind) || IsKeyedHasICKind(slot_kind) || IsKeyedStoreICKind(slot_kind) || IsStoreInArrayLiteralICKind(slot_kind) || diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc index fc839fb8f8..1d4e6db1ca 100644 --- a/src/ic/accessor-assembler.cc +++ b/src/ic/accessor-assembler.cc @@ -4134,7 +4134,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) { BIND(&no_feedback); { Comment("StoreInArrayLiteralIC_NoFeedback"); - TailCallBuiltin(Builtin::kSetPropertyInLiteral, p->context(), p->receiver(), + TailCallBuiltin(Builtin::kCreateDataProperty, p->context(), p->receiver(), p->name(), p->value()); } @@ -4782,7 +4782,7 @@ void AccessorAssembler::GenerateCloneObjectIC_Slow() { ForEachEnumerableOwnProperty( context, source_map, CAST(source), kPropertyAdditionOrder, [=](TNode key, TNode value) { - SetPropertyInLiteral(context, result, key, value); + CreateDataProperty(context, result, key, value); }, &call_runtime); Goto(&done); diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 7fa46f95bf..1cb03c2dc5 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -2859,7 +2859,7 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) { kind = vector->GetKind(vector_slot); } - DCHECK(IsStoreICKind(kind) || IsDefineNamedOwnICKind(kind)); + DCHECK(IsSetNamedICKind(kind) || IsDefineNamedOwnICKind(kind)); StoreIC ic(isolate, vector, vector_slot, kind); ic.UpdateState(receiver, key); RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); @@ -3151,7 +3151,7 @@ RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) { StoreOwnElement(isolate, Handle::cast(object), key, value); return *value; } else { - DCHECK(IsKeyedStoreICKind(kind) || IsStoreICKind(kind) || + DCHECK(IsKeyedStoreICKind(kind) || IsSetNamedICKind(kind) || IsDefineKeyedOwnICKind(kind)); RETURN_RESULT_OR_FAILURE( isolate, diff --git a/src/ic/ic.h b/src/ic/ic.h index f1c489efbe..61a8171e89 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -53,7 +53,7 @@ class IC { return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC(); } bool IsAnyStore() const { - return IsStoreIC() || IsDefineNamedOwnIC() || IsStoreGlobalIC() || + return IsSetNamedIC() || IsDefineNamedOwnIC() || IsStoreGlobalIC() || IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind()) || IsDefineKeyedOwnIC(); } @@ -121,7 +121,7 @@ class IC { bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); } bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); } bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); } - bool IsStoreIC() const { return IsStoreICKind(kind_); } + bool IsSetNamedIC() const { return IsSetNamedICKind(kind_); } bool IsDefineNamedOwnIC() const { return IsDefineNamedOwnICKind(kind_); } bool IsStoreInArrayLiteralIC() const { return IsStoreInArrayLiteralICKind(kind_); diff --git a/src/ic/keyed-store-generic.cc b/src/ic/keyed-store-generic.cc index a93c6838f0..dbab0d92ca 100644 --- a/src/ic/keyed-store-generic.cc +++ b/src/ic/keyed-store-generic.cc @@ -17,16 +17,28 @@ namespace v8 { namespace internal { enum class StoreMode { - // TODO(v8:12548): rename to kSet and kDefineKeyedOwnInLiteral - kOrdinary, - kInLiteral, - - // kDefineNamedOwn performs an ordinary property store without traversing the - // prototype chain. In the case of private fields, it will throw if the - // field does not already exist. - // kDefineKeyedOwn is similar to kDefineNamedOwn, but for private class - // fields, it will throw if the field does already exist. + // kSet implements [[Set]] in the spec and traverses the prototype + // chain to invoke setters. it's used by KeyedStoreIC and StoreIC to + // set the properties when there is no feedback. + kSet, + // kDefineKeyedOwnInLiteral implements [[CreateDataProperty]] in the spec, + // and it assumes that the receiver is a JSObject that is created by us. + // It is used by Object.fromEntries(), CloneObjectIC and + // StoreInArrayLiteralIC to define a property in an object without + // traversing the prototype chain. + // TODO(v8:12548): merge this into the more generic kDefineKeyedOwn. + kDefineKeyedOwnInLiteral, + // kDefineNamedOwn implements [[CreateDataProperty]] but it can deal with + // user-defined receivers such as a JSProxy. It also assumes that the key + // is statically known. It's used to initialize named roperties in object + // literals and named public class fields. kDefineNamedOwn, + // kDefineKeyedOwn implements [[CreateDataProperty]], but it can deal with + // user-defined receivers such as a JSProxy, and for private class fields, + // it will throw if the field does already exist. It's different from + // kDefineNamedOwn in that it does not assume the key is statically known. + // It's used to initialized computed public class fields and private + // class fields. kDefineKeyedOwn }; @@ -44,19 +56,20 @@ class KeyedStoreGenericAssembler : public AccessorAssembler { void StoreIC_NoFeedback(); - // Generates code for [[Set]] operation, the |unique_name| is supposed to be - // unique otherwise this code will always go to runtime. - void SetProperty(TNode context, TNode receiver, - TNode is_simple_receiver, TNode unique_name, - TNode value, LanguageMode language_mode); + // Generates code for [[Set]] or [[CreateDataProperty]] operation, + // the |unique_name| is supposed to be unique otherwise this code will + // always go to runtime. + void StoreProperty(TNode context, TNode receiver, + TNode is_simple_receiver, TNode unique_name, + TNode value, LanguageMode language_mode); - // [[Set]], but more generic than the above. This impl does essentially the - // same as "KeyedStoreGeneric" but does not use feedback slot and uses a - // hardcoded LanguageMode instead of trying to deduce it from the feedback - // slot's kind. - void SetProperty(TNode context, TNode receiver, - TNode key, TNode value, - LanguageMode language_mode); + // This does [[Set]] or [[CreateDataProperty]] but it's more generic than + // the above. It is essentially the same as "KeyedStoreGeneric" but does not + // use feedback slot and uses a hardcoded LanguageMode instead of trying + // to deduce it from the feedback slot's kind. + void StoreProperty(TNode context, TNode receiver, + TNode key, TNode value, + LanguageMode language_mode); private: StoreMode mode_; @@ -69,7 +82,7 @@ class KeyedStoreGenericAssembler : public AccessorAssembler { enum UseStubCache { kUseStubCache, kDontUseStubCache }; - // Helper that is used by the public KeyedStoreGeneric and by SetProperty. + // Helper that is used by the public KeyedStoreGeneric and by StoreProperty. void KeyedStoreGeneric(TNode context, TNode receiver, TNode key, TNode value, Maybe language_mode); @@ -147,31 +160,33 @@ class KeyedStoreGenericAssembler : public AccessorAssembler { TNode name, Label* slow); - bool IsKeyedStore() const { return mode_ == StoreMode::kOrdinary; } - bool IsStoreInLiteral() const { return mode_ == StoreMode::kInLiteral; } + bool IsSet() const { return mode_ == StoreMode::kSet; } + bool IsDefineKeyedOwnInLiteral() const { + return mode_ == StoreMode::kDefineKeyedOwnInLiteral; + } bool IsDefineNamedOwn() const { return mode_ == StoreMode::kDefineNamedOwn; } bool IsDefineKeyedOwn() const { return mode_ == StoreMode::kDefineKeyedOwn; } bool IsAnyDefineOwn() const { return IsDefineNamedOwn() || IsDefineKeyedOwn(); } - bool ShouldCheckPrototype() const { return IsKeyedStore(); } - bool ShouldReconfigureExisting() const { return IsStoreInLiteral(); } - bool ShouldCallSetter() const { return IsKeyedStore(); } + bool ShouldCheckPrototype() const { return IsSet(); } + bool ShouldReconfigureExisting() const { return IsDefineKeyedOwnInLiteral(); } + bool ShouldCallSetter() const { return IsSet(); } bool ShouldCheckPrototypeValidity() const { // We don't do this for "in-literal" stores, because it is impossible for // the target object to be a "prototype". // We don't need the prototype validity check for "own" stores, because // we don't care about the prototype chain. // Thus, we need the prototype check only for ordinary stores. - DCHECK_IMPLIES(!IsKeyedStore(), IsStoreInLiteral() || IsDefineNamedOwn() || - IsDefineKeyedOwn()); - return IsKeyedStore(); + DCHECK_IMPLIES(!IsSet(), IsDefineKeyedOwnInLiteral() || + IsDefineNamedOwn() || IsDefineKeyedOwn()); + return IsSet(); } }; void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state) { - KeyedStoreGenericAssembler assembler(state, StoreMode::kOrdinary); + KeyedStoreGenericAssembler assembler(state, StoreMode::kSet); assembler.KeyedStoreGeneric(); } @@ -182,7 +197,7 @@ void DefineKeyedOwnGenericGenerator::Generate( } void StoreICNoFeedbackGenerator::Generate(compiler::CodeAssemblerState* state) { - KeyedStoreGenericAssembler assembler(state, StoreMode::kOrdinary); + KeyedStoreGenericAssembler assembler(state, StoreMode::kSet); assembler.StoreIC_NoFeedback(); } @@ -198,24 +213,25 @@ void KeyedStoreGenericGenerator::SetProperty( compiler::CodeAssemblerState* state, TNode context, TNode receiver, TNode is_simple_receiver, TNode name, TNode value, LanguageMode language_mode) { - KeyedStoreGenericAssembler assembler(state, StoreMode::kOrdinary); - assembler.SetProperty(context, receiver, is_simple_receiver, name, value, - language_mode); + KeyedStoreGenericAssembler assembler(state, StoreMode::kSet); + assembler.StoreProperty(context, receiver, is_simple_receiver, name, value, + language_mode); } void KeyedStoreGenericGenerator::SetProperty( compiler::CodeAssemblerState* state, TNode context, TNode receiver, TNode key, TNode value, LanguageMode language_mode) { - KeyedStoreGenericAssembler assembler(state, StoreMode::kOrdinary); - assembler.SetProperty(context, receiver, key, value, language_mode); + KeyedStoreGenericAssembler assembler(state, StoreMode::kSet); + assembler.StoreProperty(context, receiver, key, value, language_mode); } -void KeyedStoreGenericGenerator::SetPropertyInLiteral( +void KeyedStoreGenericGenerator::CreateDataProperty( compiler::CodeAssemblerState* state, TNode context, TNode receiver, TNode key, TNode value) { - KeyedStoreGenericAssembler assembler(state, StoreMode::kInLiteral); - assembler.SetProperty(context, receiver, key, value, LanguageMode::kStrict); + KeyedStoreGenericAssembler assembler(state, + StoreMode::kDefineKeyedOwnInLiteral); + assembler.StoreProperty(context, receiver, key, value, LanguageMode::kStrict); } void KeyedStoreGenericAssembler::BranchIfPrototypesMayHaveReadOnlyElements( @@ -381,7 +397,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity( { TNode offset = ElementOffsetFromIndex(index, PACKED_ELEMENTS, kHeaderSize); - if (!IsStoreInLiteral()) { + if (!IsDefineKeyedOwnInLiteral()) { // Check if we're about to overwrite the hole. We can safely do that // only if there can be no setters on the prototype chain. // If we know that we're storing beyond the previous array length, we @@ -484,7 +500,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity( { TNode offset = ElementOffsetFromIndex(index, PACKED_DOUBLE_ELEMENTS, kHeaderSize); - if (!IsStoreInLiteral()) { + if (!IsDefineKeyedOwnInLiteral()) { // Check if we're about to overwrite the hole. We can safely do that // only if there can be no setters on the prototype chain. { @@ -1053,7 +1069,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( } } -// Helper that is used by the public KeyedStoreGeneric and by SetProperty. +// Helper that is used by the public KeyedStoreGeneric and by StoreProperty. void KeyedStoreGenericAssembler::KeyedStoreGeneric( TNode context, TNode receiver_maybe_smi, TNode key, TNode value, Maybe language_mode) { @@ -1102,7 +1118,7 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric( BIND(&slow); { - if (IsKeyedStore() || IsDefineNamedOwn()) { + if (IsSet() || IsDefineNamedOwn()) { // The DefineNamedOwnIC hacky reuse should never reach here. CSA_DCHECK(this, BoolConstant(!IsDefineNamedOwn())); Comment("KeyedStoreGeneric_slow"); @@ -1112,7 +1128,7 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric( TailCallRuntime(Runtime::kDefineObjectOwnProperty, context, receiver, key, value); } else { - DCHECK(IsStoreInLiteral()); + DCHECK(IsDefineKeyedOwnInLiteral()); TailCallRuntime(Runtime::kDefineKeyedOwnPropertyInLiteral_Simple, context, receiver, key, value); } @@ -1130,11 +1146,11 @@ void KeyedStoreGenericAssembler::KeyedStoreGeneric() { KeyedStoreGeneric(context, receiver, name, value, Nothing()); } -void KeyedStoreGenericAssembler::SetProperty(TNode context, - TNode receiver, - TNode key, - TNode value, - LanguageMode language_mode) { +void KeyedStoreGenericAssembler::StoreProperty(TNode context, + TNode receiver, + TNode key, + TNode value, + LanguageMode language_mode) { KeyedStoreGeneric(context, receiver, key, value, Just(language_mode)); } @@ -1177,12 +1193,12 @@ void KeyedStoreGenericAssembler::StoreIC_NoFeedback() { } } -void KeyedStoreGenericAssembler::SetProperty(TNode context, - TNode receiver, - TNode is_simple_receiver, - TNode unique_name, - TNode value, - LanguageMode language_mode) { +void KeyedStoreGenericAssembler::StoreProperty(TNode context, + TNode receiver, + TNode is_simple_receiver, + TNode unique_name, + TNode value, + LanguageMode language_mode) { StoreICParameters p(context, receiver, unique_name, value, {}, UndefinedConstant(), StoreICMode::kDefault); @@ -1200,7 +1216,7 @@ void KeyedStoreGenericAssembler::SetProperty(TNode context, BIND(&slow); { - if (IsStoreInLiteral()) { + if (IsDefineKeyedOwnInLiteral()) { CallRuntime(Runtime::kDefineKeyedOwnPropertyInLiteral_Simple, context, receiver, unique_name, value); } else { diff --git a/src/ic/keyed-store-generic.h b/src/ic/keyed-store-generic.h index 6618ed3b26..e2a82a0910 100644 --- a/src/ic/keyed-store-generic.h +++ b/src/ic/keyed-store-generic.h @@ -28,10 +28,10 @@ class KeyedStoreGenericGenerator { TNode key, TNode value, LanguageMode language_mode); - static void SetPropertyInLiteral(compiler::CodeAssemblerState* state, - TNode context, - TNode receiver, TNode key, - TNode value); + static void CreateDataProperty(compiler::CodeAssemblerState* state, + TNode context, + TNode receiver, TNode key, + TNode value); }; class DefineKeyedOwnGenericGenerator { diff --git a/src/objects/feedback-vector.cc b/src/objects/feedback-vector.cc index acbbf069e4..789f2c651a 100644 --- a/src/objects/feedback-vector.cc +++ b/src/objects/feedback-vector.cc @@ -1427,7 +1427,7 @@ void FeedbackNexus::ResetTypeProfile() { FeedbackIterator::FeedbackIterator(const FeedbackNexus* nexus) : done_(false), index_(-1), state_(kOther) { DCHECK( - IsLoadICKind(nexus->kind()) || IsStoreICKind(nexus->kind()) || + IsLoadICKind(nexus->kind()) || IsSetNamedICKind(nexus->kind()) || IsKeyedLoadICKind(nexus->kind()) || IsKeyedStoreICKind(nexus->kind()) || IsDefineNamedOwnICKind(nexus->kind()) || IsDefineKeyedOwnPropertyInLiteralKind(nexus->kind()) || diff --git a/src/objects/feedback-vector.h b/src/objects/feedback-vector.h index fa1f47a613..42da62fe10 100644 --- a/src/objects/feedback-vector.h +++ b/src/objects/feedback-vector.h @@ -94,7 +94,7 @@ inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) { kind == FeedbackSlotKind::kStoreGlobalStrict; } -inline bool IsStoreICKind(FeedbackSlotKind kind) { +inline bool IsSetNamedICKind(FeedbackSlotKind kind) { return kind == FeedbackSlotKind::kSetNamedSloppy || kind == FeedbackSlotKind::kSetNamedStrict; } @@ -140,7 +140,7 @@ inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) { } inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) { - DCHECK(IsStoreICKind(kind) || IsDefineNamedOwnICKind(kind) || + DCHECK(IsSetNamedICKind(kind) || IsDefineNamedOwnICKind(kind) || IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind) || IsDefineKeyedOwnICKind(kind)); STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <= @@ -290,7 +290,7 @@ class FeedbackVector DEFINE_SLOT_KIND_PREDICATE(IsLoadIC) DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC) DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC) - DEFINE_SLOT_KIND_PREDICATE(IsStoreIC) + DEFINE_SLOT_KIND_PREDICATE(IsSetNamedIC) DEFINE_SLOT_KIND_PREDICATE(IsDefineNamedOwnIC) DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC) DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)