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

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

Issue 873423004: First stab at try-catch and try-finally in TurboFan. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Whitespace change. Created 5 years, 10 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') | src/compiler/control-builders.h » ('j') | 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/linkage.h" 10 #include "src/compiler/linkage.h"
11 #include "src/compiler/machine-operator.h" 11 #include "src/compiler/machine-operator.h"
12 #include "src/compiler/node-matchers.h" 12 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/node-properties.h" 13 #include "src/compiler/node-properties.h"
14 #include "src/compiler/operator-properties.h" 14 #include "src/compiler/operator-properties.h"
15 #include "src/full-codegen.h" 15 #include "src/full-codegen.h"
16 #include "src/parser.h" 16 #include "src/parser.h"
17 #include "src/scopes.h" 17 #include "src/scopes.h"
18 18
19 namespace v8 { 19 namespace v8 {
20 namespace internal { 20 namespace internal {
21 namespace compiler { 21 namespace compiler {
22 22
23 23
24 // Scoped class tracking control statements entered by the visitor. There are
25 // different types of statements participating in this stack to properly track
26 // local as well as non-local control flow:
27 // - IterationStatement : Allows proper 'break' and 'continue' behavior.
28 // - BreakableStatement : Allows 'break' from block and switch statements.
29 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges.
30 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
31 class AstGraphBuilder::ControlScope BASE_EMBEDDED {
32 public:
33 ControlScope(AstGraphBuilder* builder, int stack_delta)
34 : builder_(builder),
35 next_(builder->execution_control()),
36 stack_delta_(stack_delta) {
37 builder_->set_execution_control(this); // Push.
38 }
39
40 virtual ~ControlScope() {
41 builder_->set_execution_control(next_); // Pop.
42 }
43
44 // Either 'break' or 'continue' to the target statement.
45 void BreakTo(BreakableStatement* target);
46 void ContinueTo(BreakableStatement* target);
47
48 // Either 'return' or 'throw' the given value.
49 void ReturnValue(Node* return_value);
50 void ThrowValue(Node* exception_value);
51
52 class DeferredCommands;
53
54 protected:
55 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
56
57 // Performs one of the above commands on this stack of control scopes. This
58 // walks through the stack giving each scope a chance to execute or defer the
59 // given command by overriding the {Execute} method appropriately. Note that
60 // this also drops extra operands from the environment for each skipped scope.
61 void PerformCommand(Command cmd, Statement* target, Node* value);
62
63 // Interface to execute a given command in this scope. Returning {true} here
64 // indicates successful execution whereas {false} requests to skip scope.
65 virtual bool Execute(Command cmd, Statement* target, Node* value);
66
67 Environment* environment() { return builder_->environment(); }
68 AstGraphBuilder* builder() const { return builder_; }
69 int stack_delta() const { return stack_delta_; }
70
71 private:
72 AstGraphBuilder* builder_;
73 ControlScope* next_;
74 int stack_delta_;
75 };
76
77
78 // Control scope implementation for a BreakableStatement.
79 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
80 public:
81 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
82 ControlBuilder* control)
83 : ControlScope(owner, 0), target_(target), control_(control) {}
84
85 protected:
86 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE;
titzer 2015/02/03 09:50:13 Would be nice to have the bodies inline here :-)
Michael Starzinger 2015/02/03 09:59:21 Done. You slight preference is my command. :)
87
88 private:
89 BreakableStatement* target_;
90 ControlBuilder* control_;
91 };
92
93
94 // Control scope implementation for an IterationStatement.
95 class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
96 public:
97 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
98 LoopBuilder* control, int stack_delta)
99 : ControlScope(owner, stack_delta), target_(target), control_(control) {}
100
101 protected:
102 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE;
103
104 private:
105 BreakableStatement* target_;
106 LoopBuilder* control_;
107 };
108
109
110 // Control scope implementation for a TryCatchStatement.
111 class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
112 public:
113 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control)
114 : ControlScope(owner, 0), control_(control) {}
115
116 protected:
117 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE;
118
119 private:
120 TryCatchBuilder* control_;
121 };
122
123
124 // Control scope implementation for a TryFinallyStatement.
125 class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
126 public:
127 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands,
128 TryFinallyBuilder* control)
129 : ControlScope(owner, 0), commands_(commands), control_(control) {}
130
131 protected:
132 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE;
133
134 private:
135 DeferredCommands* commands_;
136 TryFinallyBuilder* control_;
137 };
138
139
24 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, 140 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
25 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) 141 JSGraph* jsgraph, LoopAssignmentAnalysis* loop)
26 : local_zone_(local_zone), 142 : local_zone_(local_zone),
27 info_(info), 143 info_(info),
28 jsgraph_(jsgraph), 144 jsgraph_(jsgraph),
29 environment_(nullptr), 145 environment_(nullptr),
30 ast_context_(nullptr), 146 ast_context_(nullptr),
31 globals_(0, local_zone), 147 globals_(0, local_zone),
32 breakable_(nullptr), 148 execution_control_(nullptr),
33 execution_context_(nullptr), 149 execution_context_(nullptr),
34 input_buffer_size_(0), 150 input_buffer_size_(0),
35 input_buffer_(nullptr), 151 input_buffer_(nullptr),
36 current_context_(nullptr), 152 current_context_(nullptr),
37 exit_control_(nullptr), 153 exit_control_(nullptr),
38 loop_assignment_analysis_(loop) { 154 loop_assignment_analysis_(loop) {
39 InitializeAstVisitor(info->isolate(), local_zone); 155 InitializeAstVisitor(info->isolate(), local_zone);
40 } 156 }
41 157
42 158
(...skipping 20 matching lines...) Expand all
63 179
64 180
65 bool AstGraphBuilder::CreateGraph() { 181 bool AstGraphBuilder::CreateGraph() {
66 Scope* scope = info()->scope(); 182 Scope* scope = info()->scope();
67 DCHECK(graph() != NULL); 183 DCHECK(graph() != NULL);
68 184
69 // Set up the basic structure of the graph. 185 // Set up the basic structure of the graph.
70 int parameter_count = info()->num_parameters(); 186 int parameter_count = info()->num_parameters();
71 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); 187 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count)));
72 188
73 Node* start = graph()->start(); 189 // Initialize control scope.
190 ControlScope control(this, 0);
191
74 // Initialize the top-level environment. 192 // Initialize the top-level environment.
75 Environment env(this, scope, start); 193 Environment env(this, scope, graph()->start());
76 set_environment(&env); 194 set_environment(&env);
77 195
78 if (info()->is_osr()) { 196 if (info()->is_osr()) {
79 // Use OSR normal entry as the start of the top-level environment. 197 // Use OSR normal entry as the start of the top-level environment.
80 // It will be replaced with {Dead} after typing and optimizations. 198 // It will be replaced with {Dead} after typing and optimizations.
81 NewNode(common()->OsrNormalEntry()); 199 NewNode(common()->OsrNormalEntry());
82 } 200 }
83 201
84 // Initialize the incoming context. 202 // Initialize the incoming context.
85 Node* outer_context = GetFunctionContext(); 203 Node* outer_context = GetFunctionContext();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 if (HasStackOverflow()) return false; 241 if (HasStackOverflow()) return false;
124 242
125 // Emit tracing call if requested to do so. 243 // Emit tracing call if requested to do so.
126 if (FLAG_trace) { 244 if (FLAG_trace) {
127 // TODO(mstarzinger): Only traces implicit return. 245 // TODO(mstarzinger): Only traces implicit return.
128 Node* return_value = jsgraph()->UndefinedConstant(); 246 Node* return_value = jsgraph()->UndefinedConstant();
129 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); 247 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
130 } 248 }
131 249
132 // Return 'undefined' in case we can fall off the end. 250 // Return 'undefined' in case we can fall off the end.
133 Node* control = NewNode(common()->Return(), jsgraph()->UndefinedConstant()); 251 BuildReturn(jsgraph()->UndefinedConstant());
134 UpdateControlDependencyToLeaveFunction(control);
135 252
136 // Finish the basic structure of the graph. 253 // Finish the basic structure of the graph.
137 environment()->UpdateControlDependency(exit_control()); 254 environment()->UpdateControlDependency(exit_control());
138 graph()->SetEnd(NewNode(common()->End())); 255 graph()->SetEnd(NewNode(common()->End()));
139 256
140 return true; 257 return true;
141 } 258 }
142 259
143 260
144 // Left-hand side can only be a property, a global or a variable slot. 261 // Left-hand side can only be a property, a global or a variable slot.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 Node* AstGraphBuilder::AstValueContext::ConsumeValue() { 412 Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
296 return environment()->Pop(); 413 return environment()->Pop();
297 } 414 }
298 415
299 416
300 Node* AstGraphBuilder::AstTestContext::ConsumeValue() { 417 Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
301 return environment()->Pop(); 418 return environment()->Pop();
302 } 419 }
303 420
304 421
305 AstGraphBuilder::BreakableScope* AstGraphBuilder::BreakableScope::FindBreakable( 422 // Helper class for a try-finally control scope. It can record intercepted
306 BreakableStatement* target) { 423 // control-flow commands that cause entry into a finally-block, and re-apply
307 BreakableScope* current = this; 424 // them after again leaving that block. Special tokens are used to identify
308 while (current != NULL && current->target_ != target) { 425 // paths going through the finally-block to dispatch after leaving the block.
309 owner_->environment()->Drop(current->drop_extra_); 426 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
310 current = current->next_; 427 public:
428 explicit DeferredCommands(AstGraphBuilder* owner)
429 : owner_(owner), deferred_(owner->zone()) {}
430
431 // One recorded control-flow command.
432 struct Entry {
433 Command command; // The command type being applied on this path.
434 Statement* statement; // The target statement for the command or {NULL}.
435 Node* value; // The passed value node for the command or {NULL}.
436 Node* token; // A token identifying this particular path.
437 };
438
439 // Records a control-flow command while entering the finally-block. This also
440 // generates a new dispatch token that identifies one particular path.
441 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
442 Node* token = NewPathTokenForDeferredCommand();
443 deferred_.push_back({cmd, stmt, value, token});
444 return token;
311 } 445 }
312 DCHECK(current != NULL); // Always found (unless stack is malformed). 446
313 return current; 447 // Returns the dispatch token to be used to identify the implicit fall-through
448 // path at the end of a try-block into the corresponding finally-block.
449 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
450
451 // Applies all recorded control-flow commands after the finally-block again.
452 // This generates a dynamic dispatch on the token from the entry point.
453 void ApplyDeferredCommands(Node* token) {
454 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
455 dispatch.BeginSwitch();
456 for (size_t i = 0; i < deferred_.size(); ++i) {
457 Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
458 dispatch.BeginLabel(static_cast<int>(i), condition);
459 dispatch.EndLabel();
460 }
461 for (size_t i = 0; i < deferred_.size(); ++i) {
462 dispatch.BeginCase(static_cast<int>(i));
463 owner_->execution_control()->PerformCommand(
464 deferred_[i].command, deferred_[i].statement, deferred_[i].value);
465 dispatch.EndCase();
466 }
467 dispatch.EndSwitch();
468 }
469
470 protected:
471 Node* NewPathTokenForDeferredCommand() {
472 return owner_->jsgraph()->Constant(static_cast<int>(deferred_.size()));
473 }
474 Node* NewPathTokenForImplicitFallThrough() {
475 return owner_->jsgraph()->Constant(-1);
476 }
477 Node* NewPathDispatchCondition(Node* t1, Node* t2) {
478 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
479 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
480 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
481 }
482
483 private:
484 AstGraphBuilder* owner_;
485 ZoneVector<Entry> deferred_;
486 };
487
488
489 bool AstGraphBuilder::ControlScope::Execute(Command command, Statement* target,
490 Node* value) {
491 // For function-level control.
492 switch (command) {
493 case CMD_THROW:
494 builder()->BuildThrow(value);
495 return true;
496 case CMD_RETURN:
497 builder()->BuildReturn(value);
498 return true;
499 case CMD_BREAK:
500 case CMD_CONTINUE:
501 break;
502 }
503 return false;
314 } 504 }
315 505
316 506
317 void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) { 507 bool AstGraphBuilder::ControlScopeForBreakable::Execute(Command command,
318 FindBreakable(stmt)->control_->Break(); 508 Statement* target,
509 Node* value) {
510 if (target != target_) return false; // We are not the command target.
511 switch (command) {
512 case CMD_BREAK:
513 control_->Break();
514 return true;
515 case CMD_CONTINUE:
516 case CMD_THROW:
517 case CMD_RETURN:
518 break;
519 }
520 return false;
319 } 521 }
320 522
321 523
322 void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) { 524 bool AstGraphBuilder::ControlScopeForIteration::Execute(Command command,
323 FindBreakable(stmt)->control_->Continue(); 525 Statement* target,
526 Node* value) {
527 if (target != target_) return false; // We are not the command target.
528 switch (command) {
529 case CMD_BREAK:
530 control_->Break();
531 return true;
532 case CMD_CONTINUE:
533 control_->Continue();
534 return true;
535 case CMD_THROW:
536 case CMD_RETURN:
537 break;
538 }
539 return false;
324 } 540 }
325 541
326 542
543 bool AstGraphBuilder::ControlScopeForCatch::Execute(Command command,
544 Statement* target,
545 Node* value) {
546 switch (command) {
547 case CMD_THROW:
548 control_->Throw(value);
549 return true;
550 case CMD_BREAK:
551 case CMD_CONTINUE:
552 case CMD_RETURN:
553 break;
554 }
555 return false;
556 }
557
558
559 bool AstGraphBuilder::ControlScopeForFinally::Execute(Command cmd,
560 Statement* target,
561 Node* value) {
562 Node* token = commands_->RecordCommand(cmd, target, value);
563 control_->LeaveTry(token);
564 return true;
565 }
566
567
568 void AstGraphBuilder::ControlScope::PerformCommand(Command command,
569 Statement* target,
570 Node* value) {
571 Environment* env = environment()->CopyAsUnreachable();
572 ControlScope* current = this;
573 while (current != NULL) {
574 if (current->Execute(command, target, value)) break;
575 environment()->Drop(current->stack_delta());
576 current = current->next_;
577 }
578 // TODO(mstarzinger): Unconditionally kill environment once throw is control.
579 if (command != CMD_THROW) builder()->set_environment(env);
580 DCHECK(current != NULL); // Always handled (unless stack is malformed).
581 }
582
583
584 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
585 PerformCommand(CMD_BREAK, stmt, nullptr);
586 }
587
588
589 void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
590 PerformCommand(CMD_CONTINUE, stmt, nullptr);
591 }
592
593
594 void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
595 PerformCommand(CMD_RETURN, nullptr, return_value);
596 }
597
598
599 void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
600 PerformCommand(CMD_THROW, nullptr, exception_value);
601 }
602
603
327 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { 604 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
328 if (expr == NULL) { 605 if (expr == NULL) {
329 return environment()->Push(jsgraph()->NullConstant()); 606 return environment()->Push(jsgraph()->NullConstant());
330 } 607 }
331 VisitForValue(expr); 608 VisitForValue(expr);
332 } 609 }
333 610
334 611
335 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { 612 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
336 if (expr == NULL) { 613 if (expr == NULL) {
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 753
477 754
478 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); } 755 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }
479 756
480 757
481 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); } 758 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }
482 759
483 760
484 void AstGraphBuilder::VisitBlock(Block* stmt) { 761 void AstGraphBuilder::VisitBlock(Block* stmt) {
485 BlockBuilder block(this); 762 BlockBuilder block(this);
486 BreakableScope scope(this, stmt, &block, 0); 763 ControlScopeForBreakable scope(this, stmt, &block);
487 if (stmt->labels() != NULL) block.BeginBlock(); 764 if (stmt->labels() != NULL) block.BeginBlock();
488 if (stmt->scope() == NULL) { 765 if (stmt->scope() == NULL) {
489 // Visit statements in the same scope, no declarations. 766 // Visit statements in the same scope, no declarations.
490 VisitStatements(stmt->statements()); 767 VisitStatements(stmt->statements());
491 } else { 768 } else {
492 // Visit declarations and statements in a block scope. 769 // Visit declarations and statements in a block scope.
493 Node* context = BuildLocalBlockContext(stmt->scope()); 770 Node* context = BuildLocalBlockContext(stmt->scope());
494 ContextScope scope(this, stmt->scope(), context); 771 ContextScope scope(this, stmt->scope(), context);
495 VisitDeclarations(stmt->scope()->declarations()); 772 VisitDeclarations(stmt->scope()->declarations());
496 VisitStatements(stmt->statements()); 773 VisitStatements(stmt->statements());
(...skipping 24 matching lines...) Expand all
521 compare_if.If(condition); 798 compare_if.If(condition);
522 compare_if.Then(); 799 compare_if.Then();
523 Visit(stmt->then_statement()); 800 Visit(stmt->then_statement());
524 compare_if.Else(); 801 compare_if.Else();
525 Visit(stmt->else_statement()); 802 Visit(stmt->else_statement());
526 compare_if.End(); 803 compare_if.End();
527 } 804 }
528 805
529 806
530 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 807 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
531 Environment* env = environment()->CopyAsUnreachable(); 808 execution_control()->ContinueTo(stmt->target());
532 breakable()->ContinueTarget(stmt->target());
533 set_environment(env);
534 } 809 }
535 810
536 811
537 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 812 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
538 Environment* env = environment()->CopyAsUnreachable(); 813 execution_control()->BreakTo(stmt->target());
539 breakable()->BreakTarget(stmt->target());
540 set_environment(env);
541 } 814 }
542 815
543 816
544 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 817 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
545 VisitForValue(stmt->expression()); 818 VisitForValue(stmt->expression());
546 Node* result = environment()->Pop(); 819 Node* result = environment()->Pop();
547 Node* control = NewNode(common()->Return(), result); 820 execution_control()->ReturnValue(result);
548 UpdateControlDependencyToLeaveFunction(control);
549 } 821 }
550 822
551 823
552 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { 824 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
553 VisitForValue(stmt->expression()); 825 VisitForValue(stmt->expression());
554 Node* value = environment()->Pop(); 826 Node* value = environment()->Pop();
555 const Operator* op = javascript()->CreateWithContext(); 827 const Operator* op = javascript()->CreateWithContext();
556 Node* context = NewNode(op, value, GetFunctionClosure()); 828 Node* context = NewNode(op, value, GetFunctionClosure());
557 PrepareFrameState(context, stmt->EntryId()); 829 PrepareFrameState(context, stmt->EntryId());
558 ContextScope scope(this, stmt->scope(), context); 830 ContextScope scope(this, stmt->scope(), context);
559 Visit(stmt->statement()); 831 Visit(stmt->statement());
560 } 832 }
561 833
562 834
563 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 835 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
564 ZoneList<CaseClause*>* clauses = stmt->cases(); 836 ZoneList<CaseClause*>* clauses = stmt->cases();
565 SwitchBuilder compare_switch(this, clauses->length()); 837 SwitchBuilder compare_switch(this, clauses->length());
566 BreakableScope scope(this, stmt, &compare_switch, 0); 838 ControlScopeForBreakable scope(this, stmt, &compare_switch);
567 compare_switch.BeginSwitch(); 839 compare_switch.BeginSwitch();
568 int default_index = -1; 840 int default_index = -1;
569 841
570 // Keep the switch value on the stack until a case matches. 842 // Keep the switch value on the stack until a case matches.
571 VisitForValue(stmt->tag()); 843 VisitForValue(stmt->tag());
572 Node* tag = environment()->Top(); 844 Node* tag = environment()->Top();
573 845
574 // Iterate over all cases and create nodes for label comparison. 846 // Iterate over all cases and create nodes for label comparison.
575 for (int i = 0; i < clauses->length(); i++) { 847 for (int i = 0; i < clauses->length(); i++) {
576 CaseClause* clause = clauses->at(i); 848 CaseClause* clause = clauses->at(i);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 Node* condition = environment()->Pop(); 1081 Node* condition = environment()->Pop();
810 for_loop.BreakWhen(condition); 1082 for_loop.BreakWhen(condition);
811 VisitForEffect(stmt->assign_each()); 1083 VisitForEffect(stmt->assign_each());
812 VisitIterationBody(stmt, &for_loop, 0); 1084 VisitIterationBody(stmt, &for_loop, 0);
813 for_loop.EndBody(); 1085 for_loop.EndBody();
814 for_loop.EndLoop(); 1086 for_loop.EndLoop();
815 } 1087 }
816 1088
817 1089
818 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 1090 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
819 // TODO(turbofan): Implement try-catch here. 1091 TryCatchBuilder try_control(this);
820 SetStackOverflow(); 1092
1093 // Evaluate the try-block inside a control scope. This simulates a handler
1094 // that is intercepting 'throw' control commands.
1095 try_control.BeginTry();
1096 {
1097 ControlScopeForCatch scope(this, &try_control);
1098 Visit(stmt->try_block());
1099 }
1100 try_control.EndTry();
1101
1102 // Create a catch scope that binds the exception.
1103 Node* exception = try_control.GetExceptionNode();
1104 if (exception == NULL) exception = jsgraph()->NullConstant();
1105 Unique<String> name = MakeUnique(stmt->variable()->name());
1106 const Operator* op = javascript()->CreateCatchContext(name);
1107 Node* context = NewNode(op, exception, GetFunctionClosure());
1108 PrepareFrameState(context, BailoutId::None());
1109 ContextScope scope(this, stmt->scope(), context);
1110 DCHECK(stmt->scope()->declarations()->is_empty());
1111
1112 // Evaluate the catch-block.
1113 Visit(stmt->catch_block());
1114 try_control.EndCatch();
1115
1116 // TODO(mstarzinger): Remove bailout once everything works.
1117 if (!FLAG_turbo_exceptions) SetStackOverflow();
821 } 1118 }
822 1119
823 1120
824 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1121 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
825 // TODO(turbofan): Implement try-catch here. 1122 TryFinallyBuilder try_control(this);
826 SetStackOverflow(); 1123
1124 // We keep a record of all paths that enter the finally-block to be able to
1125 // dispatch to the correct continuation point after the statements in the
1126 // finally-block have been evaluated.
1127 //
1128 // The try-finally construct can enter the finally-block in three ways:
1129 // 1. By exiting the try-block normally, falling through at the end.
1130 // 2. By exiting the try-block with a function-local control flow transfer
1131 // (i.e. through break/continue/return statements).
1132 // 3. By exiting the try-block with a thrown exception.
1133 ControlScope::DeferredCommands* commands =
1134 new (zone()) ControlScope::DeferredCommands(this);
1135
1136 // Evaluate the try-block inside a control scope. This simulates a handler
1137 // that is intercepting all control commands.
1138 try_control.BeginTry();
1139 {
1140 ControlScopeForFinally scope(this, commands, &try_control);
1141 Visit(stmt->try_block());
1142 }
1143 try_control.EndTry(commands->GetFallThroughToken());
1144
1145 // Evaluate the finally-block.
1146 Visit(stmt->finally_block());
1147 try_control.EndFinally();
1148
1149 // Dynamic dispatch after the finally-block.
1150 Node* token = try_control.GetDispatchTokenNode();
1151 commands->ApplyDeferredCommands(token);
1152
1153 // TODO(mstarzinger): Remove bailout once everything works.
1154 if (!FLAG_turbo_exceptions) SetStackOverflow();
827 } 1155 }
828 1156
829 1157
830 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 1158 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
831 // TODO(turbofan): Do we really need a separate reloc-info for this? 1159 // TODO(turbofan): Do we really need a separate reloc-info for this?
832 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); 1160 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0));
833 PrepareFrameState(node, stmt->DebugBreakId()); 1161 PrepareFrameState(node, stmt->DebugBreakId());
834 } 1162 }
835 1163
836 1164
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 void AstGraphBuilder::VisitYield(Yield* expr) { 1708 void AstGraphBuilder::VisitYield(Yield* expr) {
1381 // TODO(turbofan): Implement yield here. 1709 // TODO(turbofan): Implement yield here.
1382 SetStackOverflow(); 1710 SetStackOverflow();
1383 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); 1711 ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1384 } 1712 }
1385 1713
1386 1714
1387 void AstGraphBuilder::VisitThrow(Throw* expr) { 1715 void AstGraphBuilder::VisitThrow(Throw* expr) {
1388 VisitForValue(expr->exception()); 1716 VisitForValue(expr->exception());
1389 Node* exception = environment()->Pop(); 1717 Node* exception = environment()->Pop();
1390 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1); 1718 if (FLAG_turbo_exceptions) {
1391 Node* value = NewNode(op, exception); 1719 execution_control()->ThrowValue(exception);
1392 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1720 ast_context()->ProduceValue(exception);
1393 ast_context()->ProduceValue(value); 1721 } else {
1722 // TODO(mstarzinger): Temporary workaround for bailout-id for debugger.
1723 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
1724 Node* value = NewNode(op, exception);
1725 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1726 ast_context()->ProduceValue(value);
1727 }
1394 } 1728 }
1395 1729
1396 1730
1397 void AstGraphBuilder::VisitProperty(Property* expr) { 1731 void AstGraphBuilder::VisitProperty(Property* expr) {
1398 Node* value; 1732 Node* value;
1399 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); 1733 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
1400 if (expr->key()->IsPropertyName()) { 1734 if (expr->key()->IsPropertyName()) {
1401 VisitForValue(expr->obj()); 1735 VisitForValue(expr->obj());
1402 Node* object = environment()->Pop(); 1736 Node* object = environment()->Pop();
1403 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); 1737 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName());
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 } 2159 }
1826 2160
1827 2161
1828 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { 2162 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
1829 if (stmt == NULL) return; 2163 if (stmt == NULL) return;
1830 Visit(stmt); 2164 Visit(stmt);
1831 } 2165 }
1832 2166
1833 2167
1834 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, 2168 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
1835 LoopBuilder* loop, int drop_extra) { 2169 LoopBuilder* loop, int stack_delta) {
1836 BreakableScope scope(this, stmt, loop, drop_extra); 2170 ControlScopeForIteration scope(this, stmt, loop, stack_delta);
1837 Visit(stmt->body()); 2171 Visit(stmt->body());
1838 } 2172 }
1839 2173
1840 2174
1841 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { 2175 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
1842 Node* value; 2176 Node* value;
1843 if (expr->expression()->IsVariableProxy()) { 2177 if (expr->expression()->IsVariableProxy()) {
1844 // Delete of an unqualified identifier is only allowed in classic mode but 2178 // Delete of an unqualified identifier is only allowed in classic mode but
1845 // deleting "this" is allowed in all language modes. 2179 // deleting "this" is allowed in all language modes.
1846 Variable* variable = expr->expression()->AsVariableProxy()->var(); 2180 Variable* variable = expr->expression()->AsVariableProxy()->var();
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
2353 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { 2687 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
2354 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. 2688 // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
2355 const Operator* op = 2689 const Operator* op =
2356 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0); 2690 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
2357 Node* call = NewNode(op); 2691 Node* call = NewNode(op);
2358 PrepareFrameState(call, bailout_id); 2692 PrepareFrameState(call, bailout_id);
2359 return call; 2693 return call;
2360 } 2694 }
2361 2695
2362 2696
2697 Node* AstGraphBuilder::BuildReturn(Node* return_value) {
2698 Node* control = NewNode(common()->Return(), return_value);
2699 UpdateControlDependencyToLeaveFunction(control);
2700 return control;
2701 }
2702
2703
2704 Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
2705 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
2706 Node* control = NewNode(op, exception_value);
2707 // TODO(mstarzinger): Thread through the correct bailout id to this point.
2708 // PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2709 PrepareFrameState(control, BailoutId::None());
2710 return control;
2711 }
2712
2713
2363 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { 2714 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
2364 const Operator* js_op; 2715 const Operator* js_op;
2365 switch (op) { 2716 switch (op) {
2366 case Token::BIT_OR: 2717 case Token::BIT_OR:
2367 js_op = javascript()->BitwiseOr(); 2718 js_op = javascript()->BitwiseOr();
2368 break; 2719 break;
2369 case Token::BIT_AND: 2720 case Token::BIT_AND:
2370 js_op = javascript()->BitwiseAnd(); 2721 js_op = javascript()->BitwiseAnd();
2371 break; 2722 break;
2372 case Token::BIT_XOR: 2723 case Token::BIT_XOR:
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
2682 Node* dead_node = graph()->NewNode(common()->Dead()); 3033 Node* dead_node = graph()->NewNode(common()->Dead());
2683 dead_control_.set(dead_node); 3034 dead_control_.set(dead_node);
2684 return dead_node; 3035 return dead_node;
2685 } 3036 }
2686 return dead_control_.get(); 3037 return dead_control_.get();
2687 } 3038 }
2688 3039
2689 } // namespace compiler 3040 } // namespace compiler
2690 } // namespace internal 3041 } // namespace internal
2691 } // namespace v8 3042 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698