| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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(®ular_call) | 948 ->Bind(®ular_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |