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/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 | 603 |
604 // Visit illegal re-declaration and bail out if it exists. | 604 // Visit illegal re-declaration and bail out if it exists. |
605 if (scope()->HasIllegalRedeclaration()) { | 605 if (scope()->HasIllegalRedeclaration()) { |
606 VisitForEffect(scope()->GetIllegalRedeclaration()); | 606 VisitForEffect(scope()->GetIllegalRedeclaration()); |
607 return; | 607 return; |
608 } | 608 } |
609 | 609 |
610 // Visit declarations within the function scope. | 610 // Visit declarations within the function scope. |
611 VisitDeclarations(scope()->declarations()); | 611 VisitDeclarations(scope()->declarations()); |
612 | 612 |
| 613 // Perform a stack-check before the body. |
| 614 builder()->StackCheck(); |
| 615 |
613 // Visit statements in the function body. | 616 // Visit statements in the function body. |
614 VisitStatements(info()->literal()->body()); | 617 VisitStatements(info()->literal()->body()); |
615 } | 618 } |
616 | 619 |
617 | 620 |
618 void BytecodeGenerator::VisitBlock(Block* stmt) { | 621 void BytecodeGenerator::VisitBlock(Block* stmt) { |
619 // Visit declarations and statements. | 622 // Visit declarations and statements. |
620 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { | 623 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { |
621 VisitNewLocalBlockContext(stmt->scope()); | 624 VisitNewLocalBlockContext(stmt->scope()); |
622 ContextScope scope(this, stmt->scope()); | 625 ContextScope scope(this, stmt->scope()); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 | 915 |
913 switch_builder.SetBreakTarget(done_label); | 916 switch_builder.SetBreakTarget(done_label); |
914 } | 917 } |
915 | 918 |
916 | 919 |
917 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 920 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
918 // Handled entirely in VisitSwitchStatement. | 921 // Handled entirely in VisitSwitchStatement. |
919 UNREACHABLE(); | 922 UNREACHABLE(); |
920 } | 923 } |
921 | 924 |
| 925 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, |
| 926 LoopBuilder* loop_builder) { |
| 927 ControlScopeForIteration execution_control(this, stmt, loop_builder); |
| 928 builder()->StackCheck(); |
| 929 Visit(stmt->body()); |
| 930 } |
922 | 931 |
923 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 932 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
924 LoopBuilder loop_builder(builder()); | 933 LoopBuilder loop_builder(builder()); |
925 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
926 loop_builder.LoopHeader(); | 934 loop_builder.LoopHeader(); |
927 if (stmt->cond()->ToBooleanIsFalse()) { | 935 if (stmt->cond()->ToBooleanIsFalse()) { |
928 Visit(stmt->body()); | 936 VisitIterationBody(stmt, &loop_builder); |
929 loop_builder.Condition(); | 937 loop_builder.Condition(); |
930 } else if (stmt->cond()->ToBooleanIsTrue()) { | 938 } else if (stmt->cond()->ToBooleanIsTrue()) { |
931 loop_builder.Condition(); | 939 loop_builder.Condition(); |
932 Visit(stmt->body()); | 940 VisitIterationBody(stmt, &loop_builder); |
933 loop_builder.JumpToHeader(); | 941 loop_builder.JumpToHeader(); |
934 } else { | 942 } else { |
935 Visit(stmt->body()); | 943 VisitIterationBody(stmt, &loop_builder); |
936 loop_builder.Condition(); | 944 loop_builder.Condition(); |
937 VisitForAccumulatorValue(stmt->cond()); | 945 VisitForAccumulatorValue(stmt->cond()); |
938 loop_builder.JumpToHeaderIfTrue(); | 946 loop_builder.JumpToHeaderIfTrue(); |
939 } | 947 } |
940 loop_builder.EndLoop(); | 948 loop_builder.EndLoop(); |
941 } | 949 } |
942 | 950 |
943 | |
944 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 951 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
945 if (stmt->cond()->ToBooleanIsFalse()) { | 952 if (stmt->cond()->ToBooleanIsFalse()) { |
946 // If the condition is false there is no need to generate the loop. | 953 // If the condition is false there is no need to generate the loop. |
947 return; | 954 return; |
948 } | 955 } |
949 | 956 |
950 LoopBuilder loop_builder(builder()); | 957 LoopBuilder loop_builder(builder()); |
951 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
952 loop_builder.LoopHeader(); | 958 loop_builder.LoopHeader(); |
953 loop_builder.Condition(); | 959 loop_builder.Condition(); |
954 if (!stmt->cond()->ToBooleanIsTrue()) { | 960 if (!stmt->cond()->ToBooleanIsTrue()) { |
955 VisitForAccumulatorValue(stmt->cond()); | 961 VisitForAccumulatorValue(stmt->cond()); |
956 loop_builder.BreakIfFalse(); | 962 loop_builder.BreakIfFalse(); |
957 } | 963 } |
958 Visit(stmt->body()); | 964 VisitIterationBody(stmt, &loop_builder); |
959 loop_builder.JumpToHeader(); | 965 loop_builder.JumpToHeader(); |
960 loop_builder.EndLoop(); | 966 loop_builder.EndLoop(); |
961 } | 967 } |
962 | 968 |
963 | 969 |
964 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 970 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
965 if (stmt->init() != nullptr) { | 971 if (stmt->init() != nullptr) { |
966 Visit(stmt->init()); | 972 Visit(stmt->init()); |
967 } | 973 } |
968 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 974 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
969 // If the condition is known to be false there is no need to generate | 975 // If the condition is known to be false there is no need to generate |
970 // body, next or condition blocks. Init block should be generated. | 976 // body, next or condition blocks. Init block should be generated. |
971 return; | 977 return; |
972 } | 978 } |
973 | 979 |
974 LoopBuilder loop_builder(builder()); | 980 LoopBuilder loop_builder(builder()); |
975 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | |
976 | |
977 loop_builder.LoopHeader(); | 981 loop_builder.LoopHeader(); |
978 loop_builder.Condition(); | 982 loop_builder.Condition(); |
979 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 983 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
980 VisitForAccumulatorValue(stmt->cond()); | 984 VisitForAccumulatorValue(stmt->cond()); |
981 loop_builder.BreakIfFalse(); | 985 loop_builder.BreakIfFalse(); |
982 } | 986 } |
983 Visit(stmt->body()); | 987 VisitIterationBody(stmt, &loop_builder); |
984 if (stmt->next() != nullptr) { | 988 if (stmt->next() != nullptr) { |
985 loop_builder.Next(); | 989 loop_builder.Next(); |
986 Visit(stmt->next()); | 990 Visit(stmt->next()); |
987 } | 991 } |
988 loop_builder.JumpToHeader(); | 992 loop_builder.JumpToHeader(); |
989 loop_builder.EndLoop(); | 993 loop_builder.EndLoop(); |
990 } | 994 } |
991 | 995 |
992 | 996 |
993 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 997 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 | 1038 |
1035 | 1039 |
1036 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 1040 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
1037 if (stmt->subject()->IsNullLiteral() || | 1041 if (stmt->subject()->IsNullLiteral() || |
1038 stmt->subject()->IsUndefinedLiteral(isolate())) { | 1042 stmt->subject()->IsUndefinedLiteral(isolate())) { |
1039 // ForIn generates lots of code, skip if it wouldn't produce any effects. | 1043 // ForIn generates lots of code, skip if it wouldn't produce any effects. |
1040 return; | 1044 return; |
1041 } | 1045 } |
1042 | 1046 |
1043 LoopBuilder loop_builder(builder()); | 1047 LoopBuilder loop_builder(builder()); |
1044 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | |
1045 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; | 1048 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; |
1046 | 1049 |
1047 // Prepare the state for executing ForIn. | 1050 // Prepare the state for executing ForIn. |
1048 VisitForAccumulatorValue(stmt->subject()); | 1051 VisitForAccumulatorValue(stmt->subject()); |
1049 builder()->JumpIfUndefined(&subject_undefined_label); | 1052 builder()->JumpIfUndefined(&subject_undefined_label); |
1050 builder()->JumpIfNull(&subject_null_label); | 1053 builder()->JumpIfNull(&subject_null_label); |
1051 Register receiver = register_allocator()->NewRegister(); | 1054 Register receiver = register_allocator()->NewRegister(); |
1052 builder()->CastAccumulatorToJSObject(); | 1055 builder()->CastAccumulatorToJSObject(); |
1053 builder()->JumpIfNull(¬_object_label); | 1056 builder()->JumpIfNull(¬_object_label); |
1054 builder()->StoreAccumulatorInRegister(receiver); | 1057 builder()->StoreAccumulatorInRegister(receiver); |
(...skipping 13 matching lines...) Expand all Loading... |
1068 | 1071 |
1069 // The loop | 1072 // The loop |
1070 loop_builder.LoopHeader(); | 1073 loop_builder.LoopHeader(); |
1071 loop_builder.Condition(); | 1074 loop_builder.Condition(); |
1072 builder()->ForInDone(index, cache_length); | 1075 builder()->ForInDone(index, cache_length); |
1073 loop_builder.BreakIfTrue(); | 1076 loop_builder.BreakIfTrue(); |
1074 DCHECK(Register::AreContiguous(cache_type, cache_array)); | 1077 DCHECK(Register::AreContiguous(cache_type, cache_array)); |
1075 builder()->ForInNext(receiver, index, cache_type); | 1078 builder()->ForInNext(receiver, index, cache_type); |
1076 loop_builder.ContinueIfUndefined(); | 1079 loop_builder.ContinueIfUndefined(); |
1077 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1080 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
1078 Visit(stmt->body()); | 1081 VisitIterationBody(stmt, &loop_builder); |
1079 loop_builder.Next(); | 1082 loop_builder.Next(); |
1080 builder()->ForInStep(index); | 1083 builder()->ForInStep(index); |
1081 builder()->StoreAccumulatorInRegister(index); | 1084 builder()->StoreAccumulatorInRegister(index); |
1082 loop_builder.JumpToHeader(); | 1085 loop_builder.JumpToHeader(); |
1083 loop_builder.EndLoop(); | 1086 loop_builder.EndLoop(); |
1084 builder()->Bind(¬_object_label); | 1087 builder()->Bind(¬_object_label); |
1085 builder()->Bind(&subject_null_label); | 1088 builder()->Bind(&subject_null_label); |
1086 builder()->Bind(&subject_undefined_label); | 1089 builder()->Bind(&subject_undefined_label); |
1087 } | 1090 } |
1088 | 1091 |
1089 | 1092 |
1090 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 1093 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
1091 LoopBuilder loop_builder(builder()); | 1094 LoopBuilder loop_builder(builder()); |
1092 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 1095 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
1093 | 1096 |
1094 VisitForEffect(stmt->assign_iterator()); | 1097 VisitForEffect(stmt->assign_iterator()); |
1095 | 1098 |
1096 loop_builder.LoopHeader(); | 1099 loop_builder.LoopHeader(); |
1097 loop_builder.Next(); | 1100 loop_builder.Next(); |
1098 VisitForEffect(stmt->next_result()); | 1101 VisitForEffect(stmt->next_result()); |
1099 VisitForAccumulatorValue(stmt->result_done()); | 1102 VisitForAccumulatorValue(stmt->result_done()); |
1100 loop_builder.BreakIfTrue(); | 1103 loop_builder.BreakIfTrue(); |
1101 | 1104 |
1102 VisitForEffect(stmt->assign_each()); | 1105 VisitForEffect(stmt->assign_each()); |
1103 Visit(stmt->body()); | 1106 VisitIterationBody(stmt, &loop_builder); |
1104 loop_builder.JumpToHeader(); | 1107 loop_builder.JumpToHeader(); |
1105 loop_builder.EndLoop(); | 1108 loop_builder.EndLoop(); |
1106 } | 1109 } |
1107 | 1110 |
1108 | 1111 |
1109 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1112 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1110 TryCatchBuilder try_control_builder(builder()); | 1113 TryCatchBuilder try_control_builder(builder()); |
1111 | 1114 |
1112 // Preserve the context in a dedicated register, so that it can be restored | 1115 // Preserve the context in a dedicated register, so that it can be restored |
1113 // when the handler is entered by the stack-unwinding machinery. | 1116 // when the handler is entered by the stack-unwinding machinery. |
(...skipping 1393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2507 } | 2510 } |
2508 | 2511 |
2509 | 2512 |
2510 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2513 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2511 return info()->feedback_vector()->GetIndex(slot); | 2514 return info()->feedback_vector()->GetIndex(slot); |
2512 } | 2515 } |
2513 | 2516 |
2514 } // namespace interpreter | 2517 } // namespace interpreter |
2515 } // namespace internal | 2518 } // namespace internal |
2516 } // namespace v8 | 2519 } // namespace v8 |
OLD | NEW |