Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(721)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 2795183002: [Interpreter] Move ToBoolean elision in BytecodeGenerator. (Closed)
Patch Set: tests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-peephole-optimizer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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(&not_resuming); 840 .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &not_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(&not_resuming); 843 builder()->Bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-peephole-optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698