| 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/js-type-feedback.h" | 10 #include "src/compiler/js-type-feedback.h" |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 | 518 |
| 519 // Initialize the incoming context. | 519 // Initialize the incoming context. |
| 520 CreateFunctionContext(constant_context); | 520 CreateFunctionContext(constant_context); |
| 521 ContextScope incoming(this, scope, function_context_.get()); | 521 ContextScope incoming(this, scope, function_context_.get()); |
| 522 | 522 |
| 523 // Initialize control scope. | 523 // Initialize control scope. |
| 524 ControlScope control(this); | 524 ControlScope control(this); |
| 525 | 525 |
| 526 // Build receiver check for sloppy mode if necessary. | 526 // Build receiver check for sloppy mode if necessary. |
| 527 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 527 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
| 528 Node* patched_receiver = nullptr; | |
| 529 if (scope->has_this_declaration()) { | 528 if (scope->has_this_declaration()) { |
| 530 Node* original_receiver = NewNode(common()->Parameter(0), graph()->start()); | 529 Node* original_receiver = env.RawParameterLookup(0); |
| 531 patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 530 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
| 532 if (scope->receiver()->IsStackAllocated()) { | 531 env.RawParameterBind(0, patched_receiver); |
| 533 env.Bind(scope->receiver(), patched_receiver); | |
| 534 } | |
| 535 } | 532 } |
| 536 | 533 |
| 537 // Build function context only if there are context allocated variables. | 534 // Build function context only if there are context allocated variables. |
| 538 if (info()->num_heap_slots() > 0) { | 535 if (info()->num_heap_slots() > 0) { |
| 539 // Push a new inner context scope for the function. | 536 // Push a new inner context scope for the function. |
| 540 Node* inner_context = | 537 Node* inner_context = BuildLocalFunctionContext(function_context_.get()); |
| 541 BuildLocalFunctionContext(function_context_.get(), patched_receiver); | |
| 542 ContextScope top_context(this, scope, inner_context); | 538 ContextScope top_context(this, scope, inner_context); |
| 543 CreateGraphBody(stack_check); | 539 CreateGraphBody(stack_check); |
| 544 } else { | 540 } else { |
| 545 // Simply use the outer function context in building the graph. | 541 // Simply use the outer function context in building the graph. |
| 546 CreateGraphBody(stack_check); | 542 CreateGraphBody(stack_check); |
| 547 } | 543 } |
| 548 | 544 |
| 549 // Finish the basic structure of the graph. | 545 // Finish the basic structure of the graph. |
| 550 DCHECK_NE(0u, exit_controls_.size()); | 546 DCHECK_NE(0u, exit_controls_.size()); |
| 551 int const input_count = static_cast<int>(exit_controls_.size()); | 547 int const input_count = static_cast<int>(exit_controls_.size()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 control_dependency_(control_dependency), | 674 control_dependency_(control_dependency), |
| 679 effect_dependency_(control_dependency), | 675 effect_dependency_(control_dependency), |
| 680 parameters_node_(nullptr), | 676 parameters_node_(nullptr), |
| 681 locals_node_(nullptr), | 677 locals_node_(nullptr), |
| 682 stack_node_(nullptr) { | 678 stack_node_(nullptr) { |
| 683 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); | 679 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); |
| 684 | 680 |
| 685 // Bind the receiver variable. | 681 // Bind the receiver variable. |
| 686 int param_num = 0; | 682 int param_num = 0; |
| 687 if (builder->info()->is_this_defined()) { | 683 if (builder->info()->is_this_defined()) { |
| 688 Node* receiver = builder->graph()->NewNode( | 684 const Operator* op = common()->Parameter(param_num++, "%this"); |
| 689 common()->Parameter(param_num++, "%this"), builder->graph()->start()); | 685 Node* receiver = builder->graph()->NewNode(op, builder->graph()->start()); |
| 690 values()->push_back(receiver); | 686 values()->push_back(receiver); |
| 691 } else { | 687 } else { |
| 692 values()->push_back(builder->jsgraph()->UndefinedConstant()); | 688 values()->push_back(builder->jsgraph()->UndefinedConstant()); |
| 693 } | 689 } |
| 694 | 690 |
| 695 // Bind all parameter variables. The parameter indices are shifted by 1 | 691 // Bind all parameter variables. The parameter indices are shifted by 1 |
| 696 // (receiver is parameter index -1 but environment index 0). | 692 // (receiver is parameter index -1 but environment index 0). |
| 697 for (int i = 0; i < scope->num_parameters(); ++i) { | 693 for (int i = 0; i < scope->num_parameters(); ++i) { |
| 698 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i); | 694 const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i); |
| 699 Node* parameter = | 695 const Operator* op = common()->Parameter(param_num++, debug_name); |
| 700 builder->graph()->NewNode(common()->Parameter(param_num++, debug_name), | 696 Node* parameter = builder->graph()->NewNode(op, builder->graph()->start()); |
| 701 builder->graph()->start()); | |
| 702 values()->push_back(parameter); | 697 values()->push_back(parameter); |
| 703 } | 698 } |
| 704 | 699 |
| 705 // Bind all local variables to undefined. | 700 // Bind all local variables to undefined. |
| 706 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); | 701 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); |
| 707 values()->insert(values()->end(), locals_count(), undefined_constant); | 702 values()->insert(values()->end(), locals_count(), undefined_constant); |
| 708 } | 703 } |
| 709 | 704 |
| 710 | 705 |
| 711 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy, | 706 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 732 | 727 |
| 733 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) { | 728 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) { |
| 734 DCHECK(variable->IsStackAllocated()); | 729 DCHECK(variable->IsStackAllocated()); |
| 735 if (variable->IsParameter()) { | 730 if (variable->IsParameter()) { |
| 736 // The parameter indices are shifted by 1 (receiver is parameter | 731 // The parameter indices are shifted by 1 (receiver is parameter |
| 737 // index -1 but environment index 0). | 732 // index -1 but environment index 0). |
| 738 values()->at(variable->index() + 1) = node; | 733 values()->at(variable->index() + 1) = node; |
| 739 } else { | 734 } else { |
| 740 DCHECK(variable->IsStackLocal()); | 735 DCHECK(variable->IsStackLocal()); |
| 741 values()->at(variable->index() + parameters_count_) = node; | 736 values()->at(variable->index() + parameters_count_) = node; |
| 742 | |
| 743 DCHECK(IsLivenessBlockConsistent()); | 737 DCHECK(IsLivenessBlockConsistent()); |
| 744 if (liveness_block() != nullptr) { | 738 if (liveness_block() != nullptr) { |
| 745 liveness_block()->Bind(variable->index()); | 739 liveness_block()->Bind(variable->index()); |
| 746 } | 740 } |
| 747 } | 741 } |
| 748 } | 742 } |
| 749 | 743 |
| 750 | 744 |
| 751 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) { | 745 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) { |
| 752 DCHECK(variable->IsStackAllocated()); | 746 DCHECK(variable->IsStackAllocated()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 768 void AstGraphBuilder::Environment::MarkAllLocalsLive() { | 762 void AstGraphBuilder::Environment::MarkAllLocalsLive() { |
| 769 DCHECK(IsLivenessBlockConsistent()); | 763 DCHECK(IsLivenessBlockConsistent()); |
| 770 if (liveness_block() != nullptr) { | 764 if (liveness_block() != nullptr) { |
| 771 for (int i = 0; i < locals_count_; i++) { | 765 for (int i = 0; i < locals_count_; i++) { |
| 772 liveness_block()->Lookup(i); | 766 liveness_block()->Lookup(i); |
| 773 } | 767 } |
| 774 } | 768 } |
| 775 } | 769 } |
| 776 | 770 |
| 777 | 771 |
| 772 void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) { |
| 773 DCHECK_LT(index, parameters_count()); |
| 774 values()->at(index) = node; |
| 775 } |
| 776 |
| 777 |
| 778 Node* AstGraphBuilder::Environment::RawParameterLookup(int index) { |
| 779 DCHECK_LT(index, parameters_count()); |
| 780 return values()->at(index); |
| 781 } |
| 782 |
| 783 |
| 778 AstGraphBuilder::Environment* | 784 AstGraphBuilder::Environment* |
| 779 AstGraphBuilder::Environment::CopyForConditional() { | 785 AstGraphBuilder::Environment::CopyForConditional() { |
| 780 LivenessAnalyzerBlock* copy_liveness_block = nullptr; | 786 LivenessAnalyzerBlock* copy_liveness_block = nullptr; |
| 781 if (liveness_block() != nullptr) { | 787 if (liveness_block() != nullptr) { |
| 782 copy_liveness_block = | 788 copy_liveness_block = |
| 783 builder_->liveness_analyzer()->NewBlock(liveness_block()); | 789 builder_->liveness_analyzer()->NewBlock(liveness_block()); |
| 784 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); | 790 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); |
| 785 } | 791 } |
| 786 return new (zone()) Environment(this, copy_liveness_block); | 792 return new (zone()) Environment(this, copy_liveness_block); |
| 787 } | 793 } |
| (...skipping 2274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3062 receiver_check.Then(); | 3068 receiver_check.Then(); |
| 3063 Node* proxy = BuildLoadGlobalProxy(); | 3069 Node* proxy = BuildLoadGlobalProxy(); |
| 3064 environment()->Push(proxy); | 3070 environment()->Push(proxy); |
| 3065 receiver_check.Else(); | 3071 receiver_check.Else(); |
| 3066 environment()->Push(receiver); | 3072 environment()->Push(receiver); |
| 3067 receiver_check.End(); | 3073 receiver_check.End(); |
| 3068 return environment()->Pop(); | 3074 return environment()->Pop(); |
| 3069 } | 3075 } |
| 3070 | 3076 |
| 3071 | 3077 |
| 3072 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, | 3078 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context) { |
| 3073 Node* patched_receiver) { | |
| 3074 Scope* scope = info()->scope(); | 3079 Scope* scope = info()->scope(); |
| 3075 Node* closure = GetFunctionClosure(); | 3080 Node* closure = GetFunctionClosure(); |
| 3076 | 3081 |
| 3077 // Allocate a new local context. | 3082 // Allocate a new local context. |
| 3078 Node* local_context = | 3083 Node* local_context = |
| 3079 scope->is_script_scope() | 3084 scope->is_script_scope() |
| 3080 ? BuildLocalScriptContext(scope) | 3085 ? BuildLocalScriptContext(scope) |
| 3081 : NewNode(javascript()->CreateFunctionContext(), closure); | 3086 : NewNode(javascript()->CreateFunctionContext(), closure); |
| 3082 | 3087 |
| 3083 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 3088 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 3084 DCHECK_NOT_NULL(patched_receiver); | 3089 Node* receiver = environment()->RawParameterLookup(0); |
| 3085 // Context variable (at bottom of the context chain). | 3090 // Context variable (at bottom of the context chain). |
| 3086 Variable* variable = scope->receiver(); | 3091 Variable* variable = scope->receiver(); |
| 3087 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3092 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3088 const Operator* op = javascript()->StoreContext(0, variable->index()); | 3093 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 3089 NewNode(op, local_context, patched_receiver); | 3094 NewNode(op, local_context, receiver); |
| 3090 } | 3095 } |
| 3091 | 3096 |
| 3092 // Copy parameters into context if necessary. | 3097 // Copy parameters into context if necessary. |
| 3093 int num_parameters = scope->num_parameters(); | 3098 int num_parameters = scope->num_parameters(); |
| 3094 for (int i = 0; i < num_parameters; i++) { | 3099 for (int i = 0; i < num_parameters; i++) { |
| 3095 Variable* variable = scope->parameter(i); | 3100 Variable* variable = scope->parameter(i); |
| 3096 if (!variable->IsContextSlot()) continue; | 3101 if (!variable->IsContextSlot()) continue; |
| 3097 // Temporary parameter node. The parameter indices are shifted by 1 | 3102 Node* parameter = environment()->RawParameterLookup(i + 1); |
| 3098 // (receiver is parameter index -1 but environment index 0). | |
| 3099 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); | |
| 3100 // Context variable (at bottom of the context chain). | 3103 // Context variable (at bottom of the context chain). |
| 3101 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3104 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3102 const Operator* op = javascript()->StoreContext(0, variable->index()); | 3105 const Operator* op = javascript()->StoreContext(0, variable->index()); |
| 3103 NewNode(op, local_context, parameter); | 3106 NewNode(op, local_context, parameter); |
| 3104 } | 3107 } |
| 3105 | 3108 |
| 3106 return local_context; | 3109 return local_context; |
| 3107 } | 3110 } |
| 3108 | 3111 |
| 3109 | 3112 |
| (...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4170 // Phi does not exist yet, introduce one. | 4173 // Phi does not exist yet, introduce one. |
| 4171 value = NewPhi(inputs, value, control); | 4174 value = NewPhi(inputs, value, control); |
| 4172 value->ReplaceInput(inputs - 1, other); | 4175 value->ReplaceInput(inputs - 1, other); |
| 4173 } | 4176 } |
| 4174 return value; | 4177 return value; |
| 4175 } | 4178 } |
| 4176 | 4179 |
| 4177 } // namespace compiler | 4180 } // namespace compiler |
| 4178 } // namespace internal | 4181 } // namespace internal |
| 4179 } // namespace v8 | 4182 } // namespace v8 |
| OLD | NEW |