OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/interpreter/bytecode-flags.h" | 10 #include "src/interpreter/bytecode-flags.h" |
| 11 #include "src/interpreter/bytecode-label.h" |
11 #include "src/interpreter/bytecode-register-allocator.h" | 12 #include "src/interpreter/bytecode-register-allocator.h" |
12 #include "src/interpreter/control-flow-builders.h" | 13 #include "src/interpreter/control-flow-builders.h" |
13 #include "src/objects.h" | 14 #include "src/objects.h" |
14 #include "src/parsing/parser.h" | 15 #include "src/parsing/parser.h" |
15 #include "src/parsing/token.h" | 16 #include "src/parsing/token.h" |
16 | 17 |
17 namespace v8 { | 18 namespace v8 { |
18 namespace internal { | 19 namespace internal { |
19 namespace interpreter { | 20 namespace interpreter { |
20 | 21 |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 generator_->set_execution_result(this); | 439 generator_->set_execution_result(this); |
439 } | 440 } |
440 | 441 |
441 virtual ~ExpressionResultScope() { | 442 virtual ~ExpressionResultScope() { |
442 generator_->set_execution_result(outer_); | 443 generator_->set_execution_result(outer_); |
443 DCHECK(result_identified() || generator_->HasStackOverflow()); | 444 DCHECK(result_identified() || generator_->HasStackOverflow()); |
444 } | 445 } |
445 | 446 |
446 bool IsEffect() const { return kind_ == Expression::kEffect; } | 447 bool IsEffect() const { return kind_ == Expression::kEffect; } |
447 bool IsValue() const { return kind_ == Expression::kValue; } | 448 bool IsValue() const { return kind_ == Expression::kValue; } |
| 449 bool IsTest() const { return kind_ == Expression::kTest; } |
| 450 |
| 451 TestResultScope* AsTest() { |
| 452 DCHECK(IsTest()); |
| 453 return reinterpret_cast<TestResultScope*>(this); |
| 454 } |
448 | 455 |
449 virtual void SetResultInAccumulator() = 0; | 456 virtual void SetResultInAccumulator() = 0; |
450 virtual void SetResultInRegister(Register reg) = 0; | 457 virtual void SetResultInRegister(Register reg) = 0; |
451 | 458 |
452 protected: | 459 protected: |
453 ExpressionResultScope* outer() const { return outer_; } | 460 ExpressionResultScope* outer() const { return outer_; } |
454 BytecodeArrayBuilder* builder() const { return generator_->builder(); } | 461 BytecodeArrayBuilder* builder() const { return generator_->builder(); } |
455 BytecodeGenerator* generator() const { return generator_; } | 462 BytecodeGenerator* generator() const { return generator_; } |
456 const RegisterAllocationScope* allocator() const { return &allocator_; } | 463 const RegisterAllocationScope* allocator() const { return &allocator_; } |
457 | 464 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 if (generator()->HasStackOverflow() && !result_identified()) { | 535 if (generator()->HasStackOverflow() && !result_identified()) { |
529 SetResultInAccumulator(); | 536 SetResultInAccumulator(); |
530 } | 537 } |
531 return result_register_; | 538 return result_register_; |
532 } | 539 } |
533 | 540 |
534 private: | 541 private: |
535 Register result_register_; | 542 Register result_register_; |
536 }; | 543 }; |
537 | 544 |
| 545 // Scoped class used when the result of the current expression to be |
| 546 // evaluated is only tested with jumps to two branches. |
| 547 class BytecodeGenerator::TestResultScope final : public ExpressionResultScope { |
| 548 public: |
| 549 TestResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels, |
| 550 BytecodeLabels* else_labels, TestFallthrough fallthrough) |
| 551 : ExpressionResultScope(generator, Expression::kTest), |
| 552 then_labels_(then_labels), |
| 553 else_labels_(else_labels), |
| 554 fallthrough_(fallthrough), |
| 555 result_consumed_by_test_(false) {} |
| 556 |
| 557 virtual void SetResultInAccumulator() { set_result_identified(); } |
| 558 |
| 559 virtual void SetResultInRegister(Register reg) { |
| 560 builder()->LoadAccumulatorWithRegister(reg); |
| 561 set_result_identified(); |
| 562 } |
| 563 |
| 564 // Used when code special cases for TestResultScope and consumes any |
| 565 // possible value by testing and jumping to a then/else label. |
| 566 void SetResultConsumedByTest() { |
| 567 result_consumed_by_test_ = true; |
| 568 set_result_identified(); |
| 569 } |
| 570 |
| 571 bool ResultConsumedByTest() { return result_consumed_by_test_; } |
| 572 |
| 573 BytecodeLabel* NewThenLabel() { return then_labels_->New(); } |
| 574 BytecodeLabel* NewElseLabel() { return else_labels_->New(); } |
| 575 |
| 576 BytecodeLabels* then_labels() const { return then_labels_; } |
| 577 BytecodeLabels* else_labels() const { return else_labels_; } |
| 578 |
| 579 TestFallthrough fallthrough() const { return fallthrough_; } |
| 580 TestFallthrough inverted_fallthrough() const { |
| 581 switch (fallthrough_) { |
| 582 case TestFallthrough::kThen: |
| 583 return TestFallthrough::kElse; |
| 584 case TestFallthrough::kElse: |
| 585 return TestFallthrough::kThen; |
| 586 default: |
| 587 return TestFallthrough::kNone; |
| 588 } |
| 589 } |
| 590 |
| 591 private: |
| 592 BytecodeLabels* then_labels_; |
| 593 BytecodeLabels* else_labels_; |
| 594 TestFallthrough fallthrough_; |
| 595 bool result_consumed_by_test_; |
| 596 |
| 597 DISALLOW_COPY_AND_ASSIGN(TestResultScope); |
| 598 }; |
| 599 |
538 // Used to build a list of global declaration initial value pairs. | 600 // Used to build a list of global declaration initial value pairs. |
539 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { | 601 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { |
540 public: | 602 public: |
541 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone) | 603 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone) |
542 : isolate_(isolate), | 604 : isolate_(isolate), |
543 declarations_(0, zone), | 605 declarations_(0, zone), |
544 constant_pool_entry_(0), | 606 constant_pool_entry_(0), |
545 has_constant_pool_entry_(false) {} | 607 has_constant_pool_entry_(false) {} |
546 | 608 |
547 void AddFunctionDeclaration(FeedbackVectorSlot slot, FunctionLiteral* func) { | 609 void AddFunctionDeclaration(FeedbackVectorSlot slot, FunctionLiteral* func) { |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 1038 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
977 builder()->SetStatementPosition(stmt); | 1039 builder()->SetStatementPosition(stmt); |
978 VisitForEffect(stmt->expression()); | 1040 VisitForEffect(stmt->expression()); |
979 } | 1041 } |
980 | 1042 |
981 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 1043 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
982 } | 1044 } |
983 | 1045 |
984 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 1046 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
985 builder()->SetStatementPosition(stmt); | 1047 builder()->SetStatementPosition(stmt); |
986 BytecodeLabel else_label, end_label; | |
987 if (stmt->condition()->ToBooleanIsTrue()) { | 1048 if (stmt->condition()->ToBooleanIsTrue()) { |
988 // Generate then block unconditionally as always true. | 1049 // Generate then block unconditionally as always true. |
989 Visit(stmt->then_statement()); | 1050 Visit(stmt->then_statement()); |
990 } else if (stmt->condition()->ToBooleanIsFalse()) { | 1051 } else if (stmt->condition()->ToBooleanIsFalse()) { |
991 // Generate else block unconditionally if it exists. | 1052 // Generate else block unconditionally if it exists. |
992 if (stmt->HasElseStatement()) { | 1053 if (stmt->HasElseStatement()) { |
993 Visit(stmt->else_statement()); | 1054 Visit(stmt->else_statement()); |
994 } | 1055 } |
995 } else { | 1056 } else { |
996 // TODO(oth): If then statement is BreakStatement or | 1057 // TODO(oth): If then statement is BreakStatement or |
997 // ContinueStatement we can reduce number of generated | 1058 // ContinueStatement we can reduce number of generated |
998 // jump/jump_ifs here. See BasicLoops test. | 1059 // jump/jump_ifs here. See BasicLoops test. |
999 VisitForAccumulatorValue(stmt->condition()); | 1060 BytecodeLabel end_label; |
1000 builder()->JumpIfFalse(&else_label); | 1061 BytecodeLabels then_labels(zone()), else_labels(zone()); |
| 1062 VisitForTest(stmt->condition(), &then_labels, &else_labels, |
| 1063 TestFallthrough::kThen); |
| 1064 |
| 1065 then_labels.Bind(builder()); |
1001 Visit(stmt->then_statement()); | 1066 Visit(stmt->then_statement()); |
| 1067 |
1002 if (stmt->HasElseStatement()) { | 1068 if (stmt->HasElseStatement()) { |
1003 builder()->Jump(&end_label); | 1069 builder()->Jump(&end_label); |
1004 builder()->Bind(&else_label); | 1070 else_labels.Bind(builder()); |
1005 Visit(stmt->else_statement()); | 1071 Visit(stmt->else_statement()); |
1006 } else { | 1072 } else { |
1007 builder()->Bind(&else_label); | 1073 else_labels.Bind(builder()); |
1008 } | 1074 } |
1009 builder()->Bind(&end_label); | 1075 builder()->Bind(&end_label); |
1010 } | 1076 } |
1011 } | 1077 } |
1012 | 1078 |
1013 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 1079 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( |
1014 SloppyBlockFunctionStatement* stmt) { | 1080 SloppyBlockFunctionStatement* stmt) { |
1015 Visit(stmt->statement()); | 1081 Visit(stmt->statement()); |
1016 } | 1082 } |
1017 | 1083 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 if (stmt->cond()->ToBooleanIsFalse()) { | 1172 if (stmt->cond()->ToBooleanIsFalse()) { |
1107 VisitIterationBody(stmt, &loop_builder); | 1173 VisitIterationBody(stmt, &loop_builder); |
1108 } else if (stmt->cond()->ToBooleanIsTrue()) { | 1174 } else if (stmt->cond()->ToBooleanIsTrue()) { |
1109 VisitIterationHeader(stmt, &loop_builder); | 1175 VisitIterationHeader(stmt, &loop_builder); |
1110 VisitIterationBody(stmt, &loop_builder); | 1176 VisitIterationBody(stmt, &loop_builder); |
1111 loop_builder.JumpToHeader(); | 1177 loop_builder.JumpToHeader(); |
1112 } else { | 1178 } else { |
1113 VisitIterationHeader(stmt, &loop_builder); | 1179 VisitIterationHeader(stmt, &loop_builder); |
1114 VisitIterationBody(stmt, &loop_builder); | 1180 VisitIterationBody(stmt, &loop_builder); |
1115 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1181 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1182 // TODO(klaasb) VisitForTest for loop conditions |
1116 VisitForAccumulatorValue(stmt->cond()); | 1183 VisitForAccumulatorValue(stmt->cond()); |
1117 loop_builder.JumpToHeaderIfTrue(); | 1184 loop_builder.JumpToHeaderIfTrue(); |
1118 } | 1185 } |
1119 loop_builder.EndLoop(); | 1186 loop_builder.EndLoop(); |
1120 } | 1187 } |
1121 | 1188 |
1122 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 1189 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
1123 if (stmt->cond()->ToBooleanIsFalse()) { | 1190 if (stmt->cond()->ToBooleanIsFalse()) { |
1124 // If the condition is false there is no need to generate the loop. | 1191 // If the condition is false there is no need to generate the loop. |
1125 return; | 1192 return; |
1126 } | 1193 } |
1127 | 1194 |
1128 LoopBuilder loop_builder(builder()); | 1195 LoopBuilder loop_builder(builder()); |
1129 VisitIterationHeader(stmt, &loop_builder); | 1196 VisitIterationHeader(stmt, &loop_builder); |
1130 if (!stmt->cond()->ToBooleanIsTrue()) { | 1197 if (!stmt->cond()->ToBooleanIsTrue()) { |
1131 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1198 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1199 // TODO(klaasb) VisitForTest for loop conditions |
1132 VisitForAccumulatorValue(stmt->cond()); | 1200 VisitForAccumulatorValue(stmt->cond()); |
1133 loop_builder.BreakIfFalse(); | 1201 loop_builder.BreakIfFalse(); |
1134 } | 1202 } |
1135 VisitIterationBody(stmt, &loop_builder); | 1203 VisitIterationBody(stmt, &loop_builder); |
1136 loop_builder.JumpToHeader(); | 1204 loop_builder.JumpToHeader(); |
1137 loop_builder.EndLoop(); | 1205 loop_builder.EndLoop(); |
1138 } | 1206 } |
1139 | 1207 |
1140 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 1208 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
1141 if (stmt->init() != nullptr) { | 1209 if (stmt->init() != nullptr) { |
1142 Visit(stmt->init()); | 1210 Visit(stmt->init()); |
1143 } | 1211 } |
1144 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 1212 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
1145 // If the condition is known to be false there is no need to generate | 1213 // If the condition is known to be false there is no need to generate |
1146 // body, next or condition blocks. Init block should be generated. | 1214 // body, next or condition blocks. Init block should be generated. |
1147 return; | 1215 return; |
1148 } | 1216 } |
1149 | 1217 |
1150 LoopBuilder loop_builder(builder()); | 1218 LoopBuilder loop_builder(builder()); |
1151 VisitIterationHeader(stmt, &loop_builder); | 1219 VisitIterationHeader(stmt, &loop_builder); |
1152 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 1220 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
1153 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1221 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1222 // TODO(klaasb) VisitForTest for loop conditions |
1154 VisitForAccumulatorValue(stmt->cond()); | 1223 VisitForAccumulatorValue(stmt->cond()); |
1155 loop_builder.BreakIfFalse(); | 1224 loop_builder.BreakIfFalse(); |
1156 } | 1225 } |
1157 VisitIterationBody(stmt, &loop_builder); | 1226 VisitIterationBody(stmt, &loop_builder); |
1158 if (stmt->next() != nullptr) { | 1227 if (stmt->next() != nullptr) { |
1159 builder()->SetStatementPosition(stmt->next()); | 1228 builder()->SetStatementPosition(stmt->next()); |
1160 Visit(stmt->next()); | 1229 Visit(stmt->next()); |
1161 } | 1230 } |
1162 loop_builder.JumpToHeader(); | 1231 loop_builder.JumpToHeader(); |
1163 loop_builder.EndLoop(); | 1232 loop_builder.EndLoop(); |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 native_function_literals_.push_back(std::make_pair(expr, entry)); | 1631 native_function_literals_.push_back(std::make_pair(expr, entry)); |
1563 execution_result()->SetResultInAccumulator(); | 1632 execution_result()->SetResultInAccumulator(); |
1564 } | 1633 } |
1565 | 1634 |
1566 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { | 1635 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { |
1567 VisitBlock(expr->block()); | 1636 VisitBlock(expr->block()); |
1568 VisitVariableProxy(expr->result()); | 1637 VisitVariableProxy(expr->result()); |
1569 } | 1638 } |
1570 | 1639 |
1571 void BytecodeGenerator::VisitConditional(Conditional* expr) { | 1640 void BytecodeGenerator::VisitConditional(Conditional* expr) { |
1572 // TODO(rmcilroy): Spot easy cases where there code would not need to | 1641 if (expr->condition()->ToBooleanIsTrue()) { |
1573 // emit the then block or the else block, e.g. condition is | 1642 // Generate then block unconditionally as always true. |
1574 // obviously true/1/false/0. | 1643 VisitForAccumulatorValue(expr->then_expression()); |
| 1644 } else if (expr->condition()->ToBooleanIsFalse()) { |
| 1645 // Generate else block unconditionally if it exists. |
| 1646 VisitForAccumulatorValue(expr->else_expression()); |
| 1647 } else { |
| 1648 BytecodeLabel end_label; |
| 1649 BytecodeLabels then_labels(zone()), else_labels(zone()); |
1575 | 1650 |
1576 BytecodeLabel else_label, end_label; | 1651 VisitForTest(expr->condition(), &then_labels, &else_labels, |
| 1652 TestFallthrough::kThen); |
1577 | 1653 |
1578 VisitForAccumulatorValue(expr->condition()); | 1654 then_labels.Bind(builder()); |
1579 builder()->JumpIfFalse(&else_label); | 1655 VisitForAccumulatorValue(expr->then_expression()); |
| 1656 builder()->Jump(&end_label); |
1580 | 1657 |
1581 VisitForAccumulatorValue(expr->then_expression()); | 1658 else_labels.Bind(builder()); |
1582 builder()->Jump(&end_label); | 1659 VisitForAccumulatorValue(expr->else_expression()); |
1583 | 1660 builder()->Bind(&end_label); |
1584 builder()->Bind(&else_label); | 1661 } |
1585 VisitForAccumulatorValue(expr->else_expression()); | |
1586 builder()->Bind(&end_label); | |
1587 | 1662 |
1588 execution_result()->SetResultInAccumulator(); | 1663 execution_result()->SetResultInAccumulator(); |
1589 } | 1664 } |
1590 | 1665 |
1591 void BytecodeGenerator::VisitLiteral(Literal* expr) { | 1666 void BytecodeGenerator::VisitLiteral(Literal* expr) { |
1592 if (!execution_result()->IsEffect()) { | 1667 if (!execution_result()->IsEffect()) { |
1593 const AstValue* raw_value = expr->raw_value(); | 1668 const AstValue* raw_value = expr->raw_value(); |
1594 if (raw_value->IsSmi()) { | 1669 if (raw_value->IsSmi()) { |
1595 builder()->LoadLiteral(raw_value->AsSmi()); | 1670 builder()->LoadLiteral(raw_value->AsSmi()); |
1596 } else if (raw_value->IsUndefined()) { | 1671 } else if (raw_value->IsUndefined()) { |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 BuildThrowIfHole(variable->name()); | 1934 BuildThrowIfHole(variable->name()); |
1860 } | 1935 } |
1861 } | 1936 } |
1862 | 1937 |
1863 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1938 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
1864 FeedbackVectorSlot slot, | 1939 FeedbackVectorSlot slot, |
1865 TypeofMode typeof_mode) { | 1940 TypeofMode typeof_mode) { |
1866 switch (variable->location()) { | 1941 switch (variable->location()) { |
1867 case VariableLocation::LOCAL: { | 1942 case VariableLocation::LOCAL: { |
1868 Register source(Register(variable->index())); | 1943 Register source(Register(variable->index())); |
| 1944 // We need to load the variable into the accumulator, even when in a |
| 1945 // VisitForRegisterScope, in order to avoid register aliasing if |
| 1946 // subsequent expressions assign to the same variable. |
1869 builder()->LoadAccumulatorWithRegister(source); | 1947 builder()->LoadAccumulatorWithRegister(source); |
1870 BuildHoleCheckForVariableLoad(variable); | 1948 BuildHoleCheckForVariableLoad(variable); |
1871 break; | 1949 break; |
1872 } | 1950 } |
1873 case VariableLocation::PARAMETER: { | 1951 case VariableLocation::PARAMETER: { |
1874 // The parameter indices are shifted by 1 (receiver is variable | 1952 // The parameter indices are shifted by 1 (receiver is variable |
1875 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1953 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1876 Register source = builder()->Parameter(variable->index() + 1); | 1954 Register source = builder()->Parameter(variable->index() + 1); |
| 1955 // We need to load the variable into the accumulator, even when in a |
| 1956 // VisitForRegisterScope, in order to avoid register aliasing if |
| 1957 // subsequent expressions assign to the same variable. |
1877 builder()->LoadAccumulatorWithRegister(source); | 1958 builder()->LoadAccumulatorWithRegister(source); |
1878 BuildHoleCheckForVariableLoad(variable); | 1959 BuildHoleCheckForVariableLoad(variable); |
1879 break; | 1960 break; |
1880 } | 1961 } |
1881 case VariableLocation::GLOBAL: | 1962 case VariableLocation::GLOBAL: |
1882 case VariableLocation::UNALLOCATED: { | 1963 case VariableLocation::UNALLOCATED: { |
1883 builder()->LoadGlobal(feedback_index(slot), typeof_mode); | 1964 builder()->LoadGlobal(feedback_index(slot), typeof_mode); |
1884 break; | 1965 break; |
1885 } | 1966 } |
1886 case VariableLocation::CONTEXT: { | 1967 case VariableLocation::CONTEXT: { |
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2711 VisitVariableLoadForAccumulatorValue( | 2792 VisitVariableLoadForAccumulatorValue( |
2712 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); | 2793 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); |
2713 } else { | 2794 } else { |
2714 VisitForAccumulatorValue(expr->expression()); | 2795 VisitForAccumulatorValue(expr->expression()); |
2715 } | 2796 } |
2716 builder()->TypeOf(); | 2797 builder()->TypeOf(); |
2717 execution_result()->SetResultInAccumulator(); | 2798 execution_result()->SetResultInAccumulator(); |
2718 } | 2799 } |
2719 | 2800 |
2720 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 2801 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
2721 VisitForAccumulatorValue(expr->expression()); | 2802 if (execution_result()->IsEffect()) { |
2722 builder()->LogicalNot(); | 2803 VisitForEffect(expr->expression()); |
2723 execution_result()->SetResultInAccumulator(); | 2804 } else if (execution_result()->IsTest()) { |
| 2805 TestResultScope* test_result = execution_result()->AsTest(); |
| 2806 // No actual logical negation happening, we just swap the control flow by |
| 2807 // swapping the target labels and the fallthrough branch. |
| 2808 VisitForTest(expr->expression(), test_result->else_labels(), |
| 2809 test_result->then_labels(), |
| 2810 test_result->inverted_fallthrough()); |
| 2811 test_result->SetResultConsumedByTest(); |
| 2812 } else { |
| 2813 VisitForAccumulatorValue(expr->expression()); |
| 2814 builder()->LogicalNot(); |
| 2815 execution_result()->SetResultInAccumulator(); |
| 2816 } |
2724 } | 2817 } |
2725 | 2818 |
2726 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 2819 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
2727 switch (expr->op()) { | 2820 switch (expr->op()) { |
2728 case Token::Value::NOT: | 2821 case Token::Value::NOT: |
2729 VisitNot(expr); | 2822 VisitNot(expr); |
2730 break; | 2823 break; |
2731 case Token::Value::TYPEOF: | 2824 case Token::Value::TYPEOF: |
2732 VisitTypeOf(expr); | 2825 VisitTypeOf(expr); |
2733 break; | 2826 break; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2989 | 3082 |
2990 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | 3083 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { |
2991 VisitForEffect(binop->left()); | 3084 VisitForEffect(binop->left()); |
2992 Visit(binop->right()); | 3085 Visit(binop->right()); |
2993 } | 3086 } |
2994 | 3087 |
2995 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | 3088 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { |
2996 Expression* left = binop->left(); | 3089 Expression* left = binop->left(); |
2997 Expression* right = binop->right(); | 3090 Expression* right = binop->right(); |
2998 | 3091 |
2999 // Short-circuit evaluation- If it is known that left is always true, | 3092 if (execution_result()->IsTest()) { |
3000 // no need to visit right | 3093 TestResultScope* test_result = execution_result()->AsTest(); |
3001 if (left->ToBooleanIsTrue()) { | 3094 |
3002 VisitForAccumulatorValue(left); | 3095 if (left->ToBooleanIsTrue() || right->ToBooleanIsTrue()) { |
| 3096 builder()->Jump(test_result->NewThenLabel()); |
| 3097 } else if (left->ToBooleanIsFalse() && right->ToBooleanIsFalse()) { |
| 3098 builder()->Jump(test_result->NewElseLabel()); |
| 3099 } else { |
| 3100 BytecodeLabels test_right(zone()); |
| 3101 VisitForTest(left, test_result->then_labels(), &test_right, |
| 3102 TestFallthrough::kElse); |
| 3103 test_right.Bind(builder()); |
| 3104 VisitForTest(right, test_result->then_labels(), |
| 3105 test_result->else_labels(), test_result->fallthrough()); |
| 3106 } |
| 3107 test_result->SetResultConsumedByTest(); |
3003 } else { | 3108 } else { |
3004 BytecodeLabel end_label; | 3109 if (left->ToBooleanIsTrue()) { |
3005 VisitForAccumulatorValue(left); | 3110 VisitForAccumulatorValue(left); |
3006 builder()->JumpIfTrue(&end_label); | 3111 } else if (left->ToBooleanIsFalse()) { |
3007 VisitForAccumulatorValue(right); | 3112 VisitForAccumulatorValue(right); |
3008 builder()->Bind(&end_label); | 3113 } else { |
| 3114 BytecodeLabel end_label; |
| 3115 VisitForAccumulatorValue(left); |
| 3116 builder()->JumpIfTrue(&end_label); |
| 3117 VisitForAccumulatorValue(right); |
| 3118 builder()->Bind(&end_label); |
| 3119 } |
| 3120 execution_result()->SetResultInAccumulator(); |
3009 } | 3121 } |
3010 execution_result()->SetResultInAccumulator(); | |
3011 } | 3122 } |
3012 | 3123 |
3013 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { | 3124 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { |
3014 Expression* left = binop->left(); | 3125 Expression* left = binop->left(); |
3015 Expression* right = binop->right(); | 3126 Expression* right = binop->right(); |
3016 | 3127 |
3017 // Short-circuit evaluation- If it is known that left is always false, | 3128 if (execution_result()->IsTest()) { |
3018 // no need to visit right | 3129 TestResultScope* test_result = execution_result()->AsTest(); |
3019 if (left->ToBooleanIsFalse()) { | 3130 |
3020 VisitForAccumulatorValue(left); | 3131 if (left->ToBooleanIsFalse() || right->ToBooleanIsFalse()) { |
| 3132 builder()->Jump(test_result->NewElseLabel()); |
| 3133 } else if (left->ToBooleanIsTrue() && right->ToBooleanIsTrue()) { |
| 3134 builder()->Jump(test_result->NewThenLabel()); |
| 3135 } else { |
| 3136 BytecodeLabels test_right(zone()); |
| 3137 VisitForTest(left, &test_right, test_result->else_labels(), |
| 3138 TestFallthrough::kThen); |
| 3139 test_right.Bind(builder()); |
| 3140 VisitForTest(right, test_result->then_labels(), |
| 3141 test_result->else_labels(), test_result->fallthrough()); |
| 3142 } |
| 3143 test_result->SetResultConsumedByTest(); |
3021 } else { | 3144 } else { |
3022 BytecodeLabel end_label; | 3145 if (left->ToBooleanIsFalse()) { |
3023 VisitForAccumulatorValue(left); | 3146 VisitForAccumulatorValue(left); |
3024 builder()->JumpIfFalse(&end_label); | 3147 } else if (left->ToBooleanIsTrue()) { |
3025 VisitForAccumulatorValue(right); | 3148 VisitForAccumulatorValue(right); |
3026 builder()->Bind(&end_label); | 3149 } else { |
| 3150 BytecodeLabel end_label; |
| 3151 VisitForAccumulatorValue(left); |
| 3152 builder()->JumpIfFalse(&end_label); |
| 3153 VisitForAccumulatorValue(right); |
| 3154 builder()->Bind(&end_label); |
| 3155 } |
| 3156 execution_result()->SetResultInAccumulator(); |
3027 } | 3157 } |
3028 execution_result()->SetResultInAccumulator(); | |
3029 } | 3158 } |
3030 | 3159 |
3031 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 3160 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
3032 Visit(expr->expression()); | 3161 Visit(expr->expression()); |
3033 } | 3162 } |
3034 | 3163 |
3035 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 3164 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
3036 AccumulatorResultScope accumulator_execution_result(this); | 3165 AccumulatorResultScope accumulator_execution_result(this); |
3037 Scope* scope = this->scope(); | 3166 Scope* scope = this->scope(); |
3038 | 3167 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3260 | 3389 |
3261 // Visits the expression |expr| and stores the expression result in | 3390 // Visits the expression |expr| and stores the expression result in |
3262 // |destination|. | 3391 // |destination|. |
3263 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, | 3392 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, |
3264 Register destination) { | 3393 Register destination) { |
3265 AccumulatorResultScope register_scope(this); | 3394 AccumulatorResultScope register_scope(this); |
3266 Visit(expr); | 3395 Visit(expr); |
3267 builder()->StoreAccumulatorInRegister(destination); | 3396 builder()->StoreAccumulatorInRegister(destination); |
3268 } | 3397 } |
3269 | 3398 |
| 3399 // Visits the expression |expr| for testing its boolean value and jumping to the |
| 3400 // |then| or |other| label depending on value and short-circuit semantics |
| 3401 void BytecodeGenerator::VisitForTest(Expression* expr, |
| 3402 BytecodeLabels* then_labels, |
| 3403 BytecodeLabels* else_labels, |
| 3404 TestFallthrough fallthrough) { |
| 3405 bool result_consumed; |
| 3406 { |
| 3407 // To make sure that all temporary registers are returned before generating |
| 3408 // jumps below, we ensure that the result scope is deleted before doing so. |
| 3409 // Dead registers might be materialized otherwise. |
| 3410 TestResultScope test_result(this, then_labels, else_labels, fallthrough); |
| 3411 Visit(expr); |
| 3412 result_consumed = test_result.ResultConsumedByTest(); |
| 3413 } |
| 3414 if (!result_consumed) { |
| 3415 switch (fallthrough) { |
| 3416 case TestFallthrough::kThen: |
| 3417 builder()->JumpIfFalse(else_labels->New()); |
| 3418 break; |
| 3419 case TestFallthrough::kElse: |
| 3420 builder()->JumpIfTrue(then_labels->New()); |
| 3421 break; |
| 3422 case TestFallthrough::kNone: |
| 3423 builder()->JumpIfTrue(then_labels->New()); |
| 3424 builder()->Jump(else_labels->New()); |
| 3425 } |
| 3426 } |
| 3427 } |
| 3428 |
3270 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { | 3429 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { |
3271 ContextScope context_scope(this, scope); | 3430 ContextScope context_scope(this, scope); |
3272 DCHECK(scope->declarations()->is_empty()); | 3431 DCHECK(scope->declarations()->is_empty()); |
3273 Visit(stmt); | 3432 Visit(stmt); |
3274 } | 3433 } |
3275 | 3434 |
3276 LanguageMode BytecodeGenerator::language_mode() const { | 3435 LanguageMode BytecodeGenerator::language_mode() const { |
3277 return execution_context()->scope()->language_mode(); | 3436 return execution_context()->scope()->language_mode(); |
3278 } | 3437 } |
3279 | 3438 |
3280 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3439 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3281 return TypeFeedbackVector::GetIndex(slot); | 3440 return TypeFeedbackVector::GetIndex(slot); |
3282 } | 3441 } |
3283 | 3442 |
3284 } // namespace interpreter | 3443 } // namespace interpreter |
3285 } // namespace internal | 3444 } // namespace internal |
3286 } // namespace v8 | 3445 } // namespace v8 |
OLD | NEW |