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 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
711 decl->fun(), info()->script(), info()); | 711 decl->fun(), info()->script(), info()); |
712 // Check for stack-overflow exception. | 712 // Check for stack-overflow exception. |
713 if (function.is_null()) return SetStackOverflow(); | 713 if (function.is_null()) return SetStackOverflow(); |
714 globals()->push_back(variable->name()); | 714 globals()->push_back(variable->name()); |
715 globals()->push_back(function); | 715 globals()->push_back(function); |
716 break; | 716 break; |
717 } | 717 } |
718 case VariableLocation::PARAMETER: | 718 case VariableLocation::PARAMETER: |
719 case VariableLocation::LOCAL: { | 719 case VariableLocation::LOCAL: { |
720 VisitForAccumulatorValue(decl->fun()); | 720 VisitForAccumulatorValue(decl->fun()); |
721 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 721 DCHECK(variable->mode() == LET || variable->mode() == VAR); |
722 VisitVariableAssignment(variable, Token::INIT, | |
723 FeedbackVectorSlot::Invalid()); | |
722 break; | 724 break; |
723 } | 725 } |
724 case VariableLocation::CONTEXT: { | 726 case VariableLocation::CONTEXT: { |
725 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 727 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
726 VisitForAccumulatorValue(decl->fun()); | 728 VisitForAccumulatorValue(decl->fun()); |
727 builder()->StoreContextSlot(execution_context()->reg(), | 729 builder()->StoreContextSlot(execution_context()->reg(), |
728 variable->index()); | 730 variable->index()); |
729 break; | 731 break; |
730 } | 732 } |
731 case VariableLocation::LOOKUP: { | 733 case VariableLocation::LOOKUP: { |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
993 FeedbackVectorSlot slot) { | 995 FeedbackVectorSlot slot) { |
994 DCHECK(expr->IsValidReferenceExpression()); | 996 DCHECK(expr->IsValidReferenceExpression()); |
995 | 997 |
996 // Evaluate assignment starting with the value to be stored in the | 998 // Evaluate assignment starting with the value to be stored in the |
997 // accumulator. | 999 // accumulator. |
998 Property* property = expr->AsProperty(); | 1000 Property* property = expr->AsProperty(); |
999 LhsKind assign_type = Property::GetAssignType(property); | 1001 LhsKind assign_type = Property::GetAssignType(property); |
1000 switch (assign_type) { | 1002 switch (assign_type) { |
1001 case VARIABLE: { | 1003 case VARIABLE: { |
1002 Variable* variable = expr->AsVariableProxy()->var(); | 1004 Variable* variable = expr->AsVariableProxy()->var(); |
1003 VisitVariableAssignment(variable, slot); | 1005 VisitVariableAssignment(variable, Token::ASSIGN, slot); |
1004 break; | 1006 break; |
1005 } | 1007 } |
1006 case NAMED_PROPERTY: { | 1008 case NAMED_PROPERTY: { |
1007 RegisterAllocationScope register_scope(this); | 1009 RegisterAllocationScope register_scope(this); |
1008 Register value = register_allocator()->NewRegister(); | 1010 Register value = register_allocator()->NewRegister(); |
1009 builder()->StoreAccumulatorInRegister(value); | 1011 builder()->StoreAccumulatorInRegister(value); |
1010 Register object = VisitForRegisterValue(property->obj()); | 1012 Register object = VisitForRegisterValue(property->obj()); |
1011 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); | 1013 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); |
1012 builder()->LoadAccumulatorWithRegister(value); | 1014 builder()->LoadAccumulatorWithRegister(value); |
1013 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1015 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1493 builder()->LoadAccumulatorWithRegister(literal); | 1495 builder()->LoadAccumulatorWithRegister(literal); |
1494 } | 1496 } |
1495 execution_result()->SetResultInAccumulator(); | 1497 execution_result()->SetResultInAccumulator(); |
1496 } | 1498 } |
1497 | 1499 |
1498 | 1500 |
1499 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1501 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
1500 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1502 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
1501 } | 1503 } |
1502 | 1504 |
1505 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | |
1506 Handle<String> name) { | |
1507 if (mode == CONST_LEGACY) { | |
1508 BytecodeLabel end_label; | |
1509 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label); | |
1510 } else if (mode == LET || mode == CONST) { | |
1511 BuildThrowIfHole(name); | |
1512 } | |
1513 } | |
1503 | 1514 |
1504 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1515 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
1505 FeedbackVectorSlot slot, | 1516 FeedbackVectorSlot slot, |
1506 TypeofMode typeof_mode) { | 1517 TypeofMode typeof_mode) { |
1518 VariableMode mode = variable->mode(); | |
1507 switch (variable->location()) { | 1519 switch (variable->location()) { |
1508 case VariableLocation::LOCAL: { | 1520 case VariableLocation::LOCAL: { |
1509 Register source(Register(variable->index())); | 1521 Register source(Register(variable->index())); |
1510 builder()->LoadAccumulatorWithRegister(source); | 1522 builder()->LoadAccumulatorWithRegister(source); |
1523 BuildHoleCheckForVariableLoad(mode, variable->name()); | |
1511 execution_result()->SetResultInAccumulator(); | 1524 execution_result()->SetResultInAccumulator(); |
1512 break; | 1525 break; |
1513 } | 1526 } |
1514 case VariableLocation::PARAMETER: { | 1527 case VariableLocation::PARAMETER: { |
1515 // The parameter indices are shifted by 1 (receiver is variable | 1528 // The parameter indices are shifted by 1 (receiver is variable |
1516 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1529 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1517 Register source = builder()->Parameter(variable->index() + 1); | 1530 Register source = builder()->Parameter(variable->index() + 1); |
1518 builder()->LoadAccumulatorWithRegister(source); | 1531 builder()->LoadAccumulatorWithRegister(source); |
1532 BuildHoleCheckForVariableLoad(mode, variable->name()); | |
1519 execution_result()->SetResultInAccumulator(); | 1533 execution_result()->SetResultInAccumulator(); |
1520 break; | 1534 break; |
1521 } | 1535 } |
1522 case VariableLocation::GLOBAL: | 1536 case VariableLocation::GLOBAL: |
1523 case VariableLocation::UNALLOCATED: { | 1537 case VariableLocation::UNALLOCATED: { |
1524 builder()->LoadGlobal(variable->name(), feedback_index(slot), | 1538 builder()->LoadGlobal(variable->name(), feedback_index(slot), |
1525 language_mode(), typeof_mode); | 1539 language_mode(), typeof_mode); |
1526 execution_result()->SetResultInAccumulator(); | 1540 execution_result()->SetResultInAccumulator(); |
1527 break; | 1541 break; |
1528 } | 1542 } |
(...skipping 12 matching lines...) Expand all Loading... | |
1541 // when this changes. | 1555 // when this changes. |
1542 builder() | 1556 builder() |
1543 ->LoadAccumulatorWithRegister(execution_context()->reg()) | 1557 ->LoadAccumulatorWithRegister(execution_context()->reg()) |
1544 .StoreAccumulatorInRegister(context_reg); | 1558 .StoreAccumulatorInRegister(context_reg); |
1545 for (int i = 0; i < depth; ++i) { | 1559 for (int i = 0; i < depth; ++i) { |
1546 builder() | 1560 builder() |
1547 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 1561 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
1548 .StoreAccumulatorInRegister(context_reg); | 1562 .StoreAccumulatorInRegister(context_reg); |
1549 } | 1563 } |
1550 } | 1564 } |
1565 | |
1551 builder()->LoadContextSlot(context_reg, variable->index()); | 1566 builder()->LoadContextSlot(context_reg, variable->index()); |
1567 BuildHoleCheckForVariableLoad(mode, variable->name()); | |
1552 execution_result()->SetResultInAccumulator(); | 1568 execution_result()->SetResultInAccumulator(); |
1553 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | |
1554 // let variables. | |
1555 break; | 1569 break; |
1556 } | 1570 } |
1557 case VariableLocation::LOOKUP: { | 1571 case VariableLocation::LOOKUP: { |
1558 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1572 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
1559 execution_result()->SetResultInAccumulator(); | 1573 execution_result()->SetResultInAccumulator(); |
1560 break; | 1574 break; |
1561 } | 1575 } |
1562 } | 1576 } |
1563 } | 1577 } |
1564 | 1578 |
1565 | 1579 |
1566 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1580 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
1567 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1581 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
1568 AccumulatorResultScope accumulator_result(this); | 1582 AccumulatorResultScope accumulator_result(this); |
1569 VisitVariableLoad(variable, slot, typeof_mode); | 1583 VisitVariableLoad(variable, slot, typeof_mode); |
1570 } | 1584 } |
1571 | 1585 |
1572 | 1586 |
1573 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( | 1587 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( |
1574 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1588 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
1575 RegisterResultScope register_scope(this); | 1589 RegisterResultScope register_scope(this); |
1576 VisitVariableLoad(variable, slot, typeof_mode); | 1590 VisitVariableLoad(variable, slot, typeof_mode); |
1577 return register_scope.ResultRegister(); | 1591 return register_scope.ResultRegister(); |
1578 } | 1592 } |
1579 | 1593 |
1594 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { | |
1595 Register name_reg = register_allocator()->NewRegister(); | |
1596 BytecodeLabel end_label; | |
1597 builder() | |
1598 ->JumpIfNotHole(&end_label) | |
1599 .LoadLiteral(name) | |
1600 .StoreAccumulatorInRegister(name_reg) | |
1601 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
1602 .Bind(&end_label); | |
1603 } | |
1604 | |
1605 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) { | |
1606 Register name_reg = register_allocator()->NewRegister(); | |
1607 BytecodeLabel end_label; | |
1608 builder() | |
1609 ->JumpIfHole(&end_label) | |
1610 .LoadLiteral(name) | |
1611 .StoreAccumulatorInRegister(name_reg) | |
1612 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
1613 .Bind(&end_label); | |
1614 } | |
1615 | |
1616 void BytecodeGenerator::BuildThrowReassignConstant(Register destination, | |
1617 Handle<String> name) { | |
mythria
2016/01/26 13:08:33
This is used for throwing when constant is re-assi
| |
1618 Register name_reg = register_allocator()->NewRegister(); | |
1619 BytecodeLabel else_label; | |
1620 builder() | |
1621 ->LoadLiteral(name) | |
1622 .StoreAccumulatorInRegister(name_reg) | |
1623 .LoadAccumulatorWithRegister(destination) | |
1624 .JumpIfNotHole(&else_label) | |
1625 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
1626 .Bind(&else_label) | |
1627 .CallRuntime(Runtime::kThrowConstAssignError, name_reg, 1); | |
1628 } | |
1629 | |
1630 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) { | |
1631 Register name_reg = register_allocator()->NewRegister(); | |
1632 BytecodeLabel else_label; | |
1633 builder() | |
1634 ->JumpIfNotHole(&else_label) | |
1635 .LoadLiteral(name) | |
1636 .StoreAccumulatorInRegister(name_reg) | |
1637 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
1638 .Bind(&else_label) | |
1639 .LoadLiteral(name) | |
1640 .StoreAccumulatorInRegister(name_reg) | |
1641 .CallRuntime(Runtime::kThrowConstAssignError, name_reg, 1); | |
1642 } | |
1580 | 1643 |
1581 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1644 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
1645 Token::Value op, | |
1582 FeedbackVectorSlot slot) { | 1646 FeedbackVectorSlot slot) { |
1647 VariableMode mode = variable->mode(); | |
1648 RegisterAllocationScope assignment_register_scope(this); | |
1649 BytecodeLabel end_label; | |
1650 bool hole_check_required = | |
1651 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) || | |
1652 (mode == CONST && op != Token::INIT) || | |
1653 (mode == CONST && op == Token::INIT && variable->is_this()); | |
1583 switch (variable->location()) { | 1654 switch (variable->location()) { |
1655 case VariableLocation::PARAMETER: | |
1584 case VariableLocation::LOCAL: { | 1656 case VariableLocation::LOCAL: { |
1585 // TODO(rmcilroy): support const mode initialization. | 1657 Register destination; |
1586 Register destination(variable->index()); | 1658 if (VariableLocation::PARAMETER == variable->location()) { |
1587 builder()->StoreAccumulatorInRegister(destination); | 1659 destination = Register(builder()->Parameter(variable->index() + 1)); |
1588 break; | 1660 } else { |
1589 } | 1661 destination = Register(variable->index()); |
1590 case VariableLocation::PARAMETER: { | 1662 } |
1591 // The parameter indices are shifted by 1 (receiver is variable | 1663 |
1592 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1664 if (!hole_check_required) { |
1593 Register destination(builder()->Parameter(variable->index() + 1)); | 1665 builder()->StoreAccumulatorInRegister(destination); |
1594 builder()->StoreAccumulatorInRegister(destination); | 1666 } else if (mode == CONST && op != Token::INIT) { |
1667 // Assigning to constant is not allowed. Throw an appropriate | |
1668 // exception. Accumulator is not restored back. | |
1669 BuildThrowReassignConstant(destination, variable->name()); | |
1670 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
1671 // TODO(mythria): Find a test case for strict mode legacy constants. | |
1672 DCHECK(!is_strict(language_mode())); | |
1673 } else { | |
1674 // Store accumulator to a temporary register and load destination to | |
1675 // perform hole check. | |
1676 BytecodeLabel end_label; | |
1677 Register value_temp = register_allocator()->NewRegister(); | |
1678 builder() | |
1679 ->StoreAccumulatorInRegister(value_temp) | |
1680 .LoadAccumulatorWithRegister(destination); | |
1681 if (mode == CONST_LEGACY && op == Token::INIT) { | |
1682 // If the destination is already initialized silently ignore this | |
1683 // assignment. Restore the accumulator. | |
1684 builder() | |
1685 ->JumpIfNotHole(&end_label) | |
1686 .MoveRegister(value_temp, destination) | |
1687 .Bind(&end_label) | |
1688 .LoadAccumulatorWithRegister(value_temp); | |
1689 } else if (mode == LET && op != Token::INIT) { | |
1690 BuildThrowIfHole(variable->name()); | |
1691 // Move does not help here, because accumulator should be restored to | |
1692 // value_temp as well. | |
1693 builder() | |
1694 ->LoadAccumulatorWithRegister(value_temp) | |
1695 .StoreAccumulatorInRegister(destination); | |
1696 } else { | |
1697 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT); | |
1698 // Perform an initialization check for 'this'. 'this' variable is the | |
1699 // only variable being able to trigger bind operations outside the TDZ | |
1700 // via 'super' calls. | |
1701 BuildThrowIfNotHole(variable->name()); | |
1702 builder() | |
1703 ->LoadAccumulatorWithRegister(value_temp) | |
1704 .StoreAccumulatorInRegister(destination); | |
1705 } | |
1706 } | |
1595 break; | 1707 break; |
1596 } | 1708 } |
1597 case VariableLocation::GLOBAL: | 1709 case VariableLocation::GLOBAL: |
1598 case VariableLocation::UNALLOCATED: { | 1710 case VariableLocation::UNALLOCATED: { |
1599 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 1711 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
1600 language_mode()); | 1712 language_mode()); |
1601 break; | 1713 break; |
1602 } | 1714 } |
1603 case VariableLocation::CONTEXT: { | 1715 case VariableLocation::CONTEXT: { |
1604 // TODO(rmcilroy): support const mode initialization. | |
1605 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1716 int depth = execution_context()->ContextChainDepth(variable->scope()); |
1606 ContextScope* context = execution_context()->Previous(depth); | 1717 ContextScope* context = execution_context()->Previous(depth); |
1607 Register context_reg; | 1718 Register context_reg; |
1719 Register value_temp; | |
1720 bool value_in_accumulator = true; | |
1721 | |
1608 if (context) { | 1722 if (context) { |
1609 context_reg = context->reg(); | 1723 context_reg = context->reg(); |
1610 } else { | 1724 } else { |
1611 Register value_temp = register_allocator()->NewRegister(); | 1725 value_temp = register_allocator()->NewRegister(); |
1612 context_reg = register_allocator()->NewRegister(); | 1726 context_reg = register_allocator()->NewRegister(); |
1613 // Walk the context chain to find the context at the given depth. | 1727 // Walk the context chain to find the context at the given depth. |
1614 // TODO(rmcilroy): Perform this work in a bytecode handler once we have | 1728 // TODO(rmcilroy): Perform this work in a bytecode handler once we have |
1615 // a generic mechanism for performing jumps in interpreter.cc. | 1729 // a generic mechanism for performing jumps in interpreter.cc. |
1616 // TODO(mythria): Also update bytecode graph builder with correct depth | 1730 // TODO(mythria): Also update bytecode graph builder with correct depth |
1617 // when this changes. | 1731 // when this changes. |
1618 builder() | 1732 builder() |
1619 ->StoreAccumulatorInRegister(value_temp) | 1733 ->StoreAccumulatorInRegister(value_temp) |
1620 .LoadAccumulatorWithRegister(execution_context()->reg()) | 1734 .LoadAccumulatorWithRegister(execution_context()->reg()) |
1621 .StoreAccumulatorInRegister(context_reg); | 1735 .StoreAccumulatorInRegister(context_reg); |
1622 for (int i = 0; i < depth; ++i) { | 1736 for (int i = 0; i < depth; ++i) { |
1623 builder() | 1737 builder() |
1624 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 1738 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
1625 .StoreAccumulatorInRegister(context_reg); | 1739 .StoreAccumulatorInRegister(context_reg); |
1626 } | 1740 } |
1627 builder()->LoadAccumulatorWithRegister(value_temp); | 1741 value_in_accumulator = false; |
1628 } | 1742 } |
1629 builder()->StoreContextSlot(context_reg, variable->index()); | 1743 |
1744 if (!hole_check_required) { | |
1745 if (!value_in_accumulator) { | |
1746 builder()->LoadAccumulatorWithRegister(value_temp); | |
1747 } | |
1748 builder()->StoreContextSlot(context_reg, variable->index()); | |
1749 } else if (mode == CONST && op != Token::INIT) { | |
1750 // Assigning to constant is not allowed. Throw an appropriate | |
1751 // exception. Accumulator is not restored back. | |
1752 builder()->LoadContextSlot(context_reg, variable->index()); | |
1753 BuildThrowReassignConstant(variable->name()); | |
1754 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
1755 // TODO(mythria): Find a test case for strict mode legacy constants. | |
1756 DCHECK(!is_strict(language_mode())); | |
1757 // Accumulator has to be restored back. | |
1758 if (!value_in_accumulator) { | |
1759 builder()->LoadAccumulatorWithRegister(value_temp); | |
1760 } | |
1761 } else { | |
1762 // Store accumulator to a temporary register and load destination to | |
1763 // perform hole check. | |
1764 if (value_in_accumulator) { | |
1765 value_temp = register_allocator()->NewRegister(); | |
1766 builder()->StoreAccumulatorInRegister(value_temp); | |
1767 } | |
1768 builder()->LoadContextSlot(context_reg, variable->index()); | |
1769 BytecodeLabel end_label; | |
1770 if (mode == CONST_LEGACY && op == Token::INIT) { | |
1771 // If the destination is already initialized silently ignore this | |
1772 // assignment and restore back the accumulator. | |
1773 builder() | |
1774 ->JumpIfNotHole(&end_label) | |
1775 .LoadAccumulatorWithRegister(value_temp) | |
1776 .StoreContextSlot(context_reg, variable->index()) | |
1777 .Bind(&end_label) | |
1778 .LoadAccumulatorWithRegister(value_temp); | |
1779 } else if (mode == LET && op != Token::INIT) { | |
1780 BuildThrowIfHole(variable->name()); | |
1781 builder() | |
1782 ->LoadAccumulatorWithRegister(value_temp) | |
1783 .StoreContextSlot(context_reg, variable->index()); | |
1784 } else { | |
1785 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT); | |
1786 // Perform an initialization check for 'this'. 'this' variable is the | |
1787 // only variable being able to trigger bind operations outside the TDZ | |
1788 // via 'super' calls. | |
1789 BuildThrowIfNotHole(variable->name()); | |
1790 builder() | |
1791 ->LoadAccumulatorWithRegister(value_temp) | |
1792 .StoreContextSlot(context_reg, variable->index()); | |
1793 } | |
1794 } | |
1630 break; | 1795 break; |
1631 } | 1796 } |
1632 case VariableLocation::LOOKUP: { | 1797 case VariableLocation::LOOKUP: { |
1633 // TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for | 1798 if (mode == CONST_LEGACY && op == Token::INIT) { |
1634 // initializations of const declarations. | 1799 register_allocator()->PrepareForConsecutiveAllocations(3); |
1635 builder()->StoreLookupSlot(variable->name(), language_mode()); | 1800 Register value = register_allocator()->NextConsecutiveRegister(); |
1801 Register context = register_allocator()->NextConsecutiveRegister(); | |
1802 Register name = register_allocator()->NextConsecutiveRegister(); | |
1803 | |
1804 // InitializeLegacyConstLookupSlot runtime call returns the 'value' | |
1805 // passed to it. So, accumulator will have its original contents when | |
1806 // runtime call returns. | |
1807 builder() | |
1808 ->StoreAccumulatorInRegister(value) | |
1809 .MoveRegister(execution_context()->reg(), context) | |
1810 .LoadLiteral(variable->name()) | |
1811 .StoreAccumulatorInRegister(name) | |
1812 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3); | |
1813 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
1814 // TODO(mythria): Find a test case for strict mode. We should throw in | |
1815 // strict mode. | |
1816 DCHECK(!is_strict(language_mode())); | |
1817 } else { | |
1818 builder()->StoreLookupSlot(variable->name(), language_mode()); | |
1819 } | |
1636 break; | 1820 break; |
1637 } | 1821 } |
1638 } | 1822 } |
1639 } | 1823 } |
1640 | 1824 |
1641 | 1825 |
1642 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 1826 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
1643 DCHECK(expr->target()->IsValidReferenceExpression()); | 1827 DCHECK(expr->target()->IsValidReferenceExpression()); |
1644 Register object, key; | 1828 Register object, key; |
1645 Handle<String> name; | 1829 Handle<String> name; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1718 VisitForAccumulatorValue(expr->value()); | 1902 VisitForAccumulatorValue(expr->value()); |
1719 } | 1903 } |
1720 | 1904 |
1721 // Store the value. | 1905 // Store the value. |
1722 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 1906 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
1723 switch (assign_type) { | 1907 switch (assign_type) { |
1724 case VARIABLE: { | 1908 case VARIABLE: { |
1725 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. | 1909 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. |
1726 // Is the value in the accumulator safe? Yes, but scary. | 1910 // Is the value in the accumulator safe? Yes, but scary. |
1727 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1911 Variable* variable = expr->target()->AsVariableProxy()->var(); |
1728 VisitVariableAssignment(variable, slot); | 1912 VisitVariableAssignment(variable, expr->op(), slot); |
1729 break; | 1913 break; |
1730 } | 1914 } |
1731 case NAMED_PROPERTY: | 1915 case NAMED_PROPERTY: |
1732 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1916 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
1733 language_mode()); | 1917 language_mode()); |
1734 break; | 1918 break; |
1735 case KEYED_PROPERTY: | 1919 case KEYED_PROPERTY: |
1736 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 1920 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
1737 language_mode()); | 1921 language_mode()); |
1738 break; | 1922 break; |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2144 } | 2328 } |
2145 | 2329 |
2146 // Perform +1/-1 operation. | 2330 // Perform +1/-1 operation. |
2147 builder()->CountOperation(expr->binary_op(), language_mode_strength()); | 2331 builder()->CountOperation(expr->binary_op(), language_mode_strength()); |
2148 | 2332 |
2149 // Store the value. | 2333 // Store the value. |
2150 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 2334 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
2151 switch (assign_type) { | 2335 switch (assign_type) { |
2152 case VARIABLE: { | 2336 case VARIABLE: { |
2153 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2337 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
2154 VisitVariableAssignment(variable, feedback_slot); | 2338 VisitVariableAssignment(variable, expr->op(), feedback_slot); |
2155 break; | 2339 break; |
2156 } | 2340 } |
2157 case NAMED_PROPERTY: { | 2341 case NAMED_PROPERTY: { |
2158 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), | 2342 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), |
2159 language_mode()); | 2343 language_mode()); |
2160 break; | 2344 break; |
2161 } | 2345 } |
2162 case KEYED_PROPERTY: { | 2346 case KEYED_PROPERTY: { |
2163 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), | 2347 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), |
2164 language_mode()); | 2348 language_mode()); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2408 | 2592 |
2409 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); | 2593 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); |
2410 | 2594 |
2411 // Allocate and initialize a new arguments object and assign to the | 2595 // Allocate and initialize a new arguments object and assign to the |
2412 // {arguments} variable. | 2596 // {arguments} variable. |
2413 CreateArgumentsType type = | 2597 CreateArgumentsType type = |
2414 is_strict(language_mode()) || !info()->has_simple_parameters() | 2598 is_strict(language_mode()) || !info()->has_simple_parameters() |
2415 ? CreateArgumentsType::kUnmappedArguments | 2599 ? CreateArgumentsType::kUnmappedArguments |
2416 : CreateArgumentsType::kMappedArguments; | 2600 : CreateArgumentsType::kMappedArguments; |
2417 builder()->CreateArguments(type); | 2601 builder()->CreateArguments(type); |
2418 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 2602 VisitVariableAssignment(variable, Token::ASSIGN, |
2603 FeedbackVectorSlot::Invalid()); | |
2419 } | 2604 } |
2420 | 2605 |
2421 | 2606 |
2422 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { | 2607 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
2423 if (variable == nullptr) return; | 2608 if (variable == nullptr) return; |
2424 | 2609 |
2425 // TODO(rmcilroy): Remove once we have tests which exercise this code path. | 2610 // TODO(rmcilroy): Remove once we have tests which exercise this code path. |
2426 UNIMPLEMENTED(); | 2611 UNIMPLEMENTED(); |
2427 | 2612 |
2428 // Store the closure we were called with in the given variable. | 2613 // Store the closure we were called with in the given variable. |
2429 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2614 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
2430 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 2615 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
2431 } | 2616 } |
2432 | 2617 |
2433 | 2618 |
2434 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { | 2619 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
2435 if (variable == nullptr) return; | 2620 if (variable == nullptr) return; |
2436 | 2621 |
2437 // Store the new target we were called with in the given variable. | 2622 // Store the new target we were called with in the given variable. |
2438 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 2623 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
2439 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 2624 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
2440 } | 2625 } |
2441 | 2626 |
2442 | 2627 |
2443 void BytecodeGenerator::VisitFunctionClosureForContext() { | 2628 void BytecodeGenerator::VisitFunctionClosureForContext() { |
2444 AccumulatorResultScope accumulator_execution_result(this); | 2629 AccumulatorResultScope accumulator_execution_result(this); |
2445 Scope* closure_scope = execution_context()->scope()->ClosureScope(); | 2630 Scope* closure_scope = execution_context()->scope()->ClosureScope(); |
2446 if (closure_scope->is_script_scope() || | 2631 if (closure_scope->is_script_scope() || |
2447 closure_scope->is_module_scope()) { | 2632 closure_scope->is_module_scope()) { |
2448 // Contexts nested in the native context have a canonical empty function as | 2633 // Contexts nested in the native context have a canonical empty function as |
2449 // their closure, not the anonymous closure containing the global code. | 2634 // their closure, not the anonymous closure containing the global code. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2501 } | 2686 } |
2502 | 2687 |
2503 | 2688 |
2504 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2689 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2505 return info()->feedback_vector()->GetIndex(slot); | 2690 return info()->feedback_vector()->GetIndex(slot); |
2506 } | 2691 } |
2507 | 2692 |
2508 } // namespace interpreter | 2693 } // namespace interpreter |
2509 } // namespace internal | 2694 } // namespace internal |
2510 } // namespace v8 | 2695 } // namespace v8 |
OLD | NEW |