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/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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |