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

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

Issue 2654423004: [async-functions] support await expressions in finally statements (Closed)
Patch Set: I'd like to build with -Wunused-variables locally, but how!? 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
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/parsing/parser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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, generator_object_,
799 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 BuildTryCatchFinally(HandlerTable::ASYNC_AWAIT, try_block, catch_block,
856 finally_block);
857 } else if (kIsGeneratorFunction) {
858 BuildTryFinally(try_block, finally_block);
859 } else {
860 DCHECK(kIsModule);
861 try_block();
862 }
863 return;
864 }
865
742 // Visit statements in the function body. 866 // Visit statements in the function body.
867 if (parameter_init_block != nullptr) {
868 VisitBlock(parameter_init_block);
869 }
743 VisitStatements(info()->literal()->body()); 870 VisitStatements(info()->literal()->body());
744 } 871 }
745 872
746 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, 873 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
747 size_t size, 874 size_t size,
748 ZoneVector<BytecodeLabel>& targets) { 875 ZoneVector<BytecodeLabel>& targets) {
749 // TODO(neis): Optimize this by using a proper jump table. 876 // TODO(neis): Optimize this by using a proper jump table.
750 DCHECK_LE(start_index + size, targets.size()); 877 DCHECK_LE(start_index + size, targets.size());
751 for (size_t i = start_index; i < start_index + size; i++) { 878 for (size_t i = start_index; i < start_index + size; i++) {
752 builder() 879 builder()
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 .PushContext(dummy) 939 .PushContext(dummy)
813 .ResumeGenerator(generator_object) 940 .ResumeGenerator(generator_object)
814 .StoreAccumulatorInRegister(generator_state_); 941 .StoreAccumulatorInRegister(generator_state_);
815 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(), 942 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
816 generator_resume_points_); 943 generator_resume_points_);
817 944
818 builder() 945 builder()
819 ->Bind(&regular_call) 946 ->Bind(&regular_call)
820 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 947 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
821 .StoreAccumulatorInRegister(generator_state_); 948 .StoreAccumulatorInRegister(generator_state_);
949
950 if (IsAsyncFunction(info()->literal()->kind())) {
951 // Create initial async function promise
952 RegisterAllocationScope register_scope(this);
953 RegisterList args = register_allocator()->NewRegisterList(1);
954 builder()
955 ->LoadUndefined()
956 .StoreAccumulatorInRegister(args[0])
957 .CallJSRuntime(Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX, args)
958 .StoreAccumulatorInRegister(promise_);
959 }
960
822 // This is a regular call. Fall through to the ordinary function prologue, 961 // 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 962 // after which we will run into the generator object creation and other extra
824 // code inserted by the parser. 963 // code inserted by the parser.
825 } 964 }
826 965
827 void BytecodeGenerator::VisitBlock(Block* stmt) { 966 void BytecodeGenerator::VisitBlock(Block* stmt) {
828 // Visit declarations and statements. 967 // Visit declarations and statements.
829 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { 968 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
830 BuildNewLocalBlockContext(stmt->scope()); 969 BuildNewLocalBlockContext(stmt->scope());
831 ContextScope scope(this, stmt->scope()); 970 ContextScope scope(this, stmt->scope());
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 VisitForEffect(stmt->next_result()); 1466 VisitForEffect(stmt->next_result());
1328 VisitForAccumulatorValue(stmt->result_done()); 1467 VisitForAccumulatorValue(stmt->result_done());
1329 loop_builder.BreakIfTrue(); 1468 loop_builder.BreakIfTrue();
1330 1469
1331 VisitForEffect(stmt->assign_each()); 1470 VisitForEffect(stmt->assign_each());
1332 VisitIterationBody(stmt, &loop_builder); 1471 VisitIterationBody(stmt, &loop_builder);
1333 loop_builder.JumpToHeader(loop_depth_); 1472 loop_builder.JumpToHeader(loop_depth_);
1334 loop_builder.EndLoop(); 1473 loop_builder.EndLoop();
1335 } 1474 }
1336 1475
1337 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 1476 void BytecodeGenerator::BuildTryCatch(
1338 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); 1477 HandlerTable::CatchPrediction catch_prediction,
1478 std::function<void()> build_try,
1479 std::function<void(Register)> build_catch) {
1480 TryCatchBuilder try_control_builder(builder(), catch_prediction);
1339 1481
1340 // Preserve the context in a dedicated register, so that it can be restored 1482 // Preserve the context in a dedicated register, so that it can be restored
1341 // when the handler is entered by the stack-unwinding machinery. 1483 // when the handler is entered by the stack-unwinding machinery.
1342 // TODO(mstarzinger): Be smarter about register allocation. 1484 // TODO(mstarzinger): Be smarter about register allocation.
1343 Register context = register_allocator()->NewRegister(); 1485 Register context = register_allocator()->NewRegister();
1344 builder()->MoveRegister(Register::current_context(), context); 1486 builder()->MoveRegister(Register::current_context(), context);
1345 1487
1346 // Evaluate the try-block inside a control scope. This simulates a handler 1488 // Evaluate the try-block inside a control scope. This simulates a handler
1347 // that is intercepting 'throw' control commands. 1489 // that is intercepting 'throw' control commands.
1348 try_control_builder.BeginTry(context); 1490 try_control_builder.BeginTry(context);
1349 { 1491 {
1350 ControlScopeForTryCatch scope(this, &try_control_builder); 1492 ControlScopeForTryCatch scope(this, &try_control_builder);
1351 Visit(stmt->try_block()); 1493 if (catch_prediction == HandlerTable::UNCAUGHT) {
1494 catch_prediction = catch_prediction_;
1495 }
1496 ScopedAssignment<HandlerTable::CatchPrediction> prediction(
1497 catch_prediction_, catch_prediction);
1498 build_try();
1352 } 1499 }
1353 try_control_builder.EndTry(); 1500 try_control_builder.EndTry();
1354 1501
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. 1502 // Evaluate the catch-block.
1368 VisitInScope(stmt->catch_block(), stmt->scope()); 1503 build_catch(context);
1369 try_control_builder.EndCatch(); 1504 try_control_builder.EndCatch();
1370 } 1505 }
1371 1506
1372 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1507 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1373 TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction()); 1508 BuildTryCatch(stmt->catch_prediction(), [=]() { Visit(stmt->try_block()); },
1509 [=](Register context) {
1510 // Create a catch scope that binds the exception.
1511 BuildNewLocalCatchContext(stmt->variable(), stmt->scope());
1512 builder()->StoreAccumulatorInRegister(context);
1513
1514 // If requested, clear message object as we enter the catch
1515 // block.
1516 if (stmt->clear_pending_message()) {
1517 builder()->LoadTheHole().SetPendingMessage();
1518 }
1519
1520 // Load the catch context into the accumulator.
1521 builder()->LoadAccumulatorWithRegister(context);
1522
1523 VisitInScope(stmt->catch_block(), stmt->scope());
1524 });
1525 }
1526
1527 void BytecodeGenerator::BuildTryFinally(std::function<void()> build_try,
1528 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([=]() { Visit(stmt->try_block()); },
1592 [=]() { Visit(stmt->finally_block()); });
1593 }
1594
1595 void BytecodeGenerator::BuildTryCatchFinally(
1596 HandlerTable::CatchPrediction catch_prediction,
1597 std::function<void()> build_try, std::function<void(Register)> build_catch,
1598 std::function<void()> build_finally) {
1599 BuildTryFinally(
1600 [=]() { BuildTryCatch(catch_prediction, build_try, build_catch); },
1601 build_finally);
1602 }
1603
1434 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 1604 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1435 builder()->SetStatementPosition(stmt); 1605 builder()->SetStatementPosition(stmt);
1436 builder()->Debugger(); 1606 builder()->Debugger();
1437 } 1607 }
1438 1608
1439 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 1609 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1440 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), 1610 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(),
1441 scope()->is_function_scope()); 1611 scope()->is_function_scope());
1442 size_t entry = builder()->AllocateConstantPoolEntry(); 1612 size_t entry = builder()->AllocateConstantPoolEntry();
1443 int slot_index = feedback_index(expr->LiteralFeedbackSlot()); 1613 int slot_index = feedback_index(expr->LiteralFeedbackSlot());
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 } 2154 }
1985 2155
1986 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( 2156 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
1987 Variable* variable, FeedbackVectorSlot slot, HoleCheckMode hole_check_mode, 2157 Variable* variable, FeedbackVectorSlot slot, HoleCheckMode hole_check_mode,
1988 TypeofMode typeof_mode) { 2158 TypeofMode typeof_mode) {
1989 ValueResultScope accumulator_result(this); 2159 ValueResultScope accumulator_result(this);
1990 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode); 2160 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode);
1991 } 2161 }
1992 2162
1993 void BytecodeGenerator::BuildReturn() { 2163 void BytecodeGenerator::BuildReturn() {
1994 if (FLAG_trace) { 2164 if (IsAsyncFunction(info()->literal()->kind())) {
1995 RegisterAllocationScope register_scope(this); 2165 RegisterList args = register_allocator()->NewRegisterList(3);
1996 Register result = register_allocator()->NewRegister(); 2166 Register receiver = args[0];
1997 // Runtime returns {result} value, preserving accumulator. 2167 Register promise = args[1];
1998 builder()->StoreAccumulatorInRegister(result).CallRuntime( 2168 Register return_value = args[2];
1999 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);
2000 } 2177 }
2178
2179 BuildTraceExit();
2001 builder()->Return(); 2180 builder()->Return();
2002 } 2181 }
2003 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
2004 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); } 2192 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
2005 2193
2006 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { 2194 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
2007 RegisterAllocationScope register_scope(this); 2195 RegisterAllocationScope register_scope(this);
2008 Register reason = register_allocator()->NewRegister(); 2196 Register reason = register_allocator()->NewRegister();
2009 builder() 2197 builder()
2010 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) 2198 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
2011 .StoreAccumulatorInRegister(reason) 2199 .StoreAccumulatorInRegister(reason)
2012 .CallRuntime(Runtime::kAbort, reason); 2200 .CallRuntime(Runtime::kAbort, reason);
2013 } 2201 }
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2280 } 2468 }
2281 case KEYED_SUPER_PROPERTY: { 2469 case KEYED_SUPER_PROPERTY: {
2282 builder() 2470 builder()
2283 ->StoreAccumulatorInRegister(super_property_args[3]) 2471 ->StoreAccumulatorInRegister(super_property_args[3])
2284 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); 2472 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
2285 break; 2473 break;
2286 } 2474 }
2287 } 2475 }
2288 } 2476 }
2289 2477
2290 void BytecodeGenerator::VisitYield(Yield* expr) { 2478 void BytecodeGenerator::BuildYieldResumePoint(int yield_id,
2291 builder()->SetExpressionPosition(expr); 2479 Yield::OnException on_exception,
2292 Register value = VisitForRegisterValue(expr->expression()); 2480 int position) {
2481 DCHECK_GE(yield_id, 0);
2482 DCHECK_LT(yield_id, generator_resume_points_.size());
2293 2483
2294 Register generator = VisitForRegisterValue(expr->generator_object()); 2484 Register generator = generator_object_;
2485 DCHECK(generator.is_valid());
2295 2486
2296 // Save context, registers, and state. Then return. 2487 builder()->Bind(&(generator_resume_points_[yield_id]));
2297 builder()
2298 ->LoadLiteral(Smi::FromInt(expr->yield_id()))
2299 .SuspendGenerator(generator)
2300 .LoadAccumulatorWithRegister(value)
2301 .Return(); // Hard return (ignore any finally blocks).
2302
2303 builder()->Bind(&(generator_resume_points_[expr->yield_id()]));
2304 // Upon resume, we continue here. 2488 // Upon resume, we continue here.
2305 2489
2306 { 2490 {
2307 RegisterAllocationScope register_scope(this); 2491 RegisterAllocationScope register_scope(this);
2308 2492
2309 // Update state to indicate that we have finished resuming. Loop headers 2493 // Update state to indicate that we have finished resuming. Loop headers
2310 // rely on this. 2494 // rely on this.
2311 builder() 2495 builder()
2312 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 2496 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
2313 .StoreAccumulatorInRegister(generator_state_); 2497 .StoreAccumulatorInRegister(generator_state_);
(...skipping 28 matching lines...) Expand all
2342 RegisterList args = register_allocator()->NewRegisterList(2); 2526 RegisterList args = register_allocator()->NewRegisterList(2);
2343 builder() 2527 builder()
2344 ->MoveRegister(input, args[0]) 2528 ->MoveRegister(input, args[0])
2345 .LoadTrue() 2529 .LoadTrue()
2346 .StoreAccumulatorInRegister(args[1]) 2530 .StoreAccumulatorInRegister(args[1])
2347 .CallRuntime(Runtime::kInlineCreateIterResultObject, args); 2531 .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
2348 execution_control()->ReturnAccumulator(); 2532 execution_control()->ReturnAccumulator();
2349 } 2533 }
2350 2534
2351 builder()->Bind(&resume_with_throw); 2535 builder()->Bind(&resume_with_throw);
2352 builder()->SetExpressionPosition(expr); 2536 builder()->SetExpressionPosition(position);
2353 builder()->LoadAccumulatorWithRegister(input); 2537 builder()->LoadAccumulatorWithRegister(input);
2354 if (expr->rethrow_on_exception()) { 2538 if (on_exception == Yield::kOnExceptionRethrow) {
2355 builder()->ReThrow(); 2539 builder()->ReThrow();
2356 } else { 2540 } else {
2357 builder()->Throw(); 2541 builder()->Throw();
2358 } 2542 }
2359 2543
2360 builder()->Bind(&resume_with_next); 2544 builder()->Bind(&resume_with_next);
2361 builder()->LoadAccumulatorWithRegister(input); 2545 builder()->LoadAccumulatorWithRegister(input);
2362 } 2546 }
2363 } 2547 }
2364 2548
2549 void BytecodeGenerator::BuildYield(int yield_id,
2550 Yield::OnException on_exception,
2551 Register value, int position) {
2552 DCHECK_GE(yield_id, 0);
2553 DCHECK_LT(yield_id, generator_resume_points_.size());
2554
2555 Register generator = generator_object_;
2556 DCHECK(generator.is_valid());
2557
2558 // Save context, registers, and state. Then return.
2559 builder()
2560 ->LoadLiteral(Smi::FromInt(yield_id))
2561 .SuspendGenerator(generator)
2562 .LoadAccumulatorWithRegister(value)
2563 .Return(); // Hard return (ignore any finally blocks).
2564
2565 BuildYieldResumePoint(yield_id, on_exception, position);
2566 }
2567
2568 void BytecodeGenerator::BuildAwait(int yield_id,
2569 Yield::OnException on_exception,
2570 Register value, int position) {
2571 DCHECK_GE(yield_id, 0);
2572 DCHECK_LT(yield_id, generator_resume_points_.size());
2573
2574 Register generator = generator_object_;
2575 DCHECK(generator.is_valid());
2576
2577 int context_index = Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX;
2578 if (catch_prediction_ == HandlerTable::ASYNC_AWAIT) {
2579 context_index = Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX;
2580 }
2581
2582 {
2583 RegisterAllocationScope register_scope(this);
2584 RegisterList args = register_allocator()->NewRegisterList(4);
2585 builder()->SetStatementPosition(position);
2586 builder()
2587 ->LoadUndefined()
2588 .StoreAccumulatorInRegister(args[0])
2589 .MoveRegister(generator, args[1])
2590 .MoveRegister(value, args[2])
2591 .MoveRegister(promise_, args[3])
2592 .CallJSRuntime(context_index, args)
2593 .LoadLiteral(Smi::FromInt(yield_id))
2594 .SuspendGenerator(generator)
2595 .LoadAccumulatorWithRegister(promise_)
2596 .Return(); // Hard return (ignore any finally blocks)
2597 }
2598
2599 BuildYieldResumePoint(yield_id, on_exception, kNoSourcePosition);
2600 }
2601
2602 void BytecodeGenerator::VisitYield(Yield* expr) {
2603 if (expr->yield_type() == Yield::kAwait) {
2604 builder()->SetExpressionPosition(kNoSourcePosition);
2605 builder()->SetStatementPosition(expr->expression()->position());
2606 Register value = VisitForRegisterValue(expr->expression());
2607 BuildAwait(expr->yield_id(), expr->on_exception(), value, expr->position());
2608 } else {
2609 builder()->SetExpressionPosition(expr);
2610 Register value = VisitForRegisterValue(expr->expression());
2611 BuildYield(expr->yield_id(), expr->on_exception(), value, expr->position());
2612 }
2613 }
2614
2365 void BytecodeGenerator::VisitThrow(Throw* expr) { 2615 void BytecodeGenerator::VisitThrow(Throw* expr) {
2366 VisitForAccumulatorValue(expr->exception()); 2616 VisitForAccumulatorValue(expr->exception());
2367 builder()->SetExpressionPosition(expr); 2617 builder()->SetExpressionPosition(expr);
2368 builder()->Throw(); 2618 builder()->Throw();
2369 } 2619 }
2370 2620
2371 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 2621 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2372 LhsKind property_kind = Property::GetAssignType(expr); 2622 LhsKind property_kind = Property::GetAssignType(expr);
2373 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 2623 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
2374 builder()->SetExpressionPosition(expr); 2624 builder()->SetExpressionPosition(expr);
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
2927 builder()->SetExpressionPosition(expr); 3177 builder()->SetExpressionPosition(expr);
2928 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); 3178 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
2929 } 3179 }
2930 3180
2931 void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); } 3181 void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); }
2932 3182
2933 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 3183 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
2934 UNREACHABLE(); 3184 UNREACHABLE();
2935 } 3185 }
2936 3186
3187 void BytecodeGenerator::VisitInternalVariable(InternalVariable* expr) {
3188 switch (expr->type()) {
3189 case InternalVariable::kGeneratorObject:
3190 DCHECK(IsGeneratorFunction(info()->literal()->kind()));
3191 builder()->LoadAccumulatorWithRegister(generator_object_);
3192 return;
3193
3194 default:
3195 break;
3196 }
3197
3198 UNREACHABLE();
3199 }
3200
2937 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { 3201 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
2938 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); 3202 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot();
2939 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); 3203 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot();
2940 3204
2941 RegisterList args = register_allocator()->NewRegisterList(1); 3205 RegisterList args = register_allocator()->NewRegisterList(1);
2942 Register method = register_allocator()->NewRegister(); 3206 Register method = register_allocator()->NewRegister();
2943 Register obj = args[0]; 3207 Register obj = args[0];
2944 3208
2945 VisitForAccumulatorValue(expr->iterable()); 3209 VisitForAccumulatorValue(expr->iterable());
2946 3210
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
3377 } 3641 }
3378 3642
3379 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3643 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3380 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3644 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3381 : Runtime::kStoreKeyedToSuper_Sloppy; 3645 : Runtime::kStoreKeyedToSuper_Sloppy;
3382 } 3646 }
3383 3647
3384 } // namespace interpreter 3648 } // namespace interpreter
3385 } // namespace internal 3649 } // namespace internal
3386 } // namespace v8 3650 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/parsing/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698