| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/bit-vector.h" | 5 #include "src/bit-vector.h" |
| 6 #include "src/compiler/escape-analysis.h" | 6 #include "src/compiler/escape-analysis.h" |
| 7 #include "src/compiler/escape-analysis-reducer.h" | 7 #include "src/compiler/escape-analysis-reducer.h" |
| 8 #include "src/compiler/graph-visualizer.h" | 8 #include "src/compiler/graph-visualizer.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
| 11 #include "src/compiler/simplified-operator.h" | 11 #include "src/compiler/simplified-operator.h" |
| 12 #include "src/types-inl.h" | 12 #include "src/types-inl.h" |
| 13 #include "src/zone-containers.h" | 13 #include "src/zone-containers.h" |
| 14 #include "test/unittests/compiler/graph-unittest.h" | 14 #include "test/unittests/compiler/graph-unittest.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 namespace compiler { | 18 namespace compiler { |
| 19 | 19 |
| 20 class EscapeAnalysisTest : public GraphTest { | 20 class EscapeAnalysisTest : public GraphTest { |
| 21 public: | 21 public: |
| 22 EscapeAnalysisTest() | 22 EscapeAnalysisTest() |
| 23 : simplified_(zone()), | 23 : simplified_(zone()), |
| 24 jsgraph_(isolate(), graph(), common(), nullptr, nullptr, nullptr), | 24 jsgraph_(isolate(), graph(), common(), nullptr, nullptr, nullptr), |
| 25 escape_objects_(graph(), common(), zone()), | 25 escape_analysis_(graph(), common(), zone()), |
| 26 escape_status_(&escape_objects_, graph(), zone()), | |
| 27 effect_(graph()->start()), | 26 effect_(graph()->start()), |
| 28 control_(graph()->start()) {} | 27 control_(graph()->start()) {} |
| 29 | 28 |
| 30 ~EscapeAnalysisTest() {} | 29 ~EscapeAnalysisTest() {} |
| 31 | 30 |
| 32 EscapeStatusAnalysis* escape_status() { return &escape_status_; } | 31 EscapeAnalysis* escape_analysis() { return &escape_analysis_; } |
| 33 EscapeObjectAnalysis* escape_objects() { return &escape_objects_; } | |
| 34 | 32 |
| 35 protected: | 33 protected: |
| 36 void Analysis() { | 34 void Analysis() { escape_analysis_.Run(); } |
| 37 escape_objects_.Run(); | |
| 38 escape_status_.Run(); | |
| 39 } | |
| 40 | 35 |
| 41 void Transformation() { | 36 void Transformation() { |
| 42 GraphReducer graph_reducer(zone(), graph()); | 37 GraphReducer graph_reducer(zone(), graph()); |
| 43 EscapeAnalysisReducer escape_reducer( | 38 EscapeAnalysisReducer escape_reducer(&graph_reducer, &jsgraph_, |
| 44 &graph_reducer, &jsgraph_, &escape_status_, &escape_objects_, zone()); | 39 &escape_analysis_, zone()); |
| 45 graph_reducer.AddReducer(&escape_reducer); | 40 graph_reducer.AddReducer(&escape_reducer); |
| 46 graph_reducer.ReduceGraph(); | 41 graph_reducer.ReduceGraph(); |
| 47 } | 42 } |
| 48 | 43 |
| 49 // ---------------------------------Node Creation Helper---------------------- | 44 // ---------------------------------Node Creation Helper---------------------- |
| 50 | 45 |
| 51 Node* BeginRegion(Node* effect = nullptr) { | 46 Node* BeginRegion(Node* effect = nullptr) { |
| 52 if (!effect) { | 47 if (!effect) { |
| 53 effect = effect_; | 48 effect = effect_; |
| 54 } | 49 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 | 133 |
| 139 FieldAccess AccessAtIndex(int offset) { | 134 FieldAccess AccessAtIndex(int offset) { |
| 140 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(), | 135 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(), |
| 141 kMachAnyTagged}; | 136 kMachAnyTagged}; |
| 142 return access; | 137 return access; |
| 143 } | 138 } |
| 144 | 139 |
| 145 // ---------------------------------Assertion Helper-------------------------- | 140 // ---------------------------------Assertion Helper-------------------------- |
| 146 | 141 |
| 147 void ExpectReplacement(Node* node, Node* rep) { | 142 void ExpectReplacement(Node* node, Node* rep) { |
| 148 EXPECT_EQ(rep, escape_objects()->GetReplacement(node, node->id())); | 143 EXPECT_EQ(rep, escape_analysis()->GetReplacement(node, node->id())); |
| 149 } | 144 } |
| 150 | 145 |
| 151 void ExpectReplacementPhi(Node* node, Node* left, Node* right) { | 146 void ExpectReplacementPhi(Node* node, Node* left, Node* right) { |
| 152 Node* rep = escape_objects()->GetReplacement(node, node->id()); | 147 Node* rep = escape_analysis()->GetReplacement(node, node->id()); |
| 153 ASSERT_NE(nullptr, rep); | 148 ASSERT_NE(nullptr, rep); |
| 154 ASSERT_EQ(IrOpcode::kPhi, rep->opcode()); | 149 ASSERT_EQ(IrOpcode::kPhi, rep->opcode()); |
| 155 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0)); | 150 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0)); |
| 156 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1)); | 151 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1)); |
| 157 } | 152 } |
| 158 | 153 |
| 159 void ExpectVirtual(Node* node) { | 154 void ExpectVirtual(Node* node) { |
| 160 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || | 155 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || |
| 161 node->opcode() == IrOpcode::kFinishRegion); | 156 node->opcode() == IrOpcode::kFinishRegion); |
| 162 EXPECT_TRUE(escape_status()->IsVirtual(node)); | 157 EXPECT_TRUE(escape_analysis()->IsVirtual(node)); |
| 163 } | 158 } |
| 164 | 159 |
| 165 void ExpectEscaped(Node* node) { | 160 void ExpectEscaped(Node* node) { |
| 166 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || | 161 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || |
| 167 node->opcode() == IrOpcode::kFinishRegion); | 162 node->opcode() == IrOpcode::kFinishRegion); |
| 168 EXPECT_TRUE(escape_status()->IsEscaped(node)); | 163 EXPECT_TRUE(escape_analysis()->IsEscaped(node)); |
| 169 } | 164 } |
| 170 | 165 |
| 171 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 166 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
| 172 | 167 |
| 173 Node* effect() { return effect_; } | 168 Node* effect() { return effect_; } |
| 174 | 169 |
| 175 private: | 170 private: |
| 176 SimplifiedOperatorBuilder simplified_; | 171 SimplifiedOperatorBuilder simplified_; |
| 177 JSGraph jsgraph_; | 172 JSGraph jsgraph_; |
| 178 EscapeObjectAnalysis escape_objects_; | 173 EscapeAnalysis escape_analysis_; |
| 179 EscapeStatusAnalysis escape_status_; | |
| 180 | 174 |
| 181 Node* effect_; | 175 Node* effect_; |
| 182 Node* control_; | 176 Node* control_; |
| 183 }; | 177 }; |
| 184 | 178 |
| 185 | 179 |
| 186 // ----------------------------------------------------------------------------- | 180 // ----------------------------------------------------------------------------- |
| 187 // Test cases. | 181 // Test cases. |
| 188 | 182 |
| 189 | 183 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue); | 263 Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue); |
| 270 Node* merge = Merge2(ifFalse, ifTrue); | 264 Node* merge = Merge2(ifFalse, ifTrue); |
| 271 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge); | 265 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge); |
| 272 Node* load = Load(AccessAtIndex(0), finish, phi, merge); | 266 Node* load = Load(AccessAtIndex(0), finish, phi, merge); |
| 273 Node* result = Return(load, phi); | 267 Node* result = Return(load, phi); |
| 274 EndGraph(); | 268 EndGraph(); |
| 275 Analysis(); | 269 Analysis(); |
| 276 | 270 |
| 277 ExpectVirtual(allocation); | 271 ExpectVirtual(allocation); |
| 278 ExpectReplacementPhi(load, object1, object2); | 272 ExpectReplacementPhi(load, object1, object2); |
| 279 Node* replacement_phi = escape_objects()->GetReplacement(load, load->id()); | 273 Node* replacement_phi = escape_analysis()->GetReplacement(load, load->id()); |
| 280 | 274 |
| 281 Transformation(); | 275 Transformation(); |
| 282 | 276 |
| 283 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0)); | 277 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0)); |
| 284 } | 278 } |
| 285 | 279 |
| 286 | 280 |
| 287 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { | 281 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { |
| 288 Node* object1 = Constant(1); | 282 Node* object1 = Constant(1); |
| 289 Node* object2 = Constant(2); | 283 Node* object2 = Constant(2); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 302 ExpectReplacement(load2, object1); | 296 ExpectReplacement(load2, object1); |
| 303 | 297 |
| 304 Transformation(); | 298 Transformation(); |
| 305 | 299 |
| 306 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); | 300 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 307 } | 301 } |
| 308 | 302 |
| 309 } // namespace compiler | 303 } // namespace compiler |
| 310 } // namespace internal | 304 } // namespace internal |
| 311 } // namespace v8 | 305 } // namespace v8 |
| OLD | NEW |