| 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" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 void ProduceValue(Node* value) FINAL; | 98 void ProduceValue(Node* value) FINAL; |
| 99 Node* ConsumeValue() FINAL; | 99 Node* ConsumeValue() FINAL; |
| 100 }; | 100 }; |
| 101 | 101 |
| 102 | 102 |
| 103 // Scoped class tracking context objects created by the visitor. Represents | 103 // Scoped class tracking context objects created by the visitor. Represents |
| 104 // mutations of the context chain within the function body and allows to | 104 // mutations of the context chain within the function body and allows to |
| 105 // change the current {scope} and {context} during visitation. | 105 // change the current {scope} and {context} during visitation. |
| 106 class AstGraphBuilder::ContextScope BASE_EMBEDDED { | 106 class AstGraphBuilder::ContextScope BASE_EMBEDDED { |
| 107 public: | 107 public: |
| 108 ContextScope(AstGraphBuilder* owner, Scope* scope, Node* context) | 108 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context) |
| 109 : owner_(owner), | 109 : builder_(builder), |
| 110 next_(owner->execution_context()), | 110 outer_(builder->execution_context()), |
| 111 outer_(owner->current_context()), | 111 scope_(scope), |
| 112 scope_(scope) { | 112 context_(context) { |
| 113 owner_->set_execution_context(this); // Push. | 113 builder_->set_execution_context(this); // Push. |
| 114 owner_->set_current_context(context); | |
| 115 } | 114 } |
| 116 | 115 |
| 117 ~ContextScope() { | 116 ~ContextScope() { |
| 118 owner_->set_execution_context(next_); // Pop. | 117 builder_->set_execution_context(outer_); // Pop. |
| 119 owner_->set_current_context(outer_); | |
| 120 } | 118 } |
| 121 | 119 |
| 122 // Current scope during visitation. | 120 // Current scope during visitation. |
| 123 Scope* scope() const { return scope_; } | 121 Scope* scope() const { return scope_; } |
| 122 // Current context node during visitation. |
| 123 Node* context() const { return context_; } |
| 124 | 124 |
| 125 private: | 125 private: |
| 126 AstGraphBuilder* owner_; | 126 AstGraphBuilder* builder_; |
| 127 ContextScope* next_; | 127 ContextScope* outer_; |
| 128 Node* outer_; | |
| 129 Scope* scope_; | 128 Scope* scope_; |
| 129 Node* context_; |
| 130 }; | 130 }; |
| 131 | 131 |
| 132 | 132 |
| 133 // Scoped class tracking control statements entered by the visitor. There are | 133 // Scoped class tracking control statements entered by the visitor. There are |
| 134 // different types of statements participating in this stack to properly track | 134 // different types of statements participating in this stack to properly track |
| 135 // local as well as non-local control flow: | 135 // local as well as non-local control flow: |
| 136 // - IterationStatement : Allows proper 'break' and 'continue' behavior. | 136 // - IterationStatement : Allows proper 'break' and 'continue' behavior. |
| 137 // - BreakableStatement : Allows 'break' from block and switch statements. | 137 // - BreakableStatement : Allows 'break' from block and switch statements. |
| 138 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. | 138 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. |
| 139 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. | 139 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. |
| 140 class AstGraphBuilder::ControlScope BASE_EMBEDDED { | 140 class AstGraphBuilder::ControlScope BASE_EMBEDDED { |
| 141 public: | 141 public: |
| 142 ControlScope(AstGraphBuilder* builder, int stack_delta) | 142 ControlScope(AstGraphBuilder* builder, int stack_delta) |
| 143 : builder_(builder), | 143 : builder_(builder), |
| 144 next_(builder->execution_control()), | 144 outer_(builder->execution_control()), |
| 145 stack_delta_(stack_delta) { | 145 stack_delta_(stack_delta) { |
| 146 builder_->set_execution_control(this); // Push. | 146 builder_->set_execution_control(this); // Push. |
| 147 } | 147 } |
| 148 | 148 |
| 149 virtual ~ControlScope() { | 149 virtual ~ControlScope() { |
| 150 builder_->set_execution_control(next_); // Pop. | 150 builder_->set_execution_control(outer_); // Pop. |
| 151 } | 151 } |
| 152 | 152 |
| 153 // Either 'break' or 'continue' to the target statement. | 153 // Either 'break' or 'continue' to the target statement. |
| 154 void BreakTo(BreakableStatement* target); | 154 void BreakTo(BreakableStatement* target); |
| 155 void ContinueTo(BreakableStatement* target); | 155 void ContinueTo(BreakableStatement* target); |
| 156 | 156 |
| 157 // Either 'return' or 'throw' the given value. | 157 // Either 'return' or 'throw' the given value. |
| 158 void ReturnValue(Node* return_value); | 158 void ReturnValue(Node* return_value); |
| 159 void ThrowValue(Node* exception_value); | 159 void ThrowValue(Node* exception_value); |
| 160 | 160 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 186 } | 186 } |
| 187 return false; | 187 return false; |
| 188 } | 188 } |
| 189 | 189 |
| 190 Environment* environment() { return builder_->environment(); } | 190 Environment* environment() { return builder_->environment(); } |
| 191 AstGraphBuilder* builder() const { return builder_; } | 191 AstGraphBuilder* builder() const { return builder_; } |
| 192 int stack_delta() const { return stack_delta_; } | 192 int stack_delta() const { return stack_delta_; } |
| 193 | 193 |
| 194 private: | 194 private: |
| 195 AstGraphBuilder* builder_; | 195 AstGraphBuilder* builder_; |
| 196 ControlScope* next_; | 196 ControlScope* outer_; |
| 197 int stack_delta_; | 197 int stack_delta_; |
| 198 }; | 198 }; |
| 199 | 199 |
| 200 | 200 |
| 201 // Helper class for a try-finally control scope. It can record intercepted | 201 // Helper class for a try-finally control scope. It can record intercepted |
| 202 // control-flow commands that cause entry into a finally-block, and re-apply | 202 // control-flow commands that cause entry into a finally-block, and re-apply |
| 203 // them after again leaving that block. Special tokens are used to identify | 203 // them after again leaving that block. Special tokens are used to identify |
| 204 // paths going through the finally-block to dispatch after leaving the block. | 204 // paths going through the finally-block to dispatch after leaving the block. |
| 205 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { | 205 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
| 206 public: | 206 public: |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 : local_zone_(local_zone), | 373 : local_zone_(local_zone), |
| 374 info_(info), | 374 info_(info), |
| 375 jsgraph_(jsgraph), | 375 jsgraph_(jsgraph), |
| 376 environment_(nullptr), | 376 environment_(nullptr), |
| 377 ast_context_(nullptr), | 377 ast_context_(nullptr), |
| 378 globals_(0, local_zone), | 378 globals_(0, local_zone), |
| 379 execution_control_(nullptr), | 379 execution_control_(nullptr), |
| 380 execution_context_(nullptr), | 380 execution_context_(nullptr), |
| 381 input_buffer_size_(0), | 381 input_buffer_size_(0), |
| 382 input_buffer_(nullptr), | 382 input_buffer_(nullptr), |
| 383 current_context_(nullptr), | |
| 384 exit_control_(nullptr), | 383 exit_control_(nullptr), |
| 385 loop_assignment_analysis_(loop) { | 384 loop_assignment_analysis_(loop) { |
| 386 InitializeAstVisitor(info->isolate(), local_zone); | 385 InitializeAstVisitor(info->isolate(), local_zone); |
| 387 } | 386 } |
| 388 | 387 |
| 389 | 388 |
| 390 Node* AstGraphBuilder::GetFunctionClosure() { | 389 Node* AstGraphBuilder::GetFunctionClosure() { |
| 391 if (!function_closure_.is_set()) { | 390 if (!function_closure_.is_set()) { |
| 392 const Operator* op = | 391 const Operator* op = |
| 393 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); | 392 common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 424 Environment env(this, scope, graph()->start()); | 423 Environment env(this, scope, graph()->start()); |
| 425 set_environment(&env); | 424 set_environment(&env); |
| 426 | 425 |
| 427 if (info()->is_osr()) { | 426 if (info()->is_osr()) { |
| 428 // Use OSR normal entry as the start of the top-level environment. | 427 // Use OSR normal entry as the start of the top-level environment. |
| 429 // It will be replaced with {Dead} after typing and optimizations. | 428 // It will be replaced with {Dead} after typing and optimizations. |
| 430 NewNode(common()->OsrNormalEntry()); | 429 NewNode(common()->OsrNormalEntry()); |
| 431 } | 430 } |
| 432 | 431 |
| 433 // Initialize the incoming context. | 432 // Initialize the incoming context. |
| 434 Node* outer_context = GetFunctionContext(); | 433 Node* incoming_context = GetFunctionContext(); |
| 435 set_current_context(outer_context); | 434 ContextScope incoming(this, scope, incoming_context); |
| 436 | 435 |
| 437 // Build receiver check for sloppy mode if necessary. | 436 // Build receiver check for sloppy mode if necessary. |
| 438 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 437 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
| 439 Node* original_receiver = env.Lookup(scope->receiver()); | 438 Node* original_receiver = env.Lookup(scope->receiver()); |
| 440 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 439 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
| 441 env.Bind(scope->receiver(), patched_receiver); | 440 env.Bind(scope->receiver(), patched_receiver); |
| 442 | 441 |
| 443 // Build node to initialize local function context. | 442 // Build node to initialize local function context. |
| 444 Node* closure = GetFunctionClosure(); | 443 Node* closure = GetFunctionClosure(); |
| 445 Node* inner_context = BuildLocalFunctionContext(outer_context, closure); | 444 Node* inner_context = BuildLocalFunctionContext(incoming_context, closure); |
| 446 | 445 |
| 447 // Push top-level function scope for the function body. | 446 // Push top-level function context for the function body. |
| 448 ContextScope top_context(this, scope, inner_context); | 447 ContextScope top_context(this, scope, inner_context); |
| 449 | 448 |
| 450 // Build the arguments object if it is used. | 449 // Build the arguments object if it is used. |
| 451 BuildArgumentsObject(scope->arguments()); | 450 BuildArgumentsObject(scope->arguments()); |
| 452 | 451 |
| 453 // Emit tracing call if requested to do so. | 452 // Emit tracing call if requested to do so. |
| 454 if (FLAG_trace) { | 453 if (FLAG_trace) { |
| 455 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0)); | 454 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0)); |
| 456 } | 455 } |
| 457 | 456 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 Node* AstGraphBuilder::AstTestContext::ConsumeValue() { | 647 Node* AstGraphBuilder::AstTestContext::ConsumeValue() { |
| 649 return environment()->Pop(); | 648 return environment()->Pop(); |
| 650 } | 649 } |
| 651 | 650 |
| 652 | 651 |
| 653 Scope* AstGraphBuilder::current_scope() const { | 652 Scope* AstGraphBuilder::current_scope() const { |
| 654 return execution_context_->scope(); | 653 return execution_context_->scope(); |
| 655 } | 654 } |
| 656 | 655 |
| 657 | 656 |
| 657 Node* AstGraphBuilder::current_context() const { |
| 658 return execution_context_->context(); |
| 659 } |
| 660 |
| 661 |
| 658 void AstGraphBuilder::ControlScope::PerformCommand(Command command, | 662 void AstGraphBuilder::ControlScope::PerformCommand(Command command, |
| 659 Statement* target, | 663 Statement* target, |
| 660 Node* value) { | 664 Node* value) { |
| 661 Environment* env = environment()->CopyAsUnreachable(); | 665 Environment* env = environment()->CopyAsUnreachable(); |
| 662 ControlScope* current = this; | 666 ControlScope* current = this; |
| 663 while (current != NULL) { | 667 while (current != NULL) { |
| 664 if (current->Execute(command, target, value)) break; | 668 if (current->Execute(command, target, value)) break; |
| 665 environment()->Drop(current->stack_delta()); | 669 environment()->Drop(current->stack_delta()); |
| 666 current = current->next_; | 670 current = current->outer_; |
| 667 } | 671 } |
| 668 builder()->set_environment(env); | 672 builder()->set_environment(env); |
| 669 DCHECK(current != NULL); // Always handled (unless stack is malformed). | 673 DCHECK(current != NULL); // Always handled (unless stack is malformed). |
| 670 } | 674 } |
| 671 | 675 |
| 672 | 676 |
| 673 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { | 677 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { |
| 674 PerformCommand(CMD_BREAK, stmt, nullptr); | 678 PerformCommand(CMD_BREAK, stmt, nullptr); |
| 675 } | 679 } |
| 676 | 680 |
| (...skipping 1724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2401 } | 2405 } |
| 2402 | 2406 |
| 2403 | 2407 |
| 2404 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { | 2408 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { |
| 2405 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 2409 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 2406 if (heap_slots <= 0) return context; | 2410 if (heap_slots <= 0) return context; |
| 2407 | 2411 |
| 2408 // Allocate a new local context. | 2412 // Allocate a new local context. |
| 2409 const Operator* op = javascript()->CreateFunctionContext(); | 2413 const Operator* op = javascript()->CreateFunctionContext(); |
| 2410 Node* local_context = NewNode(op, closure); | 2414 Node* local_context = NewNode(op, closure); |
| 2411 set_current_context(local_context); | |
| 2412 | 2415 |
| 2413 // Copy parameters into context if necessary. | 2416 // Copy parameters into context if necessary. |
| 2414 int num_parameters = info()->scope()->num_parameters(); | 2417 int num_parameters = info()->scope()->num_parameters(); |
| 2415 for (int i = 0; i < num_parameters; i++) { | 2418 for (int i = 0; i < num_parameters; i++) { |
| 2416 Variable* variable = info()->scope()->parameter(i); | 2419 Variable* variable = info()->scope()->parameter(i); |
| 2417 if (!variable->IsContextSlot()) continue; | 2420 if (!variable->IsContextSlot()) continue; |
| 2418 // Temporary parameter node. The parameter indices are shifted by 1 | 2421 // Temporary parameter node. The parameter indices are shifted by 1 |
| 2419 // (receiver is parameter index -1 but environment index 0). | 2422 // (receiver is parameter index -1 but environment index 0). |
| 2420 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); | 2423 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); |
| 2421 // Context variable (at bottom of the context chain). | 2424 // Context variable (at bottom of the context chain). |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3120 Node* dead_node = graph()->NewNode(common()->Dead()); | 3123 Node* dead_node = graph()->NewNode(common()->Dead()); |
| 3121 dead_control_.set(dead_node); | 3124 dead_control_.set(dead_node); |
| 3122 return dead_node; | 3125 return dead_node; |
| 3123 } | 3126 } |
| 3124 return dead_control_.get(); | 3127 return dead_control_.get(); |
| 3125 } | 3128 } |
| 3126 | 3129 |
| 3127 } // namespace compiler | 3130 } // namespace compiler |
| 3128 } // namespace internal | 3131 } // namespace internal |
| 3129 } // namespace v8 | 3132 } // namespace v8 |
| OLD | NEW |