[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:
parent
5b6624b184
commit
286a59e543
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user