| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| 11 #include "src/compiler/liveness-analyzer.h" |
| 11 #include "src/compiler/machine-operator.h" | 12 #include "src/compiler/machine-operator.h" |
| 12 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
| 13 #include "src/compiler/node-properties.h" | 14 #include "src/compiler/node-properties.h" |
| 14 #include "src/compiler/operator-properties.h" | 15 #include "src/compiler/operator-properties.h" |
| 15 #include "src/compiler/state-values-utils.h" | 16 #include "src/compiler/state-values-utils.h" |
| 16 #include "src/full-codegen.h" | 17 #include "src/full-codegen.h" |
| 17 #include "src/parser.h" | 18 #include "src/parser.h" |
| 18 #include "src/scopes.h" | 19 #include "src/scopes.h" |
| 19 | 20 |
| 20 namespace v8 { | 21 namespace v8 { |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 environment_(nullptr), | 388 environment_(nullptr), |
| 388 ast_context_(nullptr), | 389 ast_context_(nullptr), |
| 389 globals_(0, local_zone), | 390 globals_(0, local_zone), |
| 390 execution_control_(nullptr), | 391 execution_control_(nullptr), |
| 391 execution_context_(nullptr), | 392 execution_context_(nullptr), |
| 392 try_nesting_level_(0), | 393 try_nesting_level_(0), |
| 393 input_buffer_size_(0), | 394 input_buffer_size_(0), |
| 394 input_buffer_(nullptr), | 395 input_buffer_(nullptr), |
| 395 exit_control_(nullptr), | 396 exit_control_(nullptr), |
| 396 loop_assignment_analysis_(loop), | 397 loop_assignment_analysis_(loop), |
| 397 state_values_cache_(jsgraph) { | 398 state_values_cache_(jsgraph), |
| 399 liveness_analyzer_(new (local_zone) LivenessAnalyzer( |
| 400 static_cast<size_t>(info->scope()->num_stack_slots()), local_zone)) { |
| 398 InitializeAstVisitor(info->isolate(), local_zone); | 401 InitializeAstVisitor(info->isolate(), local_zone); |
| 399 } | 402 } |
| 400 | 403 |
| 401 | 404 |
| 402 Node* AstGraphBuilder::GetFunctionClosure() { | 405 Node* AstGraphBuilder::GetFunctionClosure() { |
| 403 if (!function_closure_.is_set()) { | 406 if (!function_closure_.is_set()) { |
| 404 const Operator* op = | 407 const Operator* op = |
| 405 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); | 408 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); |
| 406 Node* node = NewNode(op, graph()->start()); | 409 Node* node = NewNode(op, graph()->start()); |
| 407 function_closure_.set(node); | 410 function_closure_.set(node); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 ContextScope top_context(this, scope, inner_context); | 476 ContextScope top_context(this, scope, inner_context); |
| 474 CreateGraphBody(stack_check); | 477 CreateGraphBody(stack_check); |
| 475 } else { | 478 } else { |
| 476 // Simply use the outer function context in building the graph. | 479 // Simply use the outer function context in building the graph. |
| 477 CreateGraphBody(stack_check); | 480 CreateGraphBody(stack_check); |
| 478 } | 481 } |
| 479 | 482 |
| 480 // Finish the basic structure of the graph. | 483 // Finish the basic structure of the graph. |
| 481 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); | 484 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); |
| 482 | 485 |
| 486 // Compute local variable liveness information and use it to relax |
| 487 // frame states. |
| 488 ClearNonLiveSlotsInFrameStates(); |
| 489 |
| 483 // Failures indicated by stack overflow. | 490 // Failures indicated by stack overflow. |
| 484 return !HasStackOverflow(); | 491 return !HasStackOverflow(); |
| 485 } | 492 } |
| 486 | 493 |
| 487 | 494 |
| 488 void AstGraphBuilder::CreateGraphBody(bool stack_check) { | 495 void AstGraphBuilder::CreateGraphBody(bool stack_check) { |
| 489 Scope* scope = info()->scope(); | 496 Scope* scope = info()->scope(); |
| 490 | 497 |
| 491 // Build the arguments object if it is used. | 498 // Build the arguments object if it is used. |
| 492 BuildArgumentsObject(scope->arguments()); | 499 BuildArgumentsObject(scope->arguments()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 523 // TODO(mstarzinger): Only traces implicit return. | 530 // TODO(mstarzinger): Only traces implicit return. |
| 524 Node* return_value = jsgraph()->UndefinedConstant(); | 531 Node* return_value = jsgraph()->UndefinedConstant(); |
| 525 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); | 532 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); |
| 526 } | 533 } |
| 527 | 534 |
| 528 // Return 'undefined' in case we can fall off the end. | 535 // Return 'undefined' in case we can fall off the end. |
| 529 BuildReturn(jsgraph()->UndefinedConstant()); | 536 BuildReturn(jsgraph()->UndefinedConstant()); |
| 530 } | 537 } |
| 531 | 538 |
| 532 | 539 |
| 540 void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() { |
| 541 if (!FLAG_analyze_environment_liveness) return; |
| 542 |
| 543 NonLiveFrameStateSlotReplacer replacer( |
| 544 &state_values_cache_, jsgraph()->UndefinedConstant(), |
| 545 liveness_analyzer()->local_count(), local_zone()); |
| 546 Variable* arguments = info()->scope()->arguments(); |
| 547 if (arguments != nullptr && arguments->IsStackAllocated()) { |
| 548 replacer.MarkPermanentlyLive(arguments->index()); |
| 549 } |
| 550 liveness_analyzer()->Run(&replacer); |
| 551 if (FLAG_trace_environment_liveness) { |
| 552 OFStream os(stdout); |
| 553 liveness_analyzer()->Print(os); |
| 554 } |
| 555 } |
| 556 |
| 557 |
| 533 // Left-hand side can only be a property, a global or a variable slot. | 558 // Left-hand side can only be a property, a global or a variable slot. |
| 534 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 559 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 535 | 560 |
| 536 | 561 |
| 537 // Determine the left-hand side kind of an assignment. | 562 // Determine the left-hand side kind of an assignment. |
| 538 static LhsKind DetermineLhsKind(Expression* expr) { | 563 static LhsKind DetermineLhsKind(Expression* expr) { |
| 539 Property* property = expr->AsProperty(); | 564 Property* property = expr->AsProperty(); |
| 540 DCHECK(expr->IsValidReferenceExpression()); | 565 DCHECK(expr->IsValidReferenceExpression()); |
| 541 LhsKind lhs_kind = | 566 LhsKind lhs_kind = |
| 542 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) | 567 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) |
| 543 ? NAMED_PROPERTY | 568 ? NAMED_PROPERTY |
| 544 : KEYED_PROPERTY; | 569 : KEYED_PROPERTY; |
| 545 return lhs_kind; | 570 return lhs_kind; |
| 546 } | 571 } |
| 547 | 572 |
| 548 | 573 |
| 549 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, | 574 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, |
| 550 Scope* scope, | 575 Scope* scope, |
| 551 Node* control_dependency) | 576 Node* control_dependency) |
| 552 : builder_(builder), | 577 : builder_(builder), |
| 553 parameters_count_(scope->num_parameters() + 1), | 578 parameters_count_(scope->num_parameters() + 1), |
| 554 locals_count_(scope->num_stack_slots()), | 579 locals_count_(scope->num_stack_slots()), |
| 580 liveness_block_(builder_->liveness_analyzer()->New()), |
| 555 values_(builder_->local_zone()), | 581 values_(builder_->local_zone()), |
| 556 contexts_(builder_->local_zone()), | 582 contexts_(builder_->local_zone()), |
| 557 control_dependency_(control_dependency), | 583 control_dependency_(control_dependency), |
| 558 effect_dependency_(control_dependency), | 584 effect_dependency_(control_dependency), |
| 559 parameters_node_(nullptr), | 585 parameters_node_(nullptr), |
| 560 locals_node_(nullptr), | 586 locals_node_(nullptr), |
| 561 stack_node_(nullptr) { | 587 stack_node_(nullptr) { |
| 562 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); | 588 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); |
| 563 | 589 |
| 564 // Bind the receiver variable. | 590 // Bind the receiver variable. |
| 565 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), | 591 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), |
| 566 builder->graph()->start()); | 592 builder->graph()->start()); |
| 567 values()->push_back(receiver); | 593 values()->push_back(receiver); |
| 568 | 594 |
| 569 // Bind all parameter variables. The parameter indices are shifted by 1 | 595 // Bind all parameter variables. The parameter indices are shifted by 1 |
| 570 // (receiver is parameter index -1 but environment index 0). | 596 // (receiver is parameter index -1 but environment index 0). |
| 571 for (int i = 0; i < scope->num_parameters(); ++i) { | 597 for (int i = 0; i < scope->num_parameters(); ++i) { |
| 572 Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1), | 598 Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1), |
| 573 builder->graph()->start()); | 599 builder->graph()->start()); |
| 574 values()->push_back(parameter); | 600 values()->push_back(parameter); |
| 575 } | 601 } |
| 576 | 602 |
| 577 // Bind all local variables to undefined. | 603 // Bind all local variables to undefined. |
| 578 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); | 604 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); |
| 579 values()->insert(values()->end(), locals_count(), undefined_constant); | 605 values()->insert(values()->end(), locals_count(), undefined_constant); |
| 580 } | 606 } |
| 581 | 607 |
| 582 | 608 |
| 583 AstGraphBuilder::Environment::Environment( | 609 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy) |
| 584 const AstGraphBuilder::Environment* copy) | |
| 585 : builder_(copy->builder_), | 610 : builder_(copy->builder_), |
| 586 parameters_count_(copy->parameters_count_), | 611 parameters_count_(copy->parameters_count_), |
| 587 locals_count_(copy->locals_count_), | 612 locals_count_(copy->locals_count_), |
| 588 values_(copy->zone()), | 613 values_(copy->zone()), |
| 589 contexts_(copy->zone()), | 614 contexts_(copy->zone()), |
| 590 control_dependency_(copy->control_dependency_), | 615 control_dependency_(copy->control_dependency_), |
| 591 effect_dependency_(copy->effect_dependency_), | 616 effect_dependency_(copy->effect_dependency_), |
| 592 parameters_node_(copy->parameters_node_), | 617 parameters_node_(copy->parameters_node_), |
| 593 locals_node_(copy->locals_node_), | 618 locals_node_(copy->locals_node_), |
| 594 stack_node_(copy->stack_node_) { | 619 stack_node_(copy->stack_node_) { |
| 595 const size_t kStackEstimate = 7; // optimum from experimentation! | 620 const size_t kStackEstimate = 7; // optimum from experimentation! |
| 596 values_.reserve(copy->values_.size() + kStackEstimate); | 621 values_.reserve(copy->values_.size() + kStackEstimate); |
| 597 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end()); | 622 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end()); |
| 598 contexts_.reserve(copy->contexts_.size()); | 623 contexts_.reserve(copy->contexts_.size()); |
| 599 contexts_.insert(contexts_.begin(), copy->contexts_.begin(), | 624 contexts_.insert(contexts_.begin(), copy->contexts_.begin(), |
| 600 copy->contexts_.end()); | 625 copy->contexts_.end()); |
| 626 |
| 627 if (FLAG_analyze_environment_liveness) { |
| 628 // Split the liveness blocks. |
| 629 copy->liveness_block_ = |
| 630 builder_->liveness_analyzer()->New(copy->liveness_block()); |
| 631 liveness_block_ = |
| 632 builder_->liveness_analyzer()->New(copy->liveness_block()); |
| 633 } |
| 601 } | 634 } |
| 602 | 635 |
| 603 | 636 |
| 637 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) { |
| 638 DCHECK(variable->IsStackAllocated()); |
| 639 if (variable->IsParameter()) { |
| 640 // The parameter indices are shifted by 1 (receiver is parameter |
| 641 // index -1 but environment index 0). |
| 642 values()->at(variable->index() + 1) = node; |
| 643 } else { |
| 644 DCHECK(variable->IsStackLocal()); |
| 645 values()->at(variable->index() + parameters_count_) = node; |
| 646 if (FLAG_analyze_environment_liveness) { |
| 647 liveness_block()->Bind(variable->index()); |
| 648 } |
| 649 } |
| 650 } |
| 651 |
| 652 |
| 653 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) { |
| 654 DCHECK(variable->IsStackAllocated()); |
| 655 if (variable->IsParameter()) { |
| 656 // The parameter indices are shifted by 1 (receiver is parameter |
| 657 // index -1 but environment index 0). |
| 658 return values()->at(variable->index() + 1); |
| 659 } else { |
| 660 DCHECK(variable->IsStackLocal()); |
| 661 if (FLAG_analyze_environment_liveness) { |
| 662 liveness_block()->Lookup(variable->index()); |
| 663 } |
| 664 return values()->at(variable->index() + parameters_count_); |
| 665 } |
| 666 } |
| 667 |
| 668 |
| 669 void AstGraphBuilder::Environment::MarkAllLocalsLive() { |
| 670 if (FLAG_analyze_environment_liveness) { |
| 671 for (int i = 0; i < locals_count_; i++) { |
| 672 liveness_block()->Lookup(i); |
| 673 } |
| 674 } |
| 675 } |
| 676 |
| 677 |
| 678 AstGraphBuilder::Environment* |
| 679 AstGraphBuilder::Environment::CopyAndShareLiveness() { |
| 680 Environment* env = new (zone()) Environment(this); |
| 681 if (FLAG_analyze_environment_liveness) { |
| 682 env->liveness_block_ = liveness_block(); |
| 683 } |
| 684 return env; |
| 685 } |
| 686 |
| 687 |
| 604 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, | 688 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, |
| 605 int offset, int count) { | 689 int offset, int count) { |
| 606 bool should_update = false; | 690 bool should_update = false; |
| 607 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); | 691 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); |
| 608 if (*state_values == NULL || (*state_values)->InputCount() != count) { | 692 if (*state_values == NULL || (*state_values)->InputCount() != count) { |
| 609 should_update = true; | 693 should_update = true; |
| 610 } else { | 694 } else { |
| 611 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); | 695 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); |
| 612 for (int i = 0; i < count; i++) { | 696 for (int i = 0; i < count; i++) { |
| 613 if ((*state_values)->InputAt(i) != env_values[i]) { | 697 if ((*state_values)->InputAt(i) != env_values[i]) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 635 BailoutId ast_id, OutputFrameStateCombine combine) { | 719 BailoutId ast_id, OutputFrameStateCombine combine) { |
| 636 if (!FLAG_turbo_deoptimization) return nullptr; | 720 if (!FLAG_turbo_deoptimization) return nullptr; |
| 637 | 721 |
| 638 UpdateStateValues(¶meters_node_, 0, parameters_count()); | 722 UpdateStateValues(¶meters_node_, 0, parameters_count()); |
| 639 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count()); | 723 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count()); |
| 640 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), | 724 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), |
| 641 stack_height()); | 725 stack_height()); |
| 642 | 726 |
| 643 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine); | 727 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine); |
| 644 | 728 |
| 645 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, | 729 Node* result = graph()->NewNode(op, parameters_node_, locals_node_, |
| 646 builder()->current_context(), | 730 stack_node_, builder()->current_context(), |
| 647 builder()->jsgraph()->UndefinedConstant()); | 731 builder()->jsgraph()->UndefinedConstant()); |
| 732 if (FLAG_analyze_environment_liveness) { |
| 733 liveness_block()->Checkpoint(result); |
| 734 } |
| 735 return result; |
| 648 } | 736 } |
| 649 | 737 |
| 650 | 738 |
| 651 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, | 739 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, |
| 652 Expression::Context kind) | 740 Expression::Context kind) |
| 653 : kind_(kind), owner_(own), outer_(own->ast_context()) { | 741 : kind_(kind), owner_(own), outer_(own->ast_context()) { |
| 654 owner()->set_ast_context(this); // Push. | 742 owner()->set_ast_context(this); // Push. |
| 655 #ifdef DEBUG | 743 #ifdef DEBUG |
| 656 original_height_ = environment()->stack_height(); | 744 original_height_ = environment()->stack_height(); |
| 657 #endif | 745 #endif |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 | 1414 |
| 1327 // TODO(mstarzinger): Remove bailout once everything works. | 1415 // TODO(mstarzinger): Remove bailout once everything works. |
| 1328 if (!FLAG_turbo_exceptions) SetStackOverflow(); | 1416 if (!FLAG_turbo_exceptions) SetStackOverflow(); |
| 1329 } | 1417 } |
| 1330 | 1418 |
| 1331 | 1419 |
| 1332 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1420 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1333 // TODO(turbofan): Do we really need a separate reloc-info for this? | 1421 // TODO(turbofan): Do we really need a separate reloc-info for this? |
| 1334 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); | 1422 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); |
| 1335 PrepareFrameState(node, stmt->DebugBreakId()); | 1423 PrepareFrameState(node, stmt->DebugBreakId()); |
| 1424 environment()->MarkAllLocalsLive(); |
| 1336 } | 1425 } |
| 1337 | 1426 |
| 1338 | 1427 |
| 1339 void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 1428 void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 1340 Node* context = current_context(); | 1429 Node* context = current_context(); |
| 1341 | 1430 |
| 1342 // Build a new shared function info if we cannot find one in the baseline | 1431 // Build a new shared function info if we cannot find one in the baseline |
| 1343 // code. We also have a stack overflow if the recursive compilation did. | 1432 // code. We also have a stack overflow if the recursive compilation did. |
| 1344 expr->InitializeSharedInfo(handle(info()->shared_info()->code())); | 1433 expr->InitializeSharedInfo(handle(info()->shared_info()->code())); |
| 1345 Handle<SharedFunctionInfo> shared_info = expr->shared_info(); | 1434 Handle<SharedFunctionInfo> shared_info = expr->shared_info(); |
| (...skipping 1821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 DCHECK(contexts_.size() <= other->contexts_.size()); | 3256 DCHECK(contexts_.size() <= other->contexts_.size()); |
| 3168 | 3257 |
| 3169 // Nothing to do if the other environment is dead. | 3258 // Nothing to do if the other environment is dead. |
| 3170 if (other->IsMarkedAsUnreachable()) return; | 3259 if (other->IsMarkedAsUnreachable()) return; |
| 3171 | 3260 |
| 3172 // Resurrect a dead environment by copying the contents of the other one and | 3261 // Resurrect a dead environment by copying the contents of the other one and |
| 3173 // placing a singleton merge as the new control dependency. | 3262 // placing a singleton merge as the new control dependency. |
| 3174 if (this->IsMarkedAsUnreachable()) { | 3263 if (this->IsMarkedAsUnreachable()) { |
| 3175 Node* other_control = other->control_dependency_; | 3264 Node* other_control = other->control_dependency_; |
| 3176 Node* inputs[] = {other_control}; | 3265 Node* inputs[] = {other_control}; |
| 3266 liveness_block_ = other->liveness_block_; |
| 3177 control_dependency_ = | 3267 control_dependency_ = |
| 3178 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); | 3268 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); |
| 3179 effect_dependency_ = other->effect_dependency_; | 3269 effect_dependency_ = other->effect_dependency_; |
| 3180 values_ = other->values_; | 3270 values_ = other->values_; |
| 3181 // TODO(titzer): make context stack heights match. | 3271 // TODO(titzer): make context stack heights match. |
| 3182 size_t min = std::min(contexts_.size(), other->contexts_.size()); | 3272 size_t min = std::min(contexts_.size(), other->contexts_.size()); |
| 3183 contexts_ = other->contexts_; | 3273 contexts_ = other->contexts_; |
| 3184 contexts_.resize(min, nullptr); | 3274 contexts_.resize(min, nullptr); |
| 3185 return; | 3275 return; |
| 3186 } | 3276 } |
| 3187 | 3277 |
| 3278 // Record the merge for the local variable liveness calculation. |
| 3279 // Unfortunately, we have to mirror the logic in the MergeControl method: |
| 3280 // connect before merge or loop, or create a new merge otherwise. |
| 3281 if (FLAG_analyze_environment_liveness) { |
| 3282 if (GetControlDependency()->opcode() != IrOpcode::kLoop && |
| 3283 GetControlDependency()->opcode() != IrOpcode::kMerge) { |
| 3284 liveness_block_ = builder_->liveness_analyzer()->New(liveness_block()); |
| 3285 } |
| 3286 liveness_block()->AddPredecessor(other->liveness_block()); |
| 3287 } |
| 3288 |
| 3188 // Create a merge of the control dependencies of both environments and update | 3289 // Create a merge of the control dependencies of both environments and update |
| 3189 // the current environment's control dependency accordingly. | 3290 // the current environment's control dependency accordingly. |
| 3190 Node* control = builder_->MergeControl(this->GetControlDependency(), | 3291 Node* control = builder_->MergeControl(this->GetControlDependency(), |
| 3191 other->GetControlDependency()); | 3292 other->GetControlDependency()); |
| 3192 UpdateControlDependency(control); | 3293 UpdateControlDependency(control); |
| 3193 | 3294 |
| 3194 // Create a merge of the effect dependencies of both environments and update | 3295 // Create a merge of the effect dependencies of both environments and update |
| 3195 // the current environment's effect dependency accordingly. | 3296 // the current environment's effect dependency accordingly. |
| 3196 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), | 3297 Node* effect = builder_->MergeEffect(this->GetEffectDependency(), |
| 3197 other->GetEffectDependency(), control); | 3298 other->GetEffectDependency(), control); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3348 // Phi does not exist yet, introduce one. | 3449 // Phi does not exist yet, introduce one. |
| 3349 value = NewPhi(inputs, value, control); | 3450 value = NewPhi(inputs, value, control); |
| 3350 value->ReplaceInput(inputs - 1, other); | 3451 value->ReplaceInput(inputs - 1, other); |
| 3351 } | 3452 } |
| 3352 return value; | 3453 return value; |
| 3353 } | 3454 } |
| 3354 | 3455 |
| 3355 } // namespace compiler | 3456 } // namespace compiler |
| 3356 } // namespace internal | 3457 } // namespace internal |
| 3357 } // namespace v8 | 3458 } // namespace v8 |
| OLD | NEW |