From 286a59e5430d2383e47c6c623d0f8b10defae1f9 Mon Sep 17 00:00:00 2001 From: Dan Elphick Date: Fri, 27 Sep 2019 09:34:20 +0100 Subject: [PATCH] [cleanup] Move CSA::BranchIfPrototypesHaveNoElements Moves CodeStubAssembler::BranchIfPrototypesHaveNoElements to AccessorAssembler and TNodifies it on the way. Bug: v8:9396 Change-Id: Ie5d8ad5abc3dbdb688c0cbee4610cd441ba1a9b1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1826736 Auto-Submit: Dan Elphick Reviewed-by: Mythri Alle Reviewed-by: Jakob Gruber Commit-Queue: Dan Elphick Cr-Commit-Position: refs/heads/master@{#64057} --- src/codegen/code-stub-assembler.cc | 50 ---------------------- src/codegen/code-stub-assembler.h | 4 -- src/ic/accessor-assembler.cc | 66 ++++++++++++++++++++++++++---- src/ic/accessor-assembler.h | 8 +++- 4 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/codegen/code-stub-assembler.cc b/src/codegen/code-stub-assembler.cc index 6d4c54e4b0..c807f7729d 100644 --- a/src/codegen/code-stub-assembler.cc +++ b/src/codegen/code-stub-assembler.cc @@ -1217,56 +1217,6 @@ TNode CodeStubAssembler::LoadDoubleWithHoleCheck( INTPTR_PARAMETERS, if_hole); } -void CodeStubAssembler::BranchIfPrototypesHaveNoElements( - Node* receiver_map, Label* definitely_no_elements, - Label* possibly_elements) { - CSA_SLOW_ASSERT(this, IsMap(receiver_map)); - VARIABLE(var_map, MachineRepresentation::kTagged, receiver_map); - Label loop_body(this, &var_map); - TNode empty_fixed_array = EmptyFixedArrayConstant(); - TNode empty_slow_element_dictionary = - EmptySlowElementDictionaryConstant(); - Goto(&loop_body); - - BIND(&loop_body); - { - Node* map = var_map.value(); - TNode prototype = LoadMapPrototype(map); - GotoIf(IsNull(prototype), definitely_no_elements); - TNode prototype_map = LoadMap(prototype); - TNode prototype_instance_type = LoadMapInstanceType(prototype_map); - - // Pessimistically assume elements if a Proxy, Special API Object, - // or JSPrimitiveWrapper wrapper is found on the prototype chain. After this - // instance type check, it's not necessary to check for interceptors or - // access checks. - Label if_custom(this, Label::kDeferred), if_notcustom(this); - Branch(IsCustomElementsReceiverInstanceType(prototype_instance_type), - &if_custom, &if_notcustom); - - BIND(&if_custom); - { - // For string JSPrimitiveWrapper wrappers we still support the checks as - // long as they wrap the empty string. - GotoIfNot( - InstanceTypeEqual(prototype_instance_type, JS_PRIMITIVE_WRAPPER_TYPE), - possibly_elements); - TNode prototype_value = - LoadJSPrimitiveWrapperValue(CAST(prototype)); - Branch(IsEmptyString(prototype_value), &if_notcustom, possibly_elements); - } - - BIND(&if_notcustom); - { - TNode prototype_elements = LoadElements(CAST(prototype)); - var_map.Bind(prototype_map); - GotoIf(TaggedEqual(prototype_elements, empty_fixed_array), &loop_body); - Branch(TaggedEqual(prototype_elements, empty_slow_element_dictionary), - &loop_body, possibly_elements); - } - } -} - void CodeStubAssembler::BranchIfJSReceiver(SloppyTNode object, Label* if_true, Label* if_false) { GotoIf(TaggedIsSmi(object), if_false); diff --git a/src/codegen/code-stub-assembler.h b/src/codegen/code-stub-assembler.h index 3c41e1143e..2ceb7c47c1 100644 --- a/src/codegen/code-stub-assembler.h +++ b/src/codegen/code-stub-assembler.h @@ -3675,10 +3675,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler TNode TryToIntptr(SloppyTNode key, Label* miss); - void BranchIfPrototypesHaveNoElements(Node* receiver_map, - Label* definitely_no_elements, - Label* possibly_elements); - void InitializeFunctionContext(Node* native_context, Node* context, int slots); diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc index 6eb3a85391..9580ef01af 100644 --- a/src/ic/accessor-assembler.cc +++ b/src/ic/accessor-assembler.cc @@ -2241,7 +2241,8 @@ void AccessorAssembler::InvalidateValidityCellIfPrototype(Node* map, BIND(&cont); } -void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, +void AccessorAssembler::GenericElementLoad(Node* receiver, + TNode receiver_map, SloppyTNode instance_type, Node* index, Label* slow) { Comment("integer index"); @@ -2302,11 +2303,9 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, } } -void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, - SloppyTNode instance_type, - const LoadICParameters* p, - Label* slow, - UseStubCache use_stub_cache) { +void AccessorAssembler::GenericPropertyLoad( + Node* receiver, TNode receiver_map, SloppyTNode instance_type, + const LoadICParameters* p, Label* slow, UseStubCache use_stub_cache) { ExitPoint direct_exit(this); Comment("key is unique name"); @@ -2406,13 +2405,13 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, BIND(&lookup_prototype_chain); { - VARIABLE(var_holder_map, MachineRepresentation::kTagged); + TVARIABLE(Map, var_holder_map); VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32); Label return_undefined(this), is_private_symbol(this); Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type}; Label loop(this, arraysize(merged_variables), merged_variables); - var_holder_map.Bind(receiver_map); + var_holder_map = receiver_map; var_holder_instance_type.Bind(instance_type); GotoIf(IsPrivateSymbol(name), &is_private_symbol); @@ -2427,7 +2426,7 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, GotoIf(TaggedEqual(proto, NullConstant()), &return_undefined); TNode proto_map = LoadMap(proto); TNode proto_instance_type = LoadMapInstanceType(proto_map); - var_holder_map.Bind(proto_map); + var_holder_map = proto_map; var_holder_instance_type.Bind(proto_instance_type); Label next_proto(this), return_value(this, &var_value), goto_slow(this); TryGetOwnProperty(p->context(), receiver, proto, proto_map, @@ -4034,5 +4033,54 @@ void AccessorAssembler::GenerateKeyedHasIC_PolymorphicName() { KeyedLoadICPolymorphicName(&p, LoadAccessMode::kHas); } +void AccessorAssembler::BranchIfPrototypesHaveNoElements( + TNode receiver_map, Label* definitely_no_elements, + Label* possibly_elements) { + TVARIABLE(Map, var_map, receiver_map); + Label loop_body(this, &var_map); + TNode empty_fixed_array = EmptyFixedArrayConstant(); + TNode empty_slow_element_dictionary = + EmptySlowElementDictionaryConstant(); + Goto(&loop_body); + + BIND(&loop_body); + { + TNode map = var_map.value(); + TNode prototype = LoadMapPrototype(map); + GotoIf(IsNull(prototype), definitely_no_elements); + TNode prototype_map = LoadMap(prototype); + TNode prototype_instance_type = LoadMapInstanceType(prototype_map); + + // Pessimistically assume elements if a Proxy, Special API Object, + // or JSPrimitiveWrapper wrapper is found on the prototype chain. After this + // instance type check, it's not necessary to check for interceptors or + // access checks. + Label if_custom(this, Label::kDeferred), if_notcustom(this); + Branch(IsCustomElementsReceiverInstanceType(prototype_instance_type), + &if_custom, &if_notcustom); + + BIND(&if_custom); + { + // For string JSPrimitiveWrapper wrappers we still support the checks as + // long as they wrap the empty string. + GotoIfNot( + InstanceTypeEqual(prototype_instance_type, JS_PRIMITIVE_WRAPPER_TYPE), + possibly_elements); + TNode prototype_value = + LoadJSPrimitiveWrapperValue(CAST(prototype)); + Branch(IsEmptyString(prototype_value), &if_notcustom, possibly_elements); + } + + BIND(&if_notcustom); + { + TNode prototype_elements = LoadElements(CAST(prototype)); + var_map = prototype_map; + GotoIf(TaggedEqual(prototype_elements, empty_fixed_array), &loop_body); + Branch(TaggedEqual(prototype_elements, empty_slow_element_dictionary), + &loop_body, possibly_elements); + } + } +} + } // namespace internal } // namespace v8 diff --git a/src/ic/accessor-assembler.h b/src/ic/accessor-assembler.h index 37939126d8..af2d8391d2 100644 --- a/src/ic/accessor-assembler.h +++ b/src/ic/accessor-assembler.h @@ -334,12 +334,12 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { // KeyedLoadIC_Generic implementation. - void GenericElementLoad(Node* receiver, Node* receiver_map, + void GenericElementLoad(Node* receiver, TNode receiver_map, SloppyTNode instance_type, Node* index, Label* slow); enum UseStubCache { kUseStubCache, kDontUseStubCache }; - void GenericPropertyLoad(Node* receiver, Node* receiver_map, + void GenericPropertyLoad(Node* receiver, TNode receiver_map, SloppyTNode instance_type, const LoadICParameters* p, Label* slow, UseStubCache use_stub_cache = kUseStubCache); @@ -399,6 +399,10 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { TNode map, Label* if_handler, TVariable* var_handler, Label* if_miss); + + void BranchIfPrototypesHaveNoElements(TNode receiver_map, + Label* definitely_no_elements, + Label* possibly_elements); }; // Abstraction over direct and indirect exit points. Direct exits correspond to