From c636334829065d5ff5fb064693655e6db6444afd Mon Sep 17 00:00:00 2001 From: jkummerow Date: Fri, 23 Sep 2016 11:48:04 -0700 Subject: [PATCH] [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} --- src/builtins/builtins.h | 46 +++++++++---------- src/code-stub-assembler.cc | 93 ++++++++++++++++++++++---------------- src/code-stub-assembler.h | 5 ++ 3 files changed, 81 insertions(+), 63 deletions(-) diff --git a/src/builtins/builtins.h b/src/builtins/builtins.h index aba947beff..1e54f6e370 100644 --- a/src/builtins/builtins.h +++ b/src/builtins/builtins.h @@ -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) \ diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index 1fcd8938e2..4e1c4a44f7 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -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(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(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(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); diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h index 36842c8398..25299b5503 100644 --- a/src/code-stub-assembler.h +++ b/src/code-stub-assembler.h @@ -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,