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

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: remove unused/refactored code, add comment 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
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"
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 generator_->set_execution_result(this); 438 generator_->set_execution_result(this);
439 } 439 }
440 440
441 virtual ~ExpressionResultScope() { 441 virtual ~ExpressionResultScope() {
442 generator_->set_execution_result(outer_); 442 generator_->set_execution_result(outer_);
443 DCHECK(result_identified() || generator_->HasStackOverflow()); 443 DCHECK(result_identified() || generator_->HasStackOverflow());
444 } 444 }
445 445
446 bool IsEffect() const { return kind_ == Expression::kEffect; } 446 bool IsEffect() const { return kind_ == Expression::kEffect; }
447 bool IsValue() const { return kind_ == Expression::kValue; } 447 bool IsValue() const { return kind_ == Expression::kValue; }
448 bool IsTest() const { return kind_ == Expression::kTest; }
448 449
449 virtual void SetResultInAccumulator() = 0; 450 virtual void SetResultInAccumulator() = 0;
450 virtual void SetResultInRegister(Register reg) = 0; 451 virtual void SetResultInRegister(Register reg) = 0;
451 452
452 protected: 453 protected:
453 ExpressionResultScope* outer() const { return outer_; } 454 ExpressionResultScope* outer() const { return outer_; }
454 BytecodeArrayBuilder* builder() const { return generator_->builder(); } 455 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
455 BytecodeGenerator* generator() const { return generator_; } 456 BytecodeGenerator* generator() const { return generator_; }
456 const RegisterAllocationScope* allocator() const { return &allocator_; } 457 const RegisterAllocationScope* allocator() const { return &allocator_; }
457 458
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 if (generator()->HasStackOverflow() && !result_identified()) { 529 if (generator()->HasStackOverflow() && !result_identified()) {
529 SetResultInAccumulator(); 530 SetResultInAccumulator();
530 } 531 }
531 return result_register_; 532 return result_register_;
532 } 533 }
533 534
534 private: 535 private:
535 Register result_register_; 536 Register result_register_;
536 }; 537 };
537 538
539 enum class BytecodeGenerator::ControlFallthrough { THEN, ELSE, NONE };
rmcilroy 2016/08/12 11:15:25 Just define this in the header. Also, enum class u
klaasb 2016/08/12 16:00:12 Done.
540
541 // Scoped class used for generating multiple jumps to the same location
542 class BytecodeGenerator::BytecodeLabels {
rmcilroy 2016/08/12 11:15:26 How about moving this to bytecode-label.h/cc?
klaasb 2016/08/12 16:00:12 Done.
543 public:
544 BytecodeLabels() = default;
545
546 BytecodeLabel* New() {
547 labels_.emplace_back();
548 return &labels_.back();
549 }
550
551 void Bind(BytecodeArrayBuilder* builder) {
552 for (auto label : labels_) {
553 builder->Bind(&label);
554 }
555 }
556
557 private:
558 std::vector<BytecodeLabel> labels_;
rmcilroy 2016/08/12 11:15:25 use ZoneVector (which means you will need to pass
klaasb 2016/08/12 16:00:13 Done.
559
560 DISALLOW_COPY_AND_ASSIGN(BytecodeLabels);
561 };
562
563 // Scoped class used when the result of the current expression to be
564 // evaluated is only tested with jumps to two branches.
565 class BytecodeGenerator::ControlResultScope final
566 : public ExpressionResultScope {
567 public:
568 ControlResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels,
569 BytecodeLabels* else_labels,
570 ControlFallthrough fallthrough)
571 : ExpressionResultScope(generator, Expression::kTest),
572 then_labels_(then_labels),
573 else_labels_(else_labels),
574 fallthrough_(fallthrough),
575 has_result_(true) {}
576
577 virtual void SetResultInAccumulator() {
578 DCHECK(has_result_);
rmcilroy 2016/08/12 11:15:26 No need for these DCHECKS - the set_result_identif
klaasb 2016/08/12 16:00:12 Done.
579 set_result_identified();
580 }
581
582 virtual void SetResultInRegister(Register reg) {
583 DCHECK(has_result_);
584 builder()->LoadAccumulatorWithRegister(reg);
585 set_result_identified();
586 }
587
588 // Used when code special cases for ControlResultScope and consumes any
589 // possible value by testing and jumping to a then/else label.
590 void SetNoResult() {
rmcilroy 2016/08/12 11:15:25 How about SetResultConsumedByTest
klaasb 2016/08/12 16:00:12 Done.
591 DCHECK(has_result_);
592 has_result_ = false;
593 set_result_identified();
594 }
595
596 bool HasResultValue() { return has_result_; }
rmcilroy 2016/08/12 11:15:26 ResultConsumedByTest() (and invert the boolean)
klaasb 2016/08/12 16:00:13 Done.
597
598 BytecodeLabel* NewThenLabel() { return then_labels_->New(); }
599 BytecodeLabel* NewElseLabel() { return else_labels_->New(); }
600
601 BytecodeLabels* ThenLabels() { return then_labels_; }
602 BytecodeLabels* ElseLabels() { return else_labels_; }
603
604 ControlFallthrough Fallthrough() { return fallthrough_; }
605 ControlFallthrough InvertedFallthrough() {
rmcilroy 2016/08/12 11:15:26 These are all getters, so lowercase - then_labels,
klaasb 2016/08/12 16:00:12 Done.
606 switch (fallthrough_) {
607 case ControlFallthrough::THEN:
608 return ControlFallthrough::ELSE;
609 case ControlFallthrough::ELSE:
610 return ControlFallthrough::THEN;
611 default:
612 return ControlFallthrough::NONE;
613 }
614 }
615
616 private:
617 BytecodeLabels* then_labels_;
618 BytecodeLabels* else_labels_;
619 ControlFallthrough fallthrough_;
620 bool has_result_;
621
622 DISALLOW_COPY_AND_ASSIGN(ControlResultScope);
623 };
624
538 // Used to build a list of global declaration initial value pairs. 625 // Used to build a list of global declaration initial value pairs.
539 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { 626 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
540 public: 627 public:
541 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone) 628 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone)
542 : isolate_(isolate), 629 : isolate_(isolate),
543 declarations_(0, zone), 630 declarations_(0, zone),
544 constant_pool_entry_(0), 631 constant_pool_entry_(0),
545 has_constant_pool_entry_(false) {} 632 has_constant_pool_entry_(false) {}
546 633
547 void AddFunctionDeclaration(FeedbackVectorSlot slot, FunctionLiteral* func) { 634 void AddFunctionDeclaration(FeedbackVectorSlot slot, FunctionLiteral* func) {
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 1059 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
973 builder()->SetStatementPosition(stmt); 1060 builder()->SetStatementPosition(stmt);
974 VisitForEffect(stmt->expression()); 1061 VisitForEffect(stmt->expression());
975 } 1062 }
976 1063
977 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 1064 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
978 } 1065 }
979 1066
980 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 1067 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
981 builder()->SetStatementPosition(stmt); 1068 builder()->SetStatementPosition(stmt);
982 BytecodeLabel else_label, end_label; 1069 BytecodeLabel end_label;
rmcilroy 2016/08/12 11:15:26 nit - move end_label into inner else branch too.
klaasb 2016/08/12 16:00:12 Done.
983 if (stmt->condition()->ToBooleanIsTrue()) { 1070 if (stmt->condition()->ToBooleanIsTrue()) {
984 // Generate then block unconditionally as always true. 1071 // Generate then block unconditionally as always true.
985 Visit(stmt->then_statement()); 1072 Visit(stmt->then_statement());
986 } else if (stmt->condition()->ToBooleanIsFalse()) { 1073 } else if (stmt->condition()->ToBooleanIsFalse()) {
987 // Generate else block unconditionally if it exists. 1074 // Generate else block unconditionally if it exists.
988 if (stmt->HasElseStatement()) { 1075 if (stmt->HasElseStatement()) {
989 Visit(stmt->else_statement()); 1076 Visit(stmt->else_statement());
990 } 1077 }
991 } else { 1078 } else {
992 // TODO(oth): If then statement is BreakStatement or 1079 // TODO(oth): If then statement is BreakStatement or
993 // ContinueStatement we can reduce number of generated 1080 // ContinueStatement we can reduce number of generated
994 // jump/jump_ifs here. See BasicLoops test. 1081 // jump/jump_ifs here. See BasicLoops test.
995 VisitForAccumulatorValue(stmt->condition()); 1082 BytecodeLabels then_labels;
rmcilroy 2016/08/12 11:15:26 nit - BytecodeLabels then_labels, else_labels;
klaasb 2016/08/12 16:00:12 Done.
996 builder()->JumpIfFalse(&else_label); 1083 BytecodeLabels else_labels;
1084 VisitForControl(stmt->condition(), &then_labels, &else_labels,
1085 ControlFallthrough::THEN);
1086
1087 then_labels.Bind(builder());
997 Visit(stmt->then_statement()); 1088 Visit(stmt->then_statement());
1089
998 if (stmt->HasElseStatement()) { 1090 if (stmt->HasElseStatement()) {
999 builder()->Jump(&end_label); 1091 builder()->Jump(&end_label);
1000 builder()->Bind(&else_label); 1092 }
1093 else_labels.Bind(builder());
1094 if (stmt->HasElseStatement()) {
rmcilroy 2016/08/12 11:15:26 could you keep the if/else form: if (stmt->HasEls
klaasb 2016/08/12 16:00:12 Done.
1001 Visit(stmt->else_statement()); 1095 Visit(stmt->else_statement());
1002 } else {
1003 builder()->Bind(&else_label);
1004 } 1096 }
1005 builder()->Bind(&end_label); 1097 builder()->Bind(&end_label);
1006 } 1098 }
1007 } 1099 }
1008 1100
1009 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( 1101 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
1010 SloppyBlockFunctionStatement* stmt) { 1102 SloppyBlockFunctionStatement* stmt) {
1011 Visit(stmt->statement()); 1103 Visit(stmt->statement());
1012 } 1104 }
1013 1105
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 if (stmt->cond()->ToBooleanIsFalse()) { 1194 if (stmt->cond()->ToBooleanIsFalse()) {
1103 VisitIterationBody(stmt, &loop_builder); 1195 VisitIterationBody(stmt, &loop_builder);
1104 } else if (stmt->cond()->ToBooleanIsTrue()) { 1196 } else if (stmt->cond()->ToBooleanIsTrue()) {
1105 VisitIterationHeader(stmt, &loop_builder); 1197 VisitIterationHeader(stmt, &loop_builder);
1106 VisitIterationBody(stmt, &loop_builder); 1198 VisitIterationBody(stmt, &loop_builder);
1107 loop_builder.JumpToHeader(); 1199 loop_builder.JumpToHeader();
1108 } else { 1200 } else {
1109 VisitIterationHeader(stmt, &loop_builder); 1201 VisitIterationHeader(stmt, &loop_builder);
1110 VisitIterationBody(stmt, &loop_builder); 1202 VisitIterationBody(stmt, &loop_builder);
1111 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1203 builder()->SetExpressionAsStatementPosition(stmt->cond());
1204 // TODO(klaasb) VisitForControl for loop conditions
1112 VisitForAccumulatorValue(stmt->cond()); 1205 VisitForAccumulatorValue(stmt->cond());
1113 loop_builder.JumpToHeaderIfTrue(); 1206 loop_builder.JumpToHeaderIfTrue();
1114 } 1207 }
1115 loop_builder.EndLoop(); 1208 loop_builder.EndLoop();
1116 } 1209 }
1117 1210
1118 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 1211 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1119 if (stmt->cond()->ToBooleanIsFalse()) { 1212 if (stmt->cond()->ToBooleanIsFalse()) {
1120 // If the condition is false there is no need to generate the loop. 1213 // If the condition is false there is no need to generate the loop.
1121 return; 1214 return;
1122 } 1215 }
1123 1216
1124 LoopBuilder loop_builder(builder()); 1217 LoopBuilder loop_builder(builder());
1125 VisitIterationHeader(stmt, &loop_builder); 1218 VisitIterationHeader(stmt, &loop_builder);
1126 if (!stmt->cond()->ToBooleanIsTrue()) { 1219 if (!stmt->cond()->ToBooleanIsTrue()) {
1127 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1220 builder()->SetExpressionAsStatementPosition(stmt->cond());
1221 // TODO(klaasb) VisitForControl for loop conditions
1128 VisitForAccumulatorValue(stmt->cond()); 1222 VisitForAccumulatorValue(stmt->cond());
1129 loop_builder.BreakIfFalse(); 1223 loop_builder.BreakIfFalse();
1130 } 1224 }
1131 VisitIterationBody(stmt, &loop_builder); 1225 VisitIterationBody(stmt, &loop_builder);
1132 loop_builder.JumpToHeader(); 1226 loop_builder.JumpToHeader();
1133 loop_builder.EndLoop(); 1227 loop_builder.EndLoop();
1134 } 1228 }
1135 1229
1136 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 1230 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1137 if (stmt->init() != nullptr) { 1231 if (stmt->init() != nullptr) {
1138 Visit(stmt->init()); 1232 Visit(stmt->init());
1139 } 1233 }
1140 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { 1234 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1141 // If the condition is known to be false there is no need to generate 1235 // If the condition is known to be false there is no need to generate
1142 // body, next or condition blocks. Init block should be generated. 1236 // body, next or condition blocks. Init block should be generated.
1143 return; 1237 return;
1144 } 1238 }
1145 1239
1146 LoopBuilder loop_builder(builder()); 1240 LoopBuilder loop_builder(builder());
1147 VisitIterationHeader(stmt, &loop_builder); 1241 VisitIterationHeader(stmt, &loop_builder);
1148 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 1242 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
1149 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1243 builder()->SetExpressionAsStatementPosition(stmt->cond());
1244 // TODO(klaasb) VisitForControl for loop conditions
1150 VisitForAccumulatorValue(stmt->cond()); 1245 VisitForAccumulatorValue(stmt->cond());
1151 loop_builder.BreakIfFalse(); 1246 loop_builder.BreakIfFalse();
1152 } 1247 }
1153 VisitIterationBody(stmt, &loop_builder); 1248 VisitIterationBody(stmt, &loop_builder);
1154 if (stmt->next() != nullptr) { 1249 if (stmt->next() != nullptr) {
1155 builder()->SetStatementPosition(stmt->next()); 1250 builder()->SetStatementPosition(stmt->next());
1156 Visit(stmt->next()); 1251 Visit(stmt->next());
1157 } 1252 }
1158 loop_builder.JumpToHeader(); 1253 loop_builder.JumpToHeader();
1159 loop_builder.EndLoop(); 1254 loop_builder.EndLoop();
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
1558 native_function_literals_.push_back(std::make_pair(expr, entry)); 1653 native_function_literals_.push_back(std::make_pair(expr, entry));
1559 execution_result()->SetResultInAccumulator(); 1654 execution_result()->SetResultInAccumulator();
1560 } 1655 }
1561 1656
1562 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { 1657 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
1563 VisitBlock(expr->block()); 1658 VisitBlock(expr->block());
1564 VisitVariableProxy(expr->result()); 1659 VisitVariableProxy(expr->result());
1565 } 1660 }
1566 1661
1567 void BytecodeGenerator::VisitConditional(Conditional* expr) { 1662 void BytecodeGenerator::VisitConditional(Conditional* expr) {
1568 // TODO(rmcilroy): Spot easy cases where there code would not need to 1663 if (expr->condition()->ToBooleanIsTrue()) {
1569 // emit the then block or the else block, e.g. condition is 1664 // Generate then block unconditionally as always true.
1570 // obviously true/1/false/0. 1665 VisitForAccumulatorValue(expr->then_expression());
1666 } else if (expr->condition()->ToBooleanIsFalse()) {
1667 // Generate else block unconditionally if it exists.
1668 VisitForAccumulatorValue(expr->else_expression());
1669 } else {
1670 BytecodeLabel end_label;
1671 BytecodeLabels then_labels;
1672 BytecodeLabels else_labels;
rmcilroy 2016/08/12 11:15:26 nit - BytecodeLabels then_labels, else_labels;
klaasb 2016/08/12 16:00:12 Done.
1571 1673
1572 BytecodeLabel else_label, end_label; 1674 VisitForControl(expr->condition(), &then_labels, &else_labels,
1675 ControlFallthrough::THEN);
1573 1676
1574 VisitForAccumulatorValue(expr->condition()); 1677 then_labels.Bind(builder());
1575 builder()->JumpIfFalse(&else_label); 1678 VisitForAccumulatorValue(expr->then_expression());
1679 builder()->Jump(&end_label);
1576 1680
1577 VisitForAccumulatorValue(expr->then_expression()); 1681 else_labels.Bind(builder());
1578 builder()->Jump(&end_label); 1682 VisitForAccumulatorValue(expr->else_expression());
1579 1683 builder()->Bind(&end_label);
1580 builder()->Bind(&else_label); 1684 }
1581 VisitForAccumulatorValue(expr->else_expression());
1582 builder()->Bind(&end_label);
1583 1685
1584 execution_result()->SetResultInAccumulator(); 1686 execution_result()->SetResultInAccumulator();
1585 } 1687 }
1586 1688
1587 void BytecodeGenerator::VisitLiteral(Literal* expr) { 1689 void BytecodeGenerator::VisitLiteral(Literal* expr) {
1588 if (!execution_result()->IsEffect()) { 1690 if (!execution_result()->IsEffect()) {
1589 const AstValue* raw_value = expr->raw_value(); 1691 const AstValue* raw_value = expr->raw_value();
1590 if (raw_value->IsSmi()) { 1692 if (raw_value->IsSmi()) {
1591 builder()->LoadLiteral(raw_value->AsSmi()); 1693 builder()->LoadLiteral(raw_value->AsSmi());
1592 } else if (raw_value->IsUndefined()) { 1694 } else if (raw_value->IsUndefined()) {
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1861 } 1963 }
1862 1964
1863 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1965 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1864 FeedbackVectorSlot slot, 1966 FeedbackVectorSlot slot,
1865 TypeofMode typeof_mode) { 1967 TypeofMode typeof_mode) {
1866 switch (variable->location()) { 1968 switch (variable->location()) {
1867 case VariableLocation::LOCAL: { 1969 case VariableLocation::LOCAL: {
1868 Register source(Register(variable->index())); 1970 Register source(Register(variable->index()));
1869 builder()->LoadAccumulatorWithRegister(source); 1971 builder()->LoadAccumulatorWithRegister(source);
1870 BuildHoleCheckForVariableLoad(variable); 1972 BuildHoleCheckForVariableLoad(variable);
1973 // this will generate a new register when within a RegisterResultScope
rmcilroy 2016/08/12 11:15:26 Thanks for updating this. How about: We need to l
klaasb 2016/08/12 16:00:12 Done.
1974 // which is needed when expressions assign to variables as side-effect
1871 execution_result()->SetResultInAccumulator(); 1975 execution_result()->SetResultInAccumulator();
1872 break; 1976 break;
1873 } 1977 }
1874 case VariableLocation::PARAMETER: { 1978 case VariableLocation::PARAMETER: {
1875 // The parameter indices are shifted by 1 (receiver is variable 1979 // The parameter indices are shifted by 1 (receiver is variable
1876 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1980 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1877 Register source = builder()->Parameter(variable->index() + 1); 1981 Register source = builder()->Parameter(variable->index() + 1);
1878 builder()->LoadAccumulatorWithRegister(source); 1982 builder()->LoadAccumulatorWithRegister(source);
1879 BuildHoleCheckForVariableLoad(variable); 1983 BuildHoleCheckForVariableLoad(variable);
1984 // this will generate a new register when within a RegisterResultScope
rmcilroy 2016/08/12 11:15:25 ditto
klaasb 2016/08/12 16:00:12 Done.
1985 // which is needed when expressions assign to variables as side-effect
1880 execution_result()->SetResultInAccumulator(); 1986 execution_result()->SetResultInAccumulator();
1881 break; 1987 break;
1882 } 1988 }
1883 case VariableLocation::GLOBAL: 1989 case VariableLocation::GLOBAL:
1884 case VariableLocation::UNALLOCATED: { 1990 case VariableLocation::UNALLOCATED: {
1885 builder()->LoadGlobal(feedback_index(slot), typeof_mode); 1991 builder()->LoadGlobal(feedback_index(slot), typeof_mode);
1886 execution_result()->SetResultInAccumulator(); 1992 execution_result()->SetResultInAccumulator();
1887 break; 1993 break;
1888 } 1994 }
1889 case VariableLocation::CONTEXT: { 1995 case VariableLocation::CONTEXT: {
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
2729 VisitVariableLoadForAccumulatorValue( 2835 VisitVariableLoadForAccumulatorValue(
2730 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); 2836 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF);
2731 } else { 2837 } else {
2732 VisitForAccumulatorValue(expr->expression()); 2838 VisitForAccumulatorValue(expr->expression());
2733 } 2839 }
2734 builder()->TypeOf(); 2840 builder()->TypeOf();
2735 execution_result()->SetResultInAccumulator(); 2841 execution_result()->SetResultInAccumulator();
2736 } 2842 }
2737 2843
2738 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { 2844 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
2739 VisitForAccumulatorValue(expr->expression()); 2845 if (execution_result()->IsTest()) {
rmcilroy 2016/08/12 11:15:26 Could you also add the IsEffect shortcut here (jus
klaasb 2016/08/12 16:00:12 Done.
2740 builder()->LogicalNot(); 2846 ControlResultScope* control_result =
2741 execution_result()->SetResultInAccumulator(); 2847 static_cast<ControlResultScope*>(execution_result());
rmcilroy 2016/08/12 11:15:26 Could you add an AsTest() function with DCHECKS to
klaasb 2016/08/12 16:00:12 Done.
2848 VisitForControl(expr->expression(), control_result->ElseLabels(),
rmcilroy 2016/08/12 11:15:26 nit - comment that you are swapping the control fl
klaasb 2016/08/12 16:00:12 Done.
2849 control_result->ThenLabels(),
2850 control_result->InvertedFallthrough());
2851 control_result->SetNoResult();
2852 } else {
2853 VisitForAccumulatorValue(expr->expression());
2854 builder()->LogicalNot();
2855 execution_result()->SetResultInAccumulator();
2856 }
2742 } 2857 }
2743 2858
2744 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2859 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2745 switch (expr->op()) { 2860 switch (expr->op()) {
2746 case Token::Value::NOT: 2861 case Token::Value::NOT:
2747 VisitNot(expr); 2862 VisitNot(expr);
2748 break; 2863 break;
2749 case Token::Value::TYPEOF: 2864 case Token::Value::TYPEOF:
2750 VisitTypeOf(expr); 2865 VisitTypeOf(expr);
2751 break; 2866 break;
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
3010 3125
3011 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { 3126 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
3012 VisitForEffect(binop->left()); 3127 VisitForEffect(binop->left());
3013 Visit(binop->right()); 3128 Visit(binop->right());
3014 } 3129 }
3015 3130
3016 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { 3131 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
3017 Expression* left = binop->left(); 3132 Expression* left = binop->left();
3018 Expression* right = binop->right(); 3133 Expression* right = binop->right();
3019 3134
3020 // Short-circuit evaluation- If it is known that left is always true, 3135 if (execution_result()->IsTest()) {
3021 // no need to visit right 3136 ControlResultScope* control_result =
3022 if (left->ToBooleanIsTrue()) { 3137 static_cast<ControlResultScope*>(execution_result());
3023 VisitForAccumulatorValue(left); 3138
3139 if (left->ToBooleanIsTrue()) {
rmcilroy 2016/08/12 11:15:26 I think you could do: if (left->ToBooleanIsTrue()
klaasb 2016/08/12 16:00:12 Done.
3140 builder()->Jump(control_result->NewThenLabel());
3141 } else {
3142 BytecodeLabels test_right;
3143 VisitForControl(left, control_result->ThenLabels(), &test_right,
3144 ControlFallthrough::ELSE);
3145 test_right.Bind(builder());
3146 VisitForControl(right, control_result->ThenLabels(),
3147 control_result->ElseLabels(),
3148 control_result->Fallthrough());
3149 }
3150 control_result->SetNoResult();
3024 } else { 3151 } else {
3025 BytecodeLabel end_label; 3152 // Short-circuit evaluation- If it is known that left is always true,
3026 VisitForAccumulatorValue(left); 3153 // no need to visit right
rmcilroy 2016/08/12 11:15:26 Just remove this comment (ditto below)
klaasb 2016/08/12 16:00:13 Done.
3027 builder()->JumpIfTrue(&end_label); 3154 if (left->ToBooleanIsTrue()) {
3028 VisitForAccumulatorValue(right); 3155 VisitForAccumulatorValue(left);
3029 builder()->Bind(&end_label); 3156 } else {
rmcilroy 2016/08/12 11:15:25 I know this isn't your code, but we should also be
klaasb 2016/08/12 16:00:12 Done.
3157 BytecodeLabel end_label;
3158 VisitForAccumulatorValue(left);
3159 builder()->JumpIfTrue(&end_label);
3160 VisitForAccumulatorValue(right);
3161 builder()->Bind(&end_label);
3162 }
3163 execution_result()->SetResultInAccumulator();
3030 } 3164 }
3031 execution_result()->SetResultInAccumulator();
3032 } 3165 }
3033 3166
3034 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { 3167 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
3035 Expression* left = binop->left(); 3168 Expression* left = binop->left();
3036 Expression* right = binop->right(); 3169 Expression* right = binop->right();
3037 3170
3038 // Short-circuit evaluation- If it is known that left is always false, 3171 if (execution_result()->IsTest()) {
3039 // no need to visit right 3172 ControlResultScope* control_result =
3040 if (left->ToBooleanIsFalse()) { 3173 static_cast<ControlResultScope*>(execution_result());
3041 VisitForAccumulatorValue(left); 3174
3175 if (left->ToBooleanIsFalse()) {
rmcilroy 2016/08/12 11:15:26 Same suggestion (for AND) as above for OR.
klaasb 2016/08/12 16:00:12 Done.
3176 builder()->Jump(control_result->NewElseLabel());
3177 } else {
3178 BytecodeLabels test_right;
3179 VisitForControl(left, &test_right, control_result->ElseLabels(),
3180 ControlFallthrough::THEN);
3181 test_right.Bind(builder());
3182 VisitForControl(right, control_result->ThenLabels(),
3183 control_result->ElseLabels(),
3184 control_result->Fallthrough());
3185 }
3186 control_result->SetNoResult();
3042 } else { 3187 } else {
3043 BytecodeLabel end_label; 3188 // Short-circuit evaluation- If it is known that left is always false,
3044 VisitForAccumulatorValue(left); 3189 // no need to visit right
rmcilroy 2016/08/12 11:15:26 ditto
klaasb 2016/08/12 16:00:12 Done.
3045 builder()->JumpIfFalse(&end_label); 3190 if (left->ToBooleanIsFalse()) {
rmcilroy 2016/08/12 11:15:25 Same suggestion as above.
klaasb 2016/08/12 16:00:12 Done.
3046 VisitForAccumulatorValue(right); 3191 VisitForAccumulatorValue(left);
3047 builder()->Bind(&end_label); 3192 } else {
3193 BytecodeLabel end_label;
3194 VisitForAccumulatorValue(left);
3195 builder()->JumpIfFalse(&end_label);
3196 VisitForAccumulatorValue(right);
3197 builder()->Bind(&end_label);
3198 }
3199 execution_result()->SetResultInAccumulator();
3048 } 3200 }
3049 execution_result()->SetResultInAccumulator();
3050 } 3201 }
3051 3202
3052 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { 3203 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
3053 Visit(expr->expression()); 3204 Visit(expr->expression());
3054 } 3205 }
3055 3206
3056 void BytecodeGenerator::VisitNewLocalFunctionContext() { 3207 void BytecodeGenerator::VisitNewLocalFunctionContext() {
3057 AccumulatorResultScope accumulator_execution_result(this); 3208 AccumulatorResultScope accumulator_execution_result(this);
3058 Scope* scope = this->scope(); 3209 Scope* scope = this->scope();
3059 3210
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
3281 3432
3282 // Visits the expression |expr| and stores the expression result in 3433 // Visits the expression |expr| and stores the expression result in
3283 // |destination|. 3434 // |destination|.
3284 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, 3435 void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3285 Register destination) { 3436 Register destination) {
3286 AccumulatorResultScope register_scope(this); 3437 AccumulatorResultScope register_scope(this);
3287 Visit(expr); 3438 Visit(expr);
3288 builder()->StoreAccumulatorInRegister(destination); 3439 builder()->StoreAccumulatorInRegister(destination);
3289 } 3440 }
3290 3441
3442 // Visits the expression |expr| for testing its boolean value and jumping to the
3443 // |then| or |other| label depending on value and short-circuit semantics
3444 void BytecodeGenerator::VisitForControl(Expression* expr,
3445 BytecodeLabels* then_labels,
3446 BytecodeLabels* else_labels,
3447 ControlFallthrough fallthrough) {
3448 bool has_result;
3449 {
3450 // to make sure that all temporary registers are returned before generating
rmcilroy 2016/08/12 11:15:26 /s/to/To
klaasb 2016/08/12 16:00:12 Done.
3451 // jumps below, we assure that the result scope is deleted before
3452 // otherwise dead registers might be materialized
rmcilroy 2016/08/12 11:15:26 fullstop
klaasb 2016/08/12 16:00:11 Done.
3453 ControlResultScope control_result(this, then_labels, else_labels,
3454 fallthrough);
3455 Visit(expr);
3456 has_result = control_result.HasResultValue();
3457 }
3458 if (has_result) {
3459 switch (fallthrough) {
3460 case ControlFallthrough::THEN:
3461 builder()->JumpIfFalse(else_labels->New());
3462 break;
3463 case ControlFallthrough::ELSE:
3464 builder()->JumpIfTrue(then_labels->New());
3465 break;
3466 default:
rmcilroy 2016/08/12 11:15:26 Make this explicitly case ControlFallthrough::kNon
klaasb 2016/08/12 16:00:12 Done.
3467 builder()->JumpIfTrue(then_labels->New());
3468 builder()->Jump(else_labels->New());
3469 }
3470 }
3471 }
3472
3291 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { 3473 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
3292 ContextScope context_scope(this, scope); 3474 ContextScope context_scope(this, scope);
3293 DCHECK(scope->declarations()->is_empty()); 3475 DCHECK(scope->declarations()->is_empty());
3294 Visit(stmt); 3476 Visit(stmt);
3295 } 3477 }
3296 3478
3297 LanguageMode BytecodeGenerator::language_mode() const { 3479 LanguageMode BytecodeGenerator::language_mode() const {
3298 return execution_context()->scope()->language_mode(); 3480 return execution_context()->scope()->language_mode();
3299 } 3481 }
3300 3482
3301 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 3483 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
3302 return TypeFeedbackVector::GetIndex(slot); 3484 return TypeFeedbackVector::GetIndex(slot);
3303 } 3485 }
3304 3486
3305 } // namespace interpreter 3487 } // namespace interpreter
3306 } // namespace internal 3488 } // namespace internal
3307 } // namespace v8 3489 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698