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

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 2654423004: [async-functions] support await expressions in finally statements (Closed)
Patch Set: Get everything working (except possibly inspector tests) Created 3 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/compile-time-value.h" 7 #include "src/ast/compile-time-value.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/builtins/builtins-constructor.h" 9 #include "src/builtins/builtins-constructor.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 function_literals_(0, info->zone()), 594 function_literals_(0, info->zone()),
595 native_function_literals_(0, info->zone()), 595 native_function_literals_(0, info->zone()),
596 object_literals_(0, info->zone()), 596 object_literals_(0, info->zone()),
597 array_literals_(0, info->zone()), 597 array_literals_(0, info->zone()),
598 execution_control_(nullptr), 598 execution_control_(nullptr),
599 execution_context_(nullptr), 599 execution_context_(nullptr),
600 execution_result_(nullptr), 600 execution_result_(nullptr),
601 generator_resume_points_(info->literal()->yield_count(), info->zone()), 601 generator_resume_points_(info->literal()->yield_count(), info->zone()),
602 generator_state_(), 602 generator_state_(),
603 loop_depth_(0), 603 loop_depth_(0),
604 catch_prediction_(HandlerTable::UNCAUGHT),
604 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), 605 home_object_symbol_(info->isolate()->factory()->home_object_symbol()),
605 iterator_symbol_(info->isolate()->factory()->iterator_symbol()), 606 iterator_symbol_(info->isolate()->factory()->iterator_symbol()),
606 prototype_string_(info->isolate()->factory()->prototype_string()), 607 prototype_string_(info->isolate()->factory()->prototype_string()),
607 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()), 608 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()),
608 undefined_string_( 609 undefined_string_(
609 info->isolate()->ast_string_constants()->undefined_string()) {} 610 info->isolate()->ast_string_constants()->undefined_string()) {}
610 611
611 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { 612 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) {
612 AllocateDeferredConstants(isolate); 613 AllocateDeferredConstants(isolate);
613 if (HasStackOverflow()) return Handle<BytecodeArray>(); 614 if (HasStackOverflow()) return Handle<BytecodeArray>();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 674
674 InitializeAstVisitor(stack_limit); 675 InitializeAstVisitor(stack_limit);
675 676
676 // Initialize the incoming context. 677 // Initialize the incoming context.
677 ContextScope incoming_context(this, scope(), false); 678 ContextScope incoming_context(this, scope(), false);
678 679
679 // Initialize control scope. 680 // Initialize control scope.
680 ControlScopeForTopLevel control(this); 681 ControlScopeForTopLevel control(this);
681 682
682 RegisterAllocationScope register_scope(this); 683 RegisterAllocationScope register_scope(this);
683 684 if (IsResumableFunction(info()->literal()->kind()) ||
684 if (IsResumableFunction(info()->literal()->kind())) { 685 scope()->is_module_scope()) {
686 generator_object_ = register_allocator()->NewRegister();
685 generator_state_ = register_allocator()->NewRegister(); 687 generator_state_ = register_allocator()->NewRegister();
688 if (IsAsyncFunction(info()->literal()->kind())) {
689 promise_ = register_allocator()->NewRegister();
690 }
686 VisitGeneratorPrologue(); 691 VisitGeneratorPrologue();
687 } 692 }
688 693
689 if (scope()->NeedsContext()) { 694 if (scope()->NeedsContext()) {
690 // Push a new inner context scope for the function. 695 // Push a new inner context scope for the function.
691 BuildNewLocalActivationContext(); 696 BuildNewLocalActivationContext();
692 ContextScope local_function_context(this, scope(), false); 697 ContextScope local_function_context(this, scope(), false);
693 BuildLocalActivationContextInitialization(); 698 BuildLocalActivationContextInitialization();
694 GenerateBytecodeBody(); 699 GenerateBytecodeBody();
695 } else { 700 } else {
(...skipping 11 matching lines...) Expand all
707 // Emit an implicit return instruction in case control flow can fall off the 712 // Emit an implicit return instruction in case control flow can fall off the
708 // end of the function without an explicit return being present on all paths. 713 // end of the function without an explicit return being present on all paths.
709 if (builder()->RequiresImplicitReturn()) { 714 if (builder()->RequiresImplicitReturn()) {
710 builder()->LoadUndefined(); 715 builder()->LoadUndefined();
711 BuildReturn(); 716 BuildReturn();
712 } 717 }
713 DCHECK(!builder()->RequiresImplicitReturn()); 718 DCHECK(!builder()->RequiresImplicitReturn());
714 } 719 }
715 720
716 void BytecodeGenerator::GenerateBytecodeBody() { 721 void BytecodeGenerator::GenerateBytecodeBody() {
722 const bool kIsModule = scope()->is_module_scope();
723 const bool kIsGeneratorFunction =
724 IsGeneratorFunction(info()->literal()->kind());
725 const bool kIsResumableFunction =
726 IsResumableFunction(info()->literal()->kind());
727
717 // Build the arguments object if it is used. 728 // Build the arguments object if it is used.
718 VisitArgumentsObject(scope()->arguments()); 729 VisitArgumentsObject(scope()->arguments());
719 730
720 // Build rest arguments array if it is used. 731 // Build rest arguments array if it is used.
721 Variable* rest_parameter = scope()->rest_parameter(); 732 Variable* rest_parameter = scope()->rest_parameter();
722 VisitRestArgumentsArray(rest_parameter); 733 VisitRestArgumentsArray(rest_parameter);
723 734
724 // Build assignment to {.this_function} variable if it is used. 735 // Build assignment to {.this_function} variable if it is used.
725 VisitThisFunctionVariable(scope()->this_function_var()); 736 VisitThisFunctionVariable(scope()->this_function_var());
726 737
727 // Build assignment to {new.target} variable if it is used. 738 // Build assignment to {new.target} variable if it is used.
728 VisitNewTargetVariable(scope()->new_target_var()); 739 VisitNewTargetVariable(scope()->new_target_var());
729 740
730 // Emit tracing call if requested to do so. 741 // Emit tracing call if requested to do so.
731 if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter); 742 if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
732 743
733 // Visit declarations within the function scope. 744 // Visit declarations within the function scope.
734 VisitDeclarations(scope()->declarations()); 745 VisitDeclarations(scope()->declarations());
735 746
736 // Emit initializing assignments for module namespace imports (if any). 747 // Emit initializing assignments for module namespace imports (if any).
737 VisitModuleNamespaceImports(); 748 VisitModuleNamespaceImports();
738 749
739 // Perform a stack-check before the body. 750 // Perform a stack-check before the body.
740 builder()->StackCheck(info()->literal()->start_position()); 751 builder()->StackCheck(info()->literal()->start_position());
741 752
753 // Build assignment to variable <function name> if function is a named
754 // expression and the variable is used.
755 if (info()->literal()->is_named_expression()) {
756 Variable* function_var = scope()->function_var();
757 if (function_var != nullptr && !function_var->IsUnallocated()) {
758 builder()->LoadAccumulatorWithRegister(Register::function_closure());
759 BuildVariableAssignment(function_var, Token::INIT,
760 FeedbackVectorSlot::Invalid(),
761 HoleCheckMode::kElided);
762 }
763 }
764
765 Block* parameter_init_block = info()->literal()->parameter_init_block();
766
767 if (kIsResumableFunction || kIsModule) {
768 if (kIsResumableFunction) {
769 // No need to store `undefined` in the generator register for Modules,
770 // as there is no finally block.
771 builder()->LoadUndefined().StoreAccumulatorInRegister(generator_object_);
772 }
773
774 auto try_block = [=]() {
775 // Try ...
776 if (parameter_init_block != nullptr) {
777 // Initialize non-simple parameters before initial yield.
778 VisitBlock(parameter_init_block);
779 }
780 // Allocate generator object
781 RegisterAllocationScope register_scope(this);
782 RegisterList args = register_allocator()->NewRegisterList(2);
783 builder()->MoveRegister(Register::function_closure(), args[0]);
784
785 int yield_position = info()->literal()->position();
786 builder()->SetExpressionPosition(yield_position);
787
788 if (IsArrowFunction(info()->literal()->kind())) {
789 builder()->LoadUndefined().StoreAccumulatorInRegister(args[1]);
790 } else {
791 builder()->MoveRegister(builder()->Receiver(), args[1]);
792 }
793 builder()
794 ->CallRuntime(Runtime::kCreateJSGeneratorObject, args)
795 .StoreAccumulatorInRegister(generator_object_);
796
797 if (kIsGeneratorFunction || kIsModule) {
798 BuildYield(0, Yield::kOnExceptionThrow, Yield::kNormal,
799 generator_object_, yield_position);
800 }
801 VisitStatements(info()->literal()->body());
802
803 if (builder()->RequiresImplicitReturn()) {
804 if (IsGeneratorFunction(info()->literal()->kind())) {
805 // Add implicit `return { value: undefined, done: true }`
806 builder()
807 ->LoadUndefined()
808 .StoreAccumulatorInRegister(args[0])
809 .LoadTrue()
810 .StoreAccumulatorInRegister(args[1])
811 .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
812 execution_control()->ReturnAccumulator();
813 }
814 }
815 };
816
817 auto catch_block = [=](Register context) {
818 // Catch ...
819 if (IsAsyncFunction(info()->literal()->kind())) {
820 RegisterAllocationScope register_scope(this);
821 RegisterList args = register_allocator()->NewRegisterList(4);
822 Register exception = args[2];
823
824 builder()
825 ->StoreAccumulatorInRegister(exception)
826 .LoadTheHole()
827 .SetPendingMessage()
828 .LoadUndefined()
829 .StoreAccumulatorInRegister(args[0])
830 .MoveRegister(promise_, args[1])
831 .LoadFalse()
832 .StoreAccumulatorInRegister(args[3])
833 .CallJSRuntime(Context::PROMISE_INTERNAL_REJECT_INDEX, args)
834 .LoadAccumulatorWithRegister(promise_)
835 .Return(); // No need to close the generator for async functions
836 }
837 };
838
839 auto finally_block = [=]() {
840 // Finally ...
841 if (kIsGeneratorFunction) {
842 BytecodeLabel if_generatorundefined;
843 builder()->LoadAccumulatorWithRegister(generator_object_);
844 builder()->JumpIfUndefined(&if_generatorundefined);
845 builder()->CallRuntime(Runtime::kInlineGeneratorClose,
846 generator_object_);
847 builder()->Bind(&if_generatorundefined);
848 }
849 };
850
851 const bool kNeedsTryCatch = IsAsyncFunction(info()->literal()->kind());
852 if (kNeedsTryCatch) {
853 // Currently, only async functions need a special behaviour for top-level
854 // exceptions
855 HandlerTable::CatchPrediction catch_prediction =
856 HandlerTable::ASYNC_AWAIT;
857 BuildTryCatchFinally(HandlerTable::UNCAUGHT, catch_prediction, try_block,
858 catch_block, finally_block);
859 } else if (kIsGeneratorFunction) {
860 BuildTryFinally(HandlerTable::UNCAUGHT, try_block, finally_block);
861 } else {
862 DCHECK(kIsModule);
863 try_block();
864 }
865 return;
866 }
867
742 // Visit statements in the function body. 868 // Visit statements in the function body.
869 if (parameter_init_block != nullptr) {
870 VisitBlock(parameter_init_block);
871 }
743 VisitStatements(info()->literal()->body()); 872 VisitStatements(info()->literal()->body());
744 } 873 }
745 874
746 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, 875 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
747 size_t size, 876 size_t size,
748 ZoneVector<BytecodeLabel>& targets) { 877 ZoneVector<BytecodeLabel>& targets) {
749 // TODO(neis): Optimize this by using a proper jump table. 878 // TODO(neis): Optimize this by using a proper jump table.
750 DCHECK_LE(start_index + size, targets.size()); 879 DCHECK_LE(start_index + size, targets.size());
751 for (size_t i = start_index; i < start_index + size; i++) { 880 for (size_t i = start_index; i < start_index + size; i++) {
752 builder() 881 builder()
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 .PushContext(dummy) 941 .PushContext(dummy)
813 .ResumeGenerator(generator_object) 942 .ResumeGenerator(generator_object)
814 .StoreAccumulatorInRegister(generator_state_); 943 .StoreAccumulatorInRegister(generator_state_);
815 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(), 944 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
816 generator_resume_points_); 945 generator_resume_points_);
817 946
818 builder() 947 builder()
819 ->Bind(&regular_call) 948 ->Bind(&regular_call)
820 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 949 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
821 .StoreAccumulatorInRegister(generator_state_); 950 .StoreAccumulatorInRegister(generator_state_);
951
952 if (IsAsyncFunction(info()->literal()->kind())) {
953 // Create initial async function promise
954 RegisterAllocationScope register_scope(this);
955 RegisterList args = register_allocator()->NewRegisterList(1);
956 builder()
957 ->LoadUndefined()
958 .StoreAccumulatorInRegister(args[0])
959 .CallJSRuntime(Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX, args)
960 .StoreAccumulatorInRegister(promise_);
961 }
962
822 // This is a regular call. Fall through to the ordinary function prologue, 963 // This is a regular call. Fall through to the ordinary function prologue,
823 // after which we will run into the generator object creation and other extra 964 // after which we will run into the generator object creation and other extra
824 // code inserted by the parser. 965 // code inserted by the parser.
825 } 966 }
826 967
827 void BytecodeGenerator::VisitBlock(Block* stmt) { 968 void BytecodeGenerator::VisitBlock(Block* stmt) {
828 // Visit declarations and statements. 969 // Visit declarations and statements.
829 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { 970 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
830 BuildNewLocalBlockContext(stmt->scope()); 971 BuildNewLocalBlockContext(stmt->scope());
831 ContextScope scope(this, stmt->scope()); 972 ContextScope scope(this, stmt->scope());
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 VisitForEffect(stmt->next_result()); 1468 VisitForEffect(stmt->next_result());
1328 VisitForAccumulatorValue(stmt->result_done()); 1469 VisitForAccumulatorValue(stmt->result_done());
1329 loop_builder.BreakIfTrue(); 1470 loop_builder.BreakIfTrue();
1330 1471
1331 VisitForEffect(stmt->assign_each()); 1472 VisitForEffect(stmt->assign_each());
1332 VisitIterationBody(stmt, &loop_builder); 1473 VisitIterationBody(stmt, &loop_builder);
1333 loop_builder.JumpToHeader(loop_depth_); 1474 loop_builder.JumpToHeader(loop_depth_);
1334 loop_builder.EndLoop(); 1475 loop_builder.EndLoop();
1335 } 1476 }
1336 1477
1337 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 1478 void BytecodeGenerator::BuildTryCatch(
1338 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); 1479 HandlerTable::CatchPrediction catch_prediction,
1480 std::function<void()> build_try,
1481 std::function<void(Register)> build_catch) {
1482 TryCatchBuilder try_control_builder(builder(), catch_prediction);
1339 1483
1340 // Preserve the context in a dedicated register, so that it can be restored 1484 // Preserve the context in a dedicated register, so that it can be restored
1341 // when the handler is entered by the stack-unwinding machinery. 1485 // when the handler is entered by the stack-unwinding machinery.
1342 // TODO(mstarzinger): Be smarter about register allocation. 1486 // TODO(mstarzinger): Be smarter about register allocation.
1343 Register context = register_allocator()->NewRegister(); 1487 Register context = register_allocator()->NewRegister();
1344 builder()->MoveRegister(Register::current_context(), context); 1488 builder()->MoveRegister(Register::current_context(), context);
1345 1489
1346 // Evaluate the try-block inside a control scope. This simulates a handler 1490 // Evaluate the try-block inside a control scope. This simulates a handler
1347 // that is intercepting 'throw' control commands. 1491 // that is intercepting 'throw' control commands.
1348 try_control_builder.BeginTry(context); 1492 try_control_builder.BeginTry(context);
1349 { 1493 {
1350 ControlScopeForTryCatch scope(this, &try_control_builder); 1494 ControlScopeForTryCatch scope(this, &try_control_builder);
1351 Visit(stmt->try_block()); 1495 ScopedAssignment<HandlerTable::CatchPrediction> prediction(
1496 catch_prediction_, catch_prediction);
1497 build_try();
1352 } 1498 }
1353 try_control_builder.EndTry(); 1499 try_control_builder.EndTry();
1354 1500
1355 // Create a catch scope that binds the exception.
1356 BuildNewLocalCatchContext(stmt->variable(), stmt->scope());
1357 builder()->StoreAccumulatorInRegister(context);
1358
1359 // If requested, clear message object as we enter the catch block.
1360 if (stmt->clear_pending_message()) {
1361 builder()->LoadTheHole().SetPendingMessage();
1362 }
1363
1364 // Load the catch context into the accumulator.
1365 builder()->LoadAccumulatorWithRegister(context);
1366
1367 // Evaluate the catch-block. 1501 // Evaluate the catch-block.
1368 VisitInScope(stmt->catch_block(), stmt->scope()); 1502 build_catch(context);
1369 try_control_builder.EndCatch(); 1503 try_control_builder.EndCatch();
1370 } 1504 }
1371 1505
1372 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1506 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1373 TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction()); 1507 BuildTryCatch(stmt->catch_prediction(), [=]() { Visit(stmt->try_block()); },
1508 [=](Register context) {
1509 // Create a catch scope that binds the exception.
1510 BuildNewLocalCatchContext(stmt->variable(), stmt->scope());
1511 builder()->StoreAccumulatorInRegister(context);
1512
1513 // If requested, clear message object as we enter the catch
1514 // block.
1515 if (stmt->clear_pending_message()) {
1516 builder()->LoadTheHole().SetPendingMessage();
1517 }
1518
1519 // Load the catch context into the accumulator.
1520 builder()->LoadAccumulatorWithRegister(context);
1521
1522 VisitInScope(stmt->catch_block(), stmt->scope());
1523 });
1524 }
1525
1526 void BytecodeGenerator::BuildTryFinally(
1527 HandlerTable::CatchPrediction catch_prediction,
1528 std::function<void()> build_try, std::function<void()> build_finally) {
1529 TryFinallyBuilder try_control_builder(builder(), catch_prediction);
1374 1530
1375 // We keep a record of all paths that enter the finally-block to be able to 1531 // We keep a record of all paths that enter the finally-block to be able to
1376 // dispatch to the correct continuation point after the statements in the 1532 // dispatch to the correct continuation point after the statements in the
1377 // finally-block have been evaluated. 1533 // finally-block have been evaluated.
1378 // 1534 //
1379 // The try-finally construct can enter the finally-block in three ways: 1535 // The try-finally construct can enter the finally-block in three ways:
1380 // 1. By exiting the try-block normally, falling through at the end. 1536 // 1. By exiting the try-block normally, falling through at the end.
1381 // 2. By exiting the try-block with a function-local control flow transfer 1537 // 2. By exiting the try-block with a function-local control flow transfer
1382 // (i.e. through break/continue/return statements). 1538 // (i.e. through break/continue/return statements).
1383 // 3. By exiting the try-block with a thrown exception. 1539 // 3. By exiting the try-block with a thrown exception.
(...skipping 11 matching lines...) Expand all
1395 // when the handler is entered by the stack-unwinding machinery. 1551 // when the handler is entered by the stack-unwinding machinery.
1396 // TODO(mstarzinger): Be smarter about register allocation. 1552 // TODO(mstarzinger): Be smarter about register allocation.
1397 Register context = register_allocator()->NewRegister(); 1553 Register context = register_allocator()->NewRegister();
1398 builder()->MoveRegister(Register::current_context(), context); 1554 builder()->MoveRegister(Register::current_context(), context);
1399 1555
1400 // Evaluate the try-block inside a control scope. This simulates a handler 1556 // Evaluate the try-block inside a control scope. This simulates a handler
1401 // that is intercepting all control commands. 1557 // that is intercepting all control commands.
1402 try_control_builder.BeginTry(context); 1558 try_control_builder.BeginTry(context);
1403 { 1559 {
1404 ControlScopeForTryFinally scope(this, &try_control_builder, &commands); 1560 ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
1405 Visit(stmt->try_block()); 1561 build_try();
1406 } 1562 }
1407 try_control_builder.EndTry(); 1563 try_control_builder.EndTry();
1408 1564
1409 // Record fall-through and exception cases. 1565 // Record fall-through and exception cases.
1410 commands.RecordFallThroughPath(); 1566 commands.RecordFallThroughPath();
1411 try_control_builder.LeaveTry(); 1567 try_control_builder.LeaveTry();
1412 try_control_builder.BeginHandler(); 1568 try_control_builder.BeginHandler();
1413 commands.RecordHandlerReThrowPath(); 1569 commands.RecordHandlerReThrowPath();
1414 1570
1415 // Pending message object is saved on entry. 1571 // Pending message object is saved on entry.
1416 try_control_builder.BeginFinally(); 1572 try_control_builder.BeginFinally();
1417 Register message = context; // Reuse register. 1573 Register message = context; // Reuse register.
1418 1574
1419 // Clear message object as we enter the finally block. 1575 // Clear message object as we enter the finally block.
1420 builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister( 1576 builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister(
1421 message); 1577 message);
1422 1578
1423 // Evaluate the finally-block. 1579 // Evaluate the finally-block.
1424 Visit(stmt->finally_block()); 1580 build_finally();
1425 try_control_builder.EndFinally(); 1581 try_control_builder.EndFinally();
1426 1582
1427 // Pending message object is restored on exit. 1583 // Pending message object is restored on exit.
1428 builder()->LoadAccumulatorWithRegister(message).SetPendingMessage(); 1584 builder()->LoadAccumulatorWithRegister(message).SetPendingMessage();
1429 1585
1430 // Dynamic dispatch after the finally-block. 1586 // Dynamic dispatch after the finally-block.
1431 commands.ApplyDeferredCommands(); 1587 commands.ApplyDeferredCommands();
1432 } 1588 }
1433 1589
1590 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1591 BuildTryFinally(stmt->catch_prediction(), [=]() { Visit(stmt->try_block()); },
1592 [=]() { Visit(stmt->finally_block()); });
1593 }
1594
1595 void BytecodeGenerator::BuildTryCatchFinally(
1596 HandlerTable::CatchPrediction outer_catch_prediction,
1597 HandlerTable::CatchPrediction inner_catch_prediction,
1598 std::function<void()> build_try, std::function<void(Register)> build_catch,
1599 std::function<void()> build_finally) {
1600 BuildTryFinally(
1601 outer_catch_prediction,
1602 [=]() { BuildTryCatch(inner_catch_prediction, build_try, build_catch); },
1603 build_finally);
1604 }
1605
1434 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 1606 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1435 builder()->SetStatementPosition(stmt); 1607 builder()->SetStatementPosition(stmt);
1436 builder()->Debugger(); 1608 builder()->Debugger();
1437 } 1609 }
1438 1610
1439 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 1611 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1440 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), 1612 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(),
1441 scope()->is_function_scope()); 1613 scope()->is_function_scope());
1442 size_t entry = builder()->AllocateConstantPoolEntry(); 1614 size_t entry = builder()->AllocateConstantPoolEntry();
1443 int slot_index = feedback_index(expr->LiteralFeedbackSlot()); 1615 int slot_index = feedback_index(expr->LiteralFeedbackSlot());
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1982 } 2154 }
1983 2155
1984 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( 2156 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
1985 Variable* variable, FeedbackVectorSlot slot, HoleCheckMode hole_check_mode, 2157 Variable* variable, FeedbackVectorSlot slot, HoleCheckMode hole_check_mode,
1986 TypeofMode typeof_mode) { 2158 TypeofMode typeof_mode) {
1987 ValueResultScope accumulator_result(this); 2159 ValueResultScope accumulator_result(this);
1988 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode); 2160 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode);
1989 } 2161 }
1990 2162
1991 void BytecodeGenerator::BuildReturn() { 2163 void BytecodeGenerator::BuildReturn() {
1992 if (FLAG_trace) { 2164 if (IsAsyncFunction(info()->literal()->kind())) {
1993 RegisterAllocationScope register_scope(this); 2165 RegisterList args = register_allocator()->NewRegisterList(3);
1994 Register result = register_allocator()->NewRegister(); 2166 Register receiver = args[0];
1995 // Runtime returns {result} value, preserving accumulator. 2167 Register promise = args[1];
1996 builder()->StoreAccumulatorInRegister(result).CallRuntime( 2168 Register return_value = args[2];
1997 Runtime::kTraceExit, result); 2169
2170 builder()
2171 ->StoreAccumulatorInRegister(return_value)
2172 .LoadUndefined()
2173 .StoreAccumulatorInRegister(receiver)
2174 .MoveRegister(promise_, promise)
2175 .CallJSRuntime(Context::PROMISE_RESOLVE_INDEX, args)
2176 .LoadAccumulatorWithRegister(promise);
1998 } 2177 }
2178
2179 BuildTraceExit();
1999 builder()->Return(); 2180 builder()->Return();
2000 } 2181 }
2001 2182
2183 void BytecodeGenerator::BuildTraceExit() {
2184 if (!FLAG_trace) return;
2185 RegisterAllocationScope register_scope(this);
2186 Register result = register_allocator()->NewRegister();
2187 // Runtime returns {result} value, preserving accumulator.
2188 builder()->StoreAccumulatorInRegister(result).CallRuntime(Runtime::kTraceExit,
2189 result);
2190 }
2191
2002 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); } 2192 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
2003 2193
2004 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { 2194 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
2005 RegisterAllocationScope register_scope(this); 2195 RegisterAllocationScope register_scope(this);
2006 Register reason = register_allocator()->NewRegister(); 2196 Register reason = register_allocator()->NewRegister();
2007 builder() 2197 builder()
2008 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) 2198 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
2009 .StoreAccumulatorInRegister(reason) 2199 .StoreAccumulatorInRegister(reason)
2010 .CallRuntime(Runtime::kAbort, reason); 2200 .CallRuntime(Runtime::kAbort, reason);
2011 } 2201 }
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 } 2468 }
2279 case KEYED_SUPER_PROPERTY: { 2469 case KEYED_SUPER_PROPERTY: {
2280 builder() 2470 builder()
2281 ->StoreAccumulatorInRegister(super_property_args[3]) 2471 ->StoreAccumulatorInRegister(super_property_args[3])
2282 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); 2472 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
2283 break; 2473 break;
2284 } 2474 }
2285 } 2475 }
2286 } 2476 }
2287 2477
2288 void BytecodeGenerator::VisitYield(Yield* expr) { 2478 void BytecodeGenerator::BuildYield(int yield_id,
2289 builder()->SetExpressionPosition(expr); 2479 Yield::OnException on_exception,
2290 Register value = VisitForRegisterValue(expr->expression()); 2480 Yield::YieldType yield_type, Register value,
2481 int position) {
2482 DCHECK_GE(yield_id, 0);
2483 DCHECK_LT(yield_id, generator_resume_points_.size());
2291 2484
2292 Register generator = VisitForRegisterValue(expr->generator_object()); 2485 Register generator = generator_object_;
2486 DCHECK(generator.is_valid());
2293 2487
2294 // Save context, registers, and state. Then return. 2488 if (IsAsyncFunction(info()->literal()->kind()) &&
2295 builder() 2489 yield_type == Yield::kAwait) {
2296 ->LoadLiteral(Smi::FromInt(expr->yield_id())) 2490 RegisterAllocationScope register_scope(this);
2297 .SuspendGenerator(generator) 2491 RegisterList args = register_allocator()->NewRegisterList(4);
2298 .LoadAccumulatorWithRegister(value)
2299 .Return(); // Hard return (ignore any finally blocks).
2300 2492
2301 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); 2493 int context_index = Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX;
2494 if (catch_prediction_ == HandlerTable::ASYNC_AWAIT)
2495 context_index = Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX;
2496
2497 builder()
2498 ->LoadUndefined()
2499 .StoreAccumulatorInRegister(args[0])
2500 .MoveRegister(generator, args[1])
2501 .MoveRegister(value, args[2])
2502 .MoveRegister(promise_, args[3])
2503 .CallJSRuntime(context_index, args)
2504 .LoadLiteral(Smi::FromInt(yield_id))
2505 .SuspendGenerator(generator)
2506 .LoadAccumulatorWithRegister(promise_)
2507 .Return(); // Hard return (ignore any finally blocks)
2508 } else {
2509 // Save context, registers, and state. Then return.
2510 builder()
2511 ->LoadLiteral(Smi::FromInt(yield_id))
2512 .SuspendGenerator(generator)
2513 .LoadAccumulatorWithRegister(value)
2514 .Return(); // Hard return (ignore any finally blocks).
2515 }
2516
2517 builder()->Bind(&(generator_resume_points_[yield_id]));
2302 // Upon resume, we continue here. 2518 // Upon resume, we continue here.
2303 2519
2304 { 2520 {
2305 RegisterAllocationScope register_scope(this); 2521 RegisterAllocationScope register_scope(this);
2306 2522
2307 // Update state to indicate that we have finished resuming. Loop headers 2523 // Update state to indicate that we have finished resuming. Loop headers
2308 // rely on this. 2524 // rely on this.
2309 builder() 2525 builder()
2310 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 2526 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
2311 .StoreAccumulatorInRegister(generator_state_); 2527 .StoreAccumulatorInRegister(generator_state_);
(...skipping 28 matching lines...) Expand all
2340 RegisterList args = register_allocator()->NewRegisterList(2); 2556 RegisterList args = register_allocator()->NewRegisterList(2);
2341 builder() 2557 builder()
2342 ->MoveRegister(input, args[0]) 2558 ->MoveRegister(input, args[0])
2343 .LoadTrue() 2559 .LoadTrue()
2344 .StoreAccumulatorInRegister(args[1]) 2560 .StoreAccumulatorInRegister(args[1])
2345 .CallRuntime(Runtime::kInlineCreateIterResultObject, args); 2561 .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
2346 execution_control()->ReturnAccumulator(); 2562 execution_control()->ReturnAccumulator();
2347 } 2563 }
2348 2564
2349 builder()->Bind(&resume_with_throw); 2565 builder()->Bind(&resume_with_throw);
2350 builder()->SetExpressionPosition(expr); 2566 builder()->SetExpressionPosition(position);
2351 builder()->LoadAccumulatorWithRegister(input); 2567 builder()->LoadAccumulatorWithRegister(input);
2352 if (expr->rethrow_on_exception()) { 2568 if (on_exception == Yield::kOnExceptionRethrow) {
2353 builder()->ReThrow(); 2569 builder()->ReThrow();
2354 } else { 2570 } else {
2355 builder()->Throw(); 2571 builder()->Throw();
2356 } 2572 }
2357 2573
2358 builder()->Bind(&resume_with_next); 2574 builder()->Bind(&resume_with_next);
2359 builder()->LoadAccumulatorWithRegister(input); 2575 builder()->LoadAccumulatorWithRegister(input);
2360 } 2576 }
2361 } 2577 }
2362 2578
2579 void BytecodeGenerator::VisitYield(Yield* expr) {
2580 builder()->SetExpressionPosition(expr);
2581 Register value = VisitForRegisterValue(expr->expression());
2582
2583 BuildYield(expr->yield_id(), expr->on_exception(), expr->yield_type(), value,
2584 expr->position());
2585 }
2586
2363 void BytecodeGenerator::VisitThrow(Throw* expr) { 2587 void BytecodeGenerator::VisitThrow(Throw* expr) {
2364 VisitForAccumulatorValue(expr->exception()); 2588 VisitForAccumulatorValue(expr->exception());
2365 builder()->SetExpressionPosition(expr); 2589 builder()->SetExpressionPosition(expr);
2366 builder()->Throw(); 2590 builder()->Throw();
2367 } 2591 }
2368 2592
2369 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 2593 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2370 LhsKind property_kind = Property::GetAssignType(expr); 2594 LhsKind property_kind = Property::GetAssignType(expr);
2371 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 2595 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
2372 builder()->SetExpressionPosition(expr); 2596 builder()->SetExpressionPosition(expr);
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
2925 builder()->SetExpressionPosition(expr); 3149 builder()->SetExpressionPosition(expr);
2926 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); 3150 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
2927 } 3151 }
2928 3152
2929 void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); } 3153 void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); }
2930 3154
2931 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 3155 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
2932 UNREACHABLE(); 3156 UNREACHABLE();
2933 } 3157 }
2934 3158
3159 void BytecodeGenerator::VisitInternalVariable(InternalVariable* expr) {
3160 switch (expr->type()) {
3161 case InternalVariable::kGeneratorObject:
3162 DCHECK(IsGeneratorFunction(info()->literal()->kind()));
3163 builder()->LoadAccumulatorWithRegister(generator_object_);
3164 return;
3165
3166 default:
3167 break;
3168 }
3169
3170 UNREACHABLE();
3171 }
3172
2935 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { 3173 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
2936 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); 3174 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot();
2937 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); 3175 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot();
2938 3176
2939 RegisterList args = register_allocator()->NewRegisterList(1); 3177 RegisterList args = register_allocator()->NewRegisterList(1);
2940 Register method = register_allocator()->NewRegister(); 3178 Register method = register_allocator()->NewRegister();
2941 Register obj = args[0]; 3179 Register obj = args[0];
2942 3180
2943 VisitForAccumulatorValue(expr->iterable()); 3181 VisitForAccumulatorValue(expr->iterable());
2944 3182
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
3375 } 3613 }
3376 3614
3377 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3615 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3378 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3616 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3379 : Runtime::kStoreKeyedToSuper_Sloppy; 3617 : Runtime::kStoreKeyedToSuper_Sloppy;
3380 } 3618 }
3381 3619
3382 } // namespace interpreter 3620 } // namespace interpreter
3383 } // namespace internal 3621 } // namespace internal
3384 } // namespace v8 3622 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698