Chromium Code Reviews| 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/compiler/escape-analysis-reducer.h" | 5 #include "src/compiler/escape-analysis-reducer.h" |
| 6 | 6 |
| 7 #include "src/compiler/all-nodes.h" | 7 #include "src/compiler/all-nodes.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/simplified-operator.h" | |
| 10 #include "src/compiler/type-cache.h" | |
| 9 #include "src/counters.h" | 11 #include "src/counters.h" |
| 10 | 12 |
| 11 namespace v8 { | 13 namespace v8 { |
| 12 namespace internal { | 14 namespace internal { |
| 13 namespace compiler { | 15 namespace compiler { |
| 14 | 16 |
| 15 #ifdef DEBUG | 17 #ifdef DEBUG |
| 16 #define TRACE(...) \ | 18 #define TRACE(...) \ |
| 17 do { \ | 19 do { \ |
| 18 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ | 20 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 break; | 81 break; |
| 80 default: | 82 default: |
| 81 break; | 83 break; |
| 82 } | 84 } |
| 83 } | 85 } |
| 84 if (!depends_on_object_state) { | 86 if (!depends_on_object_state) { |
| 85 fully_reduced_.Add(node->id()); | 87 fully_reduced_.Add(node->id()); |
| 86 } | 88 } |
| 87 return NoChange(); | 89 return NoChange(); |
| 88 } | 90 } |
| 91 case IrOpcode::kNewUnmappedArgumentsElements: | |
| 92 arguments_elements_.insert(node); | |
| 93 // Fallthrough. | |
|
Jarin
2017/02/27 13:24:34
Could we get rid of the fallthrough?
Case fallthr
| |
| 89 default: | 94 default: |
| 90 // TODO(sigurds): Change this to GetFrameStateInputCount once | 95 // TODO(sigurds): Change this to GetFrameStateInputCount once |
| 91 // it is working. For now we use EffectInputCount > 0 to determine | 96 // it is working. For now we use EffectInputCount > 0 to determine |
| 92 // whether a node might have a frame state input. | 97 // whether a node might have a frame state input. |
| 93 if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { | 98 if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { |
| 94 return ReduceFrameStateUses(node); | 99 return ReduceFrameStateUses(node); |
| 95 } | 100 } |
| 96 break; | 101 break; |
| 97 } | 102 } |
| 98 return NoChange(); | 103 return NoChange(); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 #ifdef DEBUG | 395 #ifdef DEBUG |
| 391 AllNodes all(zone(), jsgraph()->graph()); | 396 AllNodes all(zone(), jsgraph()->graph()); |
| 392 for (Node* node : all.reachable) { | 397 for (Node* node : all.reachable) { |
| 393 if (node->opcode() == IrOpcode::kAllocate) { | 398 if (node->opcode() == IrOpcode::kAllocate) { |
| 394 CHECK(!escape_analysis_->IsVirtual(node)); | 399 CHECK(!escape_analysis_->IsVirtual(node)); |
| 395 } | 400 } |
| 396 } | 401 } |
| 397 #endif // DEBUG | 402 #endif // DEBUG |
| 398 } | 403 } |
| 399 | 404 |
| 405 void EscapeAnalysisReducer::Finalize() { | |
| 406 for (Node* node : arguments_elements_) { | |
| 407 DCHECK(node->opcode() == IrOpcode::kNewUnmappedArgumentsElements); | |
| 408 | |
| 409 Node* arguments_frame = NodeProperties::GetValueInput(node, 0); | |
| 410 if (arguments_frame->opcode() != IrOpcode::kArgumentsFrame) continue; | |
| 411 Node* arguments_length = NodeProperties::GetValueInput(node, 1); | |
| 412 if (arguments_length->opcode() != IrOpcode::kArgumentsLength) continue; | |
| 413 | |
| 414 bool escaping_use = false; | |
| 415 ZoneVector<Node*> loads(zone()); | |
| 416 for (Edge edge : node->use_edges()) { | |
| 417 Node* use = edge.from(); | |
| 418 if (!NodeProperties::IsValueEdge(edge)) continue; | |
| 419 switch (use->opcode()) { | |
| 420 case IrOpcode::kStateValues: | |
| 421 case IrOpcode::kTypedStateValues: | |
| 422 case IrOpcode::kObjectState: | |
| 423 case IrOpcode::kTypedObjectState: | |
| 424 break; | |
| 425 case IrOpcode::kLoadElement: | |
| 426 loads.push_back(use); | |
| 427 break; | |
| 428 case IrOpcode::kLoadField: | |
| 429 if (FieldAccessOf(use->op()).offset == FixedArray::kLengthOffset) { | |
| 430 loads.push_back(use); | |
| 431 break; | |
| 432 } | |
| 433 // Fallthrough. | |
|
Jarin
2017/02/27 13:24:34
Could not you say here
if (...) {
load.push_bac
| |
| 434 default: | |
| 435 if (!use->use_edges().empty()) { | |
|
Jarin
2017/02/27 13:24:34
Explain in a comment what this check does, please.
| |
| 436 escaping_use = true; | |
| 437 break; | |
| 438 } | |
| 439 } | |
| 440 if (escaping_use) break; | |
| 441 } | |
| 442 if (!escaping_use) { | |
| 443 int formal_parameter_count = | |
| 444 FormalParameterCountOf(arguments_length->op()); | |
| 445 Node* arguments_elements_state = jsgraph()->graph()->NewNode( | |
| 446 jsgraph()->common()->ArgumentsElementsState( | |
| 447 IsRestLengthOf(arguments_length->op()))); | |
| 448 NodeProperties::SetType(arguments_elements_state, Type::OtherInternal()); | |
| 449 ReplaceWithValue(node, arguments_elements_state); | |
| 450 | |
| 451 ElementAccess stack_access; | |
| 452 stack_access.base_is_tagged = BaseTaggedness::kUntaggedBase; | |
| 453 // Reduce base address by {kPointerSize} such that (length - index) | |
| 454 // resolves to the right position. | |
| 455 stack_access.header_size = | |
| 456 CommonFrameConstants::kFixedFrameSizeAboveFp - kPointerSize; | |
| 457 stack_access.type = Type::NonInternal(); | |
| 458 stack_access.machine_type = MachineType::AnyTagged(); | |
| 459 stack_access.write_barrier_kind = WriteBarrierKind::kNoWriteBarrier; | |
| 460 const Operator* load_stack_op = | |
| 461 jsgraph()->simplified()->LoadElement(stack_access); | |
| 462 | |
| 463 for (Node* load : loads) { | |
| 464 switch (load->opcode()) { | |
| 465 case IrOpcode::kLoadElement: { | |
| 466 Node* index = NodeProperties::GetValueInput(load, 1); | |
| 467 // {offset} is a reverted index starting from 1. The base address is | |
| 468 // adapted to allow offsets starting from 1. | |
| 469 Node* offset = jsgraph()->graph()->NewNode( | |
| 470 jsgraph()->simplified()->NumberSubtract(), arguments_length, | |
| 471 index); | |
| 472 NodeProperties::SetType(offset, | |
| 473 TypeCache::Get().kArgumentsLengthType); | |
| 474 NodeProperties::ReplaceValueInput(load, arguments_frame, 0); | |
| 475 NodeProperties::ReplaceValueInput(load, offset, 1); | |
| 476 NodeProperties::ChangeOp(load, load_stack_op); | |
| 477 break; | |
| 478 } | |
| 479 case IrOpcode::kLoadField: { | |
| 480 DCHECK_EQ(FieldAccessOf(load->op()).offset, | |
| 481 FixedArray::kLengthOffset); | |
| 482 Node* length = NodeProperties::GetValueInput(node, 1); | |
| 483 ReplaceWithValue(load, length); | |
| 484 break; | |
| 485 } | |
| 486 default: | |
| 487 UNREACHABLE(); | |
| 488 } | |
| 489 } | |
| 490 } | |
| 491 } | |
| 492 } | |
| 493 | |
| 400 } // namespace compiler | 494 } // namespace compiler |
| 401 } // namespace internal | 495 } // namespace internal |
| 402 } // namespace v8 | 496 } // namespace v8 |
| OLD | NEW |