| 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" |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 if (!effect) { | 78 if (!effect) { |
| 79 effect = effect_; | 79 effect = effect_; |
| 80 } | 80 } |
| 81 if (!control) { | 81 if (!control) { |
| 82 control = control_; | 82 control = control_; |
| 83 } | 83 } |
| 84 return effect_ = graph()->NewNode(simplified()->StoreField(access), | 84 return effect_ = graph()->NewNode(simplified()->StoreField(access), |
| 85 allocation, value, effect, control); | 85 allocation, value, effect, control); |
| 86 } | 86 } |
| 87 | 87 |
| 88 Node* StoreElement(const ElementAccess& access, Node* allocation, Node* index, |
| 89 Node* value, Node* effect = nullptr, |
| 90 Node* control = nullptr) { |
| 91 if (!effect) { |
| 92 effect = effect_; |
| 93 } |
| 94 if (!control) { |
| 95 control = control_; |
| 96 } |
| 97 return effect_ = |
| 98 graph()->NewNode(simplified()->StoreElement(access), allocation, |
| 99 index, value, effect, control); |
| 100 } |
| 101 |
| 88 Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr, | 102 Node* Load(const FieldAccess& access, Node* from, Node* effect = nullptr, |
| 89 Node* control = nullptr) { | 103 Node* control = nullptr) { |
| 90 if (!effect) { | 104 if (!effect) { |
| 91 effect = effect_; | 105 effect = effect_; |
| 92 } | 106 } |
| 93 if (!control) { | 107 if (!control) { |
| 94 control = control_; | 108 control = control_; |
| 95 } | 109 } |
| 96 return graph()->NewNode(simplified()->LoadField(access), from, effect, | 110 return graph()->NewNode(simplified()->LoadField(access), from, effect, |
| 97 control); | 111 control); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 124 Node* IfTrue() { | 138 Node* IfTrue() { |
| 125 return control_ = graph()->NewNode(common()->IfTrue(), control_); | 139 return control_ = graph()->NewNode(common()->IfTrue(), control_); |
| 126 } | 140 } |
| 127 | 141 |
| 128 Node* IfFalse() { return graph()->NewNode(common()->IfFalse(), control_); } | 142 Node* IfFalse() { return graph()->NewNode(common()->IfFalse(), control_); } |
| 129 | 143 |
| 130 Node* Merge2(Node* control1, Node* control2) { | 144 Node* Merge2(Node* control1, Node* control2) { |
| 131 return control_ = graph()->NewNode(common()->Merge(2), control1, control2); | 145 return control_ = graph()->NewNode(common()->Merge(2), control1, control2); |
| 132 } | 146 } |
| 133 | 147 |
| 134 FieldAccess AccessAtIndex(int offset) { | 148 FieldAccess FieldAccessAtIndex(int offset) { |
| 135 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(), | 149 FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(), |
| 136 MachineType::AnyTagged()}; | 150 MachineType::AnyTagged()}; |
| 137 return access; | 151 return access; |
| 138 } | 152 } |
| 139 | 153 |
| 154 ElementAccess MakeElementAccess(int header_size) { |
| 155 ElementAccess access = {kTaggedBase, header_size, Type::Any(), |
| 156 MachineType::AnyTagged()}; |
| 157 return access; |
| 158 } |
| 159 |
| 140 // ---------------------------------Assertion Helper-------------------------- | 160 // ---------------------------------Assertion Helper-------------------------- |
| 141 | 161 |
| 142 void ExpectReplacement(Node* node, Node* rep) { | 162 void ExpectReplacement(Node* node, Node* rep) { |
| 143 EXPECT_EQ(rep, escape_analysis()->GetReplacement(node)); | 163 EXPECT_EQ(rep, escape_analysis()->GetReplacement(node)); |
| 144 } | 164 } |
| 145 | 165 |
| 146 void ExpectReplacementPhi(Node* node, Node* left, Node* right) { | 166 void ExpectReplacementPhi(Node* node, Node* left, Node* right) { |
| 147 Node* rep = escape_analysis()->GetReplacement(node); | 167 Node* rep = escape_analysis()->GetReplacement(node); |
| 148 ASSERT_NE(nullptr, rep); | 168 ASSERT_NE(nullptr, rep); |
| 149 ASSERT_EQ(IrOpcode::kPhi, rep->opcode()); | 169 ASSERT_EQ(IrOpcode::kPhi, rep->opcode()); |
| 150 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0)); | 170 EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0)); |
| 151 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1)); | 171 EXPECT_EQ(right, NodeProperties::GetValueInput(rep, 1)); |
| 152 } | 172 } |
| 153 | 173 |
| 154 void ExpectVirtual(Node* node) { | 174 void ExpectVirtual(Node* node) { |
| 155 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || | 175 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || |
| 156 node->opcode() == IrOpcode::kFinishRegion); | 176 node->opcode() == IrOpcode::kFinishRegion); |
| 157 EXPECT_TRUE(escape_analysis()->IsVirtual(node)); | 177 EXPECT_TRUE(escape_analysis()->IsVirtual(node)); |
| 158 } | 178 } |
| 159 | 179 |
| 160 void ExpectEscaped(Node* node) { | 180 void ExpectEscaped(Node* node) { |
| 161 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || | 181 EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate || |
| 162 node->opcode() == IrOpcode::kFinishRegion); | 182 node->opcode() == IrOpcode::kFinishRegion); |
| 163 EXPECT_TRUE(escape_analysis()->IsEscaped(node)); | 183 EXPECT_TRUE(escape_analysis()->IsEscaped(node)); |
| 164 } | 184 } |
| 165 | 185 |
| 166 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 186 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
| 167 | 187 |
| 168 Node* effect() { return effect_; } | 188 Node* effect() { return effect_; } |
| 189 Node* control() { return control_; } |
| 169 | 190 |
| 170 private: | 191 private: |
| 171 SimplifiedOperatorBuilder simplified_; | 192 SimplifiedOperatorBuilder simplified_; |
| 172 JSGraph jsgraph_; | 193 JSGraph jsgraph_; |
| 173 EscapeAnalysis escape_analysis_; | 194 EscapeAnalysis escape_analysis_; |
| 174 | 195 |
| 175 Node* effect_; | 196 Node* effect_; |
| 176 Node* control_; | 197 Node* control_; |
| 177 }; | 198 }; |
| 178 | 199 |
| 179 | 200 |
| 180 // ----------------------------------------------------------------------------- | 201 // ----------------------------------------------------------------------------- |
| 181 // Test cases. | 202 // Test cases. |
| 182 | 203 |
| 183 | 204 |
| 184 TEST_F(EscapeAnalysisTest, StraightNonEscape) { | 205 TEST_F(EscapeAnalysisTest, StraightNonEscape) { |
| 185 Node* object1 = Constant(1); | 206 Node* object1 = Constant(1); |
| 186 BeginRegion(); | 207 BeginRegion(); |
| 187 Node* allocation = Allocate(Constant(kPointerSize)); | 208 Node* allocation = Allocate(Constant(kPointerSize)); |
| 188 Store(AccessAtIndex(0), allocation, object1); | 209 Store(FieldAccessAtIndex(0), allocation, object1); |
| 189 Node* finish = FinishRegion(allocation); | 210 Node* finish = FinishRegion(allocation); |
| 190 Node* load = Load(AccessAtIndex(0), finish); | 211 Node* load = Load(FieldAccessAtIndex(0), finish); |
| 191 Node* result = Return(load); | 212 Node* result = Return(load); |
| 192 EndGraph(); | 213 EndGraph(); |
| 193 | 214 |
| 194 Analysis(); | 215 Analysis(); |
| 195 | 216 |
| 196 ExpectVirtual(allocation); | 217 ExpectVirtual(allocation); |
| 197 ExpectReplacement(load, object1); | 218 ExpectReplacement(load, object1); |
| 198 | 219 |
| 199 Transformation(); | 220 Transformation(); |
| 200 | 221 |
| 201 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); | 222 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 202 } | 223 } |
| 203 | 224 |
| 204 | 225 |
| 226 TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) { |
| 227 Node* object1 = Constant(1); |
| 228 Node* object2 = Constant(2); |
| 229 BeginRegion(); |
| 230 Node* allocation = Allocate(Constant(kPointerSize)); |
| 231 Store(FieldAccessAtIndex(0), allocation, object1); |
| 232 Node* index = |
| 233 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), |
| 234 object1, object2, control()); |
| 235 StoreElement(MakeElementAccess(0), allocation, index, object1); |
| 236 Node* finish = FinishRegion(allocation); |
| 237 Node* load = Load(FieldAccessAtIndex(0), finish); |
| 238 Node* result = Return(load); |
| 239 EndGraph(); |
| 240 |
| 241 Analysis(); |
| 242 |
| 243 ExpectEscaped(allocation); |
| 244 ExpectReplacement(load, nullptr); |
| 245 |
| 246 Transformation(); |
| 247 |
| 248 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0)); |
| 249 } |
| 250 |
| 251 |
| 205 TEST_F(EscapeAnalysisTest, StraightEscape) { | 252 TEST_F(EscapeAnalysisTest, StraightEscape) { |
| 206 Node* object1 = Constant(1); | 253 Node* object1 = Constant(1); |
| 207 BeginRegion(); | 254 BeginRegion(); |
| 208 Node* allocation = Allocate(Constant(kPointerSize)); | 255 Node* allocation = Allocate(Constant(kPointerSize)); |
| 209 Store(AccessAtIndex(0), allocation, object1); | 256 Store(FieldAccessAtIndex(0), allocation, object1); |
| 210 Node* finish = FinishRegion(allocation); | 257 Node* finish = FinishRegion(allocation); |
| 211 Node* load = Load(AccessAtIndex(0), finish); | 258 Node* load = Load(FieldAccessAtIndex(0), finish); |
| 212 Node* result = Return(allocation); | 259 Node* result = Return(allocation); |
| 213 EndGraph(); | 260 EndGraph(); |
| 214 graph()->end()->AppendInput(zone(), load); | 261 graph()->end()->AppendInput(zone(), load); |
| 215 | 262 |
| 216 Analysis(); | 263 Analysis(); |
| 217 | 264 |
| 218 ExpectEscaped(allocation); | 265 ExpectEscaped(allocation); |
| 219 ExpectReplacement(load, object1); | 266 ExpectReplacement(load, object1); |
| 220 | 267 |
| 221 Transformation(); | 268 Transformation(); |
| 222 | 269 |
| 223 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0)); | 270 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0)); |
| 224 } | 271 } |
| 225 | 272 |
| 226 | 273 |
| 227 TEST_F(EscapeAnalysisTest, StoreLoadEscape) { | 274 TEST_F(EscapeAnalysisTest, StoreLoadEscape) { |
| 228 Node* object1 = Constant(1); | 275 Node* object1 = Constant(1); |
| 229 | 276 |
| 230 BeginRegion(); | 277 BeginRegion(); |
| 231 Node* allocation1 = Allocate(Constant(kPointerSize)); | 278 Node* allocation1 = Allocate(Constant(kPointerSize)); |
| 232 Store(AccessAtIndex(0), allocation1, object1); | 279 Store(FieldAccessAtIndex(0), allocation1, object1); |
| 233 Node* finish1 = FinishRegion(allocation1); | 280 Node* finish1 = FinishRegion(allocation1); |
| 234 | 281 |
| 235 BeginRegion(); | 282 BeginRegion(); |
| 236 Node* allocation2 = Allocate(Constant(kPointerSize)); | 283 Node* allocation2 = Allocate(Constant(kPointerSize)); |
| 237 Store(AccessAtIndex(0), allocation2, finish1); | 284 Store(FieldAccessAtIndex(0), allocation2, finish1); |
| 238 Node* finish2 = FinishRegion(allocation2); | 285 Node* finish2 = FinishRegion(allocation2); |
| 239 | 286 |
| 240 Node* load = Load(AccessAtIndex(0), finish2); | 287 Node* load = Load(FieldAccessAtIndex(0), finish2); |
| 241 Node* result = Return(load); | 288 Node* result = Return(load); |
| 242 EndGraph(); | 289 EndGraph(); |
| 243 Analysis(); | 290 Analysis(); |
| 244 | 291 |
| 245 ExpectEscaped(allocation1); | 292 ExpectEscaped(allocation1); |
| 246 ExpectVirtual(allocation2); | 293 ExpectVirtual(allocation2); |
| 247 ExpectReplacement(load, finish1); | 294 ExpectReplacement(load, finish1); |
| 248 | 295 |
| 249 Transformation(); | 296 Transformation(); |
| 250 | 297 |
| 251 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 0)); | 298 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 0)); |
| 252 } | 299 } |
| 253 | 300 |
| 254 | 301 |
| 255 TEST_F(EscapeAnalysisTest, BranchNonEscape) { | 302 TEST_F(EscapeAnalysisTest, BranchNonEscape) { |
| 256 Node* object1 = Constant(1); | 303 Node* object1 = Constant(1); |
| 257 Node* object2 = Constant(2); | 304 Node* object2 = Constant(2); |
| 258 BeginRegion(); | 305 BeginRegion(); |
| 259 Node* allocation = Allocate(Constant(kPointerSize)); | 306 Node* allocation = Allocate(Constant(kPointerSize)); |
| 260 Store(AccessAtIndex(0), allocation, object1); | 307 Store(FieldAccessAtIndex(0), allocation, object1); |
| 261 Node* finish = FinishRegion(allocation); | 308 Node* finish = FinishRegion(allocation); |
| 262 Branch(); | 309 Branch(); |
| 263 Node* ifFalse = IfFalse(); | 310 Node* ifFalse = IfFalse(); |
| 264 Node* ifTrue = IfTrue(); | 311 Node* ifTrue = IfTrue(); |
| 265 Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish, ifFalse); | 312 Node* effect1 = |
| 266 Node* effect2 = Store(AccessAtIndex(0), allocation, object2, finish, ifTrue); | 313 Store(FieldAccessAtIndex(0), allocation, object1, finish, ifFalse); |
| 314 Node* effect2 = |
| 315 Store(FieldAccessAtIndex(0), allocation, object2, finish, ifTrue); |
| 267 Node* merge = Merge2(ifFalse, ifTrue); | 316 Node* merge = Merge2(ifFalse, ifTrue); |
| 268 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge); | 317 Node* phi = graph()->NewNode(common()->EffectPhi(2), effect1, effect2, merge); |
| 269 Node* load = Load(AccessAtIndex(0), finish, phi, merge); | 318 Node* load = Load(FieldAccessAtIndex(0), finish, phi, merge); |
| 270 Node* result = Return(load, phi); | 319 Node* result = Return(load, phi); |
| 271 EndGraph(); | 320 EndGraph(); |
| 272 graph()->end()->AppendInput(zone(), result); | 321 graph()->end()->AppendInput(zone(), result); |
| 273 | 322 |
| 274 Analysis(); | 323 Analysis(); |
| 275 | 324 |
| 276 ExpectVirtual(allocation); | 325 ExpectVirtual(allocation); |
| 277 ExpectReplacementPhi(load, object1, object2); | 326 ExpectReplacementPhi(load, object1, object2); |
| 278 Node* replacement_phi = escape_analysis()->GetReplacement(load); | 327 Node* replacement_phi = escape_analysis()->GetReplacement(load); |
| 279 | 328 |
| 280 Transformation(); | 329 Transformation(); |
| 281 | 330 |
| 282 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0)); | 331 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0)); |
| 283 } | 332 } |
| 284 | 333 |
| 285 | 334 |
| 286 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { | 335 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { |
| 287 Node* object1 = Constant(1); | 336 Node* object1 = Constant(1); |
| 288 Node* object2 = Constant(2); | 337 Node* object2 = Constant(2); |
| 289 Node* allocation = Allocate(Constant(kPointerSize)); | 338 Node* allocation = Allocate(Constant(kPointerSize)); |
| 290 Node* store1 = Store(AccessAtIndex(0), allocation, object1); | 339 Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1); |
| 291 Node* load1 = Load(AccessAtIndex(0), allocation); | 340 Node* load1 = Load(FieldAccessAtIndex(0), allocation); |
| 292 Node* store2 = Store(AccessAtIndex(0), allocation, object2); | 341 Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2); |
| 293 Node* load2 = Load(AccessAtIndex(0), allocation, store1); | 342 Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1); |
| 294 Node* result = Return(load2); | 343 Node* result = Return(load2); |
| 295 EndGraph(); | 344 EndGraph(); |
| 296 graph()->end()->AppendInput(zone(), store2); | 345 graph()->end()->AppendInput(zone(), store2); |
| 297 graph()->end()->AppendInput(zone(), load1); | 346 graph()->end()->AppendInput(zone(), load1); |
| 298 | 347 |
| 299 Analysis(); | 348 Analysis(); |
| 300 | 349 |
| 301 ExpectVirtual(allocation); | 350 ExpectVirtual(allocation); |
| 302 ExpectReplacement(load1, object1); | 351 ExpectReplacement(load1, object1); |
| 303 ExpectReplacement(load2, object1); | 352 ExpectReplacement(load2, object1); |
| 304 | 353 |
| 305 Transformation(); | 354 Transformation(); |
| 306 | 355 |
| 307 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); | 356 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 308 } | 357 } |
| 309 | 358 |
| 310 | 359 |
| 311 TEST_F(EscapeAnalysisTest, DeoptReplacement) { | 360 TEST_F(EscapeAnalysisTest, DeoptReplacement) { |
| 312 Node* object1 = Constant(1); | 361 Node* object1 = Constant(1); |
| 313 BeginRegion(); | 362 BeginRegion(); |
| 314 Node* allocation = Allocate(Constant(kPointerSize)); | 363 Node* allocation = Allocate(Constant(kPointerSize)); |
| 315 Store(AccessAtIndex(0), allocation, object1); | 364 Store(FieldAccessAtIndex(0), allocation, object1); |
| 316 Node* finish = FinishRegion(allocation); | 365 Node* finish = FinishRegion(allocation); |
| 317 Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish); | 366 Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish); |
| 318 Branch(); | 367 Branch(); |
| 319 Node* ifFalse = IfFalse(); | 368 Node* ifFalse = IfFalse(); |
| 320 Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish); | 369 Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish); |
| 321 Node* state_values2 = graph()->NewNode(common()->StateValues(0)); | 370 Node* state_values2 = graph()->NewNode(common()->StateValues(0)); |
| 322 Node* state_values3 = graph()->NewNode(common()->StateValues(0)); | 371 Node* state_values3 = graph()->NewNode(common()->StateValues(0)); |
| 323 Node* frame_state = graph()->NewNode( | 372 Node* frame_state = graph()->NewNode( |
| 324 common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), | 373 common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), |
| 325 nullptr), | 374 nullptr), |
| 326 state_values1, state_values2, state_values3, UndefinedConstant(), | 375 state_values1, state_values2, state_values3, UndefinedConstant(), |
| 327 graph()->start(), graph()->start()); | 376 graph()->start(), graph()->start()); |
| 328 Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager), | 377 Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager), |
| 329 frame_state, effect1, ifFalse); | 378 frame_state, effect1, ifFalse); |
| 330 Node* ifTrue = IfTrue(); | 379 Node* ifTrue = IfTrue(); |
| 331 Node* load = Load(AccessAtIndex(0), finish, effect1, ifTrue); | 380 Node* load = Load(FieldAccessAtIndex(0), finish, effect1, ifTrue); |
| 332 Node* result = Return(load, effect1, ifTrue); | 381 Node* result = Return(load, effect1, ifTrue); |
| 333 EndGraph(); | 382 EndGraph(); |
| 334 graph()->end()->AppendInput(zone(), deopt); | 383 graph()->end()->AppendInput(zone(), deopt); |
| 335 Analysis(); | 384 Analysis(); |
| 336 | 385 |
| 337 ExpectVirtual(allocation); | 386 ExpectVirtual(allocation); |
| 338 ExpectReplacement(load, object1); | 387 ExpectReplacement(load, object1); |
| 339 | 388 |
| 340 Transformation(); | 389 Transformation(); |
| 341 | 390 |
| 342 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); | 391 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 343 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); | 392 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); |
| 344 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); | 393 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); |
| 345 ASSERT_EQ(1, object_state->op()->ValueInputCount()); | 394 ASSERT_EQ(1, object_state->op()->ValueInputCount()); |
| 346 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); | 395 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); |
| 347 } | 396 } |
| 348 | 397 |
| 349 | 398 |
| 350 TEST_F(EscapeAnalysisTest, DeoptReplacementIdentity) { | 399 TEST_F(EscapeAnalysisTest, DeoptReplacementIdentity) { |
| 351 Node* object1 = Constant(1); | 400 Node* object1 = Constant(1); |
| 352 BeginRegion(); | 401 BeginRegion(); |
| 353 Node* allocation = Allocate(Constant(kPointerSize * 2)); | 402 Node* allocation = Allocate(Constant(kPointerSize * 2)); |
| 354 Store(AccessAtIndex(0), allocation, object1); | 403 Store(FieldAccessAtIndex(0), allocation, object1); |
| 355 Store(AccessAtIndex(kPointerSize), allocation, allocation); | 404 Store(FieldAccessAtIndex(kPointerSize), allocation, allocation); |
| 356 Node* finish = FinishRegion(allocation); | 405 Node* finish = FinishRegion(allocation); |
| 357 Node* effect1 = Store(AccessAtIndex(0), allocation, object1, finish); | 406 Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish); |
| 358 Branch(); | 407 Branch(); |
| 359 Node* ifFalse = IfFalse(); | 408 Node* ifFalse = IfFalse(); |
| 360 Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish); | 409 Node* state_values1 = graph()->NewNode(common()->StateValues(1), finish); |
| 361 Node* state_values2 = graph()->NewNode(common()->StateValues(1), finish); | 410 Node* state_values2 = graph()->NewNode(common()->StateValues(1), finish); |
| 362 Node* state_values3 = graph()->NewNode(common()->StateValues(0)); | 411 Node* state_values3 = graph()->NewNode(common()->StateValues(0)); |
| 363 Node* frame_state = graph()->NewNode( | 412 Node* frame_state = graph()->NewNode( |
| 364 common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), | 413 common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), |
| 365 nullptr), | 414 nullptr), |
| 366 state_values1, state_values2, state_values3, UndefinedConstant(), | 415 state_values1, state_values2, state_values3, UndefinedConstant(), |
| 367 graph()->start(), graph()->start()); | 416 graph()->start(), graph()->start()); |
| 368 Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager), | 417 Node* deopt = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager), |
| 369 frame_state, effect1, ifFalse); | 418 frame_state, effect1, ifFalse); |
| 370 Node* ifTrue = IfTrue(); | 419 Node* ifTrue = IfTrue(); |
| 371 Node* load = Load(AccessAtIndex(0), finish, effect1, ifTrue); | 420 Node* load = Load(FieldAccessAtIndex(0), finish, effect1, ifTrue); |
| 372 Node* result = Return(load, effect1, ifTrue); | 421 Node* result = Return(load, effect1, ifTrue); |
| 373 EndGraph(); | 422 EndGraph(); |
| 374 graph()->end()->AppendInput(zone(), deopt); | 423 graph()->end()->AppendInput(zone(), deopt); |
| 375 Analysis(); | 424 Analysis(); |
| 376 | 425 |
| 377 ExpectVirtual(allocation); | 426 ExpectVirtual(allocation); |
| 378 ExpectReplacement(load, object1); | 427 ExpectReplacement(load, object1); |
| 379 | 428 |
| 380 Transformation(); | 429 Transformation(); |
| 381 | 430 |
| 382 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); | 431 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 383 | 432 |
| 384 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); | 433 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); |
| 385 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); | 434 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); |
| 386 ASSERT_EQ(2, object_state->op()->ValueInputCount()); | 435 ASSERT_EQ(2, object_state->op()->ValueInputCount()); |
| 387 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); | 436 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); |
| 388 ASSERT_EQ(object_state, NodeProperties::GetValueInput(object_state, 1)); | 437 ASSERT_EQ(object_state, NodeProperties::GetValueInput(object_state, 1)); |
| 389 | 438 |
| 390 Node* object_state2 = NodeProperties::GetValueInput(state_values1, 0); | 439 Node* object_state2 = NodeProperties::GetValueInput(state_values1, 0); |
| 391 ASSERT_EQ(object_state, object_state2); | 440 ASSERT_EQ(object_state, object_state2); |
| 392 } | 441 } |
| 393 | 442 |
| 394 } // namespace compiler | 443 } // namespace compiler |
| 395 } // namespace internal | 444 } // namespace internal |
| 396 } // namespace v8 | 445 } // namespace v8 |
| OLD | NEW |