[ic] name Set/Define/Store property operations more consistently pt.2

As a follow-up of
https://chromium-review.googlesource.com/c/v8/v8/+/3481475,
this renames a few more operations related to property stores to keep
them consistent and adds comments to explain about what they do.

Summary of the renamed identifiers:

- SetPropertyInLiteral -> CreateDataProperty: this implements
  [[CreateDataProperty]] in the spec which does [[DefineOwnProperty]]
  instead of [[Set]], so rename for clarity.
- IsStoreIC(), IsStoreICKind() -> IsSetNamedIC(), IsSetNamedICKind():
  these only check whether the feedback kind is kSetNamedSloppy or
  kSetNamedStrict, so the scope can be narrowed.
- StoreMode::kOrdinary -> StoreMode::kSet: this implements [[Set]]
  in the spec and is used by both KeyedStoreIC and
  StoreIC to set the properties when there is no feedback.
- StoreMode::kInLiteral -> StoreMode::kDefineKeyedOwnInLiteral:
  this implements [[CreateDataProperty]] while expecting the receiver
  to be a JSObject created by us (the `InLiteral` part). Prepend
  `DefineKeyedOwn` to it so that it's more aligned with other
  StoreModes - it should be possible to just merge this into the
  more generic StoreMode::kDefineKeyedOwn later.
- KeyedStoreGenericAssembler::SetProperty ->
  KeyedStoreGenericAssembler::StoreProperty: these helpers are used by
  both define and set operations, distinguished with the StoreMode,
  so rename it to the more generic StoreProperty.

Bug: v8:12548
Change-Id: Iccef673c1dc707bbdbf010f02f7db1e9ec32b3e4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3557690
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Joyee Cheung <joyee@igalia.com>
Cr-Commit-Position: refs/heads/main@{#79694}
This commit is contained in:
Joyee Cheung 2022-03-29 22:40:11 +08:00 committed by V8 LUCI CQ
parent 8ba70dfea5
commit cf5ce194b2
13 changed files with 102 additions and 86 deletions

View File

@ -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;

View File

@ -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) \
\

View File

@ -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<Context>(Descriptor::kContext);
auto receiver = Parameter<JSObject>(Descriptor::kReceiver);
auto key = Parameter<Object>(Descriptor::kKey);
auto value = Parameter<Object>(Descriptor::kValue);
KeyedStoreGenericGenerator::SetPropertyInLiteral(state(), context, receiver,
key, value);
KeyedStoreGenericGenerator::CreateDataProperty(state(), context, receiver,
key, value);
}
TF_BUILTIN(InstantiateAsmJs, CodeStubAssembler) {

View File

@ -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;

View File

@ -3229,10 +3229,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
return CallBuiltin(Builtin::kSetProperty, context, receiver, key, value);
}
TNode<Object> SetPropertyInLiteral(TNode<Context> context,
TNode<JSObject> receiver,
TNode<Object> key, TNode<Object> value) {
return CallBuiltin(Builtin::kSetPropertyInLiteral, context, receiver, key,
TNode<Object> CreateDataProperty(TNode<Context> context,
TNode<JSObject> receiver, TNode<Object> key,
TNode<Object> value) {
return CallBuiltin(Builtin::kCreateDataProperty, context, receiver, key,
value);
}

View File

@ -429,7 +429,7 @@ NamedAccessFeedback::NamedAccessFeedback(NameRef const& name,
ZoneVector<MapRef> 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) ||

View File

@ -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<Name> key, TNode<Object> value) {
SetPropertyInLiteral(context, result, key, value);
CreateDataProperty(context, result, key, value);
},
&call_runtime);
Goto(&done);

View File

@ -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<JSArray>::cast(object), key, value);
return *value;
} else {
DCHECK(IsKeyedStoreICKind(kind) || IsStoreICKind(kind) ||
DCHECK(IsKeyedStoreICKind(kind) || IsSetNamedICKind(kind) ||
IsDefineKeyedOwnICKind(kind));
RETURN_RESULT_OR_FAILURE(
isolate,

View File

@ -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_);

View File

@ -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> context, TNode<JSReceiver> receiver,
TNode<BoolT> is_simple_receiver, TNode<Name> unique_name,
TNode<Object> 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> context, TNode<JSReceiver> receiver,
TNode<BoolT> is_simple_receiver, TNode<Name> unique_name,
TNode<Object> 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> context, TNode<Object> receiver,
TNode<Object> key, TNode<Object> 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> context, TNode<Object> receiver,
TNode<Object> key, TNode<Object> 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> context, TNode<Object> receiver,
TNode<Object> key, TNode<Object> value,
Maybe<LanguageMode> language_mode);
@ -147,31 +160,33 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
TNode<Name> 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> context,
TNode<JSReceiver> receiver, TNode<BoolT> is_simple_receiver,
TNode<Name> name, TNode<Object> 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> context,
TNode<Object> receiver, TNode<Object> key, TNode<Object> 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> context,
TNode<JSObject> receiver, TNode<Object> key, TNode<Object> 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<IntPtrT> 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<IntPtrT> 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> context, TNode<Object> receiver_maybe_smi, TNode<Object> key,
TNode<Object> value, Maybe<LanguageMode> 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<LanguageMode>());
}
void KeyedStoreGenericAssembler::SetProperty(TNode<Context> context,
TNode<Object> receiver,
TNode<Object> key,
TNode<Object> value,
LanguageMode language_mode) {
void KeyedStoreGenericAssembler::StoreProperty(TNode<Context> context,
TNode<Object> receiver,
TNode<Object> key,
TNode<Object> 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> context,
TNode<JSReceiver> receiver,
TNode<BoolT> is_simple_receiver,
TNode<Name> unique_name,
TNode<Object> value,
LanguageMode language_mode) {
void KeyedStoreGenericAssembler::StoreProperty(TNode<Context> context,
TNode<JSReceiver> receiver,
TNode<BoolT> is_simple_receiver,
TNode<Name> unique_name,
TNode<Object> value,
LanguageMode language_mode) {
StoreICParameters p(context, receiver, unique_name, value, {},
UndefinedConstant(), StoreICMode::kDefault);
@ -1200,7 +1216,7 @@ void KeyedStoreGenericAssembler::SetProperty(TNode<Context> context,
BIND(&slow);
{
if (IsStoreInLiteral()) {
if (IsDefineKeyedOwnInLiteral()) {
CallRuntime(Runtime::kDefineKeyedOwnPropertyInLiteral_Simple, context,
receiver, unique_name, value);
} else {

View File

@ -28,10 +28,10 @@ class KeyedStoreGenericGenerator {
TNode<Object> key, TNode<Object> value,
LanguageMode language_mode);
static void SetPropertyInLiteral(compiler::CodeAssemblerState* state,
TNode<Context> context,
TNode<JSObject> receiver, TNode<Object> key,
TNode<Object> value);
static void CreateDataProperty(compiler::CodeAssemblerState* state,
TNode<Context> context,
TNode<JSObject> receiver, TNode<Object> key,
TNode<Object> value);
};
class DefineKeyedOwnGenericGenerator {

View File

@ -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()) ||

View File

@ -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)