| 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 |