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/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/interpreter/bytecode-flags.h" | 10 #include "src/interpreter/bytecode-flags.h" |
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 SwitchBuilder switch_builder(builder(), clauses->length()); | 1112 SwitchBuilder switch_builder(builder(), clauses->length()); |
1113 ControlScopeForBreakable scope(this, stmt, &switch_builder); | 1113 ControlScopeForBreakable scope(this, stmt, &switch_builder); |
1114 int default_index = -1; | 1114 int default_index = -1; |
1115 | 1115 |
1116 builder()->SetStatementPosition(stmt); | 1116 builder()->SetStatementPosition(stmt); |
1117 | 1117 |
1118 // Keep the switch value in a register until a case matches. | 1118 // Keep the switch value in a register until a case matches. |
1119 Register tag = VisitForRegisterValue(stmt->tag()); | 1119 Register tag = VisitForRegisterValue(stmt->tag()); |
1120 | 1120 |
1121 // Iterate over all cases and create nodes for label comparison. | 1121 // Iterate over all cases and create nodes for label comparison. |
1122 BytecodeLabel done_label; | |
1123 for (int i = 0; i < clauses->length(); i++) { | 1122 for (int i = 0; i < clauses->length(); i++) { |
1124 CaseClause* clause = clauses->at(i); | 1123 CaseClause* clause = clauses->at(i); |
1125 | 1124 |
1126 // The default is not a test, remember index. | 1125 // The default is not a test, remember index. |
1127 if (clause->is_default()) { | 1126 if (clause->is_default()) { |
1128 default_index = i; | 1127 default_index = i; |
1129 continue; | 1128 continue; |
1130 } | 1129 } |
1131 | 1130 |
1132 // Perform label comparison as if via '===' with tag. | 1131 // Perform label comparison as if via '===' with tag. |
1133 VisitForAccumulatorValue(clause->label()); | 1132 VisitForAccumulatorValue(clause->label()); |
1134 builder()->CompareOperation(Token::Value::EQ_STRICT, tag); | 1133 builder()->CompareOperation(Token::Value::EQ_STRICT, tag); |
1135 switch_builder.Case(i); | 1134 switch_builder.Case(i); |
1136 } | 1135 } |
1137 | 1136 |
1138 if (default_index >= 0) { | 1137 if (default_index >= 0) { |
1139 // Emit default jump if there is a default case. | 1138 // Emit default jump if there is a default case. |
1140 switch_builder.DefaultAt(default_index); | 1139 switch_builder.DefaultAt(default_index); |
1141 } else { | 1140 } else { |
1142 // Otherwise if we have reached here none of the cases matched, so jump to | 1141 // Otherwise if we have reached here none of the cases matched, so jump to |
1143 // done. | 1142 // the end. |
1144 builder()->Jump(&done_label); | 1143 switch_builder.Break(); |
1145 } | 1144 } |
1146 | 1145 |
1147 // Iterate over all cases and create the case bodies. | 1146 // Iterate over all cases and create the case bodies. |
1148 for (int i = 0; i < clauses->length(); i++) { | 1147 for (int i = 0; i < clauses->length(); i++) { |
1149 CaseClause* clause = clauses->at(i); | 1148 CaseClause* clause = clauses->at(i); |
1150 switch_builder.SetCaseTarget(i); | 1149 switch_builder.SetCaseTarget(i); |
1151 VisitStatements(clause->statements()); | 1150 VisitStatements(clause->statements()); |
1152 } | 1151 } |
1153 builder()->Bind(&done_label); | 1152 switch_builder.BindBreakTarget(); |
1154 | |
1155 switch_builder.SetBreakTarget(done_label); | |
1156 } | 1153 } |
1157 | 1154 |
1158 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 1155 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
1159 // Handled entirely in VisitSwitchStatement. | 1156 // Handled entirely in VisitSwitchStatement. |
1160 UNREACHABLE(); | 1157 UNREACHABLE(); |
1161 } | 1158 } |
1162 | 1159 |
1163 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, | 1160 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, |
1164 LoopBuilder* loop_builder) { | 1161 LoopBuilder* loop_builder) { |
1165 ControlScopeForIteration execution_control(this, stmt, loop_builder); | 1162 ControlScopeForIteration execution_control(this, stmt, loop_builder); |
1166 builder()->StackCheck(stmt->position()); | 1163 builder()->StackCheck(stmt->position()); |
1167 Visit(stmt->body()); | 1164 Visit(stmt->body()); |
1168 loop_builder->SetContinueTarget(); | 1165 loop_builder->BindContinueTarget(); |
1169 } | 1166 } |
1170 | 1167 |
1171 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 1168 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
1172 LoopBuilder loop_builder(builder()); | 1169 LoopBuilder loop_builder(builder()); |
1173 if (stmt->cond()->ToBooleanIsFalse()) { | 1170 if (stmt->cond()->ToBooleanIsFalse()) { |
1174 VisitIterationBody(stmt, &loop_builder); | 1171 VisitIterationBody(stmt, &loop_builder); |
1175 } else if (stmt->cond()->ToBooleanIsTrue()) { | 1172 } else if (stmt->cond()->ToBooleanIsTrue()) { |
1176 VisitIterationHeader(stmt, &loop_builder); | 1173 VisitIterationHeader(stmt, &loop_builder); |
1177 VisitIterationBody(stmt, &loop_builder); | 1174 VisitIterationBody(stmt, &loop_builder); |
1178 loop_builder.JumpToHeader(); | 1175 loop_builder.JumpToHeader(); |
1179 } else { | 1176 } else { |
1180 VisitIterationHeader(stmt, &loop_builder); | 1177 VisitIterationHeader(stmt, &loop_builder); |
1181 VisitIterationBody(stmt, &loop_builder); | 1178 VisitIterationBody(stmt, &loop_builder); |
1182 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1179 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
1183 // TODO(klaasb) VisitForTest for loop conditions | 1180 VisitForTest(stmt->cond(), loop_builder.header_labels(), |
1184 VisitForAccumulatorValue(stmt->cond()); | 1181 loop_builder.break_labels(), TestFallthrough::kElse); |
1185 loop_builder.JumpToHeaderIfTrue(); | |
1186 } | 1182 } |
1187 loop_builder.EndLoop(); | 1183 loop_builder.EndLoop(); |
1188 } | 1184 } |
1189 | 1185 |
1190 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 1186 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
1191 if (stmt->cond()->ToBooleanIsFalse()) { | 1187 if (stmt->cond()->ToBooleanIsFalse()) { |
1192 // If the condition is false there is no need to generate the loop. | 1188 // If the condition is false there is no need to generate the loop. |
1193 return; | 1189 return; |
1194 } | 1190 } |
1195 | 1191 |
1196 LoopBuilder loop_builder(builder()); | 1192 LoopBuilder loop_builder(builder()); |
1197 VisitIterationHeader(stmt, &loop_builder); | 1193 VisitIterationHeader(stmt, &loop_builder); |
1198 if (!stmt->cond()->ToBooleanIsTrue()) { | 1194 if (!stmt->cond()->ToBooleanIsTrue()) { |
1199 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1195 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
1200 // TODO(klaasb) VisitForTest for loop conditions | 1196 BytecodeLabels loop_body(zone()); |
1201 VisitForAccumulatorValue(stmt->cond()); | 1197 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), |
1202 loop_builder.BreakIfFalse(); | 1198 TestFallthrough::kThen); |
| 1199 loop_body.Bind(builder()); |
1203 } | 1200 } |
1204 VisitIterationBody(stmt, &loop_builder); | 1201 VisitIterationBody(stmt, &loop_builder); |
1205 loop_builder.JumpToHeader(); | 1202 loop_builder.JumpToHeader(); |
1206 loop_builder.EndLoop(); | 1203 loop_builder.EndLoop(); |
1207 } | 1204 } |
1208 | 1205 |
1209 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 1206 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
1210 if (stmt->init() != nullptr) { | 1207 if (stmt->init() != nullptr) { |
1211 Visit(stmt->init()); | 1208 Visit(stmt->init()); |
1212 } | 1209 } |
1213 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 1210 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
1214 // If the condition is known to be false there is no need to generate | 1211 // If the condition is known to be false there is no need to generate |
1215 // body, next or condition blocks. Init block should be generated. | 1212 // body, next or condition blocks. Init block should be generated. |
1216 return; | 1213 return; |
1217 } | 1214 } |
1218 | 1215 |
1219 LoopBuilder loop_builder(builder()); | 1216 LoopBuilder loop_builder(builder()); |
1220 VisitIterationHeader(stmt, &loop_builder); | 1217 VisitIterationHeader(stmt, &loop_builder); |
1221 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 1218 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
1222 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1219 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
1223 // TODO(klaasb) VisitForTest for loop conditions | 1220 BytecodeLabels loop_body(zone()); |
1224 VisitForAccumulatorValue(stmt->cond()); | 1221 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), |
1225 loop_builder.BreakIfFalse(); | 1222 TestFallthrough::kThen); |
| 1223 loop_body.Bind(builder()); |
1226 } | 1224 } |
1227 VisitIterationBody(stmt, &loop_builder); | 1225 VisitIterationBody(stmt, &loop_builder); |
1228 if (stmt->next() != nullptr) { | 1226 if (stmt->next() != nullptr) { |
1229 builder()->SetStatementPosition(stmt->next()); | 1227 builder()->SetStatementPosition(stmt->next()); |
1230 Visit(stmt->next()); | 1228 Visit(stmt->next()); |
1231 } | 1229 } |
1232 loop_builder.JumpToHeader(); | 1230 loop_builder.JumpToHeader(); |
1233 loop_builder.EndLoop(); | 1231 loop_builder.EndLoop(); |
1234 } | 1232 } |
1235 | 1233 |
(...skipping 2173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3409 return execution_context()->scope()->language_mode(); | 3407 return execution_context()->scope()->language_mode(); |
3410 } | 3408 } |
3411 | 3409 |
3412 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3410 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3413 return TypeFeedbackVector::GetIndex(slot); | 3411 return TypeFeedbackVector::GetIndex(slot); |
3414 } | 3412 } |
3415 | 3413 |
3416 } // namespace interpreter | 3414 } // namespace interpreter |
3417 } // namespace internal | 3415 } // namespace internal |
3418 } // namespace v8 | 3416 } // namespace v8 |
OLD | NEW |