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/machine-operator.h" | 10 #include "src/compiler/machine-operator.h" |
11 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
13 #include "src/compiler/operator-properties.h" | 13 #include "src/compiler/operator-properties.h" |
14 #include "src/full-codegen.h" | 14 #include "src/full-codegen.h" |
15 #include "src/parser.h" | 15 #include "src/parser.h" |
16 #include "src/scopes.h" | 16 #include "src/scopes.h" |
17 | 17 |
18 namespace v8 { | 18 namespace v8 { |
19 namespace internal { | 19 namespace internal { |
20 namespace compiler { | 20 namespace compiler { |
21 | 21 |
22 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 22 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
23 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) | 23 JSGraph* jsgraph, LoopAssignmentAnalysis* loop) |
24 : StructuredGraphBuilder(jsgraph->isolate(), local_zone, jsgraph->graph(), | 24 : StructuredGraphBuilder(jsgraph->isolate(), local_zone, jsgraph->graph(), |
25 jsgraph->common()), | 25 jsgraph->common()), |
26 info_(info), | 26 info_(info), |
27 jsgraph_(jsgraph), | 27 jsgraph_(jsgraph), |
28 globals_(0, local_zone), | 28 globals_(0, local_zone), |
29 breakable_(NULL), | 29 execution_control_(NULL), |
30 execution_context_(NULL), | 30 execution_context_(NULL), |
31 loop_assignment_analysis_(loop) { | 31 loop_assignment_analysis_(loop) { |
32 InitializeAstVisitor(info->isolate(), local_zone); | 32 InitializeAstVisitor(info->isolate(), local_zone); |
33 } | 33 } |
34 | 34 |
35 | 35 |
36 Node* AstGraphBuilder::GetFunctionClosure() { | 36 Node* AstGraphBuilder::GetFunctionClosure() { |
37 if (!function_closure_.is_set()) { | 37 if (!function_closure_.is_set()) { |
38 // Parameter -1 is special for the function closure | 38 // Parameter -1 is special for the function closure |
39 const Operator* op = common()->Parameter(-1); | 39 const Operator* op = common()->Parameter(-1); |
(...skipping 16 matching lines...) Loading... | |
56 | 56 |
57 | 57 |
58 bool AstGraphBuilder::CreateGraph() { | 58 bool AstGraphBuilder::CreateGraph() { |
59 Scope* scope = info()->scope(); | 59 Scope* scope = info()->scope(); |
60 DCHECK(graph() != NULL); | 60 DCHECK(graph() != NULL); |
61 | 61 |
62 // Set up the basic structure of the graph. | 62 // Set up the basic structure of the graph. |
63 int parameter_count = info()->num_parameters(); | 63 int parameter_count = info()->num_parameters(); |
64 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); | 64 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); |
65 | 65 |
66 Node* start = graph()->start(); | 66 // Initialize control scope. |
67 ControlScope control(this, 0); | |
68 | |
67 // Initialize the top-level environment. | 69 // Initialize the top-level environment. |
68 Environment env(this, scope, start); | 70 Environment env(this, scope, graph()->start()); |
69 set_environment(&env); | 71 set_environment(&env); |
70 | 72 |
71 if (info()->is_osr()) { | 73 if (info()->is_osr()) { |
72 // Use OSR normal entry as the start of the top-level environment. | 74 // Use OSR normal entry as the start of the top-level environment. |
73 // It will be replaced with {Dead} after typing and optimizations. | 75 // It will be replaced with {Dead} after typing and optimizations. |
74 NewNode(common()->OsrNormalEntry()); | 76 NewNode(common()->OsrNormalEntry()); |
75 } | 77 } |
76 | 78 |
77 // Initialize the incoming context. | 79 // Initialize the incoming context. |
78 Node* outer_context = GetFunctionContext(); | 80 Node* outer_context = GetFunctionContext(); |
(...skipping 37 matching lines...) Loading... | |
116 if (HasStackOverflow()) return false; | 118 if (HasStackOverflow()) return false; |
117 | 119 |
118 // Emit tracing call if requested to do so. | 120 // Emit tracing call if requested to do so. |
119 if (FLAG_trace) { | 121 if (FLAG_trace) { |
120 // TODO(mstarzinger): Only traces implicit return. | 122 // TODO(mstarzinger): Only traces implicit return. |
121 Node* return_value = jsgraph()->UndefinedConstant(); | 123 Node* return_value = jsgraph()->UndefinedConstant(); |
122 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); | 124 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); |
123 } | 125 } |
124 | 126 |
125 // Return 'undefined' in case we can fall off the end. | 127 // Return 'undefined' in case we can fall off the end. |
126 Node* control = NewNode(common()->Return(), jsgraph()->UndefinedConstant()); | 128 BuildReturn(jsgraph()->UndefinedConstant()); |
127 UpdateControlDependencyToLeaveFunction(control); | |
128 | 129 |
129 // Finish the basic structure of the graph. | 130 // Finish the basic structure of the graph. |
130 environment()->UpdateControlDependency(exit_control()); | 131 environment()->UpdateControlDependency(exit_control()); |
131 graph()->SetEnd(NewNode(common()->End())); | 132 graph()->SetEnd(NewNode(common()->End())); |
132 | 133 |
133 return true; | 134 return true; |
134 } | 135 } |
135 | 136 |
136 | 137 |
137 // Left-hand side can only be a property, a global or a variable slot. | 138 // Left-hand side can only be a property, a global or a variable slot. |
(...skipping 146 matching lines...) Loading... | |
284 Node* AstGraphBuilder::AstValueContext::ConsumeValue() { | 285 Node* AstGraphBuilder::AstValueContext::ConsumeValue() { |
285 return environment()->Pop(); | 286 return environment()->Pop(); |
286 } | 287 } |
287 | 288 |
288 | 289 |
289 Node* AstGraphBuilder::AstTestContext::ConsumeValue() { | 290 Node* AstGraphBuilder::AstTestContext::ConsumeValue() { |
290 return environment()->Pop(); | 291 return environment()->Pop(); |
291 } | 292 } |
292 | 293 |
293 | 294 |
294 AstGraphBuilder::BreakableScope* AstGraphBuilder::BreakableScope::FindBreakable( | 295 // Helper class for a try-finally control scope. It can record intercepted |
295 BreakableStatement* target) { | 296 // control-flow commands that cause entry into a finally-block, and re-apply |
296 BreakableScope* current = this; | 297 // them after again leaving that block. Special tokens are used to identify |
297 while (current != NULL && current->target_ != target) { | 298 // paths going through the finally-block to dispatch after leaving the block. |
298 owner_->environment()->Drop(current->drop_extra_); | 299 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
299 current = current->next_; | 300 public: |
301 explicit DeferredCommands(AstGraphBuilder* owner) | |
302 : owner_(owner), deferred_(owner->zone()) {} | |
303 | |
304 // One recorded control-flow command. | |
305 struct Entry { | |
306 Command command; // The command type being applied on this path. | |
307 Statement* statement; // The target statement for the command or {NULL}. | |
308 Node* value; // The passed value node for the command or {NULL}. | |
309 Node* token; // A token identifying this particular path. | |
310 }; | |
311 | |
312 // Records a control-flow command while entering the finally-block. This also | |
313 // generates a new dispatch token that identifies one particular path. | |
314 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) { | |
315 Node* token = NewPathTokenForDeferredCommand(); | |
316 deferred_.push_back({cmd, stmt, value, token}); | |
317 return token; | |
300 } | 318 } |
301 DCHECK(current != NULL); // Always found (unless stack is malformed). | 319 |
302 return current; | 320 // Returns the dispatch token to be used to identify the implicit fall-through |
321 // path at the end of a try-block into the corresponding finally-block. | |
322 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); } | |
323 | |
324 // Applies all recorded control-flow commands after the finally-block again. | |
325 // This generates a dynamic dispatch on the token from the entry point. | |
326 void ApplyDeferredCommands(Node* token) { | |
327 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size())); | |
328 dispatch.BeginSwitch(); | |
329 for (size_t i = 0; i < deferred_.size(); ++i) { | |
330 Node* condition = NewPathDispatchCondition(token, deferred_[i].token); | |
331 dispatch.BeginLabel(static_cast<int>(i), condition); | |
332 dispatch.EndLabel(); | |
333 } | |
334 for (size_t i = 0; i < deferred_.size(); ++i) { | |
335 dispatch.BeginCase(static_cast<int>(i)); | |
336 owner_->execution_control()->PerformCommand( | |
337 deferred_[i].command, deferred_[i].statement, deferred_[i].value); | |
338 dispatch.EndCase(); | |
339 } | |
340 dispatch.EndSwitch(); | |
341 } | |
342 | |
343 protected: | |
344 Node* NewPathTokenForDeferredCommand() { | |
345 return owner_->jsgraph()->Constant(static_cast<int>(deferred_.size())); | |
346 } | |
347 Node* NewPathTokenForImplicitFallThrough() { | |
348 return owner_->jsgraph()->Constant(-1); | |
349 } | |
350 Node* NewPathDispatchCondition(Node* t1, Node* t2) { | |
351 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi | |
352 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch. | |
353 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2); | |
354 } | |
355 | |
356 private: | |
357 AstGraphBuilder* owner_; | |
358 ZoneVector<Entry> deferred_; | |
359 }; | |
360 | |
361 | |
362 bool AstGraphBuilder::ControlScope::Execute(Command command, Statement* target, | |
363 Node* value) { | |
364 // For function-level control. | |
365 switch (command) { | |
366 case CMD_THROW: | |
367 builder()->BuildThrow(value); | |
368 return true; | |
369 case CMD_RETURN: | |
370 builder()->BuildReturn(value); | |
371 return true; | |
372 case CMD_BREAK: | |
373 case CMD_CONTINUE: | |
374 break; | |
375 } | |
376 return false; | |
303 } | 377 } |
304 | 378 |
305 | 379 |
306 void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) { | 380 bool AstGraphBuilder::ControlScopeForBreakable::Execute(Command command, |
307 FindBreakable(stmt)->control_->Break(); | 381 Statement* target, |
382 Node* value) { | |
383 if (target != target_) return false; // We are not the command target. | |
384 switch (command) { | |
385 case CMD_BREAK: | |
386 control_->Break(); | |
387 return true; | |
388 case CMD_CONTINUE: | |
389 case CMD_THROW: | |
390 case CMD_RETURN: | |
391 break; | |
392 } | |
393 return false; | |
308 } | 394 } |
309 | 395 |
310 | 396 |
311 void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) { | 397 bool AstGraphBuilder::ControlScopeForIteration::Execute(Command command, |
312 FindBreakable(stmt)->control_->Continue(); | 398 Statement* target, |
399 Node* value) { | |
400 if (target != target_) return false; // We are not the command target. | |
401 switch (command) { | |
402 case CMD_BREAK: | |
403 control_->Break(); | |
404 return true; | |
405 case CMD_CONTINUE: | |
406 control_->Continue(); | |
407 return true; | |
408 case CMD_THROW: | |
409 case CMD_RETURN: | |
410 break; | |
411 } | |
412 return false; | |
313 } | 413 } |
314 | 414 |
315 | 415 |
416 bool AstGraphBuilder::ControlScopeForCatch::Execute(Command command, | |
417 Statement* target, | |
418 Node* value) { | |
419 switch (command) { | |
420 case CMD_THROW: | |
421 control_->Throw(value); | |
422 return true; | |
423 case CMD_BREAK: | |
424 case CMD_CONTINUE: | |
425 case CMD_RETURN: | |
426 break; | |
427 } | |
428 return false; | |
429 } | |
430 | |
431 | |
432 bool AstGraphBuilder::ControlScopeForFinally::Execute(Command cmd, | |
433 Statement* target, | |
434 Node* value) { | |
435 Node* token = commands_->RecordCommand(cmd, target, value); | |
436 control_->LeaveTry(token); | |
437 return true; | |
438 } | |
439 | |
440 | |
441 void AstGraphBuilder::ControlScope::PerformCommand(Command command, | |
442 Statement* target, | |
443 Node* value) { | |
444 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | |
445 ControlScope* current = this; | |
446 while (current != NULL) { | |
447 if (current->Execute(command, target, value)) break; | |
448 environment()->Drop(current->stack_delta()); | |
449 current = current->next_; | |
450 } | |
451 // TODO(mstarzinger): Unconditionally kill environment once throw is control. | |
452 if (command != CMD_THROW) builder()->set_environment(env); | |
453 DCHECK(current != NULL); // Always handled (unless stack is malformed). | |
454 } | |
455 | |
456 | |
457 void AstGraphBuilder::ControlScope::BreakTarget(BreakableStatement* stmt) { | |
titzer
2015/02/03 09:01:22
The names {BreakTarget} and {ContinueTarget} have
Michael Starzinger
2015/02/03 09:18:53
Done.
| |
458 PerformCommand(CMD_BREAK, stmt, nullptr); | |
459 } | |
460 | |
461 | |
462 void AstGraphBuilder::ControlScope::ContinueTarget(BreakableStatement* stmt) { | |
463 PerformCommand(CMD_CONTINUE, stmt, nullptr); | |
464 } | |
465 | |
466 | |
467 void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) { | |
468 PerformCommand(CMD_RETURN, nullptr, return_value); | |
469 } | |
470 | |
471 | |
472 void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) { | |
473 PerformCommand(CMD_THROW, nullptr, exception_value); | |
474 } | |
475 | |
476 | |
316 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { | 477 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { |
317 if (expr == NULL) { | 478 if (expr == NULL) { |
318 return environment()->Push(jsgraph()->NullConstant()); | 479 return environment()->Push(jsgraph()->NullConstant()); |
319 } | 480 } |
320 VisitForValue(expr); | 481 VisitForValue(expr); |
321 } | 482 } |
322 | 483 |
323 | 484 |
324 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { | 485 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { |
325 if (expr == NULL) { | 486 if (expr == NULL) { |
(...skipping 139 matching lines...) Loading... | |
465 | 626 |
466 | 627 |
467 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); } | 628 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); } |
468 | 629 |
469 | 630 |
470 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); } | 631 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); } |
471 | 632 |
472 | 633 |
473 void AstGraphBuilder::VisitBlock(Block* stmt) { | 634 void AstGraphBuilder::VisitBlock(Block* stmt) { |
474 BlockBuilder block(this); | 635 BlockBuilder block(this); |
475 BreakableScope scope(this, stmt, &block, 0); | 636 ControlScopeForBreakable scope(this, stmt, &block); |
476 if (stmt->labels() != NULL) block.BeginBlock(); | 637 if (stmt->labels() != NULL) block.BeginBlock(); |
477 if (stmt->scope() == NULL) { | 638 if (stmt->scope() == NULL) { |
478 // Visit statements in the same scope, no declarations. | 639 // Visit statements in the same scope, no declarations. |
479 VisitStatements(stmt->statements()); | 640 VisitStatements(stmt->statements()); |
480 } else { | 641 } else { |
481 // Visit declarations and statements in a block scope. | 642 // Visit declarations and statements in a block scope. |
482 Node* context = BuildLocalBlockContext(stmt->scope()); | 643 Node* context = BuildLocalBlockContext(stmt->scope()); |
483 ContextScope scope(this, stmt->scope(), context); | 644 ContextScope scope(this, stmt->scope(), context); |
484 VisitDeclarations(stmt->scope()->declarations()); | 645 VisitDeclarations(stmt->scope()->declarations()); |
485 VisitStatements(stmt->statements()); | 646 VisitStatements(stmt->statements()); |
(...skipping 24 matching lines...) Loading... | |
510 compare_if.If(condition); | 671 compare_if.If(condition); |
511 compare_if.Then(); | 672 compare_if.Then(); |
512 Visit(stmt->then_statement()); | 673 Visit(stmt->then_statement()); |
513 compare_if.Else(); | 674 compare_if.Else(); |
514 Visit(stmt->else_statement()); | 675 Visit(stmt->else_statement()); |
515 compare_if.End(); | 676 compare_if.End(); |
516 } | 677 } |
517 | 678 |
518 | 679 |
519 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 680 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
520 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | 681 execution_control()->ContinueTarget(stmt->target()); |
521 breakable()->ContinueTarget(stmt->target()); | |
522 set_environment(env); | |
523 } | 682 } |
524 | 683 |
525 | 684 |
526 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 685 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
527 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | 686 execution_control()->BreakTarget(stmt->target()); |
528 breakable()->BreakTarget(stmt->target()); | |
529 set_environment(env); | |
530 } | 687 } |
531 | 688 |
532 | 689 |
533 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 690 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
534 VisitForValue(stmt->expression()); | 691 VisitForValue(stmt->expression()); |
535 Node* result = environment()->Pop(); | 692 Node* result = environment()->Pop(); |
536 Node* control = NewNode(common()->Return(), result); | 693 execution_control()->ReturnValue(result); |
537 UpdateControlDependencyToLeaveFunction(control); | |
538 } | 694 } |
539 | 695 |
540 | 696 |
541 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 697 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
542 VisitForValue(stmt->expression()); | 698 VisitForValue(stmt->expression()); |
543 Node* value = environment()->Pop(); | 699 Node* value = environment()->Pop(); |
544 const Operator* op = javascript()->CreateWithContext(); | 700 const Operator* op = javascript()->CreateWithContext(); |
545 Node* context = NewNode(op, value, GetFunctionClosure()); | 701 Node* context = NewNode(op, value, GetFunctionClosure()); |
546 PrepareFrameState(context, stmt->EntryId()); | 702 PrepareFrameState(context, stmt->EntryId()); |
547 ContextScope scope(this, stmt->scope(), context); | 703 ContextScope scope(this, stmt->scope(), context); |
548 Visit(stmt->statement()); | 704 Visit(stmt->statement()); |
549 } | 705 } |
550 | 706 |
551 | 707 |
552 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 708 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
553 ZoneList<CaseClause*>* clauses = stmt->cases(); | 709 ZoneList<CaseClause*>* clauses = stmt->cases(); |
554 SwitchBuilder compare_switch(this, clauses->length()); | 710 SwitchBuilder compare_switch(this, clauses->length()); |
555 BreakableScope scope(this, stmt, &compare_switch, 0); | 711 ControlScopeForBreakable scope(this, stmt, &compare_switch); |
556 compare_switch.BeginSwitch(); | 712 compare_switch.BeginSwitch(); |
557 int default_index = -1; | 713 int default_index = -1; |
558 | 714 |
559 // Keep the switch value on the stack until a case matches. | 715 // Keep the switch value on the stack until a case matches. |
560 VisitForValue(stmt->tag()); | 716 VisitForValue(stmt->tag()); |
561 Node* tag = environment()->Top(); | 717 Node* tag = environment()->Top(); |
562 | 718 |
563 // Iterate over all cases and create nodes for label comparison. | 719 // Iterate over all cases and create nodes for label comparison. |
564 for (int i = 0; i < clauses->length(); i++) { | 720 for (int i = 0; i < clauses->length(); i++) { |
565 CaseClause* clause = clauses->at(i); | 721 CaseClause* clause = clauses->at(i); |
(...skipping 232 matching lines...) Loading... | |
798 Node* condition = environment()->Pop(); | 954 Node* condition = environment()->Pop(); |
799 for_loop.BreakWhen(condition); | 955 for_loop.BreakWhen(condition); |
800 VisitForEffect(stmt->assign_each()); | 956 VisitForEffect(stmt->assign_each()); |
801 VisitIterationBody(stmt, &for_loop, 0); | 957 VisitIterationBody(stmt, &for_loop, 0); |
802 for_loop.EndBody(); | 958 for_loop.EndBody(); |
803 for_loop.EndLoop(); | 959 for_loop.EndLoop(); |
804 } | 960 } |
805 | 961 |
806 | 962 |
807 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 963 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
808 // TODO(turbofan): Implement try-catch here. | 964 TryCatchBuilder try_control(this); |
809 SetStackOverflow(); | 965 |
966 // Evaluate the try-block inside a control scope. This simulates a handler | |
967 // that is intercepting 'throw' control commands. | |
968 try_control.BeginTry(); | |
969 { | |
970 ControlScopeForCatch scope(this, &try_control); | |
971 Visit(stmt->try_block()); | |
972 } | |
973 try_control.EndTry(); | |
974 | |
975 // Create a catch scope that binds the exception. | |
976 Node* exception = try_control.GetExceptionNode(); | |
977 if (exception == NULL) exception = jsgraph()->NullConstant(); | |
978 Unique<String> name = MakeUnique(stmt->variable()->name()); | |
979 const Operator* op = javascript()->CreateCatchContext(name); | |
980 Node* context = NewNode(op, exception, GetFunctionClosure()); | |
981 PrepareFrameState(context, BailoutId::None()); | |
982 ContextScope scope(this, stmt->scope(), context); | |
983 DCHECK(stmt->scope()->declarations()->is_empty()); | |
984 | |
985 // Evaluate the catch-block. | |
986 Visit(stmt->catch_block()); | |
987 try_control.EndCatch(); | |
988 | |
989 // TODO(mstarzinger): Remove bailout once everything works. | |
990 if (!FLAG_turbo_exceptions) SetStackOverflow(); | |
810 } | 991 } |
811 | 992 |
812 | 993 |
813 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 994 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
814 // TODO(turbofan): Implement try-catch here. | 995 TryFinallyBuilder try_control(this); |
815 SetStackOverflow(); | 996 |
997 // We keep a record of all paths that enter the finally-block to be able to | |
998 // dispatch to the correct continuation point after the statements in the | |
999 // finally-block have been evaluated. | |
1000 // | |
1001 // The try-finally construct can enter the finally-block in three ways: | |
1002 // 1. By exiting the try-block normally, falling through at the end. | |
1003 // 2. By exiting the try-block with a function-local control flow transfer | |
1004 // (i.e. through break/continue/return statements). | |
1005 // 3. By exiting the try-block with a thrown exception. | |
1006 ControlScope::DeferredCommands* commands = | |
1007 new (zone()) ControlScope::DeferredCommands(this); | |
1008 | |
1009 // Evaluate the try-block inside a control scope. This simulates a handler | |
1010 // that is intercepting all control commands. | |
1011 try_control.BeginTry(); | |
1012 { | |
1013 ControlScopeForFinally scope(this, commands, &try_control); | |
1014 Visit(stmt->try_block()); | |
1015 } | |
1016 try_control.EndTry(commands->GetFallThroughToken()); | |
1017 | |
1018 // Evaluate the finally-block. | |
1019 Visit(stmt->finally_block()); | |
1020 try_control.EndFinally(); | |
1021 | |
1022 // Dynamic dispatch after the finally-block. | |
1023 Node* token = try_control.GetDispatchTokenNode(); | |
1024 commands->ApplyDeferredCommands(token); | |
1025 | |
1026 // TODO(mstarzinger): Remove bailout once everything works. | |
1027 if (!FLAG_turbo_exceptions) SetStackOverflow(); | |
816 } | 1028 } |
817 | 1029 |
818 | 1030 |
819 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1031 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
820 // TODO(turbofan): Do we really need a separate reloc-info for this? | 1032 // TODO(turbofan): Do we really need a separate reloc-info for this? |
821 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); | 1033 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); |
822 PrepareFrameState(node, stmt->DebugBreakId()); | 1034 PrepareFrameState(node, stmt->DebugBreakId()); |
823 } | 1035 } |
824 | 1036 |
825 | 1037 |
(...skipping 543 matching lines...) Loading... | |
1369 void AstGraphBuilder::VisitYield(Yield* expr) { | 1581 void AstGraphBuilder::VisitYield(Yield* expr) { |
1370 // TODO(turbofan): Implement yield here. | 1582 // TODO(turbofan): Implement yield here. |
1371 SetStackOverflow(); | 1583 SetStackOverflow(); |
1372 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); | 1584 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); |
1373 } | 1585 } |
1374 | 1586 |
1375 | 1587 |
1376 void AstGraphBuilder::VisitThrow(Throw* expr) { | 1588 void AstGraphBuilder::VisitThrow(Throw* expr) { |
1377 VisitForValue(expr->exception()); | 1589 VisitForValue(expr->exception()); |
1378 Node* exception = environment()->Pop(); | 1590 Node* exception = environment()->Pop(); |
1379 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1); | 1591 if (FLAG_turbo_exceptions) { |
1380 Node* value = NewNode(op, exception); | 1592 execution_control()->ThrowValue(exception); |
1381 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 1593 ast_context()->ProduceValue(exception); |
1382 ast_context()->ProduceValue(value); | 1594 } else { |
1595 // TODO(mstarzinger): Temporary workaround for bailout-id for debugger. | |
1596 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1); | |
1597 Node* value = NewNode(op, exception); | |
1598 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | |
1599 ast_context()->ProduceValue(value); | |
1600 } | |
1383 } | 1601 } |
1384 | 1602 |
1385 | 1603 |
1386 void AstGraphBuilder::VisitProperty(Property* expr) { | 1604 void AstGraphBuilder::VisitProperty(Property* expr) { |
1387 Node* value; | 1605 Node* value; |
1388 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); | 1606 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); |
1389 if (expr->key()->IsPropertyName()) { | 1607 if (expr->key()->IsPropertyName()) { |
1390 VisitForValue(expr->obj()); | 1608 VisitForValue(expr->obj()); |
1391 Node* object = environment()->Pop(); | 1609 Node* object = environment()->Pop(); |
1392 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); | 1610 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); |
(...skipping 421 matching lines...) Loading... | |
1814 } | 2032 } |
1815 | 2033 |
1816 | 2034 |
1817 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { | 2035 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { |
1818 if (stmt == NULL) return; | 2036 if (stmt == NULL) return; |
1819 Visit(stmt); | 2037 Visit(stmt); |
1820 } | 2038 } |
1821 | 2039 |
1822 | 2040 |
1823 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, | 2041 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, |
1824 LoopBuilder* loop, int drop_extra) { | 2042 LoopBuilder* loop, int stack_delta) { |
1825 BreakableScope scope(this, stmt, loop, drop_extra); | 2043 ControlScopeForIteration scope(this, stmt, loop, stack_delta); |
1826 Visit(stmt->body()); | 2044 Visit(stmt->body()); |
1827 } | 2045 } |
1828 | 2046 |
1829 | 2047 |
1830 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { | 2048 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { |
1831 Node* value; | 2049 Node* value; |
1832 if (expr->expression()->IsVariableProxy()) { | 2050 if (expr->expression()->IsVariableProxy()) { |
1833 // Delete of an unqualified identifier is only allowed in classic mode but | 2051 // Delete of an unqualified identifier is only allowed in classic mode but |
1834 // deleting "this" is allowed in all language modes. | 2052 // deleting "this" is allowed in all language modes. |
1835 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2053 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
(...skipping 506 matching lines...) Loading... | |
2342 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { | 2560 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { |
2343 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. | 2561 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. |
2344 const Operator* op = | 2562 const Operator* op = |
2345 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0); | 2563 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0); |
2346 Node* call = NewNode(op); | 2564 Node* call = NewNode(op); |
2347 PrepareFrameState(call, bailout_id); | 2565 PrepareFrameState(call, bailout_id); |
2348 return call; | 2566 return call; |
2349 } | 2567 } |
2350 | 2568 |
2351 | 2569 |
2570 Node* AstGraphBuilder::BuildReturn(Node* return_value) { | |
2571 Node* control = NewNode(common()->Return(), return_value); | |
2572 UpdateControlDependencyToLeaveFunction(control); | |
2573 return control; | |
2574 } | |
2575 | |
2576 | |
2577 Node* AstGraphBuilder::BuildThrow(Node* exception_value) { | |
2578 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1); | |
2579 Node* control = NewNode(op, exception_value); | |
2580 // TODO(mstarzinger): Thread through the correct bailout id to this point. | |
2581 // PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | |
2582 PrepareFrameState(control, BailoutId::None()); | |
2583 return control; | |
2584 } | |
2585 | |
2586 | |
2352 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { | 2587 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { |
2353 const Operator* js_op; | 2588 const Operator* js_op; |
2354 switch (op) { | 2589 switch (op) { |
2355 case Token::BIT_OR: | 2590 case Token::BIT_OR: |
2356 js_op = javascript()->BitwiseOr(); | 2591 js_op = javascript()->BitwiseOr(); |
2357 break; | 2592 break; |
2358 case Token::BIT_AND: | 2593 case Token::BIT_AND: |
2359 js_op = javascript()->BitwiseAnd(); | 2594 js_op = javascript()->BitwiseAnd(); |
2360 break; | 2595 break; |
2361 case Token::BIT_XOR: | 2596 case Token::BIT_XOR: |
(...skipping 67 matching lines...) Loading... | |
2429 | 2664 |
2430 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2665 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
2431 IterationStatement* stmt) { | 2666 IterationStatement* stmt) { |
2432 if (loop_assignment_analysis_ == NULL) return NULL; | 2667 if (loop_assignment_analysis_ == NULL) return NULL; |
2433 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2668 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
2434 } | 2669 } |
2435 | 2670 |
2436 } // namespace compiler | 2671 } // namespace compiler |
2437 } // namespace internal | 2672 } // namespace internal |
2438 } // namespace v8 | 2673 } // namespace v8 |
OLD | NEW |