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