Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 1045703003: [turbofan] Keep AstGraphBuilder context chain length in sync. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 105
106 // Scoped class tracking context objects created by the visitor. Represents 106 // Scoped class tracking context objects created by the visitor. Represents
107 // mutations of the context chain within the function body and allows to 107 // mutations of the context chain within the function body and allows to
108 // change the current {scope} and {context} during visitation. 108 // change the current {scope} and {context} during visitation.
109 class AstGraphBuilder::ContextScope BASE_EMBEDDED { 109 class AstGraphBuilder::ContextScope BASE_EMBEDDED {
110 public: 110 public:
111 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context) 111 ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
112 : builder_(builder), 112 : builder_(builder),
113 outer_(builder->execution_context()), 113 outer_(builder->execution_context()),
114 scope_(scope), 114 scope_(scope),
115 depth_(builder_->environment()->ContextStackDepth()) { 115 depth_(builder_->environment()->context_chain_length()) {
116 builder_->environment()->PushContext(context); // Push. 116 builder_->environment()->PushContext(context); // Push.
117 builder_->set_execution_context(this); 117 builder_->set_execution_context(this);
118 } 118 }
119 119
120 ~ContextScope() { 120 ~ContextScope() {
121 builder_->set_execution_context(outer_); // Pop. 121 builder_->set_execution_context(outer_); // Pop.
122 builder_->environment()->PopContext(); 122 builder_->environment()->PopContext();
123 CHECK_EQ(depth_, builder_->environment()->ContextStackDepth()); 123 CHECK_EQ(depth_, builder_->environment()->context_chain_length());
124 } 124 }
125 125
126 // Current scope during visitation. 126 // Current scope during visitation.
127 Scope* scope() const { return scope_; } 127 Scope* scope() const { return scope_; }
128 128
129 private: 129 private:
130 AstGraphBuilder* builder_; 130 AstGraphBuilder* builder_;
131 ContextScope* outer_; 131 ContextScope* outer_;
132 Scope* scope_; 132 Scope* scope_;
133 int depth_; 133 int depth_;
134 }; 134 };
135 135
136 136
137 // Scoped class tracking control statements entered by the visitor. There are 137 // Scoped class tracking control statements entered by the visitor. There are
138 // different types of statements participating in this stack to properly track 138 // different types of statements participating in this stack to properly track
139 // local as well as non-local control flow: 139 // local as well as non-local control flow:
140 // - IterationStatement : Allows proper 'break' and 'continue' behavior. 140 // - IterationStatement : Allows proper 'break' and 'continue' behavior.
141 // - BreakableStatement : Allows 'break' from block and switch statements. 141 // - BreakableStatement : Allows 'break' from block and switch statements.
142 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. 142 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges.
143 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. 143 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
144 class AstGraphBuilder::ControlScope BASE_EMBEDDED { 144 class AstGraphBuilder::ControlScope BASE_EMBEDDED {
145 public: 145 public:
146 explicit ControlScope(AstGraphBuilder* builder) 146 explicit ControlScope(AstGraphBuilder* builder)
147 : builder_(builder), 147 : builder_(builder),
148 outer_(builder->execution_control()), 148 outer_(builder->execution_control()),
149 context_length_(builder->environment()->context_chain_length()),
149 stack_height_(builder->environment()->stack_height()) { 150 stack_height_(builder->environment()->stack_height()) {
150 builder_->set_execution_control(this); // Push. 151 builder_->set_execution_control(this); // Push.
151 } 152 }
152 153
153 virtual ~ControlScope() { 154 virtual ~ControlScope() {
154 builder_->set_execution_control(outer_); // Pop. 155 builder_->set_execution_control(outer_); // Pop.
155 } 156 }
156 157
157 // Either 'break' or 'continue' to the target statement. 158 // Either 'break' or 'continue' to the target statement.
158 void BreakTo(BreakableStatement* target); 159 void BreakTo(BreakableStatement* target);
(...skipping 27 matching lines...) Expand all
186 return true; 187 return true;
187 case CMD_BREAK: 188 case CMD_BREAK:
188 case CMD_CONTINUE: 189 case CMD_CONTINUE:
189 break; 190 break;
190 } 191 }
191 return false; 192 return false;
192 } 193 }
193 194
194 Environment* environment() { return builder_->environment(); } 195 Environment* environment() { return builder_->environment(); }
195 AstGraphBuilder* builder() const { return builder_; } 196 AstGraphBuilder* builder() const { return builder_; }
197 int context_length() const { return context_length_; }
196 int stack_height() const { return stack_height_; } 198 int stack_height() const { return stack_height_; }
197 199
198 private: 200 private:
199 AstGraphBuilder* builder_; 201 AstGraphBuilder* builder_;
200 ControlScope* outer_; 202 ControlScope* outer_;
203 int context_length_;
201 int stack_height_; 204 int stack_height_;
202 }; 205 };
203 206
204 207
205 // Helper class for a try-finally control scope. It can record intercepted 208 // Helper class for a try-finally control scope. It can record intercepted
206 // control-flow commands that cause entry into a finally-block, and re-apply 209 // control-flow commands that cause entry into a finally-block, and re-apply
207 // them after again leaving that block. Special tokens are used to identify 210 // them after again leaving that block. Special tokens are used to identify
208 // paths going through the finally-block to dispatch after leaving the block. 211 // paths going through the finally-block to dispatch after leaving the block.
209 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { 212 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
210 public: 213 public:
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 DCHECK(graph() != NULL); 446 DCHECK(graph() != NULL);
444 447
445 // Set up the basic structure of the graph. 448 // Set up the basic structure of the graph.
446 int parameter_count = info()->num_parameters(); 449 int parameter_count = info()->num_parameters();
447 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); 450 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count)));
448 451
449 // Initialize the top-level environment. 452 // Initialize the top-level environment.
450 Environment env(this, scope, graph()->start()); 453 Environment env(this, scope, graph()->start());
451 set_environment(&env); 454 set_environment(&env);
452 455
453 // Initialize control scope.
454 ControlScope control(this);
455
456 if (info()->is_osr()) { 456 if (info()->is_osr()) {
457 // Use OSR normal entry as the start of the top-level environment. 457 // Use OSR normal entry as the start of the top-level environment.
458 // It will be replaced with {Dead} after typing and optimizations. 458 // It will be replaced with {Dead} after typing and optimizations.
459 NewNode(common()->OsrNormalEntry()); 459 NewNode(common()->OsrNormalEntry());
460 } 460 }
461 461
462 // Initialize the incoming context. 462 // Initialize the incoming context.
463 CreateFunctionContext(constant_context); 463 CreateFunctionContext(constant_context);
464 ContextScope incoming(this, scope, function_context_.get()); 464 ContextScope incoming(this, scope, function_context_.get());
465 465
466 // Initialize control scope.
467 ControlScope control(this);
468
466 // Build receiver check for sloppy mode if necessary. 469 // Build receiver check for sloppy mode if necessary.
467 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? 470 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
468 Node* original_receiver = env.Lookup(scope->receiver()); 471 Node* original_receiver = env.Lookup(scope->receiver());
469 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); 472 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
470 env.Bind(scope->receiver(), patched_receiver); 473 env.Bind(scope->receiver(), patched_receiver);
471 474
472 // Build function context only if there are context allocated variables. 475 // Build function context only if there are context allocated variables.
473 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 476 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
474 if (heap_slots > 0) { 477 if (heap_slots > 0) {
475 // Push a new inner context scope for the function. 478 // Push a new inner context scope for the function.
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 return environment()->Context(); 809 return environment()->Context();
807 } 810 }
808 811
809 812
810 void AstGraphBuilder::ControlScope::PerformCommand(Command command, 813 void AstGraphBuilder::ControlScope::PerformCommand(Command command,
811 Statement* target, 814 Statement* target,
812 Node* value) { 815 Node* value) {
813 Environment* env = environment()->CopyAsUnreachable(); 816 Environment* env = environment()->CopyAsUnreachable();
814 ControlScope* current = this; 817 ControlScope* current = this;
815 while (current != NULL) { 818 while (current != NULL) {
816 environment()->Trim(current->stack_height()); 819 environment()->TrimStack(current->stack_height());
820 environment()->TrimContextChain(current->context_length());
817 if (current->Execute(command, target, value)) break; 821 if (current->Execute(command, target, value)) break;
818 current = current->outer_; 822 current = current->outer_;
819 } 823 }
820 builder()->set_environment(env); 824 builder()->set_environment(env);
821 DCHECK(current != NULL); // Always handled (unless stack is malformed). 825 DCHECK(current != NULL); // Always handled (unless stack is malformed).
822 } 826 }
823 827
824 828
825 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { 829 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
826 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant()); 830 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
(...skipping 2500 matching lines...) Expand 10 before | Expand all | Expand 10 after
3327 if (exit_control() != NULL) { 3331 if (exit_control() != NULL) {
3328 exit = MergeControl(exit_control(), exit); 3332 exit = MergeControl(exit_control(), exit);
3329 } 3333 }
3330 environment()->MarkAsUnreachable(); 3334 environment()->MarkAsUnreachable();
3331 set_exit_control(exit); 3335 set_exit_control(exit);
3332 } 3336 }
3333 3337
3334 3338
3335 void AstGraphBuilder::Environment::Merge(Environment* other) { 3339 void AstGraphBuilder::Environment::Merge(Environment* other) {
3336 DCHECK(values_.size() == other->values_.size()); 3340 DCHECK(values_.size() == other->values_.size());
3337 // TODO(titzer): make context stack heights match. 3341 DCHECK(contexts_.size() == other->contexts_.size());
3338 DCHECK(contexts_.size() <= other->contexts_.size());
3339 3342
3340 // Nothing to do if the other environment is dead. 3343 // Nothing to do if the other environment is dead.
3341 if (other->IsMarkedAsUnreachable()) return; 3344 if (other->IsMarkedAsUnreachable()) return;
3342 3345
3343 // Resurrect a dead environment by copying the contents of the other one and 3346 // Resurrect a dead environment by copying the contents of the other one and
3344 // placing a singleton merge as the new control dependency. 3347 // placing a singleton merge as the new control dependency.
3345 if (this->IsMarkedAsUnreachable()) { 3348 if (this->IsMarkedAsUnreachable()) {
3346 Node* other_control = other->control_dependency_; 3349 Node* other_control = other->control_dependency_;
3347 Node* inputs[] = {other_control}; 3350 Node* inputs[] = {other_control};
3348 liveness_block_ = other->liveness_block_; 3351 liveness_block_ = other->liveness_block_;
3349 control_dependency_ = 3352 control_dependency_ =
3350 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); 3353 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
3351 effect_dependency_ = other->effect_dependency_; 3354 effect_dependency_ = other->effect_dependency_;
3352 values_ = other->values_; 3355 values_ = other->values_;
3353 // TODO(titzer): make context stack heights match.
3354 size_t min = std::min(contexts_.size(), other->contexts_.size());
3355 contexts_ = other->contexts_; 3356 contexts_ = other->contexts_;
3356 contexts_.resize(min, nullptr);
3357 return; 3357 return;
3358 } 3358 }
3359 3359
3360 // Record the merge for the local variable liveness calculation. 3360 // Record the merge for the local variable liveness calculation.
3361 // Unfortunately, we have to mirror the logic in the MergeControl method: 3361 // Unfortunately, we have to mirror the logic in the MergeControl method:
3362 // connect before merge or loop, or create a new merge otherwise. 3362 // connect before merge or loop, or create a new merge otherwise.
3363 if (FLAG_analyze_environment_liveness) { 3363 if (FLAG_analyze_environment_liveness) {
3364 if (GetControlDependency()->opcode() != IrOpcode::kLoop && 3364 if (GetControlDependency()->opcode() != IrOpcode::kLoop &&
3365 GetControlDependency()->opcode() != IrOpcode::kMerge) { 3365 GetControlDependency()->opcode() != IrOpcode::kMerge) {
3366 liveness_block_ = 3366 liveness_block_ =
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
3532 // Phi does not exist yet, introduce one. 3532 // Phi does not exist yet, introduce one.
3533 value = NewPhi(inputs, value, control); 3533 value = NewPhi(inputs, value, control);
3534 value->ReplaceInput(inputs - 1, other); 3534 value->ReplaceInput(inputs - 1, other);
3535 } 3535 }
3536 return value; 3536 return value;
3537 } 3537 }
3538 3538
3539 } // namespace compiler 3539 } // namespace compiler
3540 } // namespace internal 3540 } // namespace internal
3541 } // namespace v8 3541 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698