[stubs] KeyedLoadIC_Megamorphic: support getters
This extends the KeyedLoadIC_Megamorphic stub to call getters it found on the receiver without falling back to a runtime call. Review-Url: https://codereview.chromium.org/2362453004 Cr-Commit-Position: refs/heads/master@{#39688}
This commit is contained in:
parent
713e247e7d
commit
c636334829
@ -49,29 +49,6 @@ namespace internal {
|
||||
// Args: name
|
||||
#define BUILTIN_LIST(CPP, API, TFJ, TFS, ASM, ASH, DBG) \
|
||||
ASM(Abort) \
|
||||
/* Handlers */ \
|
||||
ASH(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, kNoExtraICState) \
|
||||
TFS(KeyedLoadIC_Megamorphic_TF, KEYED_LOAD_IC, kNoExtraICState, \
|
||||
LoadWithVector) \
|
||||
ASM(KeyedLoadIC_Miss) \
|
||||
ASH(KeyedLoadIC_Slow, HANDLER, Code::KEYED_LOAD_IC) \
|
||||
ASH(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, kNoExtraICState) \
|
||||
ASH(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, \
|
||||
StoreICState::kStrictModeState) \
|
||||
ASM(KeyedStoreIC_Miss) \
|
||||
ASH(KeyedStoreIC_Slow, HANDLER, Code::KEYED_STORE_IC) \
|
||||
TFS(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
|
||||
TFS(LoadGlobalIC_Slow, HANDLER, Code::LOAD_GLOBAL_IC, LoadGlobalWithVector) \
|
||||
ASH(LoadIC_Getter_ForDeopt, LOAD_IC, kNoExtraICState) \
|
||||
TFS(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
|
||||
ASH(LoadIC_Normal, HANDLER, Code::LOAD_IC) \
|
||||
TFS(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector) \
|
||||
TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector) \
|
||||
ASH(StoreIC_Normal, HANDLER, Code::STORE_IC) \
|
||||
ASH(StoreIC_Setter_ForDeopt, STORE_IC, StoreICState::kStrictModeState) \
|
||||
TFS(StoreIC_SlowSloppy, HANDLER, Code::STORE_IC, StoreWithVector) \
|
||||
TFS(StoreIC_SlowStrict, HANDLER, Code::STORE_IC, StoreWithVector) \
|
||||
\
|
||||
/* Code aging */ \
|
||||
CODE_AGE_LIST_WITH_ARG(DECLARE_CODE_AGE_BUILTIN, ASM) \
|
||||
\
|
||||
@ -187,6 +164,29 @@ namespace internal {
|
||||
TFS(NonNumberToNumber, BUILTIN, kNoExtraICState, TypeConversion) \
|
||||
TFS(ToNumber, BUILTIN, kNoExtraICState, TypeConversion) \
|
||||
\
|
||||
/* Handlers */ \
|
||||
ASH(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, kNoExtraICState) \
|
||||
TFS(KeyedLoadIC_Megamorphic_TF, KEYED_LOAD_IC, kNoExtraICState, \
|
||||
LoadWithVector) \
|
||||
ASM(KeyedLoadIC_Miss) \
|
||||
ASH(KeyedLoadIC_Slow, HANDLER, Code::KEYED_LOAD_IC) \
|
||||
ASH(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, kNoExtraICState) \
|
||||
ASH(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, \
|
||||
StoreICState::kStrictModeState) \
|
||||
ASM(KeyedStoreIC_Miss) \
|
||||
ASH(KeyedStoreIC_Slow, HANDLER, Code::KEYED_STORE_IC) \
|
||||
TFS(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
|
||||
TFS(LoadGlobalIC_Slow, HANDLER, Code::LOAD_GLOBAL_IC, LoadGlobalWithVector) \
|
||||
ASH(LoadIC_Getter_ForDeopt, LOAD_IC, kNoExtraICState) \
|
||||
TFS(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
|
||||
ASH(LoadIC_Normal, HANDLER, Code::LOAD_IC) \
|
||||
TFS(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector) \
|
||||
TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector) \
|
||||
ASH(StoreIC_Normal, HANDLER, Code::STORE_IC) \
|
||||
ASH(StoreIC_Setter_ForDeopt, STORE_IC, StoreICState::kStrictModeState) \
|
||||
TFS(StoreIC_SlowSloppy, HANDLER, Code::STORE_IC, StoreWithVector) \
|
||||
TFS(StoreIC_SlowStrict, HANDLER, Code::STORE_IC, StoreWithVector) \
|
||||
\
|
||||
/* Built-in functions for Javascript */ \
|
||||
/* Special internal builtins */ \
|
||||
CPP(EmptyFunction) \
|
||||
|
@ -3565,6 +3565,52 @@ void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary,
|
||||
Comment("] LoadPropertyFromGlobalDictionary");
|
||||
}
|
||||
|
||||
// |value| is the property backing store's contents, which is either a value
|
||||
// or an accessor pair, as specified by |details|.
|
||||
// Returns either the original value, or the result of the getter call.
|
||||
Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
|
||||
Node* context, Node* receiver,
|
||||
Label* if_bailout) {
|
||||
Variable var_value(this, MachineRepresentation::kTagged);
|
||||
var_value.Bind(value);
|
||||
Label done(this);
|
||||
|
||||
Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
|
||||
GotoIf(Word32Equal(kind, Int32Constant(kData)), &done);
|
||||
|
||||
// Accessor case.
|
||||
{
|
||||
Node* accessor_pair = value;
|
||||
GotoIf(Word32Equal(LoadInstanceType(accessor_pair),
|
||||
Int32Constant(ACCESSOR_INFO_TYPE)),
|
||||
if_bailout);
|
||||
AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE);
|
||||
Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
|
||||
Node* getter_map = LoadMap(getter);
|
||||
Node* instance_type = LoadMapInstanceType(getter_map);
|
||||
// FunctionTemplateInfo getters are not supported yet.
|
||||
GotoIf(
|
||||
Word32Equal(instance_type, Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)),
|
||||
if_bailout);
|
||||
|
||||
// Return undefined if the {getter} is not callable.
|
||||
var_value.Bind(UndefinedConstant());
|
||||
GotoIf(Word32Equal(Word32And(LoadMapBitField(getter_map),
|
||||
Int32Constant(1 << Map::kIsCallable)),
|
||||
Int32Constant(0)),
|
||||
&done);
|
||||
|
||||
// Call the accessor.
|
||||
Callable callable = CodeFactory::Call(isolate());
|
||||
Node* result = CallJS(callable, context, getter, receiver);
|
||||
var_value.Bind(result);
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
Bind(&done);
|
||||
return var_value.value();
|
||||
}
|
||||
|
||||
void CodeStubAssembler::TryGetOwnProperty(
|
||||
Node* context, Node* receiver, Node* object, Node* map, Node* instance_type,
|
||||
Node* unique_name, Label* if_found_value, Variable* var_value,
|
||||
@ -3612,41 +3658,10 @@ void CodeStubAssembler::TryGetOwnProperty(
|
||||
// Here we have details and value which could be an accessor.
|
||||
Bind(&if_found);
|
||||
{
|
||||
Node* details = var_details.value();
|
||||
Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
|
||||
|
||||
Label if_accessor(this);
|
||||
Branch(Word32Equal(kind, Int32Constant(kData)), if_found_value,
|
||||
&if_accessor);
|
||||
Bind(&if_accessor);
|
||||
{
|
||||
Node* accessor_pair = var_value->value();
|
||||
GotoIf(Word32Equal(LoadInstanceType(accessor_pair),
|
||||
Int32Constant(ACCESSOR_INFO_TYPE)),
|
||||
if_bailout);
|
||||
AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE);
|
||||
Node* getter =
|
||||
LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
|
||||
Node* getter_map = LoadMap(getter);
|
||||
Node* instance_type = LoadMapInstanceType(getter_map);
|
||||
// FunctionTemplateInfo getters are not supported yet.
|
||||
GotoIf(Word32Equal(instance_type,
|
||||
Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)),
|
||||
if_bailout);
|
||||
|
||||
// Return undefined if the {getter} is not callable.
|
||||
var_value->Bind(UndefinedConstant());
|
||||
GotoIf(Word32Equal(Word32And(LoadMapBitField(getter_map),
|
||||
Int32Constant(1 << Map::kIsCallable)),
|
||||
Int32Constant(0)),
|
||||
if_found_value);
|
||||
|
||||
// Call the accessor.
|
||||
Callable callable = CodeFactory::Call(isolate());
|
||||
Node* result = CallJS(callable, context, getter, receiver);
|
||||
var_value->Bind(result);
|
||||
Goto(if_found_value);
|
||||
}
|
||||
Node* value = CallGetterIfAccessor(var_value->value(), var_details.value(),
|
||||
context, receiver, if_bailout);
|
||||
var_value->Bind(value);
|
||||
Goto(if_found_value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4884,12 +4899,10 @@ void CodeStubAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
|
||||
|
||||
Bind(&if_found_on_receiver);
|
||||
{
|
||||
Node* kind =
|
||||
BitFieldDecode<PropertyDetails::KindField>(var_details.value());
|
||||
// TODO(jkummerow): Support accessors without missing?
|
||||
GotoUnless(Word32Equal(kind, Int32Constant(kData)), &slow);
|
||||
Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
|
||||
p->context, receiver, &slow);
|
||||
IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1);
|
||||
Return(var_value.value());
|
||||
Return(value);
|
||||
}
|
||||
|
||||
Bind(&slow);
|
||||
|
@ -788,6 +788,11 @@ class CodeStubAssembler : public compiler::CodeAssembler {
|
||||
compiler::Node* descriptors, compiler::Node* nof,
|
||||
Label* if_found, Variable* var_name_index,
|
||||
Label* if_not_found);
|
||||
compiler::Node* CallGetterIfAccessor(compiler::Node* value,
|
||||
compiler::Node* details,
|
||||
compiler::Node* context,
|
||||
compiler::Node* receiver,
|
||||
Label* if_bailout);
|
||||
|
||||
void HandleLoadICHandlerCase(
|
||||
const LoadICParameters* p, compiler::Node* handler, Label* miss,
|
||||
|
Loading…
Reference in New Issue
Block a user