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/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 | 183 |
184 // Applies all recorded control-flow commands after the finally-block again. | 184 // Applies all recorded control-flow commands after the finally-block again. |
185 // This generates a dynamic dispatch on the token from the entry point. | 185 // This generates a dynamic dispatch on the token from the entry point. |
186 void ApplyDeferredCommands() { | 186 void ApplyDeferredCommands() { |
187 // The fall-through path is covered by the default case, hence +1 here. | 187 // The fall-through path is covered by the default case, hence +1 here. |
188 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1)); | 188 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1)); |
189 for (size_t i = 0; i < deferred_.size(); ++i) { | 189 for (size_t i = 0; i < deferred_.size(); ++i) { |
190 Entry& entry = deferred_[i]; | 190 Entry& entry = deferred_[i]; |
191 builder()->LoadLiteral(Smi::FromInt(entry.token)); | 191 builder()->LoadLiteral(Smi::FromInt(entry.token)); |
192 builder()->CompareOperation(Token::EQ_STRICT, token_register_); | 192 builder()->CompareOperation(Token::EQ_STRICT, token_register_); |
193 dispatch.Case(static_cast<int>(i)); | 193 dispatch.Case(ToBooleanMode::kAlreadyBoolean, static_cast<int>(i)); |
194 } | 194 } |
195 dispatch.DefaultAt(static_cast<int>(deferred_.size())); | 195 dispatch.DefaultAt(static_cast<int>(deferred_.size())); |
196 for (size_t i = 0; i < deferred_.size(); ++i) { | 196 for (size_t i = 0; i < deferred_.size(); ++i) { |
197 Entry& entry = deferred_[i]; | 197 Entry& entry = deferred_[i]; |
198 dispatch.SetCaseTarget(static_cast<int>(i)); | 198 dispatch.SetCaseTarget(static_cast<int>(i)); |
199 builder()->LoadAccumulatorWithRegister(result_register_); | 199 builder()->LoadAccumulatorWithRegister(result_register_); |
200 execution_control()->PerformCommand(entry.command, entry.statement); | 200 execution_control()->PerformCommand(entry.command, entry.statement); |
201 } | 201 } |
202 dispatch.SetCaseTarget(static_cast<int>(deferred_.size())); | 202 dispatch.SetCaseTarget(static_cast<int>(deferred_.size())); |
203 } | 203 } |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 | 404 |
405 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); | 405 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); |
406 }; | 406 }; |
407 | 407 |
408 // Scoped base class for determining how the result of an expression will be | 408 // Scoped base class for determining how the result of an expression will be |
409 // used. | 409 // used. |
410 class BytecodeGenerator::ExpressionResultScope { | 410 class BytecodeGenerator::ExpressionResultScope { |
411 public: | 411 public: |
412 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) | 412 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) |
413 : generator_(generator), | 413 : generator_(generator), |
| 414 outer_(generator->execution_result()), |
| 415 allocator_(generator), |
414 kind_(kind), | 416 kind_(kind), |
415 outer_(generator->execution_result()), | 417 type_hint_(TypeHint::kAny) { |
416 allocator_(generator) { | |
417 generator_->set_execution_result(this); | 418 generator_->set_execution_result(this); |
418 } | 419 } |
419 | 420 |
420 virtual ~ExpressionResultScope() { | 421 virtual ~ExpressionResultScope() { |
421 generator_->set_execution_result(outer_); | 422 generator_->set_execution_result(outer_); |
422 } | 423 } |
423 | 424 |
424 bool IsEffect() const { return kind_ == Expression::kEffect; } | 425 bool IsEffect() const { return kind_ == Expression::kEffect; } |
425 bool IsValue() const { return kind_ == Expression::kValue; } | 426 bool IsValue() const { return kind_ == Expression::kValue; } |
426 bool IsTest() const { return kind_ == Expression::kTest; } | 427 bool IsTest() const { return kind_ == Expression::kTest; } |
427 | 428 |
428 TestResultScope* AsTest() { | 429 TestResultScope* AsTest() { |
429 DCHECK(IsTest()); | 430 DCHECK(IsTest()); |
430 return reinterpret_cast<TestResultScope*>(this); | 431 return reinterpret_cast<TestResultScope*>(this); |
431 } | 432 } |
432 | 433 |
| 434 // Specify expression always returns a Boolean result value. |
| 435 void SetResultIsBoolean() { |
| 436 DCHECK(type_hint_ == TypeHint::kAny); |
| 437 type_hint_ = TypeHint::kBoolean; |
| 438 } |
| 439 |
| 440 TypeHint type_hint() const { return type_hint_; } |
| 441 |
433 private: | 442 private: |
434 BytecodeGenerator* generator_; | 443 BytecodeGenerator* generator_; |
435 Expression::Context kind_; | |
436 ExpressionResultScope* outer_; | 444 ExpressionResultScope* outer_; |
437 RegisterAllocationScope allocator_; | 445 RegisterAllocationScope allocator_; |
| 446 Expression::Context kind_; |
| 447 TypeHint type_hint_; |
438 | 448 |
439 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | 449 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); |
440 }; | 450 }; |
441 | 451 |
442 // Scoped class used when the result of the current expression is not | 452 // Scoped class used when the result of the current expression is not |
443 // expected to produce a result. | 453 // expected to produce a result. |
444 class BytecodeGenerator::EffectResultScope final | 454 class BytecodeGenerator::EffectResultScope final |
445 : public ExpressionResultScope { | 455 : public ExpressionResultScope { |
446 public: | 456 public: |
447 explicit EffectResultScope(BytecodeGenerator* generator) | 457 explicit EffectResultScope(BytecodeGenerator* generator) |
(...skipping 18 matching lines...) Expand all Loading... |
466 then_labels_(then_labels), | 476 then_labels_(then_labels), |
467 else_labels_(else_labels), | 477 else_labels_(else_labels), |
468 fallthrough_(fallthrough), | 478 fallthrough_(fallthrough), |
469 result_consumed_by_test_(false) {} | 479 result_consumed_by_test_(false) {} |
470 | 480 |
471 // Used when code special cases for TestResultScope and consumes any | 481 // Used when code special cases for TestResultScope and consumes any |
472 // possible value by testing and jumping to a then/else label. | 482 // possible value by testing and jumping to a then/else label. |
473 void SetResultConsumedByTest() { | 483 void SetResultConsumedByTest() { |
474 result_consumed_by_test_ = true; | 484 result_consumed_by_test_ = true; |
475 } | 485 } |
476 | 486 bool result_consumed_by_test() { return result_consumed_by_test_; } |
477 bool ResultConsumedByTest() { return result_consumed_by_test_; } | |
478 | 487 |
479 BytecodeLabel* NewThenLabel() { return then_labels_->New(); } | 488 BytecodeLabel* NewThenLabel() { return then_labels_->New(); } |
480 BytecodeLabel* NewElseLabel() { return else_labels_->New(); } | 489 BytecodeLabel* NewElseLabel() { return else_labels_->New(); } |
481 | 490 |
482 BytecodeLabels* then_labels() const { return then_labels_; } | 491 BytecodeLabels* then_labels() const { return then_labels_; } |
483 BytecodeLabels* else_labels() const { return else_labels_; } | 492 BytecodeLabels* else_labels() const { return else_labels_; } |
484 | 493 |
485 TestFallthrough fallthrough() const { return fallthrough_; } | 494 TestFallthrough fallthrough() const { return fallthrough_; } |
486 TestFallthrough inverted_fallthrough() const { | 495 TestFallthrough inverted_fallthrough() const { |
487 switch (fallthrough_) { | 496 switch (fallthrough_) { |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 | 796 |
788 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, | 797 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, |
789 size_t size, | 798 size_t size, |
790 ZoneVector<BytecodeLabel>& targets) { | 799 ZoneVector<BytecodeLabel>& targets) { |
791 // TODO(neis): Optimize this by using a proper jump table. | 800 // TODO(neis): Optimize this by using a proper jump table. |
792 DCHECK_LE(start_index + size, targets.size()); | 801 DCHECK_LE(start_index + size, targets.size()); |
793 for (size_t i = start_index; i < start_index + size; i++) { | 802 for (size_t i = start_index; i < start_index + size; i++) { |
794 builder() | 803 builder() |
795 ->LoadLiteral(Smi::FromInt(static_cast<int>(i))) | 804 ->LoadLiteral(Smi::FromInt(static_cast<int>(i))) |
796 .CompareOperation(Token::Value::EQ_STRICT, index) | 805 .CompareOperation(Token::Value::EQ_STRICT, index) |
797 .JumpIfTrue(&(targets[i])); | 806 .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &(targets[i])); |
798 } | 807 } |
799 BuildAbort(BailoutReason::kInvalidJumpTableIndex); | 808 BuildAbort(BailoutReason::kInvalidJumpTableIndex); |
800 } | 809 } |
801 | 810 |
802 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, | 811 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, |
803 LoopBuilder* loop_builder) { | 812 LoopBuilder* loop_builder) { |
804 // Recall that stmt->yield_count() is always zero inside ordinary | 813 // Recall that stmt->yield_count() is always zero inside ordinary |
805 // (i.e. non-generator) functions. | 814 // (i.e. non-generator) functions. |
806 if (stmt->suspend_count() == 0) { | 815 if (stmt->suspend_count() == 0) { |
807 loop_builder->LoopHeader(); | 816 loop_builder->LoopHeader(); |
(...skipping 13 matching lines...) Expand all Loading... |
821 } | 830 } |
822 | 831 |
823 loop_builder->LoopHeader(&resume_points_in_loop); | 832 loop_builder->LoopHeader(&resume_points_in_loop); |
824 | 833 |
825 // If we are not resuming, fall through to loop body. | 834 // If we are not resuming, fall through to loop body. |
826 // If we are resuming, perform state dispatch. | 835 // If we are resuming, perform state dispatch. |
827 BytecodeLabel not_resuming; | 836 BytecodeLabel not_resuming; |
828 builder() | 837 builder() |
829 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 838 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
830 .CompareOperation(Token::Value::EQ_STRICT, generator_state_) | 839 .CompareOperation(Token::Value::EQ_STRICT, generator_state_) |
831 .JumpIfTrue(¬_resuming); | 840 .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, ¬_resuming); |
832 BuildIndexedJump(generator_state_, first_yield, stmt->suspend_count(), | 841 BuildIndexedJump(generator_state_, first_yield, stmt->suspend_count(), |
833 generator_resume_points_); | 842 generator_resume_points_); |
834 builder()->Bind(¬_resuming); | 843 builder()->Bind(¬_resuming); |
835 } | 844 } |
836 } | 845 } |
837 | 846 |
838 void BytecodeGenerator::VisitGeneratorPrologue() { | 847 void BytecodeGenerator::VisitGeneratorPrologue() { |
839 // The generator resume trampoline abuses the new.target register both to | 848 // The generator resume trampoline abuses the new.target register both to |
840 // indicate that this is a resume call and to pass in the generator object. | 849 // indicate that this is a resume call and to pass in the generator object. |
841 // In ordinary calls, new.target is always undefined because generator | 850 // In ordinary calls, new.target is always undefined because generator |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 if (clause->is_default()) { | 1144 if (clause->is_default()) { |
1136 default_index = i; | 1145 default_index = i; |
1137 continue; | 1146 continue; |
1138 } | 1147 } |
1139 | 1148 |
1140 // Perform label comparison as if via '===' with tag. | 1149 // Perform label comparison as if via '===' with tag. |
1141 VisitForAccumulatorValue(clause->label()); | 1150 VisitForAccumulatorValue(clause->label()); |
1142 builder()->CompareOperation( | 1151 builder()->CompareOperation( |
1143 Token::Value::EQ_STRICT, tag, | 1152 Token::Value::EQ_STRICT, tag, |
1144 feedback_index(clause->CompareOperationFeedbackSlot())); | 1153 feedback_index(clause->CompareOperationFeedbackSlot())); |
1145 switch_builder.Case(i); | 1154 switch_builder.Case(ToBooleanMode::kAlreadyBoolean, i); |
1146 } | 1155 } |
1147 | 1156 |
1148 if (default_index >= 0) { | 1157 if (default_index >= 0) { |
1149 // Emit default jump if there is a default case. | 1158 // Emit default jump if there is a default case. |
1150 switch_builder.DefaultAt(default_index); | 1159 switch_builder.DefaultAt(default_index); |
1151 } else { | 1160 } else { |
1152 // Otherwise if we have reached here none of the cases matched, so jump to | 1161 // Otherwise if we have reached here none of the cases matched, so jump to |
1153 // the end. | 1162 // the end. |
1154 switch_builder.Break(); | 1163 switch_builder.Break(); |
1155 } | 1164 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 | 1346 |
1338 // Set up loop counter | 1347 // Set up loop counter |
1339 Register index = register_allocator()->NewRegister(); | 1348 Register index = register_allocator()->NewRegister(); |
1340 builder()->LoadLiteral(Smi::kZero); | 1349 builder()->LoadLiteral(Smi::kZero); |
1341 builder()->StoreAccumulatorInRegister(index); | 1350 builder()->StoreAccumulatorInRegister(index); |
1342 | 1351 |
1343 // The loop | 1352 // The loop |
1344 VisitIterationHeader(stmt, &loop_builder); | 1353 VisitIterationHeader(stmt, &loop_builder); |
1345 builder()->SetExpressionAsStatementPosition(stmt->each()); | 1354 builder()->SetExpressionAsStatementPosition(stmt->each()); |
1346 builder()->ForInContinue(index, cache_length); | 1355 builder()->ForInContinue(index, cache_length); |
1347 loop_builder.BreakIfFalse(); | 1356 loop_builder.BreakIfFalse(ToBooleanMode::kAlreadyBoolean); |
1348 FeedbackSlot slot = stmt->ForInFeedbackSlot(); | 1357 FeedbackSlot slot = stmt->ForInFeedbackSlot(); |
1349 builder()->ForInNext(receiver, index, triple.Truncate(2), | 1358 builder()->ForInNext(receiver, index, triple.Truncate(2), |
1350 feedback_index(slot)); | 1359 feedback_index(slot)); |
1351 loop_builder.ContinueIfUndefined(); | 1360 loop_builder.ContinueIfUndefined(); |
1352 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1361 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
1353 VisitIterationBody(stmt, &loop_builder); | 1362 VisitIterationBody(stmt, &loop_builder); |
1354 builder()->ForInStep(index); | 1363 builder()->ForInStep(index); |
1355 builder()->StoreAccumulatorInRegister(index); | 1364 builder()->StoreAccumulatorInRegister(index); |
1356 loop_builder.JumpToHeader(loop_depth_); | 1365 loop_builder.JumpToHeader(loop_depth_); |
1357 loop_builder.EndLoop(); | 1366 loop_builder.EndLoop(); |
1358 builder()->Bind(&subject_null_label); | 1367 builder()->Bind(&subject_null_label); |
1359 builder()->Bind(&subject_undefined_label); | 1368 builder()->Bind(&subject_undefined_label); |
1360 } | 1369 } |
1361 | 1370 |
1362 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 1371 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
1363 LoopBuilder loop_builder(builder()); | 1372 LoopBuilder loop_builder(builder()); |
1364 | 1373 |
1365 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); | 1374 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); |
1366 VisitForEffect(stmt->assign_iterator()); | 1375 VisitForEffect(stmt->assign_iterator()); |
1367 | 1376 |
1368 VisitIterationHeader(stmt, &loop_builder); | 1377 VisitIterationHeader(stmt, &loop_builder); |
1369 builder()->SetExpressionAsStatementPosition(stmt->next_result()); | 1378 builder()->SetExpressionAsStatementPosition(stmt->next_result()); |
1370 VisitForEffect(stmt->next_result()); | 1379 VisitForEffect(stmt->next_result()); |
1371 VisitForAccumulatorValue(stmt->result_done()); | 1380 TypeHint type_hint = VisitForAccumulatorValue(stmt->result_done()); |
1372 loop_builder.BreakIfTrue(); | 1381 loop_builder.BreakIfTrue(ToBooleanModeFromTypeHint(type_hint)); |
1373 | 1382 |
1374 VisitForEffect(stmt->assign_each()); | 1383 VisitForEffect(stmt->assign_each()); |
1375 VisitIterationBody(stmt, &loop_builder); | 1384 VisitIterationBody(stmt, &loop_builder); |
1376 loop_builder.JumpToHeader(loop_depth_); | 1385 loop_builder.JumpToHeader(loop_depth_); |
1377 loop_builder.EndLoop(); | 1386 loop_builder.EndLoop(); |
1378 } | 1387 } |
1379 | 1388 |
1380 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1389 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1381 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1390 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); |
1382 | 1391 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1555 | 1564 |
1556 if (property->is_static() && property->is_computed_name()) { | 1565 if (property->is_static() && property->is_computed_name()) { |
1557 // The static prototype property is read only. We handle the non computed | 1566 // The static prototype property is read only. We handle the non computed |
1558 // property name case in the parser. Since this is the only case where we | 1567 // property name case in the parser. Since this is the only case where we |
1559 // need to check for an own read only property we special case this so we | 1568 // need to check for an own read only property we special case this so we |
1560 // do not need to do this for every property. | 1569 // do not need to do this for every property. |
1561 BytecodeLabel done; | 1570 BytecodeLabel done; |
1562 builder() | 1571 builder() |
1563 ->LoadLiteral(ast_string_constants()->prototype_string()) | 1572 ->LoadLiteral(ast_string_constants()->prototype_string()) |
1564 .CompareOperation(Token::Value::EQ_STRICT, key) | 1573 .CompareOperation(Token::Value::EQ_STRICT, key) |
1565 .JumpIfFalse(&done) | 1574 .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done) |
1566 .CallRuntime(Runtime::kThrowStaticPrototypeError) | 1575 .CallRuntime(Runtime::kThrowStaticPrototypeError) |
1567 .Bind(&done); | 1576 .Bind(&done); |
1568 } | 1577 } |
1569 | 1578 |
1570 VisitForRegisterValue(property->value(), value); | 1579 VisitForRegisterValue(property->value(), value); |
1571 VisitSetHomeObject(value, receiver, property); | 1580 VisitSetHomeObject(value, receiver, property); |
1572 | 1581 |
1573 if (!attr_assigned) { | 1582 if (!attr_assigned) { |
1574 builder() | 1583 builder() |
1575 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) | 1584 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1655 else_labels.Bind(builder()); | 1664 else_labels.Bind(builder()); |
1656 VisitForAccumulatorValue(expr->else_expression()); | 1665 VisitForAccumulatorValue(expr->else_expression()); |
1657 builder()->Bind(&end_label); | 1666 builder()->Bind(&end_label); |
1658 } | 1667 } |
1659 } | 1668 } |
1660 | 1669 |
1661 void BytecodeGenerator::VisitLiteral(Literal* expr) { | 1670 void BytecodeGenerator::VisitLiteral(Literal* expr) { |
1662 if (!execution_result()->IsEffect()) { | 1671 if (!execution_result()->IsEffect()) { |
1663 const AstValue* raw_value = expr->raw_value(); | 1672 const AstValue* raw_value = expr->raw_value(); |
1664 builder()->LoadLiteral(raw_value); | 1673 builder()->LoadLiteral(raw_value); |
| 1674 if (raw_value->IsTrue() || raw_value->IsFalse()) { |
| 1675 execution_result()->SetResultIsBoolean(); |
| 1676 } |
1665 } | 1677 } |
1666 } | 1678 } |
1667 | 1679 |
1668 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1680 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1669 // Materialize a regular expression literal. | 1681 // Materialize a regular expression literal. |
1670 builder()->CreateRegExpLiteral( | 1682 builder()->CreateRegExpLiteral( |
1671 expr->raw_pattern(), feedback_index(expr->literal_slot()), expr->flags()); | 1683 expr->raw_pattern(), feedback_index(expr->literal_slot()), expr->flags()); |
1672 } | 1684 } |
1673 | 1685 |
1674 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1686 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2443 | 2455 |
2444 // Now dispatch on resume mode. | 2456 // Now dispatch on resume mode. |
2445 | 2457 |
2446 BytecodeLabel resume_with_next; | 2458 BytecodeLabel resume_with_next; |
2447 BytecodeLabel resume_with_return; | 2459 BytecodeLabel resume_with_return; |
2448 BytecodeLabel resume_with_throw; | 2460 BytecodeLabel resume_with_throw; |
2449 | 2461 |
2450 builder() | 2462 builder() |
2451 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) | 2463 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) |
2452 .CompareOperation(Token::EQ_STRICT, resume_mode) | 2464 .CompareOperation(Token::EQ_STRICT, resume_mode) |
2453 .JumpIfTrue(&resume_with_next) | 2465 .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_with_next) |
2454 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) | 2466 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) |
2455 .CompareOperation(Token::EQ_STRICT, resume_mode) | 2467 .CompareOperation(Token::EQ_STRICT, resume_mode) |
2456 .JumpIfTrue(&resume_with_throw) | 2468 .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_with_throw) |
2457 .Jump(&resume_with_return); | 2469 .Jump(&resume_with_return); |
2458 | 2470 |
2459 builder()->Bind(&resume_with_return); | 2471 builder()->Bind(&resume_with_return); |
2460 { | 2472 { |
2461 if (expr->is_async_generator()) { | 2473 if (expr->is_async_generator()) { |
2462 // Async generator methods will produce the iter result object. | 2474 // Async generator methods will produce the iter result object. |
2463 builder()->LoadAccumulatorWithRegister(input); | 2475 builder()->LoadAccumulatorWithRegister(input); |
2464 execution_control()->AsyncReturnAccumulator(); | 2476 execution_control()->AsyncReturnAccumulator(); |
2465 } else { | 2477 } else { |
2466 RegisterList args = register_allocator()->NewRegisterList(2); | 2478 RegisterList args = register_allocator()->NewRegisterList(2); |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2807 VisitForEffect(expr->expression()); | 2819 VisitForEffect(expr->expression()); |
2808 } else if (execution_result()->IsTest()) { | 2820 } else if (execution_result()->IsTest()) { |
2809 TestResultScope* test_result = execution_result()->AsTest(); | 2821 TestResultScope* test_result = execution_result()->AsTest(); |
2810 // No actual logical negation happening, we just swap the control flow by | 2822 // No actual logical negation happening, we just swap the control flow by |
2811 // swapping the target labels and the fallthrough branch. | 2823 // swapping the target labels and the fallthrough branch. |
2812 VisitForTest(expr->expression(), test_result->else_labels(), | 2824 VisitForTest(expr->expression(), test_result->else_labels(), |
2813 test_result->then_labels(), | 2825 test_result->then_labels(), |
2814 test_result->inverted_fallthrough()); | 2826 test_result->inverted_fallthrough()); |
2815 test_result->SetResultConsumedByTest(); | 2827 test_result->SetResultConsumedByTest(); |
2816 } else { | 2828 } else { |
2817 VisitForAccumulatorValue(expr->expression()); | 2829 TypeHint type_hint = VisitForAccumulatorValue(expr->expression()); |
2818 builder()->LogicalNot(); | 2830 builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint)); |
2819 } | 2831 } |
| 2832 // Always returns a boolean value. |
| 2833 execution_result()->SetResultIsBoolean(); |
2820 } | 2834 } |
2821 | 2835 |
2822 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 2836 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
2823 switch (expr->op()) { | 2837 switch (expr->op()) { |
2824 case Token::Value::NOT: | 2838 case Token::Value::NOT: |
2825 VisitNot(expr); | 2839 VisitNot(expr); |
2826 break; | 2840 break; |
2827 case Token::Value::TYPEOF: | 2841 case Token::Value::TYPEOF: |
2828 VisitTypeOf(expr); | 2842 VisitTypeOf(expr); |
2829 break; | 2843 break; |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3088 Register lhs = VisitForRegisterValue(expr->left()); | 3102 Register lhs = VisitForRegisterValue(expr->left()); |
3089 VisitForAccumulatorValue(expr->right()); | 3103 VisitForAccumulatorValue(expr->right()); |
3090 builder()->SetExpressionPosition(expr); | 3104 builder()->SetExpressionPosition(expr); |
3091 FeedbackSlot slot = expr->CompareOperationFeedbackSlot(); | 3105 FeedbackSlot slot = expr->CompareOperationFeedbackSlot(); |
3092 if (slot.IsInvalid()) { | 3106 if (slot.IsInvalid()) { |
3093 builder()->CompareOperation(expr->op(), lhs); | 3107 builder()->CompareOperation(expr->op(), lhs); |
3094 } else { | 3108 } else { |
3095 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot)); | 3109 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot)); |
3096 } | 3110 } |
3097 } | 3111 } |
| 3112 // Always returns a boolean value. |
| 3113 execution_result()->SetResultIsBoolean(); |
3098 } | 3114 } |
3099 | 3115 |
3100 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 3116 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
3101 // TODO(rmcilroy): Special case "x * 1.0" and "x * -1" which are generated for | 3117 // TODO(rmcilroy): Special case "x * 1.0" and "x * -1" which are generated for |
3102 // +x and -x by the parser. | 3118 // +x and -x by the parser. |
3103 Register lhs = VisitForRegisterValue(expr->left()); | 3119 Register lhs = VisitForRegisterValue(expr->left()); |
3104 VisitForAccumulatorValue(expr->right()); | 3120 VisitForAccumulatorValue(expr->right()); |
3105 FeedbackSlot slot = expr->BinaryOperationFeedbackSlot(); | 3121 FeedbackSlot slot = expr->BinaryOperationFeedbackSlot(); |
3106 builder()->SetExpressionPosition(expr); | 3122 builder()->SetExpressionPosition(expr); |
3107 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); | 3123 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3222 test_result->else_labels(), test_result->fallthrough()); | 3238 test_result->else_labels(), test_result->fallthrough()); |
3223 } | 3239 } |
3224 test_result->SetResultConsumedByTest(); | 3240 test_result->SetResultConsumedByTest(); |
3225 } else { | 3241 } else { |
3226 if (left->ToBooleanIsTrue()) { | 3242 if (left->ToBooleanIsTrue()) { |
3227 VisitForAccumulatorValue(left); | 3243 VisitForAccumulatorValue(left); |
3228 } else if (left->ToBooleanIsFalse()) { | 3244 } else if (left->ToBooleanIsFalse()) { |
3229 VisitForAccumulatorValue(right); | 3245 VisitForAccumulatorValue(right); |
3230 } else { | 3246 } else { |
3231 BytecodeLabel end_label; | 3247 BytecodeLabel end_label; |
3232 VisitForAccumulatorValue(left); | 3248 TypeHint type_hint = VisitForAccumulatorValue(left); |
3233 builder()->JumpIfTrue(&end_label); | 3249 builder()->JumpIfTrue(ToBooleanModeFromTypeHint(type_hint), &end_label); |
3234 VisitForAccumulatorValue(right); | 3250 VisitForAccumulatorValue(right); |
3235 builder()->Bind(&end_label); | 3251 builder()->Bind(&end_label); |
3236 } | 3252 } |
3237 } | 3253 } |
3238 } | 3254 } |
3239 | 3255 |
3240 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { | 3256 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { |
3241 Expression* left = binop->left(); | 3257 Expression* left = binop->left(); |
3242 Expression* right = binop->right(); | 3258 Expression* right = binop->right(); |
3243 | 3259 |
(...skipping 13 matching lines...) Expand all Loading... |
3257 test_result->else_labels(), test_result->fallthrough()); | 3273 test_result->else_labels(), test_result->fallthrough()); |
3258 } | 3274 } |
3259 test_result->SetResultConsumedByTest(); | 3275 test_result->SetResultConsumedByTest(); |
3260 } else { | 3276 } else { |
3261 if (left->ToBooleanIsFalse()) { | 3277 if (left->ToBooleanIsFalse()) { |
3262 VisitForAccumulatorValue(left); | 3278 VisitForAccumulatorValue(left); |
3263 } else if (left->ToBooleanIsTrue()) { | 3279 } else if (left->ToBooleanIsTrue()) { |
3264 VisitForAccumulatorValue(right); | 3280 VisitForAccumulatorValue(right); |
3265 } else { | 3281 } else { |
3266 BytecodeLabel end_label; | 3282 BytecodeLabel end_label; |
3267 VisitForAccumulatorValue(left); | 3283 TypeHint type_hint = VisitForAccumulatorValue(left); |
3268 builder()->JumpIfFalse(&end_label); | 3284 builder()->JumpIfFalse(ToBooleanModeFromTypeHint(type_hint), &end_label); |
3269 VisitForAccumulatorValue(right); | 3285 VisitForAccumulatorValue(right); |
3270 builder()->Bind(&end_label); | 3286 builder()->Bind(&end_label); |
3271 } | 3287 } |
3272 } | 3288 } |
3273 } | 3289 } |
3274 | 3290 |
3275 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 3291 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
3276 Visit(expr->expression()); | 3292 Visit(expr->expression()); |
3277 } | 3293 } |
3278 | 3294 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3478 Context::CLOSURE_INDEX, 0, | 3494 Context::CLOSURE_INDEX, 0, |
3479 BytecodeArrayBuilder::kImmutableSlot); | 3495 BytecodeArrayBuilder::kImmutableSlot); |
3480 } else { | 3496 } else { |
3481 DCHECK(closure_scope()->is_function_scope() || | 3497 DCHECK(closure_scope()->is_function_scope() || |
3482 closure_scope()->is_module_scope()); | 3498 closure_scope()->is_module_scope()); |
3483 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3499 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
3484 } | 3500 } |
3485 } | 3501 } |
3486 | 3502 |
3487 // Visits the expression |expr| and places the result in the accumulator. | 3503 // Visits the expression |expr| and places the result in the accumulator. |
3488 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3504 BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue( |
| 3505 Expression* expr) { |
3489 ValueResultScope accumulator_scope(this); | 3506 ValueResultScope accumulator_scope(this); |
3490 Visit(expr); | 3507 Visit(expr); |
| 3508 return accumulator_scope.type_hint(); |
3491 } | 3509 } |
3492 | 3510 |
3493 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { | 3511 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { |
3494 if (expr == nullptr) { | 3512 if (expr == nullptr) { |
3495 builder()->LoadTheHole(); | 3513 builder()->LoadTheHole(); |
3496 } else { | 3514 } else { |
3497 VisitForAccumulatorValue(expr); | 3515 VisitForAccumulatorValue(expr); |
3498 } | 3516 } |
3499 } | 3517 } |
3500 | 3518 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3544 builder()->LoadUndefined().StoreAccumulatorInRegister(reg); | 3562 builder()->LoadUndefined().StoreAccumulatorInRegister(reg); |
3545 } | 3563 } |
3546 | 3564 |
3547 // Visits the expression |expr| for testing its boolean value and jumping to the | 3565 // Visits the expression |expr| for testing its boolean value and jumping to the |
3548 // |then| or |other| label depending on value and short-circuit semantics | 3566 // |then| or |other| label depending on value and short-circuit semantics |
3549 void BytecodeGenerator::VisitForTest(Expression* expr, | 3567 void BytecodeGenerator::VisitForTest(Expression* expr, |
3550 BytecodeLabels* then_labels, | 3568 BytecodeLabels* then_labels, |
3551 BytecodeLabels* else_labels, | 3569 BytecodeLabels* else_labels, |
3552 TestFallthrough fallthrough) { | 3570 TestFallthrough fallthrough) { |
3553 bool result_consumed; | 3571 bool result_consumed; |
| 3572 TypeHint type_hint; |
3554 { | 3573 { |
3555 // To make sure that all temporary registers are returned before generating | 3574 // To make sure that all temporary registers are returned before generating |
3556 // jumps below, we ensure that the result scope is deleted before doing so. | 3575 // jumps below, we ensure that the result scope is deleted before doing so. |
3557 // Dead registers might be materialized otherwise. | 3576 // Dead registers might be materialized otherwise. |
3558 TestResultScope test_result(this, then_labels, else_labels, fallthrough); | 3577 TestResultScope test_result(this, then_labels, else_labels, fallthrough); |
3559 Visit(expr); | 3578 Visit(expr); |
3560 result_consumed = test_result.ResultConsumedByTest(); | 3579 result_consumed = test_result.result_consumed_by_test(); |
| 3580 type_hint = test_result.type_hint(); |
3561 } | 3581 } |
3562 if (!result_consumed) { | 3582 if (!result_consumed) { |
| 3583 ToBooleanMode mode(ToBooleanModeFromTypeHint(type_hint)); |
3563 switch (fallthrough) { | 3584 switch (fallthrough) { |
3564 case TestFallthrough::kThen: | 3585 case TestFallthrough::kThen: |
3565 builder()->JumpIfFalse(else_labels->New()); | 3586 builder()->JumpIfFalse(mode, else_labels->New()); |
3566 break; | 3587 break; |
3567 case TestFallthrough::kElse: | 3588 case TestFallthrough::kElse: |
3568 builder()->JumpIfTrue(then_labels->New()); | 3589 builder()->JumpIfTrue(mode, then_labels->New()); |
3569 break; | 3590 break; |
3570 case TestFallthrough::kNone: | 3591 case TestFallthrough::kNone: |
3571 builder()->JumpIfTrue(then_labels->New()); | 3592 builder()->JumpIfTrue(mode, then_labels->New()); |
3572 builder()->Jump(else_labels->New()); | 3593 builder()->Jump(else_labels->New()); |
3573 } | 3594 } |
3574 } | 3595 } |
3575 } | 3596 } |
3576 | 3597 |
3577 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { | 3598 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { |
3578 DCHECK(scope->declarations()->is_empty()); | 3599 DCHECK(scope->declarations()->is_empty()); |
3579 CurrentScope current_scope(this, scope); | 3600 CurrentScope current_scope(this, scope); |
3580 ContextScope context_scope(this, scope); | 3601 ContextScope context_scope(this, scope); |
3581 Visit(stmt); | 3602 Visit(stmt); |
3582 } | 3603 } |
3583 | 3604 |
| 3605 BytecodeArrayBuilder::ToBooleanMode |
| 3606 BytecodeGenerator::ToBooleanModeFromTypeHint(TypeHint type_hint) { |
| 3607 return type_hint == TypeHint::kBoolean ? ToBooleanMode::kAlreadyBoolean |
| 3608 : ToBooleanMode::kConvertToBoolean; |
| 3609 } |
| 3610 |
3584 LanguageMode BytecodeGenerator::language_mode() const { | 3611 LanguageMode BytecodeGenerator::language_mode() const { |
3585 return current_scope()->language_mode(); | 3612 return current_scope()->language_mode(); |
3586 } | 3613 } |
3587 | 3614 |
3588 int BytecodeGenerator::feedback_index(FeedbackSlot slot) const { | 3615 int BytecodeGenerator::feedback_index(FeedbackSlot slot) const { |
3589 return FeedbackVector::GetIndex(slot); | 3616 return FeedbackVector::GetIndex(slot); |
3590 } | 3617 } |
3591 | 3618 |
3592 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { | 3619 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { |
3593 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 3620 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
3594 : Runtime::kStoreToSuper_Sloppy; | 3621 : Runtime::kStoreToSuper_Sloppy; |
3595 } | 3622 } |
3596 | 3623 |
3597 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3624 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3598 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3625 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3599 : Runtime::kStoreKeyedToSuper_Sloppy; | 3626 : Runtime::kStoreKeyedToSuper_Sloppy; |
3600 } | 3627 } |
3601 | 3628 |
3602 } // namespace interpreter | 3629 } // namespace interpreter |
3603 } // namespace internal | 3630 } // namespace internal |
3604 } // namespace v8 | 3631 } // namespace v8 |
OLD | NEW |