[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 <delphick@chromium.org>
Reviewed-by: Mythri Alle <mythria@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64057}
This commit is contained in:
Dan Elphick 2019-09-27 09:34:20 +01:00 committed by Commit Bot
parent 5b6624b184
commit 286a59e543
4 changed files with 63 additions and 65 deletions

View File

@ -1217,56 +1217,6 @@ TNode<Float64T> CodeStubAssembler::LoadDoubleWithHoleCheck(
INTPTR_PARAMETERS, if_hole); 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<FixedArray> empty_fixed_array = EmptyFixedArrayConstant();
TNode<NumberDictionary> empty_slow_element_dictionary =
EmptySlowElementDictionaryConstant();
Goto(&loop_body);
BIND(&loop_body);
{
Node* map = var_map.value();
TNode<HeapObject> prototype = LoadMapPrototype(map);
GotoIf(IsNull(prototype), definitely_no_elements);
TNode<Map> prototype_map = LoadMap(prototype);
TNode<Uint16T> 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<Object> prototype_value =
LoadJSPrimitiveWrapperValue(CAST(prototype));
Branch(IsEmptyString(prototype_value), &if_notcustom, possibly_elements);
}
BIND(&if_notcustom);
{
TNode<FixedArrayBase> 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> object, void CodeStubAssembler::BranchIfJSReceiver(SloppyTNode<Object> object,
Label* if_true, Label* if_false) { Label* if_true, Label* if_false) {
GotoIf(TaggedIsSmi(object), if_false); GotoIf(TaggedIsSmi(object), if_false);

View File

@ -3675,10 +3675,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<IntPtrT> TryToIntptr(SloppyTNode<Object> key, Label* miss); TNode<IntPtrT> TryToIntptr(SloppyTNode<Object> key, Label* miss);
void BranchIfPrototypesHaveNoElements(Node* receiver_map,
Label* definitely_no_elements,
Label* possibly_elements);
void InitializeFunctionContext(Node* native_context, Node* context, void InitializeFunctionContext(Node* native_context, Node* context,
int slots); int slots);

View File

@ -2241,7 +2241,8 @@ void AccessorAssembler::InvalidateValidityCellIfPrototype(Node* map,
BIND(&cont); BIND(&cont);
} }
void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, void AccessorAssembler::GenericElementLoad(Node* receiver,
TNode<Map> receiver_map,
SloppyTNode<Int32T> instance_type, SloppyTNode<Int32T> instance_type,
Node* index, Label* slow) { Node* index, Label* slow) {
Comment("integer index"); Comment("integer index");
@ -2302,11 +2303,9 @@ void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
} }
} }
void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, void AccessorAssembler::GenericPropertyLoad(
SloppyTNode<Int32T> instance_type, Node* receiver, TNode<Map> receiver_map, SloppyTNode<Int32T> instance_type,
const LoadICParameters* p, const LoadICParameters* p, Label* slow, UseStubCache use_stub_cache) {
Label* slow,
UseStubCache use_stub_cache) {
ExitPoint direct_exit(this); ExitPoint direct_exit(this);
Comment("key is unique name"); Comment("key is unique name");
@ -2406,13 +2405,13 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
BIND(&lookup_prototype_chain); BIND(&lookup_prototype_chain);
{ {
VARIABLE(var_holder_map, MachineRepresentation::kTagged); TVARIABLE(Map, var_holder_map);
VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32); VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32);
Label return_undefined(this), is_private_symbol(this); Label return_undefined(this), is_private_symbol(this);
Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type}; Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type};
Label loop(this, arraysize(merged_variables), merged_variables); 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); var_holder_instance_type.Bind(instance_type);
GotoIf(IsPrivateSymbol(name), &is_private_symbol); GotoIf(IsPrivateSymbol(name), &is_private_symbol);
@ -2427,7 +2426,7 @@ void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
GotoIf(TaggedEqual(proto, NullConstant()), &return_undefined); GotoIf(TaggedEqual(proto, NullConstant()), &return_undefined);
TNode<Map> proto_map = LoadMap(proto); TNode<Map> proto_map = LoadMap(proto);
TNode<Uint16T> proto_instance_type = LoadMapInstanceType(proto_map); TNode<Uint16T> 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); var_holder_instance_type.Bind(proto_instance_type);
Label next_proto(this), return_value(this, &var_value), goto_slow(this); Label next_proto(this), return_value(this, &var_value), goto_slow(this);
TryGetOwnProperty(p->context(), receiver, proto, proto_map, TryGetOwnProperty(p->context(), receiver, proto, proto_map,
@ -4034,5 +4033,54 @@ void AccessorAssembler::GenerateKeyedHasIC_PolymorphicName() {
KeyedLoadICPolymorphicName(&p, LoadAccessMode::kHas); KeyedLoadICPolymorphicName(&p, LoadAccessMode::kHas);
} }
void AccessorAssembler::BranchIfPrototypesHaveNoElements(
TNode<Map> receiver_map, Label* definitely_no_elements,
Label* possibly_elements) {
TVARIABLE(Map, var_map, receiver_map);
Label loop_body(this, &var_map);
TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant();
TNode<NumberDictionary> empty_slow_element_dictionary =
EmptySlowElementDictionaryConstant();
Goto(&loop_body);
BIND(&loop_body);
{
TNode<Map> map = var_map.value();
TNode<HeapObject> prototype = LoadMapPrototype(map);
GotoIf(IsNull(prototype), definitely_no_elements);
TNode<Map> prototype_map = LoadMap(prototype);
TNode<Uint16T> 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<Object> prototype_value =
LoadJSPrimitiveWrapperValue(CAST(prototype));
Branch(IsEmptyString(prototype_value), &if_notcustom, possibly_elements);
}
BIND(&if_notcustom);
{
TNode<FixedArrayBase> 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 internal
} // namespace v8 } // namespace v8

View File

@ -334,12 +334,12 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
// KeyedLoadIC_Generic implementation. // KeyedLoadIC_Generic implementation.
void GenericElementLoad(Node* receiver, Node* receiver_map, void GenericElementLoad(Node* receiver, TNode<Map> receiver_map,
SloppyTNode<Int32T> instance_type, Node* index, SloppyTNode<Int32T> instance_type, Node* index,
Label* slow); Label* slow);
enum UseStubCache { kUseStubCache, kDontUseStubCache }; enum UseStubCache { kUseStubCache, kDontUseStubCache };
void GenericPropertyLoad(Node* receiver, Node* receiver_map, void GenericPropertyLoad(Node* receiver, TNode<Map> receiver_map,
SloppyTNode<Int32T> instance_type, SloppyTNode<Int32T> instance_type,
const LoadICParameters* p, Label* slow, const LoadICParameters* p, Label* slow,
UseStubCache use_stub_cache = kUseStubCache); UseStubCache use_stub_cache = kUseStubCache);
@ -399,6 +399,10 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
TNode<Map> map, Label* if_handler, TNode<Map> map, Label* if_handler,
TVariable<MaybeObject>* var_handler, TVariable<MaybeObject>* var_handler,
Label* if_miss); Label* if_miss);
void BranchIfPrototypesHaveNoElements(TNode<Map> receiver_map,
Label* definitely_no_elements,
Label* possibly_elements);
}; };
// Abstraction over direct and indirect exit points. Direct exits correspond to // Abstraction over direct and indirect exit points. Direct exits correspond to