| 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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 size_t first_yield = stmt->first_yield_id(); | 819 size_t first_yield = stmt->first_yield_id(); |
| 820 DCHECK_LE(first_yield + stmt->yield_count(), generator_resume_points_.size()); | 820 DCHECK_LE(first_yield + stmt->yield_count(), generator_resume_points_.size()); |
| 821 for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) { | 821 for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) { |
| 822 auto& label = generator_resume_points_[id]; | 822 auto& label = generator_resume_points_[id]; |
| 823 resume_points_in_loop.push_back(label); | 823 resume_points_in_loop.push_back(label); |
| 824 generator_resume_points_[id] = BytecodeLabel(); | 824 generator_resume_points_[id] = BytecodeLabel(); |
| 825 } | 825 } |
| 826 | 826 |
| 827 loop_builder->LoopHeader(&resume_points_in_loop); | 827 loop_builder->LoopHeader(&resume_points_in_loop); |
| 828 | 828 |
| 829 // Insert an explicit {OsrPoll} right after the loop header, to trigger | |
| 830 // on-stack replacement when armed for the given loop nesting depth. | |
| 831 if (FLAG_ignition_osr) { | |
| 832 // TODO(4764): Merge this with another bytecode (e.g. {Jump} back edge). | |
| 833 int level = Min(loop_depth_, AbstractCode::kMaxLoopNestingMarker - 1); | |
| 834 builder()->OsrPoll(level); | |
| 835 } | |
| 836 | |
| 837 if (stmt->yield_count() > 0) { | 829 if (stmt->yield_count() > 0) { |
| 838 // If we are not resuming, fall through to loop body. | 830 // If we are not resuming, fall through to loop body. |
| 839 // If we are resuming, perform state dispatch. | 831 // If we are resuming, perform state dispatch. |
| 840 BytecodeLabel not_resuming; | 832 BytecodeLabel not_resuming; |
| 841 builder() | 833 builder() |
| 842 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 834 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
| 843 .CompareOperation(Token::Value::EQ, generator_state_) | 835 .CompareOperation(Token::Value::EQ, generator_state_) |
| 844 .JumpIfTrue(¬_resuming); | 836 .JumpIfTrue(¬_resuming); |
| 845 BuildIndexedJump(generator_state_, first_yield, | 837 BuildIndexedJump(generator_state_, first_yield, |
| 846 stmt->yield_count(), generator_resume_points_); | 838 stmt->yield_count(), generator_resume_points_); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 loop_builder->BindContinueTarget(); | 1155 loop_builder->BindContinueTarget(); |
| 1164 } | 1156 } |
| 1165 | 1157 |
| 1166 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 1158 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 1167 LoopBuilder loop_builder(builder()); | 1159 LoopBuilder loop_builder(builder()); |
| 1168 if (stmt->cond()->ToBooleanIsFalse()) { | 1160 if (stmt->cond()->ToBooleanIsFalse()) { |
| 1169 VisitIterationBody(stmt, &loop_builder); | 1161 VisitIterationBody(stmt, &loop_builder); |
| 1170 } else if (stmt->cond()->ToBooleanIsTrue()) { | 1162 } else if (stmt->cond()->ToBooleanIsTrue()) { |
| 1171 VisitIterationHeader(stmt, &loop_builder); | 1163 VisitIterationHeader(stmt, &loop_builder); |
| 1172 VisitIterationBody(stmt, &loop_builder); | 1164 VisitIterationBody(stmt, &loop_builder); |
| 1173 loop_builder.JumpToHeader(); | 1165 loop_builder.JumpToHeader(loop_depth_); |
| 1174 } else { | 1166 } else { |
| 1175 VisitIterationHeader(stmt, &loop_builder); | 1167 VisitIterationHeader(stmt, &loop_builder); |
| 1176 VisitIterationBody(stmt, &loop_builder); | 1168 VisitIterationBody(stmt, &loop_builder); |
| 1177 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1169 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1178 VisitForTest(stmt->cond(), loop_builder.header_labels(), | 1170 BytecodeLabels loop_backbranch(zone()); |
| 1179 loop_builder.break_labels(), TestFallthrough::kElse); | 1171 VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(), |
| 1172 TestFallthrough::kThen); |
| 1173 loop_backbranch.Bind(builder()); |
| 1174 loop_builder.JumpToHeader(loop_depth_); |
| 1180 } | 1175 } |
| 1181 loop_builder.EndLoop(); | 1176 loop_builder.EndLoop(); |
| 1182 } | 1177 } |
| 1183 | 1178 |
| 1184 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 1179 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 1185 if (stmt->cond()->ToBooleanIsFalse()) { | 1180 if (stmt->cond()->ToBooleanIsFalse()) { |
| 1186 // If the condition is false there is no need to generate the loop. | 1181 // If the condition is false there is no need to generate the loop. |
| 1187 return; | 1182 return; |
| 1188 } | 1183 } |
| 1189 | 1184 |
| 1190 LoopBuilder loop_builder(builder()); | 1185 LoopBuilder loop_builder(builder()); |
| 1191 VisitIterationHeader(stmt, &loop_builder); | 1186 VisitIterationHeader(stmt, &loop_builder); |
| 1192 if (!stmt->cond()->ToBooleanIsTrue()) { | 1187 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 1193 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1188 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1194 BytecodeLabels loop_body(zone()); | 1189 BytecodeLabels loop_body(zone()); |
| 1195 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), | 1190 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), |
| 1196 TestFallthrough::kThen); | 1191 TestFallthrough::kThen); |
| 1197 loop_body.Bind(builder()); | 1192 loop_body.Bind(builder()); |
| 1198 } | 1193 } |
| 1199 VisitIterationBody(stmt, &loop_builder); | 1194 VisitIterationBody(stmt, &loop_builder); |
| 1200 loop_builder.JumpToHeader(); | 1195 loop_builder.JumpToHeader(loop_depth_); |
| 1201 loop_builder.EndLoop(); | 1196 loop_builder.EndLoop(); |
| 1202 } | 1197 } |
| 1203 | 1198 |
| 1204 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 1199 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 1205 if (stmt->init() != nullptr) { | 1200 if (stmt->init() != nullptr) { |
| 1206 Visit(stmt->init()); | 1201 Visit(stmt->init()); |
| 1207 } | 1202 } |
| 1208 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 1203 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
| 1209 // If the condition is known to be false there is no need to generate | 1204 // If the condition is known to be false there is no need to generate |
| 1210 // body, next or condition blocks. Init block should be generated. | 1205 // body, next or condition blocks. Init block should be generated. |
| 1211 return; | 1206 return; |
| 1212 } | 1207 } |
| 1213 | 1208 |
| 1214 LoopBuilder loop_builder(builder()); | 1209 LoopBuilder loop_builder(builder()); |
| 1215 VisitIterationHeader(stmt, &loop_builder); | 1210 VisitIterationHeader(stmt, &loop_builder); |
| 1216 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 1211 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
| 1217 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1212 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1218 BytecodeLabels loop_body(zone()); | 1213 BytecodeLabels loop_body(zone()); |
| 1219 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), | 1214 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), |
| 1220 TestFallthrough::kThen); | 1215 TestFallthrough::kThen); |
| 1221 loop_body.Bind(builder()); | 1216 loop_body.Bind(builder()); |
| 1222 } | 1217 } |
| 1223 VisitIterationBody(stmt, &loop_builder); | 1218 VisitIterationBody(stmt, &loop_builder); |
| 1224 if (stmt->next() != nullptr) { | 1219 if (stmt->next() != nullptr) { |
| 1225 builder()->SetStatementPosition(stmt->next()); | 1220 builder()->SetStatementPosition(stmt->next()); |
| 1226 Visit(stmt->next()); | 1221 Visit(stmt->next()); |
| 1227 } | 1222 } |
| 1228 loop_builder.JumpToHeader(); | 1223 loop_builder.JumpToHeader(loop_depth_); |
| 1229 loop_builder.EndLoop(); | 1224 loop_builder.EndLoop(); |
| 1230 } | 1225 } |
| 1231 | 1226 |
| 1232 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 1227 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
| 1233 FeedbackVectorSlot slot) { | 1228 FeedbackVectorSlot slot) { |
| 1234 DCHECK(expr->IsValidReferenceExpression()); | 1229 DCHECK(expr->IsValidReferenceExpression()); |
| 1235 | 1230 |
| 1236 // Evaluate assignment starting with the value to be stored in the | 1231 // Evaluate assignment starting with the value to be stored in the |
| 1237 // accumulator. | 1232 // accumulator. |
| 1238 Property* property = expr->AsProperty(); | 1233 Property* property = expr->AsProperty(); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 builder()->ForInContinue(index, cache_length); | 1334 builder()->ForInContinue(index, cache_length); |
| 1340 loop_builder.BreakIfFalse(); | 1335 loop_builder.BreakIfFalse(); |
| 1341 DCHECK(Register::AreContiguous(cache_type, cache_array)); | 1336 DCHECK(Register::AreContiguous(cache_type, cache_array)); |
| 1342 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); | 1337 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); |
| 1343 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot)); | 1338 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot)); |
| 1344 loop_builder.ContinueIfUndefined(); | 1339 loop_builder.ContinueIfUndefined(); |
| 1345 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1340 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
| 1346 VisitIterationBody(stmt, &loop_builder); | 1341 VisitIterationBody(stmt, &loop_builder); |
| 1347 builder()->ForInStep(index); | 1342 builder()->ForInStep(index); |
| 1348 builder()->StoreAccumulatorInRegister(index); | 1343 builder()->StoreAccumulatorInRegister(index); |
| 1349 loop_builder.JumpToHeader(); | 1344 loop_builder.JumpToHeader(loop_depth_); |
| 1350 loop_builder.EndLoop(); | 1345 loop_builder.EndLoop(); |
| 1351 builder()->Bind(&subject_null_label); | 1346 builder()->Bind(&subject_null_label); |
| 1352 builder()->Bind(&subject_undefined_label); | 1347 builder()->Bind(&subject_undefined_label); |
| 1353 } | 1348 } |
| 1354 | 1349 |
| 1355 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 1350 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
| 1356 LoopBuilder loop_builder(builder()); | 1351 LoopBuilder loop_builder(builder()); |
| 1357 | 1352 |
| 1358 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); | 1353 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); |
| 1359 VisitForEffect(stmt->assign_iterator()); | 1354 VisitForEffect(stmt->assign_iterator()); |
| 1360 | 1355 |
| 1361 VisitIterationHeader(stmt, &loop_builder); | 1356 VisitIterationHeader(stmt, &loop_builder); |
| 1362 builder()->SetExpressionAsStatementPosition(stmt->next_result()); | 1357 builder()->SetExpressionAsStatementPosition(stmt->next_result()); |
| 1363 VisitForEffect(stmt->next_result()); | 1358 VisitForEffect(stmt->next_result()); |
| 1364 VisitForAccumulatorValue(stmt->result_done()); | 1359 VisitForAccumulatorValue(stmt->result_done()); |
| 1365 loop_builder.BreakIfTrue(); | 1360 loop_builder.BreakIfTrue(); |
| 1366 | 1361 |
| 1367 VisitForEffect(stmt->assign_each()); | 1362 VisitForEffect(stmt->assign_each()); |
| 1368 VisitIterationBody(stmt, &loop_builder); | 1363 VisitIterationBody(stmt, &loop_builder); |
| 1369 loop_builder.JumpToHeader(); | 1364 loop_builder.JumpToHeader(loop_depth_); |
| 1370 loop_builder.EndLoop(); | 1365 loop_builder.EndLoop(); |
| 1371 } | 1366 } |
| 1372 | 1367 |
| 1373 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1368 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1374 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1369 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); |
| 1375 Register no_reg; | 1370 Register no_reg; |
| 1376 | 1371 |
| 1377 // Preserve the context in a dedicated register, so that it can be restored | 1372 // Preserve the context in a dedicated register, so that it can be restored |
| 1378 // when the handler is entered by the stack-unwinding machinery. | 1373 // when the handler is entered by the stack-unwinding machinery. |
| 1379 // TODO(mstarzinger): Be smarter about register allocation. | 1374 // TODO(mstarzinger): Be smarter about register allocation. |
| (...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3427 return execution_context()->scope()->language_mode(); | 3422 return execution_context()->scope()->language_mode(); |
| 3428 } | 3423 } |
| 3429 | 3424 |
| 3430 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3425 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3431 return TypeFeedbackVector::GetIndex(slot); | 3426 return TypeFeedbackVector::GetIndex(slot); |
| 3432 } | 3427 } |
| 3433 | 3428 |
| 3434 } // namespace interpreter | 3429 } // namespace interpreter |
| 3435 } // namespace internal | 3430 } // namespace internal |
| 3436 } // namespace v8 | 3431 } // namespace v8 |
| OLD | NEW |