Chromium Code Reviews| 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/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
| 9 #include "src/interpreter/control-flow-builders.h" | 9 #include "src/interpreter/control-flow-builders.h" |
| 10 #include "src/objects.h" | 10 #include "src/objects.h" |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 } | 621 } |
| 622 | 622 |
| 623 | 623 |
| 624 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 624 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 625 } | 625 } |
| 626 | 626 |
| 627 | 627 |
| 628 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 628 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 629 BytecodeLabel else_label, end_label; | 629 BytecodeLabel else_label, end_label; |
| 630 if (stmt->condition()->ToBooleanIsTrue()) { | 630 if (stmt->condition()->ToBooleanIsTrue()) { |
| 631 // Generate only then block. | 631 // Generate then block unconditionally as always true. |
| 632 Visit(stmt->then_statement()); | 632 Visit(stmt->then_statement()); |
| 633 } else if (stmt->condition()->ToBooleanIsFalse()) { | 633 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 634 // Generate only else block if it exists. | 634 // Generate else block unconditionally if it exists. |
| 635 if (stmt->HasElseStatement()) { | 635 if (stmt->HasElseStatement()) { |
| 636 Visit(stmt->else_statement()); | 636 Visit(stmt->else_statement()); |
| 637 } | 637 } |
| 638 } else { | 638 } else { |
| 639 // TODO(oth): If then statement is BreakStatement or | |
| 640 // ContinueStatement we can reduce number of generated | |
| 641 // jump/jump_ifs here. See BasicLoops test. | |
| 639 VisitForAccumulatorValue(stmt->condition()); | 642 VisitForAccumulatorValue(stmt->condition()); |
| 640 builder()->JumpIfFalse(&else_label); | 643 builder()->JumpIfFalse(&else_label); |
| 641 Visit(stmt->then_statement()); | 644 Visit(stmt->then_statement()); |
| 642 if (stmt->HasElseStatement()) { | 645 if (stmt->HasElseStatement()) { |
| 643 builder()->Jump(&end_label); | 646 builder()->Jump(&end_label); |
| 644 builder()->Bind(&else_label); | 647 builder()->Bind(&else_label); |
| 645 Visit(stmt->else_statement()); | 648 Visit(stmt->else_statement()); |
| 646 } else { | 649 } else { |
| 647 builder()->Bind(&else_label); | 650 builder()->Bind(&else_label); |
| 648 } | 651 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 729 | 732 |
| 730 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 733 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 731 // Handled entirely in VisitSwitchStatement. | 734 // Handled entirely in VisitSwitchStatement. |
| 732 UNREACHABLE(); | 735 UNREACHABLE(); |
| 733 } | 736 } |
| 734 | 737 |
| 735 | 738 |
| 736 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 739 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 737 LoopBuilder loop_builder(builder()); | 740 LoopBuilder loop_builder(builder()); |
| 738 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 741 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
| 739 BytecodeLabel body_label, condition_label, done_label; | 742 loop_builder.LoopHeader(); |
| 740 if (stmt->cond()->ToBooleanIsFalse()) { | 743 if (stmt->cond()->ToBooleanIsFalse()) { |
| 741 Visit(stmt->body()); | 744 Visit(stmt->body()); |
| 742 // Bind condition_label and done_label for processing continue and break. | 745 loop_builder.Condition(); |
| 743 builder()->Bind(&condition_label); | |
| 744 builder()->Bind(&done_label); | |
| 745 } else { | 746 } else { |
| 746 builder()->Bind(&body_label); | |
| 747 Visit(stmt->body()); | |
| 748 | |
| 749 builder()->Bind(&condition_label); | |
| 750 if (stmt->cond()->ToBooleanIsTrue()) { | 747 if (stmt->cond()->ToBooleanIsTrue()) { |
|
rmcilroy
2015/12/15 17:35:44
nit - avoid nesting this if, just make it an "else
oth
2015/12/15 22:42:17
Done.
| |
| 751 builder()->Jump(&body_label); | 748 loop_builder.Condition(); |
| 749 Visit(stmt->body()); | |
| 750 loop_builder.JumpToHeader(); | |
| 752 } else { | 751 } else { |
| 752 Visit(stmt->body()); | |
| 753 loop_builder.Condition(); | |
| 753 VisitForAccumulatorValue(stmt->cond()); | 754 VisitForAccumulatorValue(stmt->cond()); |
| 754 builder()->JumpIfTrue(&body_label); | 755 loop_builder.JumpToHeaderIfTrue(); |
|
rmcilroy
2015/12/15 17:35:44
Any reason this can't be written as:
Visit(stmt-
oth
2015/12/15 22:42:17
The Condition() is the target for continue stateme
| |
| 755 } | 756 } |
| 756 builder()->Bind(&done_label); | |
| 757 } | 757 } |
| 758 loop_builder.SetBreakTarget(done_label); | 758 loop_builder.LoopEnd(); |
| 759 loop_builder.SetContinueTarget(condition_label); | |
| 760 } | 759 } |
| 761 | 760 |
| 762 | 761 |
| 763 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 762 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 764 LoopBuilder loop_builder(builder()); | |
| 765 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 766 | |
| 767 BytecodeLabel body_label, condition_label, done_label; | |
| 768 if (stmt->cond()->ToBooleanIsFalse()) { | 763 if (stmt->cond()->ToBooleanIsFalse()) { |
| 769 // If the condition is false there is no need to generate the loop. | 764 // If the condition is false there is no need to generate the loop. |
| 770 return; | 765 return; |
| 771 } | 766 } |
| 772 | 767 |
| 768 LoopBuilder loop_builder(builder()); | |
| 769 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 770 loop_builder.LoopHeader(); | |
| 771 loop_builder.Condition(); | |
| 773 if (!stmt->cond()->ToBooleanIsTrue()) { | 772 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 774 builder()->Jump(&condition_label); | 773 VisitForAccumulatorValue(stmt->cond()); |
| 774 loop_builder.BreakIfFalse(); | |
| 775 } | 775 } |
| 776 builder()->Bind(&body_label); | |
| 777 Visit(stmt->body()); | 776 Visit(stmt->body()); |
| 778 | 777 loop_builder.JumpToHeader(); |
| 779 builder()->Bind(&condition_label); | 778 loop_builder.LoopEnd(); |
| 780 if (stmt->cond()->ToBooleanIsTrue()) { | |
| 781 builder()->Jump(&body_label); | |
| 782 } else { | |
| 783 VisitForAccumulatorValue(stmt->cond()); | |
| 784 builder()->JumpIfTrue(&body_label); | |
| 785 } | |
| 786 builder()->Bind(&done_label); | |
| 787 | |
| 788 loop_builder.SetBreakTarget(done_label); | |
| 789 loop_builder.SetContinueTarget(condition_label); | |
| 790 } | 779 } |
| 791 | 780 |
| 792 | 781 |
| 793 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 782 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 794 LoopBuilder loop_builder(builder()); | |
| 795 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 796 | |
| 797 if (stmt->init() != nullptr) { | 783 if (stmt->init() != nullptr) { |
| 798 Visit(stmt->init()); | 784 Visit(stmt->init()); |
| 799 } | 785 } |
| 800 | |
| 801 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 786 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
| 802 // If the condition is known to be false there is no need to generate | 787 // If the condition is known to be false there is no need to generate |
| 803 // body, next or condition blocks. Init block should be generated. | 788 // body, next or condition blocks. Init block should be generated. |
| 804 return; | 789 return; |
| 805 } | 790 } |
| 806 | 791 |
| 807 BytecodeLabel body_label, condition_label, next_label, done_label; | 792 LoopBuilder loop_builder(builder()); |
| 793 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
| 794 | |
| 795 loop_builder.LoopHeader(); | |
| 796 loop_builder.Condition(); | |
| 808 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 797 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
| 809 builder()->Jump(&condition_label); | 798 VisitForAccumulatorValue(stmt->cond()); |
| 799 loop_builder.BreakIfFalse(); | |
| 810 } | 800 } |
| 811 builder()->Bind(&body_label); | |
| 812 Visit(stmt->body()); | 801 Visit(stmt->body()); |
| 813 builder()->Bind(&next_label); | |
| 814 if (stmt->next() != nullptr) { | 802 if (stmt->next() != nullptr) { |
| 803 loop_builder.Next(); | |
| 815 Visit(stmt->next()); | 804 Visit(stmt->next()); |
| 816 } | 805 } |
| 817 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 806 loop_builder.JumpToHeader(); |
| 818 builder()->Bind(&condition_label); | 807 loop_builder.LoopEnd(); |
| 819 VisitForAccumulatorValue(stmt->cond()); | |
| 820 builder()->JumpIfTrue(&body_label); | |
| 821 } else { | |
| 822 builder()->Jump(&body_label); | |
| 823 } | |
| 824 builder()->Bind(&done_label); | |
| 825 | |
| 826 loop_builder.SetBreakTarget(done_label); | |
| 827 loop_builder.SetContinueTarget(next_label); | |
| 828 } | 808 } |
| 829 | 809 |
| 830 | 810 |
| 831 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 811 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
| 832 FeedbackVectorSlot slot) { | 812 FeedbackVectorSlot slot) { |
| 833 DCHECK(expr->IsValidReferenceExpression()); | 813 DCHECK(expr->IsValidReferenceExpression()); |
| 834 | 814 |
| 835 // Evaluate assignment starting with the value to be stored in the | 815 // Evaluate assignment starting with the value to be stored in the |
| 836 // accumulator. | 816 // accumulator. |
| 837 Property* property = expr->AsProperty(); | 817 Property* property = expr->AsProperty(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 Register receiver = execution_result()->NewRegister(); | 871 Register receiver = execution_result()->NewRegister(); |
| 892 builder()->CastAccumulatorToJSObject(); | 872 builder()->CastAccumulatorToJSObject(); |
| 893 builder()->StoreAccumulatorInRegister(receiver); | 873 builder()->StoreAccumulatorInRegister(receiver); |
| 894 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); | 874 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); |
| 895 builder()->ForInPrepare(receiver); | 875 builder()->ForInPrepare(receiver); |
| 896 loop_builder.BreakIfUndefined(); | 876 loop_builder.BreakIfUndefined(); |
| 897 | 877 |
| 898 Register for_in_state = execution_result()->NewRegister(); | 878 Register for_in_state = execution_result()->NewRegister(); |
| 899 builder()->StoreAccumulatorInRegister(for_in_state); | 879 builder()->StoreAccumulatorInRegister(for_in_state); |
| 900 | 880 |
| 901 // The loop. | 881 // Check loop termination (accumulator holds index). |
| 902 BytecodeLabel condition_label, break_label, continue_label; | |
| 903 Register index = receiver; // Re-using register as receiver no longer used. | 882 Register index = receiver; // Re-using register as receiver no longer used. |
| 904 builder()->LoadLiteral(Smi::FromInt(0)); | 883 builder()->LoadLiteral(Smi::FromInt(0)); |
| 905 | 884 loop_builder.LoopHeader(); |
| 906 // Check loop termination (accumulator holds index). | 885 loop_builder.Condition(); |
| 907 builder() | 886 builder()->StoreAccumulatorInRegister(index).ForInDone(for_in_state); |
| 908 ->Bind(&condition_label) | |
| 909 .StoreAccumulatorInRegister(index) | |
| 910 .ForInDone(for_in_state); | |
| 911 loop_builder.BreakIfTrue(); | 887 loop_builder.BreakIfTrue(); |
| 912 | |
| 913 // Get the next item. | |
| 914 builder()->ForInNext(for_in_state, index); | 888 builder()->ForInNext(for_in_state, index); |
| 915 | |
| 916 // Start again if the item, currently in the accumulator, is undefined. | |
| 917 loop_builder.ContinueIfUndefined(); | 889 loop_builder.ContinueIfUndefined(); |
| 918 | 890 |
| 919 // Store the value in the each variable. | |
| 920 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 891 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
| 921 // NB the user's loop variable will be assigned the value of each so | |
| 922 // even an empty body will have this assignment. | |
| 923 Visit(stmt->body()); | 892 Visit(stmt->body()); |
| 924 | 893 |
| 925 // Increment the index and start loop again. | 894 // TODO(oth): replace CountOperation here with ForInStep. |
| 926 builder() | 895 loop_builder.Next(); |
| 927 ->Bind(&continue_label) | 896 builder()->LoadAccumulatorWithRegister(index).CountOperation( |
| 928 .LoadAccumulatorWithRegister(index) | 897 Token::Value::ADD, language_mode_strength()); |
| 929 .CountOperation(Token::Value::ADD, language_mode_strength()) | 898 loop_builder.JumpToHeader(); |
| 930 .Jump(&condition_label); | 899 loop_builder.LoopEnd(); |
| 931 | |
| 932 // End of the loop. | |
| 933 builder()->Bind(&break_label); | |
| 934 | |
| 935 loop_builder.SetBreakTarget(break_label); | |
| 936 loop_builder.SetContinueTarget(continue_label); | |
| 937 } | 900 } |
| 938 | 901 |
| 939 | 902 |
| 940 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 903 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
| 941 UNIMPLEMENTED(); | 904 UNIMPLEMENTED(); |
| 942 } | 905 } |
| 943 | 906 |
| 944 | 907 |
| 945 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 908 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 946 if (FLAG_ignition_fake_try_catch) { | 909 if (FLAG_ignition_fake_try_catch) { |
| (...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2237 } | 2200 } |
| 2238 | 2201 |
| 2239 | 2202 |
| 2240 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2203 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2241 return info()->feedback_vector()->GetIndex(slot); | 2204 return info()->feedback_vector()->GetIndex(slot); |
| 2242 } | 2205 } |
| 2243 | 2206 |
| 2244 } // namespace interpreter | 2207 } // namespace interpreter |
| 2245 } // namespace internal | 2208 } // namespace internal |
| 2246 } // namespace v8 | 2209 } // namespace v8 |
| OLD | NEW |