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

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

Issue 2242463002: [interpreter] VisitForTest for bytecode generator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: nit Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-label.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-label.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698