[maglev] Warm up NodeInfo with static knowledge
For constants and smi-tagging, we have some static knowledge of the node type, so warm-up the NodeType of NodeInfo in the Build*Check helpers. Similarly, don't emit map checks for constant nodes that have a known stable map. Bug: v8:7700 Change-Id: I36e4d3000cf2f4dc689e8a9ab612a88dd751cdb5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3918770 Commit-Queue: Jakob Linke <jgruber@chromium.org> Auto-Submit: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Jakob Linke <jgruber@chromium.org> Cr-Commit-Position: refs/heads/main@{#83443}
This commit is contained in:
parent
0688729cbe
commit
3b289d05d0
@ -1040,9 +1040,35 @@ void MaglevGraphBuilder::VisitStaLookupSlot() {
|
|||||||
SetAccumulator(BuildCallRuntime(StaLookupSlotFunction(flags), {name, value}));
|
SetAccumulator(BuildCallRuntime(StaLookupSlotFunction(flags), {name, value}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
NodeType StaticTypeForNode(ValueNode* node) {
|
||||||
|
DCHECK(node->is_tagged());
|
||||||
|
switch (node->opcode()) {
|
||||||
|
case Opcode::kCheckedSmiTag:
|
||||||
|
case Opcode::kSmiConstant:
|
||||||
|
return NodeType::kSmi;
|
||||||
|
case Opcode::kConstant: {
|
||||||
|
compiler::HeapObjectRef ref = node->Cast<Constant>()->object();
|
||||||
|
if (ref.IsString()) {
|
||||||
|
return NodeType::kString;
|
||||||
|
} else if (ref.IsSymbol()) {
|
||||||
|
return NodeType::kSymbol;
|
||||||
|
} else if (ref.IsHeapNumber()) {
|
||||||
|
return NodeType::kHeapNumber;
|
||||||
|
}
|
||||||
|
return NodeType::kHeapObjectWithKnownMap;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return NodeType::kUnknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void MaglevGraphBuilder::BuildCheckSmi(ValueNode* object) {
|
void MaglevGraphBuilder::BuildCheckSmi(ValueNode* object) {
|
||||||
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
||||||
if (known_info->is_smi()) return;
|
if (known_info->is_smi()) return;
|
||||||
|
known_info->type = StaticTypeForNode(object);
|
||||||
|
if (known_info->is_smi()) return;
|
||||||
|
|
||||||
// TODO(leszeks): Figure out a way to also handle CheckedSmiUntag.
|
// TODO(leszeks): Figure out a way to also handle CheckedSmiUntag.
|
||||||
AddNewNode<CheckSmi>({object});
|
AddNewNode<CheckSmi>({object});
|
||||||
@ -1052,6 +1078,8 @@ void MaglevGraphBuilder::BuildCheckSmi(ValueNode* object) {
|
|||||||
void MaglevGraphBuilder::BuildCheckHeapObject(ValueNode* object) {
|
void MaglevGraphBuilder::BuildCheckHeapObject(ValueNode* object) {
|
||||||
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
||||||
if (known_info->is_any_heap_object()) return;
|
if (known_info->is_any_heap_object()) return;
|
||||||
|
known_info->type = StaticTypeForNode(object);
|
||||||
|
if (known_info->is_any_heap_object()) return;
|
||||||
|
|
||||||
AddNewNode<CheckHeapObject>({object});
|
AddNewNode<CheckHeapObject>({object});
|
||||||
known_info->type = NodeType::kAnyHeapObject;
|
known_info->type = NodeType::kAnyHeapObject;
|
||||||
@ -1069,6 +1097,8 @@ CheckType GetCheckType(NodeInfo* known_info) {
|
|||||||
void MaglevGraphBuilder::BuildCheckString(ValueNode* object) {
|
void MaglevGraphBuilder::BuildCheckString(ValueNode* object) {
|
||||||
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
||||||
if (known_info->is_string()) return;
|
if (known_info->is_string()) return;
|
||||||
|
known_info->type = StaticTypeForNode(object);
|
||||||
|
if (known_info->is_string()) return;
|
||||||
|
|
||||||
AddNewNode<CheckString>({object}, GetCheckType(known_info));
|
AddNewNode<CheckString>({object}, GetCheckType(known_info));
|
||||||
known_info->type = NodeType::kString;
|
known_info->type = NodeType::kString;
|
||||||
@ -1077,6 +1107,8 @@ void MaglevGraphBuilder::BuildCheckString(ValueNode* object) {
|
|||||||
void MaglevGraphBuilder::BuildCheckSymbol(ValueNode* object) {
|
void MaglevGraphBuilder::BuildCheckSymbol(ValueNode* object) {
|
||||||
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
||||||
if (known_info->is_symbol()) return;
|
if (known_info->is_symbol()) return;
|
||||||
|
known_info->type = StaticTypeForNode(object);
|
||||||
|
if (known_info->is_symbol()) return;
|
||||||
|
|
||||||
AddNewNode<CheckSymbol>({object}, GetCheckType(known_info));
|
AddNewNode<CheckSymbol>({object}, GetCheckType(known_info));
|
||||||
known_info->type = NodeType::kSymbol;
|
known_info->type = NodeType::kSymbol;
|
||||||
@ -1093,10 +1125,32 @@ void MaglevGraphBuilder::BuildMapCheck(ValueNode* object,
|
|||||||
// Map is already checked.
|
// Map is already checked.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO(leszeks): Insert an unconditional deopt if the known type doesn't
|
// TODO(leszeks): Insert an unconditional deopt if the known map doesn't
|
||||||
// match the required type.
|
// match the required map.
|
||||||
}
|
}
|
||||||
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object);
|
||||||
|
if (known_info->type == NodeType::kUnknown) {
|
||||||
|
known_info->type = StaticTypeForNode(object);
|
||||||
|
if (known_info->type == NodeType::kHeapObjectWithKnownMap) {
|
||||||
|
// The only case where the type becomes a heap-object with a known map is
|
||||||
|
// when the object is a constant.
|
||||||
|
DCHECK(object->Is<Constant>());
|
||||||
|
// For constants with stable maps that match the desired map, we don't
|
||||||
|
// need to emit a map check, and can use the dependency -- we can't do
|
||||||
|
// this for unstable maps because the constant could migrate during
|
||||||
|
// compilation.
|
||||||
|
// TODO(leszeks): Insert an unconditional deopt if the constant map
|
||||||
|
// doesn't match the required map.
|
||||||
|
compiler::MapRef constant_map = object->Cast<Constant>()->object().map();
|
||||||
|
if (constant_map.equals(map) && map.is_stable()) {
|
||||||
|
DCHECK_EQ(&map_of_maps, &known_node_aspects().stable_maps);
|
||||||
|
map_of_maps.emplace(object, map);
|
||||||
|
broker()->dependencies()->DependOnStableMap(map);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (map.is_migration_target()) {
|
if (map.is_migration_target()) {
|
||||||
AddNewNode<CheckMapsWithMigration>({object}, map, GetCheckType(known_info));
|
AddNewNode<CheckMapsWithMigration>({object}, map, GetCheckType(known_info));
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,6 +72,17 @@ enum class NodeType {
|
|||||||
kHeapObjectWithKnownMap = (1 << 5) | kAnyHeapObject,
|
kHeapObjectWithKnownMap = (1 << 5) | kAnyHeapObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool NodeTypeIsSmi(NodeType type) { return type == NodeType::kSmi; }
|
||||||
|
inline bool NodeTypeIsAnyHeapObject(NodeType type) {
|
||||||
|
return static_cast<int>(type) & static_cast<int>(NodeType::kAnyHeapObject);
|
||||||
|
}
|
||||||
|
inline bool NodeTypeIsString(NodeType type) {
|
||||||
|
return type == NodeType::kString;
|
||||||
|
}
|
||||||
|
inline bool NodeTypeIsSymbol(NodeType type) {
|
||||||
|
return type == NodeType::kSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo {
|
||||||
NodeType type = NodeType::kUnknown;
|
NodeType type = NodeType::kUnknown;
|
||||||
|
|
||||||
@ -83,12 +94,10 @@ struct NodeInfo {
|
|||||||
ValueNode* int32_alternative = nullptr;
|
ValueNode* int32_alternative = nullptr;
|
||||||
ValueNode* float64_alternative = nullptr;
|
ValueNode* float64_alternative = nullptr;
|
||||||
|
|
||||||
bool is_smi() const { return type == NodeType::kSmi; }
|
bool is_smi() const { return NodeTypeIsSmi(type); }
|
||||||
bool is_any_heap_object() const {
|
bool is_any_heap_object() const { return NodeTypeIsAnyHeapObject(type); }
|
||||||
return static_cast<int>(type) & static_cast<int>(NodeType::kAnyHeapObject);
|
bool is_string() const { return NodeTypeIsString(type); }
|
||||||
}
|
bool is_symbol() const { return NodeTypeIsSymbol(type); }
|
||||||
bool is_string() const { return type == NodeType::kString; }
|
|
||||||
bool is_symbol() const { return type == NodeType::kSymbol; }
|
|
||||||
|
|
||||||
// Mutate this node info by merging in another node info, with the result
|
// Mutate this node info by merging in another node info, with the result
|
||||||
// being a node info that is the subset of information valid in both inputs.
|
// being a node info that is the subset of information valid in both inputs.
|
||||||
|
@ -2250,6 +2250,8 @@ class Constant : public FixedInputValueNodeT<0, Constant> {
|
|||||||
|
|
||||||
DECL_NODE_INTERFACE()
|
DECL_NODE_INTERFACE()
|
||||||
|
|
||||||
|
compiler::HeapObjectRef object() { return object_; }
|
||||||
|
|
||||||
void DoLoadToRegister(MaglevAssembler*, OutputRegister);
|
void DoLoadToRegister(MaglevAssembler*, OutputRegister);
|
||||||
Handle<Object> DoReify(LocalIsolate* isolate);
|
Handle<Object> DoReify(LocalIsolate* isolate);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user