Chromium Code Reviews| 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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()->IntPtrConstant(deferred_.size()); | |
| 346 } | |
| 347 Node* NewPathTokenForImplicitFallThrough() { | |
| 348 return owner_->jsgraph()->IntPtrConstant(-1); | |
| 349 } | |
| 350 Node* NewPathDispatchCondition(Node* t1, Node* t2) { | |
| 351 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2); | |
|
titzer
2015/02/02 09:47:29
I think you want pointer/integer equality here. JS
Michael Starzinger
2015/02/02 14:47:41
Done.
Michael Starzinger
2015/02/02 17:08:41
Yeah, well, ain't gonna happen as long as our Phi'
| |
| 352 } | |
| 353 | |
| 354 private: | |
| 355 AstGraphBuilder* owner_; | |
| 356 ZoneVector<Entry> deferred_; | |
| 357 }; | |
| 358 | |
| 359 | |
| 360 bool AstGraphBuilder::ControlScope::Execute(Command command, Statement* target, | |
| 361 Node* value) { | |
| 362 // For function-level control. | |
| 363 switch (command) { | |
| 364 case CMD_THROW: | |
| 365 owner()->BuildThrow(value); | |
| 366 return true; | |
| 367 case CMD_RETURN: | |
| 368 owner()->BuildReturn(value); | |
| 369 return true; | |
| 370 case CMD_BREAK: | |
| 371 case CMD_CONTINUE: | |
| 372 break; | |
| 373 } | |
| 374 return false; | |
| 303 } | 375 } |
| 304 | 376 |
| 305 | 377 |
| 306 void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) { | 378 bool AstGraphBuilder::ControlScopeForBreakable::Execute(Command command, |
| 307 FindBreakable(stmt)->control_->Break(); | 379 Statement* target, |
| 380 Node* value) { | |
| 381 if (target != target_) return false; // We are not the command target. | |
| 382 switch (command) { | |
| 383 case CMD_BREAK: | |
| 384 control_->Break(); | |
| 385 return true; | |
| 386 case CMD_CONTINUE: | |
| 387 case CMD_THROW: | |
| 388 case CMD_RETURN: | |
| 389 break; | |
| 390 } | |
| 391 return false; | |
| 308 } | 392 } |
| 309 | 393 |
| 310 | 394 |
| 311 void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) { | 395 bool AstGraphBuilder::ControlScopeForIteration::Execute(Command command, |
| 312 FindBreakable(stmt)->control_->Continue(); | 396 Statement* target, |
| 397 Node* value) { | |
| 398 if (target != target_) return false; // We are not the command target. | |
| 399 switch (command) { | |
| 400 case CMD_BREAK: | |
| 401 control_->Break(); | |
| 402 return true; | |
| 403 case CMD_CONTINUE: | |
| 404 control_->Continue(); | |
| 405 return true; | |
| 406 case CMD_THROW: | |
| 407 case CMD_RETURN: | |
| 408 break; | |
| 409 } | |
| 410 return false; | |
| 313 } | 411 } |
| 314 | 412 |
| 315 | 413 |
| 414 bool AstGraphBuilder::ControlScopeForCatch::Execute(Command command, | |
| 415 Statement* target, | |
| 416 Node* value) { | |
| 417 switch (command) { | |
| 418 case CMD_THROW: | |
| 419 control_->Throw(value); | |
| 420 return true; | |
| 421 case CMD_BREAK: | |
| 422 case CMD_CONTINUE: | |
| 423 case CMD_RETURN: | |
| 424 break; | |
| 425 } | |
| 426 return false; | |
| 427 } | |
| 428 | |
| 429 | |
| 430 bool AstGraphBuilder::ControlScopeForFinally::Execute(Command cmd, | |
| 431 Statement* target, | |
| 432 Node* value) { | |
| 433 Node* token = commands_->RecordCommand(cmd, target, value); | |
| 434 control_->LeaveTry(token); | |
| 435 return true; | |
| 436 } | |
| 437 | |
| 438 | |
| 439 void AstGraphBuilder::ControlScope::PerformCommand(Command command, | |
| 440 Statement* target, | |
| 441 Node* value) { | |
| 442 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | |
| 443 ControlScope* current = this; | |
| 444 while (current != NULL) { | |
| 445 if (current->Execute(command, target, value)) break; | |
| 446 environment()->Drop(current->drop_extra()); | |
| 447 current = current->next_; | |
| 448 } | |
| 449 // TODO(mstarzinger): Unconditionally kill environment once throw is control. | |
| 450 if (command != CMD_THROW) owner()->set_environment(env); | |
| 451 DCHECK(current != NULL); // Always handled (unless stack is malformed). | |
| 452 } | |
| 453 | |
| 454 | |
| 455 void AstGraphBuilder::ControlScope::BreakTarget(BreakableStatement* stmt) { | |
| 456 PerformCommand(CMD_BREAK, stmt, nullptr); | |
| 457 } | |
| 458 | |
| 459 | |
| 460 void AstGraphBuilder::ControlScope::ContinueTarget(BreakableStatement* stmt) { | |
| 461 PerformCommand(CMD_CONTINUE, stmt, nullptr); | |
| 462 } | |
| 463 | |
| 464 | |
| 465 void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) { | |
| 466 PerformCommand(CMD_RETURN, nullptr, return_value); | |
| 467 } | |
| 468 | |
| 469 | |
| 470 void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) { | |
| 471 PerformCommand(CMD_THROW, nullptr, exception_value); | |
| 472 } | |
| 473 | |
| 474 | |
| 316 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { | 475 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { |
| 317 if (expr == NULL) { | 476 if (expr == NULL) { |
| 318 return environment()->Push(jsgraph()->NullConstant()); | 477 return environment()->Push(jsgraph()->NullConstant()); |
| 319 } | 478 } |
| 320 VisitForValue(expr); | 479 VisitForValue(expr); |
| 321 } | 480 } |
| 322 | 481 |
| 323 | 482 |
| 324 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { | 483 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) { |
| 325 if (expr == NULL) { | 484 if (expr == NULL) { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 | 624 |
| 466 | 625 |
| 467 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); } | 626 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); } |
| 468 | 627 |
| 469 | 628 |
| 470 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); } | 629 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); } |
| 471 | 630 |
| 472 | 631 |
| 473 void AstGraphBuilder::VisitBlock(Block* stmt) { | 632 void AstGraphBuilder::VisitBlock(Block* stmt) { |
| 474 BlockBuilder block(this); | 633 BlockBuilder block(this); |
| 475 BreakableScope scope(this, stmt, &block, 0); | 634 ControlScopeForBreakable scope(this, stmt, &block); |
| 476 if (stmt->labels() != NULL) block.BeginBlock(); | 635 if (stmt->labels() != NULL) block.BeginBlock(); |
| 477 if (stmt->scope() == NULL) { | 636 if (stmt->scope() == NULL) { |
| 478 // Visit statements in the same scope, no declarations. | 637 // Visit statements in the same scope, no declarations. |
| 479 VisitStatements(stmt->statements()); | 638 VisitStatements(stmt->statements()); |
| 480 } else { | 639 } else { |
| 481 // Visit declarations and statements in a block scope. | 640 // Visit declarations and statements in a block scope. |
| 482 Node* context = BuildLocalBlockContext(stmt->scope()); | 641 Node* context = BuildLocalBlockContext(stmt->scope()); |
| 483 ContextScope scope(this, stmt->scope(), context); | 642 ContextScope scope(this, stmt->scope(), context); |
| 484 VisitDeclarations(stmt->scope()->declarations()); | 643 VisitDeclarations(stmt->scope()->declarations()); |
| 485 VisitStatements(stmt->statements()); | 644 VisitStatements(stmt->statements()); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 510 compare_if.If(condition); | 669 compare_if.If(condition); |
| 511 compare_if.Then(); | 670 compare_if.Then(); |
| 512 Visit(stmt->then_statement()); | 671 Visit(stmt->then_statement()); |
| 513 compare_if.Else(); | 672 compare_if.Else(); |
| 514 Visit(stmt->else_statement()); | 673 Visit(stmt->else_statement()); |
| 515 compare_if.End(); | 674 compare_if.End(); |
| 516 } | 675 } |
| 517 | 676 |
| 518 | 677 |
| 519 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 678 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| 520 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | 679 execution_control()->ContinueTarget(stmt->target()); |
| 521 breakable()->ContinueTarget(stmt->target()); | |
| 522 set_environment(env); | |
| 523 } | 680 } |
| 524 | 681 |
| 525 | 682 |
| 526 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 683 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 527 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); | 684 execution_control()->BreakTarget(stmt->target()); |
| 528 breakable()->BreakTarget(stmt->target()); | |
| 529 set_environment(env); | |
| 530 } | 685 } |
| 531 | 686 |
| 532 | 687 |
| 533 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 688 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 534 VisitForValue(stmt->expression()); | 689 VisitForValue(stmt->expression()); |
| 535 Node* result = environment()->Pop(); | 690 Node* result = environment()->Pop(); |
| 536 Node* control = NewNode(common()->Return(), result); | 691 execution_control()->ReturnValue(result); |
| 537 UpdateControlDependencyToLeaveFunction(control); | |
| 538 } | 692 } |
| 539 | 693 |
| 540 | 694 |
| 541 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 695 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
| 542 VisitForValue(stmt->expression()); | 696 VisitForValue(stmt->expression()); |
| 543 Node* value = environment()->Pop(); | 697 Node* value = environment()->Pop(); |
| 544 const Operator* op = javascript()->CreateWithContext(); | 698 const Operator* op = javascript()->CreateWithContext(); |
| 545 Node* context = NewNode(op, value, GetFunctionClosure()); | 699 Node* context = NewNode(op, value, GetFunctionClosure()); |
| 546 PrepareFrameState(context, stmt->EntryId()); | 700 PrepareFrameState(context, stmt->EntryId()); |
| 547 ContextScope scope(this, stmt->scope(), context); | 701 ContextScope scope(this, stmt->scope(), context); |
| 548 Visit(stmt->statement()); | 702 Visit(stmt->statement()); |
| 549 } | 703 } |
| 550 | 704 |
| 551 | 705 |
| 552 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 706 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
| 553 ZoneList<CaseClause*>* clauses = stmt->cases(); | 707 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 554 SwitchBuilder compare_switch(this, clauses->length()); | 708 SwitchBuilder compare_switch(this, clauses->length()); |
| 555 BreakableScope scope(this, stmt, &compare_switch, 0); | 709 ControlScopeForBreakable scope(this, stmt, &compare_switch); |
| 556 compare_switch.BeginSwitch(); | 710 compare_switch.BeginSwitch(); |
| 557 int default_index = -1; | 711 int default_index = -1; |
| 558 | 712 |
| 559 // Keep the switch value on the stack until a case matches. | 713 // Keep the switch value on the stack until a case matches. |
| 560 VisitForValue(stmt->tag()); | 714 VisitForValue(stmt->tag()); |
| 561 Node* tag = environment()->Top(); | 715 Node* tag = environment()->Top(); |
| 562 | 716 |
| 563 // Iterate over all cases and create nodes for label comparison. | 717 // Iterate over all cases and create nodes for label comparison. |
| 564 for (int i = 0; i < clauses->length(); i++) { | 718 for (int i = 0; i < clauses->length(); i++) { |
| 565 CaseClause* clause = clauses->at(i); | 719 CaseClause* clause = clauses->at(i); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 798 Node* condition = environment()->Pop(); | 952 Node* condition = environment()->Pop(); |
| 799 for_loop.BreakWhen(condition); | 953 for_loop.BreakWhen(condition); |
| 800 VisitForEffect(stmt->assign_each()); | 954 VisitForEffect(stmt->assign_each()); |
| 801 VisitIterationBody(stmt, &for_loop, 0); | 955 VisitIterationBody(stmt, &for_loop, 0); |
| 802 for_loop.EndBody(); | 956 for_loop.EndBody(); |
| 803 for_loop.EndLoop(); | 957 for_loop.EndLoop(); |
| 804 } | 958 } |
| 805 | 959 |
| 806 | 960 |
| 807 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 961 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 808 // TODO(turbofan): Implement try-catch here. | 962 TryCatchBuilder try_control(this); |
| 809 SetStackOverflow(); | 963 |
| 964 // Evaluate the try-block inside a control scope. This simulates a handler | |
| 965 // that is intercepting 'throw' control commands. | |
| 966 try_control.BeginTry(); | |
| 967 { | |
| 968 ControlScopeForCatch scope(this, &try_control); | |
| 969 Visit(stmt->try_block()); | |
| 970 } | |
| 971 try_control.EndTry(); | |
| 972 | |
| 973 // Create a catch scope that binds the exception. | |
| 974 Node* exception = try_control.GetExceptionNode(); | |
| 975 if (exception == NULL) exception = jsgraph()->NullConstant(); | |
| 976 Unique<String> name = MakeUnique(stmt->variable()->name()); | |
| 977 const Operator* op = javascript()->CreateCatchContext(name); | |
| 978 Node* context = NewNode(op, exception, GetFunctionClosure()); | |
| 979 PrepareFrameState(context, BailoutId::None()); | |
| 980 ContextScope scope(this, stmt->scope(), context); | |
| 981 DCHECK(stmt->scope()->declarations()->is_empty()); | |
| 982 | |
| 983 // Evaluate the catch-block. | |
| 984 Visit(stmt->catch_block()); | |
| 985 try_control.EndCatch(); | |
| 986 | |
| 987 // TODO(mstarzinger): Remove bailout once everything works. | |
| 988 if (!FLAG_turbo_exceptions) SetStackOverflow(); | |
| 810 } | 989 } |
| 811 | 990 |
| 812 | 991 |
| 813 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 992 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 814 // TODO(turbofan): Implement try-catch here. | 993 TryFinallyBuilder try_control(this); |
| 815 SetStackOverflow(); | 994 |
| 995 // We keep a record of all paths that enter the finally-block to be able to | |
| 996 // dispatch to the correct continuation point after the statements in the | |
| 997 // finally-block have been evaluated. | |
| 998 // | |
| 999 // The try-finally construct can enter the finally-block in three ways: | |
| 1000 // 1. By exiting the try-block normally, falling through at the end. | |
| 1001 // 2. By exiting the try-block with a function-local control flow transfer | |
| 1002 // (i.e. through break/continue/return statements). | |
| 1003 // 3. By exiting the try-block with a thrown exception. | |
| 1004 ControlScope::DeferredCommands* commands = | |
| 1005 new (zone()) ControlScope::DeferredCommands(this); | |
| 1006 | |
| 1007 // Evaluate the try-block inside a control scope. This simulates a handler | |
| 1008 // that is intercepting all control commands. | |
| 1009 try_control.BeginTry(); | |
| 1010 { | |
| 1011 ControlScopeForFinally scope(this, commands, &try_control); | |
| 1012 Visit(stmt->try_block()); | |
| 1013 } | |
| 1014 try_control.EndTry(commands->GetFallThroughToken()); | |
| 1015 | |
| 1016 // Evaluate the finally-block. | |
| 1017 Visit(stmt->finally_block()); | |
| 1018 try_control.EndFinally(); | |
| 1019 | |
| 1020 // Dynamic dispatch after the finally-block. | |
| 1021 Node* token = try_control.GetDispatchTokenNode(); | |
| 1022 commands->ApplyDeferredCommands(token); | |
| 1023 | |
| 1024 // TODO(mstarzinger): Remove bailout once everything works. | |
| 1025 if (!FLAG_turbo_exceptions) SetStackOverflow(); | |
| 816 } | 1026 } |
| 817 | 1027 |
| 818 | 1028 |
| 819 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1029 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 820 // TODO(turbofan): Do we really need a separate reloc-info for this? | 1030 // TODO(turbofan): Do we really need a separate reloc-info for this? |
| 821 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); | 1031 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); |
| 822 PrepareFrameState(node, stmt->DebugBreakId()); | 1032 PrepareFrameState(node, stmt->DebugBreakId()); |
| 823 } | 1033 } |
| 824 | 1034 |
| 825 | 1035 |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1369 void AstGraphBuilder::VisitYield(Yield* expr) { | 1579 void AstGraphBuilder::VisitYield(Yield* expr) { |
| 1370 // TODO(turbofan): Implement yield here. | 1580 // TODO(turbofan): Implement yield here. |
| 1371 SetStackOverflow(); | 1581 SetStackOverflow(); |
| 1372 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); | 1582 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); |
| 1373 } | 1583 } |
| 1374 | 1584 |
| 1375 | 1585 |
| 1376 void AstGraphBuilder::VisitThrow(Throw* expr) { | 1586 void AstGraphBuilder::VisitThrow(Throw* expr) { |
| 1377 VisitForValue(expr->exception()); | 1587 VisitForValue(expr->exception()); |
| 1378 Node* exception = environment()->Pop(); | 1588 Node* exception = environment()->Pop(); |
| 1379 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1); | 1589 execution_control()->ThrowValue(exception); |
| 1380 Node* value = NewNode(op, exception); | 1590 ast_context()->ProduceValue(exception); |
| 1381 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | |
| 1382 ast_context()->ProduceValue(value); | |
| 1383 } | 1591 } |
| 1384 | 1592 |
| 1385 | 1593 |
| 1386 void AstGraphBuilder::VisitProperty(Property* expr) { | 1594 void AstGraphBuilder::VisitProperty(Property* expr) { |
| 1387 Node* value; | 1595 Node* value; |
| 1388 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); | 1596 VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot()); |
| 1389 if (expr->key()->IsPropertyName()) { | 1597 if (expr->key()->IsPropertyName()) { |
| 1390 VisitForValue(expr->obj()); | 1598 VisitForValue(expr->obj()); |
| 1391 Node* object = environment()->Pop(); | 1599 Node* object = environment()->Pop(); |
| 1392 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); | 1600 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1815 | 2023 |
| 1816 | 2024 |
| 1817 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { | 2025 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { |
| 1818 if (stmt == NULL) return; | 2026 if (stmt == NULL) return; |
| 1819 Visit(stmt); | 2027 Visit(stmt); |
| 1820 } | 2028 } |
| 1821 | 2029 |
| 1822 | 2030 |
| 1823 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, | 2031 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, |
| 1824 LoopBuilder* loop, int drop_extra) { | 2032 LoopBuilder* loop, int drop_extra) { |
| 1825 BreakableScope scope(this, stmt, loop, drop_extra); | 2033 ControlScopeForIteration scope(this, stmt, loop, drop_extra); |
| 1826 Visit(stmt->body()); | 2034 Visit(stmt->body()); |
| 1827 } | 2035 } |
| 1828 | 2036 |
| 1829 | 2037 |
| 1830 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { | 2038 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { |
| 1831 Node* value; | 2039 Node* value; |
| 1832 if (expr->expression()->IsVariableProxy()) { | 2040 if (expr->expression()->IsVariableProxy()) { |
| 1833 // Delete of an unqualified identifier is only allowed in classic mode but | 2041 // Delete of an unqualified identifier is only allowed in classic mode but |
| 1834 // deleting "this" is allowed in all language modes. | 2042 // deleting "this" is allowed in all language modes. |
| 1835 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2043 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2342 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { | 2550 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { |
| 2343 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. | 2551 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. |
| 2344 const Operator* op = | 2552 const Operator* op = |
| 2345 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0); | 2553 javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2346 Node* call = NewNode(op); | 2554 Node* call = NewNode(op); |
| 2347 PrepareFrameState(call, bailout_id); | 2555 PrepareFrameState(call, bailout_id); |
| 2348 return call; | 2556 return call; |
| 2349 } | 2557 } |
| 2350 | 2558 |
| 2351 | 2559 |
| 2560 Node* AstGraphBuilder::BuildReturn(Node* return_value) { | |
| 2561 Node* control = NewNode(common()->Return(), return_value); | |
| 2562 UpdateControlDependencyToLeaveFunction(control); | |
| 2563 return control; | |
| 2564 } | |
| 2565 | |
| 2566 | |
| 2567 Node* AstGraphBuilder::BuildThrow(Node* exception_value) { | |
| 2568 const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1); | |
| 2569 Node* control = NewNode(op, exception_value); | |
| 2570 // TODO(mstarzinger): Thread through the correct bailout id to this point. | |
|
Michael Starzinger
2015/01/30 14:30:27
This is the TODO I still need to address.
Michael Starzinger
2015/02/02 15:08:02
I added a workaround that only uses the ControlSco
| |
| 2571 // PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | |
| 2572 PrepareFrameState(control, BailoutId::None()); | |
| 2573 return control; | |
| 2574 } | |
| 2575 | |
| 2576 | |
| 2352 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { | 2577 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { |
| 2353 const Operator* js_op; | 2578 const Operator* js_op; |
| 2354 switch (op) { | 2579 switch (op) { |
| 2355 case Token::BIT_OR: | 2580 case Token::BIT_OR: |
| 2356 js_op = javascript()->BitwiseOr(); | 2581 js_op = javascript()->BitwiseOr(); |
| 2357 break; | 2582 break; |
| 2358 case Token::BIT_AND: | 2583 case Token::BIT_AND: |
| 2359 js_op = javascript()->BitwiseAnd(); | 2584 js_op = javascript()->BitwiseAnd(); |
| 2360 break; | 2585 break; |
| 2361 case Token::BIT_XOR: | 2586 case Token::BIT_XOR: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2429 | 2654 |
| 2430 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2655 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
| 2431 IterationStatement* stmt) { | 2656 IterationStatement* stmt) { |
| 2432 if (loop_assignment_analysis_ == NULL) return NULL; | 2657 if (loop_assignment_analysis_ == NULL) return NULL; |
| 2433 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2658 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
| 2434 } | 2659 } |
| 2435 | 2660 |
| 2436 } // namespace compiler | 2661 } // namespace compiler |
| 2437 } // namespace internal | 2662 } // namespace internal |
| 2438 } // namespace v8 | 2663 } // namespace v8 |
| OLD | NEW |