v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
late-escape-analysis.cc
Go to the documentation of this file.
1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <optional>
8
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
18 Zone* zone)
19 : AdvancedReducer(editor),
20 dead_(graph->NewNode(common->Dead())),
21 all_allocations_(zone),
22 escaping_allocations_(zone),
23 revisit_(zone) {}
24
25namespace {
26
27bool IsStore(Edge edge) {
28 DCHECK_EQ(edge.to()->opcode(), IrOpcode::kAllocateRaw);
30
31 switch (edge.from()->opcode()) {
32 case IrOpcode::kInitializeImmutableInObject:
33 case IrOpcode::kStore:
34 case IrOpcode::kStoreElement:
35 case IrOpcode::kStoreField:
36 case IrOpcode::kStoreToObject:
37 return edge.index() == 0;
38 default:
39 return false;
40 }
41}
42
43bool IsEscapingAllocationWitness(Edge edge) {
44 if (edge.to()->opcode() != IrOpcode::kAllocateRaw) return false;
45 if (!NodeProperties::IsValueEdge(edge)) return false;
46 return !IsStore(edge);
47}
48
49} // namespace
50
52 if (node->opcode() == IrOpcode::kAllocateRaw) {
53 all_allocations_.insert(node);
54 return NoChange();
55 }
56
57 for (Edge edge : node->input_edges()) {
58 if (IsEscapingAllocationWitness(edge)) {
59 RecordEscapingAllocation(edge.to());
60 }
61 }
62
63 return NoChange();
64}
65
67 for (Node* alloc : all_allocations_) {
68 if (!IsEscaping(alloc)) {
69 RemoveAllocation(alloc);
70 }
71 }
72 while (!revisit_.empty()) {
73 Node* alloc = revisit_.front();
74 revisit_.pop_front();
75 if (!IsEscaping(alloc) && !alloc->IsDead()) {
76 RemoveAllocation(alloc);
77 }
78 }
79}
80
81namespace {
82
83std::optional<Node*> TryGetStoredValue(Node* node) {
84 int value_index;
85 switch (node->opcode()) {
86 case IrOpcode::kInitializeImmutableInObject:
87 case IrOpcode::kStore:
88 case IrOpcode::kStoreElement:
89 case IrOpcode::kStoreToObject:
90 value_index = 2;
91 break;
92 case IrOpcode::kStoreField:
93 value_index = 1;
94 break;
95 default:
96 return {};
97 }
98
99 return NodeProperties::GetValueInput(node, value_index);
100}
101
102} // namespace
103
105 DCHECK_EQ(node->opcode(), IrOpcode::kAllocateRaw);
106 auto escaping = escaping_allocations_.find(node);
107 if (escaping == escaping_allocations_.end()) return false;
108 return escaping->second != 0;
109}
110
112 DCHECK_EQ(node->opcode(), IrOpcode::kAllocateRaw);
113 for (Edge edge : node->use_edges()) {
114 if (!NodeProperties::IsValueEdge(edge)) continue;
115 Node* use = edge.from();
116 if (use->IsDead()) continue;
117 // The value stored by this Store node might be another allocation which has
118 // no more uses. Affected allocations are revisited.
119 if (std::optional<Node*> stored_value = TryGetStoredValue(use);
120 stored_value.has_value() &&
121 stored_value.value()->opcode() == IrOpcode::kAllocateRaw &&
122 stored_value.value() != node) {
123 RemoveWitness(stored_value.value());
124 revisit_.push_back(stored_value.value());
125 }
126 ReplaceWithValue(use, dead());
127 use->Kill();
128 }
129
130 // Remove the allocation from the effect and control chains.
131 ReplaceWithValue(node, dead());
132 node->Kill();
133}
134
136 DCHECK_EQ(allocation->opcode(), IrOpcode::kAllocateRaw);
137 escaping_allocations_[allocation]++;
138}
139
141 DCHECK_EQ(allocation->opcode(), IrOpcode::kAllocateRaw);
142 DCHECK_GT(escaping_allocations_[allocation], 0);
143 escaping_allocations_[allocation]--;
144}
145
146} // namespace compiler
147} // namespace internal
148} // namespace v8
void ReplaceWithValue(Node *node, Node *value, Node *effect=nullptr, Node *control=nullptr)
Node * from() const
Definition node.h:425
Node * to() const
Definition node.h:426
LateEscapeAnalysis(Editor *editor, TFGraph *graph, CommonOperatorBuilder *common, Zone *zone)
ZoneUnorderedMap< Node *, int > escaping_allocations_
static Node * GetValueInput(Node *node, int index)
constexpr IrOpcode::Value opcode() const
Definition node.h:52
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487