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 |