| 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 |