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