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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 loop_builder->BindContinueTarget(); | 1154 loop_builder->BindContinueTarget(); |
1163 } | 1155 } |
1164 | 1156 |
1165 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 1157 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
1166 LoopBuilder loop_builder(builder()); | 1158 LoopBuilder loop_builder(builder()); |
1167 if (stmt->cond()->ToBooleanIsFalse()) { | 1159 if (stmt->cond()->ToBooleanIsFalse()) { |
1168 VisitIterationBody(stmt, &loop_builder); | 1160 VisitIterationBody(stmt, &loop_builder); |
1169 } else if (stmt->cond()->ToBooleanIsTrue()) { | 1161 } else if (stmt->cond()->ToBooleanIsTrue()) { |
1170 VisitIterationHeader(stmt, &loop_builder); | 1162 VisitIterationHeader(stmt, &loop_builder); |
1171 VisitIterationBody(stmt, &loop_builder); | 1163 VisitIterationBody(stmt, &loop_builder); |
1172 loop_builder.JumpToHeader(); | 1164 loop_builder.JumpToHeader(loop_depth_); |
1173 } else { | 1165 } else { |
1174 VisitIterationHeader(stmt, &loop_builder); | 1166 VisitIterationHeader(stmt, &loop_builder); |
1175 VisitIterationBody(stmt, &loop_builder); | 1167 VisitIterationBody(stmt, &loop_builder); |
1176 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1168 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
1177 VisitForTest(stmt->cond(), loop_builder.header_labels(), | 1169 BytecodeLabels loop_backbranch(zone()); |
1178 loop_builder.break_labels(), TestFallthrough::kElse); | 1170 VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(), |
| 1171 TestFallthrough::kThen); |
| 1172 loop_backbranch.Bind(builder()); |
| 1173 loop_builder.JumpToHeader(loop_depth_); |
1179 } | 1174 } |
1180 loop_builder.EndLoop(); | 1175 loop_builder.EndLoop(); |
1181 } | 1176 } |
1182 | 1177 |
1183 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 1178 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
1184 if (stmt->cond()->ToBooleanIsFalse()) { | 1179 if (stmt->cond()->ToBooleanIsFalse()) { |
1185 // If the condition is false there is no need to generate the loop. | 1180 // If the condition is false there is no need to generate the loop. |
1186 return; | 1181 return; |
1187 } | 1182 } |
1188 | 1183 |
1189 LoopBuilder loop_builder(builder()); | 1184 LoopBuilder loop_builder(builder()); |
1190 VisitIterationHeader(stmt, &loop_builder); | 1185 VisitIterationHeader(stmt, &loop_builder); |
1191 if (!stmt->cond()->ToBooleanIsTrue()) { | 1186 if (!stmt->cond()->ToBooleanIsTrue()) { |
1192 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1187 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
1193 BytecodeLabels loop_body(zone()); | 1188 BytecodeLabels loop_body(zone()); |
1194 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), | 1189 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), |
1195 TestFallthrough::kThen); | 1190 TestFallthrough::kThen); |
1196 loop_body.Bind(builder()); | 1191 loop_body.Bind(builder()); |
1197 } | 1192 } |
1198 VisitIterationBody(stmt, &loop_builder); | 1193 VisitIterationBody(stmt, &loop_builder); |
1199 loop_builder.JumpToHeader(); | 1194 loop_builder.JumpToHeader(loop_depth_); |
1200 loop_builder.EndLoop(); | 1195 loop_builder.EndLoop(); |
1201 } | 1196 } |
1202 | 1197 |
1203 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 1198 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
1204 if (stmt->init() != nullptr) { | 1199 if (stmt->init() != nullptr) { |
1205 Visit(stmt->init()); | 1200 Visit(stmt->init()); |
1206 } | 1201 } |
1207 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 1202 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
1208 // If the condition is known to be false there is no need to generate | 1203 // If the condition is known to be false there is no need to generate |
1209 // body, next or condition blocks. Init block should be generated. | 1204 // body, next or condition blocks. Init block should be generated. |
1210 return; | 1205 return; |
1211 } | 1206 } |
1212 | 1207 |
1213 LoopBuilder loop_builder(builder()); | 1208 LoopBuilder loop_builder(builder()); |
1214 VisitIterationHeader(stmt, &loop_builder); | 1209 VisitIterationHeader(stmt, &loop_builder); |
1215 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 1210 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
1216 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1211 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
1217 BytecodeLabels loop_body(zone()); | 1212 BytecodeLabels loop_body(zone()); |
1218 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), | 1213 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), |
1219 TestFallthrough::kThen); | 1214 TestFallthrough::kThen); |
1220 loop_body.Bind(builder()); | 1215 loop_body.Bind(builder()); |
1221 } | 1216 } |
1222 VisitIterationBody(stmt, &loop_builder); | 1217 VisitIterationBody(stmt, &loop_builder); |
1223 if (stmt->next() != nullptr) { | 1218 if (stmt->next() != nullptr) { |
1224 builder()->SetStatementPosition(stmt->next()); | 1219 builder()->SetStatementPosition(stmt->next()); |
1225 Visit(stmt->next()); | 1220 Visit(stmt->next()); |
1226 } | 1221 } |
1227 loop_builder.JumpToHeader(); | 1222 loop_builder.JumpToHeader(loop_depth_); |
1228 loop_builder.EndLoop(); | 1223 loop_builder.EndLoop(); |
1229 } | 1224 } |
1230 | 1225 |
1231 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 1226 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
1232 FeedbackVectorSlot slot) { | 1227 FeedbackVectorSlot slot) { |
1233 DCHECK(expr->IsValidReferenceExpression()); | 1228 DCHECK(expr->IsValidReferenceExpression()); |
1234 | 1229 |
1235 // Evaluate assignment starting with the value to be stored in the | 1230 // Evaluate assignment starting with the value to be stored in the |
1236 // accumulator. | 1231 // accumulator. |
1237 Property* property = expr->AsProperty(); | 1232 Property* property = expr->AsProperty(); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1338 builder()->ForInContinue(index, cache_length); | 1333 builder()->ForInContinue(index, cache_length); |
1339 loop_builder.BreakIfFalse(); | 1334 loop_builder.BreakIfFalse(); |
1340 DCHECK(Register::AreContiguous(cache_type, cache_array)); | 1335 DCHECK(Register::AreContiguous(cache_type, cache_array)); |
1341 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); | 1336 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); |
1342 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot)); | 1337 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot)); |
1343 loop_builder.ContinueIfUndefined(); | 1338 loop_builder.ContinueIfUndefined(); |
1344 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1339 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
1345 VisitIterationBody(stmt, &loop_builder); | 1340 VisitIterationBody(stmt, &loop_builder); |
1346 builder()->ForInStep(index); | 1341 builder()->ForInStep(index); |
1347 builder()->StoreAccumulatorInRegister(index); | 1342 builder()->StoreAccumulatorInRegister(index); |
1348 loop_builder.JumpToHeader(); | 1343 loop_builder.JumpToHeader(loop_depth_); |
1349 loop_builder.EndLoop(); | 1344 loop_builder.EndLoop(); |
1350 builder()->Bind(&subject_null_label); | 1345 builder()->Bind(&subject_null_label); |
1351 builder()->Bind(&subject_undefined_label); | 1346 builder()->Bind(&subject_undefined_label); |
1352 } | 1347 } |
1353 | 1348 |
1354 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 1349 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
1355 LoopBuilder loop_builder(builder()); | 1350 LoopBuilder loop_builder(builder()); |
1356 | 1351 |
1357 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); | 1352 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); |
1358 VisitForEffect(stmt->assign_iterator()); | 1353 VisitForEffect(stmt->assign_iterator()); |
1359 | 1354 |
1360 VisitIterationHeader(stmt, &loop_builder); | 1355 VisitIterationHeader(stmt, &loop_builder); |
1361 builder()->SetExpressionAsStatementPosition(stmt->next_result()); | 1356 builder()->SetExpressionAsStatementPosition(stmt->next_result()); |
1362 VisitForEffect(stmt->next_result()); | 1357 VisitForEffect(stmt->next_result()); |
1363 VisitForAccumulatorValue(stmt->result_done()); | 1358 VisitForAccumulatorValue(stmt->result_done()); |
1364 loop_builder.BreakIfTrue(); | 1359 loop_builder.BreakIfTrue(); |
1365 | 1360 |
1366 VisitForEffect(stmt->assign_each()); | 1361 VisitForEffect(stmt->assign_each()); |
1367 VisitIterationBody(stmt, &loop_builder); | 1362 VisitIterationBody(stmt, &loop_builder); |
1368 loop_builder.JumpToHeader(); | 1363 loop_builder.JumpToHeader(loop_depth_); |
1369 loop_builder.EndLoop(); | 1364 loop_builder.EndLoop(); |
1370 } | 1365 } |
1371 | 1366 |
1372 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1367 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1373 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1368 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); |
1374 Register no_reg; | 1369 Register no_reg; |
1375 | 1370 |
1376 // Preserve the context in a dedicated register, so that it can be restored | 1371 // Preserve the context in a dedicated register, so that it can be restored |
1377 // when the handler is entered by the stack-unwinding machinery. | 1372 // when the handler is entered by the stack-unwinding machinery. |
1378 // TODO(mstarzinger): Be smarter about register allocation. | 1373 // TODO(mstarzinger): Be smarter about register allocation. |
(...skipping 2074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3453 return execution_context()->scope()->language_mode(); | 3448 return execution_context()->scope()->language_mode(); |
3454 } | 3449 } |
3455 | 3450 |
3456 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3451 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3457 return TypeFeedbackVector::GetIndex(slot); | 3452 return TypeFeedbackVector::GetIndex(slot); |
3458 } | 3453 } |
3459 | 3454 |
3460 } // namespace interpreter | 3455 } // namespace interpreter |
3461 } // namespace internal | 3456 } // namespace internal |
3462 } // namespace v8 | 3457 } // namespace v8 |
OLD | NEW |