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); | 746 } else if (stmt->cond()->ToBooleanIsTrue()) { |
744 builder()->Bind(&done_label); | 747 loop_builder.Condition(); |
| 748 Visit(stmt->body()); |
| 749 loop_builder.JumpToHeader(); |
745 } else { | 750 } else { |
746 builder()->Bind(&body_label); | |
747 Visit(stmt->body()); | 751 Visit(stmt->body()); |
748 | 752 loop_builder.Condition(); |
749 builder()->Bind(&condition_label); | 753 VisitForAccumulatorValue(stmt->cond()); |
750 if (stmt->cond()->ToBooleanIsTrue()) { | 754 loop_builder.JumpToHeaderIfTrue(); |
751 builder()->Jump(&body_label); | |
752 } else { | |
753 VisitForAccumulatorValue(stmt->cond()); | |
754 builder()->JumpIfTrue(&body_label); | |
755 } | |
756 builder()->Bind(&done_label); | |
757 } | 755 } |
758 loop_builder.SetBreakTarget(done_label); | 756 loop_builder.LoopEnd(); |
759 loop_builder.SetContinueTarget(condition_label); | |
760 } | 757 } |
761 | 758 |
762 | 759 |
763 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 760 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()) { | 761 if (stmt->cond()->ToBooleanIsFalse()) { |
769 // If the condition is false there is no need to generate the loop. | 762 // If the condition is false there is no need to generate the loop. |
770 return; | 763 return; |
771 } | 764 } |
772 | 765 |
| 766 LoopBuilder loop_builder(builder()); |
| 767 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
| 768 loop_builder.LoopHeader(); |
| 769 loop_builder.Condition(); |
773 if (!stmt->cond()->ToBooleanIsTrue()) { | 770 if (!stmt->cond()->ToBooleanIsTrue()) { |
774 builder()->Jump(&condition_label); | 771 VisitForAccumulatorValue(stmt->cond()); |
| 772 loop_builder.BreakIfFalse(); |
775 } | 773 } |
776 builder()->Bind(&body_label); | |
777 Visit(stmt->body()); | 774 Visit(stmt->body()); |
778 | 775 loop_builder.JumpToHeader(); |
779 builder()->Bind(&condition_label); | 776 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 } | 777 } |
791 | 778 |
792 | 779 |
793 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 780 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
794 LoopBuilder loop_builder(builder()); | |
795 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
796 | |
797 if (stmt->init() != nullptr) { | 781 if (stmt->init() != nullptr) { |
798 Visit(stmt->init()); | 782 Visit(stmt->init()); |
799 } | 783 } |
800 | |
801 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 784 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
802 // If the condition is known to be false there is no need to generate | 785 // 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. | 786 // body, next or condition blocks. Init block should be generated. |
804 return; | 787 return; |
805 } | 788 } |
806 | 789 |
807 BytecodeLabel body_label, condition_label, next_label, done_label; | 790 LoopBuilder loop_builder(builder()); |
| 791 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
| 792 |
| 793 loop_builder.LoopHeader(); |
| 794 loop_builder.Condition(); |
808 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 795 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
809 builder()->Jump(&condition_label); | 796 VisitForAccumulatorValue(stmt->cond()); |
| 797 loop_builder.BreakIfFalse(); |
810 } | 798 } |
811 builder()->Bind(&body_label); | |
812 Visit(stmt->body()); | 799 Visit(stmt->body()); |
813 builder()->Bind(&next_label); | |
814 if (stmt->next() != nullptr) { | 800 if (stmt->next() != nullptr) { |
| 801 loop_builder.Next(); |
815 Visit(stmt->next()); | 802 Visit(stmt->next()); |
816 } | 803 } |
817 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 804 loop_builder.JumpToHeader(); |
818 builder()->Bind(&condition_label); | 805 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 } | 806 } |
829 | 807 |
830 | 808 |
831 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 809 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
832 FeedbackVectorSlot slot) { | 810 FeedbackVectorSlot slot) { |
833 DCHECK(expr->IsValidReferenceExpression()); | 811 DCHECK(expr->IsValidReferenceExpression()); |
834 | 812 |
835 // Evaluate assignment starting with the value to be stored in the | 813 // Evaluate assignment starting with the value to be stored in the |
836 // accumulator. | 814 // accumulator. |
837 Property* property = expr->AsProperty(); | 815 Property* property = expr->AsProperty(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 Register receiver = execution_result()->NewRegister(); | 869 Register receiver = execution_result()->NewRegister(); |
892 builder()->CastAccumulatorToJSObject(); | 870 builder()->CastAccumulatorToJSObject(); |
893 builder()->StoreAccumulatorInRegister(receiver); | 871 builder()->StoreAccumulatorInRegister(receiver); |
894 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); | 872 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); |
895 builder()->ForInPrepare(receiver); | 873 builder()->ForInPrepare(receiver); |
896 loop_builder.BreakIfUndefined(); | 874 loop_builder.BreakIfUndefined(); |
897 | 875 |
898 Register for_in_state = execution_result()->NewRegister(); | 876 Register for_in_state = execution_result()->NewRegister(); |
899 builder()->StoreAccumulatorInRegister(for_in_state); | 877 builder()->StoreAccumulatorInRegister(for_in_state); |
900 | 878 |
901 // The loop. | 879 // 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. | 880 Register index = receiver; // Re-using register as receiver no longer used. |
904 builder()->LoadLiteral(Smi::FromInt(0)); | 881 builder()->LoadLiteral(Smi::FromInt(0)); |
905 | 882 loop_builder.LoopHeader(); |
906 // Check loop termination (accumulator holds index). | 883 loop_builder.Condition(); |
907 builder() | 884 builder()->StoreAccumulatorInRegister(index).ForInDone(for_in_state); |
908 ->Bind(&condition_label) | |
909 .StoreAccumulatorInRegister(index) | |
910 .ForInDone(for_in_state); | |
911 loop_builder.BreakIfTrue(); | 885 loop_builder.BreakIfTrue(); |
912 | |
913 // Get the next item. | |
914 builder()->ForInNext(for_in_state, index); | 886 builder()->ForInNext(for_in_state, index); |
915 | |
916 // Start again if the item, currently in the accumulator, is undefined. | |
917 loop_builder.ContinueIfUndefined(); | 887 loop_builder.ContinueIfUndefined(); |
918 | 888 |
919 // Store the value in the each variable. | |
920 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 889 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()); | 890 Visit(stmt->body()); |
924 | 891 |
925 // Increment the index and start loop again. | 892 // TODO(oth): replace CountOperation here with ForInStep. |
926 builder() | 893 loop_builder.Next(); |
927 ->Bind(&continue_label) | 894 builder()->LoadAccumulatorWithRegister(index).CountOperation( |
928 .LoadAccumulatorWithRegister(index) | 895 Token::Value::ADD, language_mode_strength()); |
929 .CountOperation(Token::Value::ADD, language_mode_strength()) | 896 loop_builder.JumpToHeader(); |
930 .Jump(&condition_label); | 897 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 } | 898 } |
938 | 899 |
939 | 900 |
940 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 901 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
941 UNIMPLEMENTED(); | 902 UNIMPLEMENTED(); |
942 } | 903 } |
943 | 904 |
944 | 905 |
945 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 906 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
946 if (FLAG_ignition_fake_try_catch) { | 907 if (FLAG_ignition_fake_try_catch) { |
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2237 } | 2198 } |
2238 | 2199 |
2239 | 2200 |
2240 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2201 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2241 return info()->feedback_vector()->GetIndex(slot); | 2202 return info()->feedback_vector()->GetIndex(slot); |
2242 } | 2203 } |
2243 | 2204 |
2244 } // namespace interpreter | 2205 } // namespace interpreter |
2245 } // namespace internal | 2206 } // namespace internal |
2246 } // namespace v8 | 2207 } // namespace v8 |
OLD | NEW |