From 3b289d05d0ce66733a686221bd16520e9ed8c136 Mon Sep 17 00:00:00 2001 From: Leszek Swirski Date: Mon, 26 Sep 2022 17:33:42 +0200 Subject: [PATCH] [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 Auto-Submit: Leszek Swirski Reviewed-by: Jakob Linke Cr-Commit-Position: refs/heads/main@{#83443} --- src/maglev/maglev-graph-builder.cc | 58 ++++++++++++++++++++- src/maglev/maglev-interpreter-frame-state.h | 21 +++++--- src/maglev/maglev-ir.h | 2 + 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc index 69cddb9cc9..398e155e6c 100644 --- a/src/maglev/maglev-graph-builder.cc +++ b/src/maglev/maglev-graph-builder.cc @@ -1040,9 +1040,35 @@ void MaglevGraphBuilder::VisitStaLookupSlot() { 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()->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) { NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object); 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. AddNewNode({object}); @@ -1052,6 +1078,8 @@ void MaglevGraphBuilder::BuildCheckSmi(ValueNode* object) { void MaglevGraphBuilder::BuildCheckHeapObject(ValueNode* object) { NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object); if (known_info->is_any_heap_object()) return; + known_info->type = StaticTypeForNode(object); + if (known_info->is_any_heap_object()) return; AddNewNode({object}); known_info->type = NodeType::kAnyHeapObject; @@ -1069,6 +1097,8 @@ CheckType GetCheckType(NodeInfo* known_info) { void MaglevGraphBuilder::BuildCheckString(ValueNode* object) { NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object); if (known_info->is_string()) return; + known_info->type = StaticTypeForNode(object); + if (known_info->is_string()) return; AddNewNode({object}, GetCheckType(known_info)); known_info->type = NodeType::kString; @@ -1077,6 +1107,8 @@ void MaglevGraphBuilder::BuildCheckString(ValueNode* object) { void MaglevGraphBuilder::BuildCheckSymbol(ValueNode* object) { NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(object); if (known_info->is_symbol()) return; + known_info->type = StaticTypeForNode(object); + if (known_info->is_symbol()) return; AddNewNode({object}, GetCheckType(known_info)); known_info->type = NodeType::kSymbol; @@ -1093,10 +1125,32 @@ void MaglevGraphBuilder::BuildMapCheck(ValueNode* object, // Map is already checked. return; } - // TODO(leszeks): Insert an unconditional deopt if the known type doesn't - // match the required type. + // TODO(leszeks): Insert an unconditional deopt if the known map doesn't + // match the required map. } 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()); + // 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()->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()) { AddNewNode({object}, map, GetCheckType(known_info)); } else { diff --git a/src/maglev/maglev-interpreter-frame-state.h b/src/maglev/maglev-interpreter-frame-state.h index bed5cc89fc..00dc36edb6 100644 --- a/src/maglev/maglev-interpreter-frame-state.h +++ b/src/maglev/maglev-interpreter-frame-state.h @@ -72,6 +72,17 @@ enum class NodeType { kHeapObjectWithKnownMap = (1 << 5) | kAnyHeapObject, }; +inline bool NodeTypeIsSmi(NodeType type) { return type == NodeType::kSmi; } +inline bool NodeTypeIsAnyHeapObject(NodeType type) { + return static_cast(type) & static_cast(NodeType::kAnyHeapObject); +} +inline bool NodeTypeIsString(NodeType type) { + return type == NodeType::kString; +} +inline bool NodeTypeIsSymbol(NodeType type) { + return type == NodeType::kSymbol; +} + struct NodeInfo { NodeType type = NodeType::kUnknown; @@ -83,12 +94,10 @@ struct NodeInfo { ValueNode* int32_alternative = nullptr; ValueNode* float64_alternative = nullptr; - bool is_smi() const { return type == NodeType::kSmi; } - bool is_any_heap_object() const { - return static_cast(type) & static_cast(NodeType::kAnyHeapObject); - } - bool is_string() const { return type == NodeType::kString; } - bool is_symbol() const { return type == NodeType::kSymbol; } + bool is_smi() const { return NodeTypeIsSmi(type); } + bool is_any_heap_object() const { return NodeTypeIsAnyHeapObject(type); } + bool is_string() const { return NodeTypeIsString(type); } + bool is_symbol() const { return NodeTypeIsSymbol(type); } // 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. diff --git a/src/maglev/maglev-ir.h b/src/maglev/maglev-ir.h index c0b74376bf..7633de58ff 100644 --- a/src/maglev/maglev-ir.h +++ b/src/maglev/maglev-ir.h @@ -2250,6 +2250,8 @@ class Constant : public FixedInputValueNodeT<0, Constant> { DECL_NODE_INTERFACE() + compiler::HeapObjectRef object() { return object_; } + void DoLoadToRegister(MaglevAssembler*, OutputRegister); Handle DoReify(LocalIsolate* isolate);