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

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

Issue 1634153002: [Interpreter] Adds support for const/let variables to interpreter. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased the patch and fixes tests. Created 4 years, 10 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/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/bytecode-register-allocator.h" 9 #include "src/interpreter/bytecode-register-allocator.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 decl->fun(), info()->script(), info()); 714 decl->fun(), info()->script(), info());
715 // Check for stack-overflow exception. 715 // Check for stack-overflow exception.
716 if (function.is_null()) return SetStackOverflow(); 716 if (function.is_null()) return SetStackOverflow();
717 globals()->push_back(variable->name()); 717 globals()->push_back(variable->name());
718 globals()->push_back(function); 718 globals()->push_back(function);
719 break; 719 break;
720 } 720 }
721 case VariableLocation::PARAMETER: 721 case VariableLocation::PARAMETER:
722 case VariableLocation::LOCAL: { 722 case VariableLocation::LOCAL: {
723 VisitForAccumulatorValue(decl->fun()); 723 VisitForAccumulatorValue(decl->fun());
724 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 724 DCHECK(variable->mode() == LET || variable->mode() == VAR ||
725 variable->mode() == CONST);
726 VisitVariableAssignment(variable, Token::INIT,
727 FeedbackVectorSlot::Invalid());
725 break; 728 break;
726 } 729 }
727 case VariableLocation::CONTEXT: { 730 case VariableLocation::CONTEXT: {
728 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); 731 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
729 VisitForAccumulatorValue(decl->fun()); 732 VisitForAccumulatorValue(decl->fun());
730 builder()->StoreContextSlot(execution_context()->reg(), 733 builder()->StoreContextSlot(execution_context()->reg(),
731 variable->index()); 734 variable->index());
732 break; 735 break;
733 } 736 }
734 case VariableLocation::LOOKUP: { 737 case VariableLocation::LOOKUP: {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 FeedbackVectorSlot slot) { 1003 FeedbackVectorSlot slot) {
1001 DCHECK(expr->IsValidReferenceExpression()); 1004 DCHECK(expr->IsValidReferenceExpression());
1002 1005
1003 // Evaluate assignment starting with the value to be stored in the 1006 // Evaluate assignment starting with the value to be stored in the
1004 // accumulator. 1007 // accumulator.
1005 Property* property = expr->AsProperty(); 1008 Property* property = expr->AsProperty();
1006 LhsKind assign_type = Property::GetAssignType(property); 1009 LhsKind assign_type = Property::GetAssignType(property);
1007 switch (assign_type) { 1010 switch (assign_type) {
1008 case VARIABLE: { 1011 case VARIABLE: {
1009 Variable* variable = expr->AsVariableProxy()->var(); 1012 Variable* variable = expr->AsVariableProxy()->var();
1010 VisitVariableAssignment(variable, slot); 1013 VisitVariableAssignment(variable, Token::ASSIGN, slot);
1011 break; 1014 break;
1012 } 1015 }
1013 case NAMED_PROPERTY: { 1016 case NAMED_PROPERTY: {
1014 RegisterAllocationScope register_scope(this); 1017 RegisterAllocationScope register_scope(this);
1015 Register value = register_allocator()->NewRegister(); 1018 Register value = register_allocator()->NewRegister();
1016 builder()->StoreAccumulatorInRegister(value); 1019 builder()->StoreAccumulatorInRegister(value);
1017 Register object = VisitForRegisterValue(property->obj()); 1020 Register object = VisitForRegisterValue(property->obj());
1018 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); 1021 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1019 builder()->LoadAccumulatorWithRegister(value); 1022 builder()->LoadAccumulatorWithRegister(value);
1020 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1023 builder()->StoreNamedProperty(object, name, feedback_index(slot),
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 builder()->LoadAccumulatorWithRegister(literal); 1522 builder()->LoadAccumulatorWithRegister(literal);
1520 } 1523 }
1521 execution_result()->SetResultInAccumulator(); 1524 execution_result()->SetResultInAccumulator();
1522 } 1525 }
1523 1526
1524 1527
1525 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 1528 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
1526 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1529 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1527 } 1530 }
1528 1531
1532 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1533 Handle<String> name) {
1534 if (mode == CONST_LEGACY) {
1535 BytecodeLabel end_label;
1536 builder()->JumpIfNotHole(&end_label);
1537 builder()->LoadUndefined();
1538 builder()->Bind(&end_label);
1539 } else if (mode == LET || mode == CONST) {
1540 BuildThrowIfHole(name);
1541 }
1542 }
1529 1543
1530 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1544 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1531 FeedbackVectorSlot slot, 1545 FeedbackVectorSlot slot,
1532 TypeofMode typeof_mode) { 1546 TypeofMode typeof_mode) {
1547 VariableMode mode = variable->mode();
1533 switch (variable->location()) { 1548 switch (variable->location()) {
1534 case VariableLocation::LOCAL: { 1549 case VariableLocation::LOCAL: {
1535 Register source(Register(variable->index())); 1550 Register source(Register(variable->index()));
1536 builder()->LoadAccumulatorWithRegister(source); 1551 builder()->LoadAccumulatorWithRegister(source);
1552 BuildHoleCheckForVariableLoad(mode, variable->name());
1537 execution_result()->SetResultInAccumulator(); 1553 execution_result()->SetResultInAccumulator();
1538 break; 1554 break;
1539 } 1555 }
1540 case VariableLocation::PARAMETER: { 1556 case VariableLocation::PARAMETER: {
1541 // The parameter indices are shifted by 1 (receiver is variable 1557 // The parameter indices are shifted by 1 (receiver is variable
1542 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1558 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1543 Register source = builder()->Parameter(variable->index() + 1); 1559 Register source = builder()->Parameter(variable->index() + 1);
1544 builder()->LoadAccumulatorWithRegister(source); 1560 builder()->LoadAccumulatorWithRegister(source);
1561 BuildHoleCheckForVariableLoad(mode, variable->name());
1545 execution_result()->SetResultInAccumulator(); 1562 execution_result()->SetResultInAccumulator();
1546 break; 1563 break;
1547 } 1564 }
1548 case VariableLocation::GLOBAL: 1565 case VariableLocation::GLOBAL:
1549 case VariableLocation::UNALLOCATED: { 1566 case VariableLocation::UNALLOCATED: {
1550 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1567 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1551 language_mode(), typeof_mode); 1568 language_mode(), typeof_mode);
1552 execution_result()->SetResultInAccumulator(); 1569 execution_result()->SetResultInAccumulator();
1553 break; 1570 break;
1554 } 1571 }
(...skipping 12 matching lines...) Expand all
1567 // when this changes. 1584 // when this changes.
1568 builder() 1585 builder()
1569 ->LoadAccumulatorWithRegister(execution_context()->reg()) 1586 ->LoadAccumulatorWithRegister(execution_context()->reg())
1570 .StoreAccumulatorInRegister(context_reg); 1587 .StoreAccumulatorInRegister(context_reg);
1571 for (int i = 0; i < depth; ++i) { 1588 for (int i = 0; i < depth; ++i) {
1572 builder() 1589 builder()
1573 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1590 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1574 .StoreAccumulatorInRegister(context_reg); 1591 .StoreAccumulatorInRegister(context_reg);
1575 } 1592 }
1576 } 1593 }
1594
1577 builder()->LoadContextSlot(context_reg, variable->index()); 1595 builder()->LoadContextSlot(context_reg, variable->index());
1596 BuildHoleCheckForVariableLoad(mode, variable->name());
1578 execution_result()->SetResultInAccumulator(); 1597 execution_result()->SetResultInAccumulator();
1579 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
1580 // let variables.
1581 break; 1598 break;
1582 } 1599 }
1583 case VariableLocation::LOOKUP: { 1600 case VariableLocation::LOOKUP: {
1584 builder()->LoadLookupSlot(variable->name(), typeof_mode); 1601 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1585 execution_result()->SetResultInAccumulator(); 1602 execution_result()->SetResultInAccumulator();
1586 break; 1603 break;
1587 } 1604 }
1588 } 1605 }
1589 } 1606 }
1590 1607
1591 1608
1592 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( 1609 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1593 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1610 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1594 AccumulatorResultScope accumulator_result(this); 1611 AccumulatorResultScope accumulator_result(this);
1595 VisitVariableLoad(variable, slot, typeof_mode); 1612 VisitVariableLoad(variable, slot, typeof_mode);
1596 } 1613 }
1597 1614
1598 1615
1599 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( 1616 Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1600 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1617 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1601 RegisterResultScope register_scope(this); 1618 RegisterResultScope register_scope(this);
1602 VisitVariableLoad(variable, slot, typeof_mode); 1619 VisitVariableLoad(variable, slot, typeof_mode);
1603 return register_scope.ResultRegister(); 1620 return register_scope.ResultRegister();
1604 } 1621 }
1605 1622
1623 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1624 Register name_reg = register_allocator()->NewRegister();
1625 BytecodeLabel end_label;
1626 // TODO(mythria): This will be replaced by a new bytecode that throws an
1627 // error if the value is the hole.
1628 builder()
1629 ->JumpIfNotHole(&end_label)
1630 .LoadLiteral(name)
1631 .StoreAccumulatorInRegister(name_reg)
1632 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1633 .Bind(&end_label);
1634 }
1635
1636 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1637 Register name_reg = register_allocator()->NewRegister();
1638 BytecodeLabel end_label;
1639 // TODO(mythria): This will be replaced by a new bytecode that throws an
1640 // error if the value is not the hole.
1641 builder()
1642 ->JumpIfHole(&end_label)
1643 .LoadLiteral(name)
1644 .StoreAccumulatorInRegister(name_reg)
1645 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1646 .Bind(&end_label);
1647 }
1648
1649 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1650 Register name_reg = register_allocator()->NewRegister();
1651 BytecodeLabel else_label;
1652 // TODO(mythria): This will be replaced by a new bytecode that throws an
1653 // appropriate error depending on the whether the value is a hole or not.
1654 builder()
1655 ->JumpIfNotHole(&else_label)
1656 .LoadLiteral(name)
1657 .StoreAccumulatorInRegister(name_reg)
1658 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1659 .Bind(&else_label)
1660 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1661 }
1662
1663 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
1664 Token::Value op) {
1665 VariableMode mode = variable->mode();
1666 DCHECK(mode != CONST_LEGACY);
1667 if (mode == CONST && op != Token::INIT) {
1668 // Non-intializing assignments to constant is not allowed.
1669 BuildThrowReassignConstant(variable->name());
1670 } else if (mode == LET && op != Token::INIT) {
1671 // Perform an initialization check for let declared variables.
1672 // E.g. let x = (x = 20); is not allowed.
1673 BuildThrowIfHole(variable->name());
1674 } else {
1675 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1676 // Perform an initialization check for 'this'. 'this' variable is the
1677 // only variable able to trigger bind operations outside the TDZ
1678 // via 'super' calls.
1679 BuildThrowIfNotHole(variable->name());
1680 }
1681 }
1606 1682
1607 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1683 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1684 Token::Value op,
1608 FeedbackVectorSlot slot) { 1685 FeedbackVectorSlot slot) {
1686 VariableMode mode = variable->mode();
1687 RegisterAllocationScope assignment_register_scope(this);
1688 BytecodeLabel end_label;
1689 bool hole_check_required =
1690 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) ||
1691 (mode == CONST && op != Token::INIT) ||
1692 (mode == CONST && op == Token::INIT && variable->is_this());
1609 switch (variable->location()) { 1693 switch (variable->location()) {
1694 case VariableLocation::PARAMETER:
1610 case VariableLocation::LOCAL: { 1695 case VariableLocation::LOCAL: {
1611 // TODO(rmcilroy): support const mode initialization. 1696 Register destination;
1612 Register destination(variable->index()); 1697 if (VariableLocation::PARAMETER == variable->location()) {
1698 destination = Register(builder()->Parameter(variable->index() + 1));
1699 } else {
1700 destination = Register(variable->index());
1701 }
1702
1703 if (hole_check_required) {
1704 // Load destination to check for hole.
1705 Register value_temp = register_allocator()->NewRegister();
1706 builder()
1707 ->StoreAccumulatorInRegister(value_temp)
1708 .LoadAccumulatorWithRegister(destination);
1709
1710 if (mode == CONST_LEGACY && op == Token::INIT) {
1711 // Perform an intialization check for legacy constants.
1712 builder()
1713 ->JumpIfNotHole(&end_label)
1714 .MoveRegister(value_temp, destination)
1715 .Bind(&end_label)
1716 .LoadAccumulatorWithRegister(value_temp);
1717 // Break here because the value should not be stored unconditionally.
1718 break;
1719 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1720 DCHECK(!is_strict(language_mode()));
1721 // Ensure accumulator is in the correct state.
1722 builder()->LoadAccumulatorWithRegister(value_temp);
1723 // Break here, non-initializing assignments to legacy constants are
1724 // ignored.
1725 break;
1726 } else {
1727 BuildHoleCheckForVariableAssignment(variable, op);
1728 builder()->LoadAccumulatorWithRegister(value_temp);
1729 }
1730 }
1731
1613 builder()->StoreAccumulatorInRegister(destination); 1732 builder()->StoreAccumulatorInRegister(destination);
1614 break; 1733 break;
1615 } 1734 }
1616 case VariableLocation::PARAMETER: {
1617 // The parameter indices are shifted by 1 (receiver is variable
1618 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1619 Register destination(builder()->Parameter(variable->index() + 1));
1620 builder()->StoreAccumulatorInRegister(destination);
1621 break;
1622 }
1623 case VariableLocation::GLOBAL: 1735 case VariableLocation::GLOBAL:
1624 case VariableLocation::UNALLOCATED: { 1736 case VariableLocation::UNALLOCATED: {
1625 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1737 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1626 language_mode()); 1738 language_mode());
1627 break; 1739 break;
1628 } 1740 }
1629 case VariableLocation::CONTEXT: { 1741 case VariableLocation::CONTEXT: {
1630 // TODO(rmcilroy): support const mode initialization.
1631 int depth = execution_context()->ContextChainDepth(variable->scope()); 1742 int depth = execution_context()->ContextChainDepth(variable->scope());
1632 ContextScope* context = execution_context()->Previous(depth); 1743 ContextScope* context = execution_context()->Previous(depth);
1633 Register context_reg; 1744 Register context_reg;
1745
1634 if (context) { 1746 if (context) {
1635 context_reg = context->reg(); 1747 context_reg = context->reg();
1636 } else { 1748 } else {
1637 Register value_temp = register_allocator()->NewRegister(); 1749 Register value_temp = register_allocator()->NewRegister();
1638 context_reg = register_allocator()->NewRegister(); 1750 context_reg = register_allocator()->NewRegister();
1639 // Walk the context chain to find the context at the given depth. 1751 // Walk the context chain to find the context at the given depth.
1640 // TODO(rmcilroy): Perform this work in a bytecode handler once we have 1752 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1641 // a generic mechanism for performing jumps in interpreter.cc. 1753 // a generic mechanism for performing jumps in interpreter.cc.
1642 // TODO(mythria): Also update bytecode graph builder with correct depth 1754 // TODO(mythria): Also update bytecode graph builder with correct depth
1643 // when this changes. 1755 // when this changes.
1644 builder() 1756 builder()
1645 ->StoreAccumulatorInRegister(value_temp) 1757 ->StoreAccumulatorInRegister(value_temp)
1646 .LoadAccumulatorWithRegister(execution_context()->reg()) 1758 .LoadAccumulatorWithRegister(execution_context()->reg())
1647 .StoreAccumulatorInRegister(context_reg); 1759 .StoreAccumulatorInRegister(context_reg);
1648 for (int i = 0; i < depth; ++i) { 1760 for (int i = 0; i < depth; ++i) {
1649 builder() 1761 builder()
1650 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1762 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1651 .StoreAccumulatorInRegister(context_reg); 1763 .StoreAccumulatorInRegister(context_reg);
1652 } 1764 }
1653 builder()->LoadAccumulatorWithRegister(value_temp); 1765 builder()->LoadAccumulatorWithRegister(value_temp);
1654 } 1766 }
1767
1768 if (hole_check_required) {
1769 // Load destination to check for hole.
1770 Register value_temp = register_allocator()->NewRegister();
1771 builder()
1772 ->StoreAccumulatorInRegister(value_temp)
1773 .LoadContextSlot(context_reg, variable->index());
1774
1775 if (mode == CONST_LEGACY && op == Token::INIT) {
1776 // Perform an intialization check for legacy constants.
1777 builder()
1778 ->JumpIfNotHole(&end_label)
1779 .LoadAccumulatorWithRegister(value_temp)
1780 .StoreContextSlot(context_reg, variable->index())
1781 .Bind(&end_label);
1782 builder()->LoadAccumulatorWithRegister(value_temp);
1783 // Break here because the value should not be stored unconditionally.
1784 // The above code performs the store conditionally.
1785 break;
1786 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1787 DCHECK(!is_strict(language_mode()));
1788 // Ensure accumulator is in the correct state.
1789 builder()->LoadAccumulatorWithRegister(value_temp);
1790 // Break here, non-initializing assignments to legacy constants are
1791 // ignored.
1792 break;
1793 } else {
1794 BuildHoleCheckForVariableAssignment(variable, op);
1795 builder()->LoadAccumulatorWithRegister(value_temp);
1796 }
1797 }
1798
1655 builder()->StoreContextSlot(context_reg, variable->index()); 1799 builder()->StoreContextSlot(context_reg, variable->index());
1656 break; 1800 break;
1657 } 1801 }
1658 case VariableLocation::LOOKUP: { 1802 case VariableLocation::LOOKUP: {
1659 // TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for 1803 if (mode == CONST_LEGACY && op == Token::INIT) {
1660 // initializations of const declarations. 1804 register_allocator()->PrepareForConsecutiveAllocations(3);
1661 builder()->StoreLookupSlot(variable->name(), language_mode()); 1805 Register value = register_allocator()->NextConsecutiveRegister();
1806 Register context = register_allocator()->NextConsecutiveRegister();
1807 Register name = register_allocator()->NextConsecutiveRegister();
1808
1809 // InitializeLegacyConstLookupSlot runtime call returns the 'value'
1810 // passed to it. So, accumulator will have its original contents when
1811 // runtime call returns.
1812 builder()
1813 ->StoreAccumulatorInRegister(value)
1814 .MoveRegister(execution_context()->reg(), context)
1815 .LoadLiteral(variable->name())
1816 .StoreAccumulatorInRegister(name)
1817 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3);
1818 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1819 // Non-intializing assignments to legacy constants are ignored.
1820 DCHECK(!is_strict(language_mode()));
1821 } else {
1822 builder()->StoreLookupSlot(variable->name(), language_mode());
1823 }
1662 break; 1824 break;
1663 } 1825 }
1664 } 1826 }
1665 } 1827 }
1666 1828
1667 1829
1668 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 1830 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
1669 DCHECK(expr->target()->IsValidReferenceExpression()); 1831 DCHECK(expr->target()->IsValidReferenceExpression());
1670 Register object, key; 1832 Register object, key;
1671 Handle<String> name; 1833 Handle<String> name;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 VisitForAccumulatorValue(expr->value()); 1906 VisitForAccumulatorValue(expr->value());
1745 } 1907 }
1746 1908
1747 // Store the value. 1909 // Store the value.
1748 FeedbackVectorSlot slot = expr->AssignmentSlot(); 1910 FeedbackVectorSlot slot = expr->AssignmentSlot();
1749 switch (assign_type) { 1911 switch (assign_type) {
1750 case VARIABLE: { 1912 case VARIABLE: {
1751 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. 1913 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
1752 // Is the value in the accumulator safe? Yes, but scary. 1914 // Is the value in the accumulator safe? Yes, but scary.
1753 Variable* variable = expr->target()->AsVariableProxy()->var(); 1915 Variable* variable = expr->target()->AsVariableProxy()->var();
1754 VisitVariableAssignment(variable, slot); 1916 VisitVariableAssignment(variable, expr->op(), slot);
1755 break; 1917 break;
1756 } 1918 }
1757 case NAMED_PROPERTY: 1919 case NAMED_PROPERTY:
1758 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1920 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1759 language_mode()); 1921 language_mode());
1760 break; 1922 break;
1761 case KEYED_PROPERTY: 1923 case KEYED_PROPERTY:
1762 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 1924 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1763 language_mode()); 1925 language_mode());
1764 break; 1926 break;
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 } 2331 }
2170 2332
2171 // Perform +1/-1 operation. 2333 // Perform +1/-1 operation.
2172 builder()->CountOperation(expr->binary_op(), language_mode_strength()); 2334 builder()->CountOperation(expr->binary_op(), language_mode_strength());
2173 2335
2174 // Store the value. 2336 // Store the value.
2175 FeedbackVectorSlot feedback_slot = expr->CountSlot(); 2337 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2176 switch (assign_type) { 2338 switch (assign_type) {
2177 case VARIABLE: { 2339 case VARIABLE: {
2178 Variable* variable = expr->expression()->AsVariableProxy()->var(); 2340 Variable* variable = expr->expression()->AsVariableProxy()->var();
2179 VisitVariableAssignment(variable, feedback_slot); 2341 VisitVariableAssignment(variable, expr->op(), feedback_slot);
2180 break; 2342 break;
2181 } 2343 }
2182 case NAMED_PROPERTY: { 2344 case NAMED_PROPERTY: {
2183 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), 2345 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot),
2184 language_mode()); 2346 language_mode());
2185 break; 2347 break;
2186 } 2348 }
2187 case KEYED_PROPERTY: { 2349 case KEYED_PROPERTY: {
2188 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), 2350 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot),
2189 language_mode()); 2351 language_mode());
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
2446 2608
2447 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); 2609 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
2448 2610
2449 // Allocate and initialize a new arguments object and assign to the 2611 // Allocate and initialize a new arguments object and assign to the
2450 // {arguments} variable. 2612 // {arguments} variable.
2451 CreateArgumentsType type = 2613 CreateArgumentsType type =
2452 is_strict(language_mode()) || !info()->has_simple_parameters() 2614 is_strict(language_mode()) || !info()->has_simple_parameters()
2453 ? CreateArgumentsType::kUnmappedArguments 2615 ? CreateArgumentsType::kUnmappedArguments
2454 : CreateArgumentsType::kMappedArguments; 2616 : CreateArgumentsType::kMappedArguments;
2455 builder()->CreateArguments(type); 2617 builder()->CreateArguments(type);
2456 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2618 VisitVariableAssignment(variable, Token::ASSIGN,
2619 FeedbackVectorSlot::Invalid());
2457 } 2620 }
2458 2621
2459 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest, int index) { 2622 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest, int index) {
2460 if (rest == nullptr) return; 2623 if (rest == nullptr) return;
2461 2624
2462 // Allocate and initialize a new arguments object and assign to the {rest} 2625 // Allocate and initialize a new arguments object and assign to the {rest}
2463 // variable. 2626 // variable.
2464 builder()->CreateRestArguments(index); 2627 builder()->CreateRestArguments(index);
2465 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); 2628 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
2466 VisitVariableAssignment(rest, FeedbackVectorSlot::Invalid()); 2629 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid());
2467 } 2630 }
2468 2631
2469 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { 2632 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
2470 if (variable == nullptr) return; 2633 if (variable == nullptr) return;
2471 2634
2472 // TODO(rmcilroy): Remove once we have tests which exercise this code path. 2635 // TODO(rmcilroy): Remove once we have tests which exercise this code path.
2473 UNIMPLEMENTED(); 2636 UNIMPLEMENTED();
2474 2637
2475 // Store the closure we were called with in the given variable. 2638 // Store the closure we were called with in the given variable.
2476 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2639 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2477 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2640 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2478 } 2641 }
2479 2642
2480 2643
2481 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { 2644 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
2482 if (variable == nullptr) return; 2645 if (variable == nullptr) return;
2483 2646
2484 // Store the new target we were called with in the given variable. 2647 // Store the new target we were called with in the given variable.
2485 builder()->LoadAccumulatorWithRegister(Register::new_target()); 2648 builder()->LoadAccumulatorWithRegister(Register::new_target());
2486 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2649 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2487 } 2650 }
2488 2651
2489 2652
2490 void BytecodeGenerator::VisitFunctionClosureForContext() { 2653 void BytecodeGenerator::VisitFunctionClosureForContext() {
2491 AccumulatorResultScope accumulator_execution_result(this); 2654 AccumulatorResultScope accumulator_execution_result(this);
2492 Scope* closure_scope = execution_context()->scope()->ClosureScope(); 2655 Scope* closure_scope = execution_context()->scope()->ClosureScope();
2493 if (closure_scope->is_script_scope() || 2656 if (closure_scope->is_script_scope() ||
2494 closure_scope->is_module_scope()) { 2657 closure_scope->is_module_scope()) {
2495 // Contexts nested in the native context have a canonical empty function as 2658 // Contexts nested in the native context have a canonical empty function as
2496 // their closure, not the anonymous closure containing the global code. 2659 // their closure, not the anonymous closure containing the global code.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2554 } 2717 }
2555 2718
2556 2719
2557 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2720 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2558 return TypeFeedbackVector::GetIndex(slot); 2721 return TypeFeedbackVector::GetIndex(slot);
2559 } 2722 }
2560 2723
2561 } // namespace interpreter 2724 } // namespace interpreter
2562 } // namespace internal 2725 } // namespace internal
2563 } // namespace v8 2726 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698