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" |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |