Chromium Code Reviews| 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 variable->mode() == CONST); | |
| 723 VisitVariableAssignment(variable, Token::INIT, | |
| 724 FeedbackVectorSlot::Invalid()); | |
| 722 break; | 725 break; |
| 723 } | 726 } |
| 724 case VariableLocation::CONTEXT: { | 727 case VariableLocation::CONTEXT: { |
| 725 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 728 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 726 VisitForAccumulatorValue(decl->fun()); | 729 VisitForAccumulatorValue(decl->fun()); |
| 727 builder()->StoreContextSlot(execution_context()->reg(), | 730 builder()->StoreContextSlot(execution_context()->reg(), |
| 728 variable->index()); | 731 variable->index()); |
| 729 break; | 732 break; |
| 730 } | 733 } |
| 731 case VariableLocation::LOOKUP: { | 734 case VariableLocation::LOOKUP: { |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 996 FeedbackVectorSlot slot) { | 999 FeedbackVectorSlot slot) { |
| 997 DCHECK(expr->IsValidReferenceExpression()); | 1000 DCHECK(expr->IsValidReferenceExpression()); |
| 998 | 1001 |
| 999 // Evaluate assignment starting with the value to be stored in the | 1002 // Evaluate assignment starting with the value to be stored in the |
| 1000 // accumulator. | 1003 // accumulator. |
| 1001 Property* property = expr->AsProperty(); | 1004 Property* property = expr->AsProperty(); |
| 1002 LhsKind assign_type = Property::GetAssignType(property); | 1005 LhsKind assign_type = Property::GetAssignType(property); |
| 1003 switch (assign_type) { | 1006 switch (assign_type) { |
| 1004 case VARIABLE: { | 1007 case VARIABLE: { |
| 1005 Variable* variable = expr->AsVariableProxy()->var(); | 1008 Variable* variable = expr->AsVariableProxy()->var(); |
| 1006 VisitVariableAssignment(variable, slot); | 1009 VisitVariableAssignment(variable, Token::ASSIGN, slot); |
| 1007 break; | 1010 break; |
| 1008 } | 1011 } |
| 1009 case NAMED_PROPERTY: { | 1012 case NAMED_PROPERTY: { |
| 1010 RegisterAllocationScope register_scope(this); | 1013 RegisterAllocationScope register_scope(this); |
| 1011 Register value = register_allocator()->NewRegister(); | 1014 Register value = register_allocator()->NewRegister(); |
| 1012 builder()->StoreAccumulatorInRegister(value); | 1015 builder()->StoreAccumulatorInRegister(value); |
| 1013 Register object = VisitForRegisterValue(property->obj()); | 1016 Register object = VisitForRegisterValue(property->obj()); |
| 1014 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); | 1017 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); |
| 1015 builder()->LoadAccumulatorWithRegister(value); | 1018 builder()->LoadAccumulatorWithRegister(value); |
| 1016 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1019 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1514 builder()->LoadAccumulatorWithRegister(literal); | 1517 builder()->LoadAccumulatorWithRegister(literal); |
| 1515 } | 1518 } |
| 1516 execution_result()->SetResultInAccumulator(); | 1519 execution_result()->SetResultInAccumulator(); |
| 1517 } | 1520 } |
| 1518 | 1521 |
| 1519 | 1522 |
| 1520 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1523 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1521 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1524 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 1522 } | 1525 } |
| 1523 | 1526 |
| 1527 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | |
| 1528 Handle<String> name) { | |
| 1529 if (mode == CONST_LEGACY) { | |
| 1530 BytecodeLabel end_label; | |
| 1531 builder()->JumpIfNotHole(&end_label); | |
| 1532 builder()->LoadUndefined(); | |
| 1533 builder()->Bind(&end_label); | |
| 1534 } else if (mode == LET || mode == CONST) { | |
| 1535 BuildThrowIfHole(name); | |
| 1536 } | |
| 1537 } | |
| 1524 | 1538 |
| 1525 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1539 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
| 1526 FeedbackVectorSlot slot, | 1540 FeedbackVectorSlot slot, |
| 1527 TypeofMode typeof_mode) { | 1541 TypeofMode typeof_mode) { |
| 1542 VariableMode mode = variable->mode(); | |
| 1528 switch (variable->location()) { | 1543 switch (variable->location()) { |
| 1529 case VariableLocation::LOCAL: { | 1544 case VariableLocation::LOCAL: { |
| 1530 Register source(Register(variable->index())); | 1545 Register source(Register(variable->index())); |
| 1531 builder()->LoadAccumulatorWithRegister(source); | 1546 builder()->LoadAccumulatorWithRegister(source); |
| 1547 BuildHoleCheckForVariableLoad(mode, variable->name()); | |
| 1532 execution_result()->SetResultInAccumulator(); | 1548 execution_result()->SetResultInAccumulator(); |
| 1533 break; | 1549 break; |
| 1534 } | 1550 } |
| 1535 case VariableLocation::PARAMETER: { | 1551 case VariableLocation::PARAMETER: { |
| 1536 // The parameter indices are shifted by 1 (receiver is variable | 1552 // The parameter indices are shifted by 1 (receiver is variable |
| 1537 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1553 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 1538 Register source = builder()->Parameter(variable->index() + 1); | 1554 Register source = builder()->Parameter(variable->index() + 1); |
| 1539 builder()->LoadAccumulatorWithRegister(source); | 1555 builder()->LoadAccumulatorWithRegister(source); |
| 1556 BuildHoleCheckForVariableLoad(mode, variable->name()); | |
| 1540 execution_result()->SetResultInAccumulator(); | 1557 execution_result()->SetResultInAccumulator(); |
| 1541 break; | 1558 break; |
| 1542 } | 1559 } |
| 1543 case VariableLocation::GLOBAL: | 1560 case VariableLocation::GLOBAL: |
| 1544 case VariableLocation::UNALLOCATED: { | 1561 case VariableLocation::UNALLOCATED: { |
| 1545 builder()->LoadGlobal(variable->name(), feedback_index(slot), | 1562 builder()->LoadGlobal(variable->name(), feedback_index(slot), |
| 1546 language_mode(), typeof_mode); | 1563 language_mode(), typeof_mode); |
| 1547 execution_result()->SetResultInAccumulator(); | 1564 execution_result()->SetResultInAccumulator(); |
| 1548 break; | 1565 break; |
| 1549 } | 1566 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1562 // when this changes. | 1579 // when this changes. |
| 1563 builder() | 1580 builder() |
| 1564 ->LoadAccumulatorWithRegister(execution_context()->reg()) | 1581 ->LoadAccumulatorWithRegister(execution_context()->reg()) |
| 1565 .StoreAccumulatorInRegister(context_reg); | 1582 .StoreAccumulatorInRegister(context_reg); |
| 1566 for (int i = 0; i < depth; ++i) { | 1583 for (int i = 0; i < depth; ++i) { |
| 1567 builder() | 1584 builder() |
| 1568 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 1585 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
| 1569 .StoreAccumulatorInRegister(context_reg); | 1586 .StoreAccumulatorInRegister(context_reg); |
| 1570 } | 1587 } |
| 1571 } | 1588 } |
| 1589 | |
| 1572 builder()->LoadContextSlot(context_reg, variable->index()); | 1590 builder()->LoadContextSlot(context_reg, variable->index()); |
| 1591 BuildHoleCheckForVariableLoad(mode, variable->name()); | |
| 1573 execution_result()->SetResultInAccumulator(); | 1592 execution_result()->SetResultInAccumulator(); |
| 1574 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | |
| 1575 // let variables. | |
| 1576 break; | 1593 break; |
| 1577 } | 1594 } |
| 1578 case VariableLocation::LOOKUP: { | 1595 case VariableLocation::LOOKUP: { |
| 1579 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1596 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
| 1580 execution_result()->SetResultInAccumulator(); | 1597 execution_result()->SetResultInAccumulator(); |
| 1581 break; | 1598 break; |
| 1582 } | 1599 } |
| 1583 } | 1600 } |
| 1584 } | 1601 } |
| 1585 | 1602 |
| 1586 | 1603 |
| 1587 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1604 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
| 1588 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1605 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 1589 AccumulatorResultScope accumulator_result(this); | 1606 AccumulatorResultScope accumulator_result(this); |
| 1590 VisitVariableLoad(variable, slot, typeof_mode); | 1607 VisitVariableLoad(variable, slot, typeof_mode); |
| 1591 } | 1608 } |
| 1592 | 1609 |
| 1593 | 1610 |
| 1594 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( | 1611 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( |
| 1595 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1612 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 1596 RegisterResultScope register_scope(this); | 1613 RegisterResultScope register_scope(this); |
| 1597 VisitVariableLoad(variable, slot, typeof_mode); | 1614 VisitVariableLoad(variable, slot, typeof_mode); |
| 1598 return register_scope.ResultRegister(); | 1615 return register_scope.ResultRegister(); |
| 1599 } | 1616 } |
| 1600 | 1617 |
| 1618 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { | |
| 1619 Register name_reg = register_allocator()->NewRegister(); | |
| 1620 BytecodeLabel end_label; | |
| 1621 // TODO(mythria): This will be replaced by a new bytecode that throws an | |
| 1622 // error if the value is the hole. | |
| 1623 builder() | |
| 1624 ->JumpIfNotHole(&end_label) | |
| 1625 .LoadLiteral(name) | |
| 1626 .StoreAccumulatorInRegister(name_reg) | |
| 1627 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
| 1628 .Bind(&end_label); | |
| 1629 } | |
| 1630 | |
| 1631 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) { | |
| 1632 Register name_reg = register_allocator()->NewRegister(); | |
| 1633 BytecodeLabel end_label; | |
| 1634 // TODO(mythria): This will be replaced by a new bytecode that throws an | |
| 1635 // error if the value is not the hole. | |
| 1636 builder() | |
| 1637 ->JumpIfHole(&end_label) | |
| 1638 .LoadLiteral(name) | |
| 1639 .StoreAccumulatorInRegister(name_reg) | |
| 1640 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
| 1641 .Bind(&end_label); | |
| 1642 } | |
| 1643 | |
| 1644 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) { | |
| 1645 Register name_reg = register_allocator()->NewRegister(); | |
| 1646 BytecodeLabel else_label; | |
| 1647 // TODO(mythria): This will be replaced by a new bytecode that throws an | |
| 1648 // appropriate error depending on the whether the value is a hole or not. | |
| 1649 builder() | |
| 1650 ->JumpIfNotHole(&else_label) | |
| 1651 .LoadLiteral(name) | |
| 1652 .StoreAccumulatorInRegister(name_reg) | |
| 1653 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1) | |
| 1654 .Bind(&else_label) | |
| 1655 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | |
| 1656 } | |
| 1657 | |
| 1658 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, | |
| 1659 Token::Value op) { | |
| 1660 VariableMode mode = variable->mode(); | |
| 1661 DCHECK(mode != CONST_LEGACY); | |
| 1662 if (mode == CONST && op != Token::INIT) { | |
| 1663 // Non-intializing assignments to constant is not allowed. | |
| 1664 BuildThrowReassignConstant(variable->name()); | |
| 1665 } else if (mode == LET && op != Token::INIT) { | |
| 1666 // Perform an initialization check for let declared variables. | |
| 1667 // let x = (x = 20); is not allowed. | |
|
rmcilroy
2016/02/04 15:19:39
/s/let/E.g. let/
mythria
2016/02/04 16:07:59
Done.
| |
| 1668 BuildThrowIfHole(variable->name()); | |
| 1669 } else { | |
| 1670 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT); | |
| 1671 // Perform an initialization check for 'this'. 'this' variable is the | |
| 1672 // only variable able to trigger bind operations outside the TDZ | |
| 1673 // via 'super' calls. | |
| 1674 BuildThrowIfNotHole(variable->name()); | |
| 1675 } | |
| 1676 } | |
| 1601 | 1677 |
| 1602 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1678 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
| 1679 Token::Value op, | |
| 1603 FeedbackVectorSlot slot) { | 1680 FeedbackVectorSlot slot) { |
| 1681 VariableMode mode = variable->mode(); | |
| 1682 RegisterAllocationScope assignment_register_scope(this); | |
| 1683 BytecodeLabel end_label; | |
| 1684 bool hole_check_required = | |
| 1685 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) || | |
| 1686 (mode == CONST && op != Token::INIT) || | |
| 1687 (mode == CONST && op == Token::INIT && variable->is_this()); | |
| 1604 switch (variable->location()) { | 1688 switch (variable->location()) { |
| 1689 case VariableLocation::PARAMETER: | |
| 1605 case VariableLocation::LOCAL: { | 1690 case VariableLocation::LOCAL: { |
| 1606 // TODO(rmcilroy): support const mode initialization. | 1691 Register destination; |
| 1607 Register destination(variable->index()); | 1692 if (VariableLocation::PARAMETER == variable->location()) { |
| 1693 destination = Register(builder()->Parameter(variable->index() + 1)); | |
| 1694 } else { | |
| 1695 destination = Register(variable->index()); | |
| 1696 } | |
| 1697 | |
| 1698 if (hole_check_required) { | |
| 1699 // Load destination to check for hole. | |
| 1700 Register value_temp = register_allocator()->NewRegister(); | |
| 1701 builder() | |
| 1702 ->StoreAccumulatorInRegister(value_temp) | |
| 1703 .LoadAccumulatorWithRegister(destination); | |
| 1704 | |
| 1705 if (mode == CONST_LEGACY && op == Token::INIT) { | |
| 1706 // Perform an intialization check for legacy constants. | |
| 1707 builder() | |
| 1708 ->JumpIfNotHole(&end_label) | |
| 1709 .MoveRegister(value_temp, destination) | |
| 1710 .Bind(&end_label) | |
| 1711 .LoadAccumulatorWithRegister(value_temp); | |
| 1712 // Break here because the value should not be stored unconditionally. | |
| 1713 break; | |
| 1714 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
| 1715 DCHECK(!is_strict(language_mode())); | |
| 1716 // Ensure accumulator is in the correct state. | |
| 1717 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 1718 // Break here, non-initializing assignments to legacy constants are | |
| 1719 // ignored. | |
| 1720 break; | |
| 1721 } else { | |
| 1722 BuildHoleCheckForVariableAssignment(variable, op); | |
| 1723 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 1724 } | |
| 1725 } | |
| 1726 | |
| 1608 builder()->StoreAccumulatorInRegister(destination); | 1727 builder()->StoreAccumulatorInRegister(destination); |
| 1609 break; | 1728 break; |
| 1610 } | 1729 } |
| 1611 case VariableLocation::PARAMETER: { | |
| 1612 // The parameter indices are shifted by 1 (receiver is variable | |
| 1613 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | |
| 1614 Register destination(builder()->Parameter(variable->index() + 1)); | |
| 1615 builder()->StoreAccumulatorInRegister(destination); | |
| 1616 break; | |
| 1617 } | |
| 1618 case VariableLocation::GLOBAL: | 1730 case VariableLocation::GLOBAL: |
| 1619 case VariableLocation::UNALLOCATED: { | 1731 case VariableLocation::UNALLOCATED: { |
| 1620 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 1732 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
| 1621 language_mode()); | 1733 language_mode()); |
| 1622 break; | 1734 break; |
| 1623 } | 1735 } |
| 1624 case VariableLocation::CONTEXT: { | 1736 case VariableLocation::CONTEXT: { |
| 1625 // TODO(rmcilroy): support const mode initialization. | |
| 1626 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1737 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 1627 ContextScope* context = execution_context()->Previous(depth); | 1738 ContextScope* context = execution_context()->Previous(depth); |
| 1628 Register context_reg; | 1739 Register context_reg; |
| 1740 | |
| 1629 if (context) { | 1741 if (context) { |
| 1630 context_reg = context->reg(); | 1742 context_reg = context->reg(); |
| 1631 } else { | 1743 } else { |
| 1632 Register value_temp = register_allocator()->NewRegister(); | 1744 Register value_temp = register_allocator()->NewRegister(); |
| 1633 context_reg = register_allocator()->NewRegister(); | 1745 context_reg = register_allocator()->NewRegister(); |
| 1634 // Walk the context chain to find the context at the given depth. | 1746 // Walk the context chain to find the context at the given depth. |
| 1635 // TODO(rmcilroy): Perform this work in a bytecode handler once we have | 1747 // TODO(rmcilroy): Perform this work in a bytecode handler once we have |
| 1636 // a generic mechanism for performing jumps in interpreter.cc. | 1748 // a generic mechanism for performing jumps in interpreter.cc. |
| 1637 // TODO(mythria): Also update bytecode graph builder with correct depth | 1749 // TODO(mythria): Also update bytecode graph builder with correct depth |
| 1638 // when this changes. | 1750 // when this changes. |
| 1639 builder() | 1751 builder() |
| 1640 ->StoreAccumulatorInRegister(value_temp) | 1752 ->StoreAccumulatorInRegister(value_temp) |
| 1641 .LoadAccumulatorWithRegister(execution_context()->reg()) | 1753 .LoadAccumulatorWithRegister(execution_context()->reg()) |
| 1642 .StoreAccumulatorInRegister(context_reg); | 1754 .StoreAccumulatorInRegister(context_reg); |
| 1643 for (int i = 0; i < depth; ++i) { | 1755 for (int i = 0; i < depth; ++i) { |
| 1644 builder() | 1756 builder() |
| 1645 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 1757 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
| 1646 .StoreAccumulatorInRegister(context_reg); | 1758 .StoreAccumulatorInRegister(context_reg); |
| 1647 } | 1759 } |
| 1648 builder()->LoadAccumulatorWithRegister(value_temp); | 1760 builder()->LoadAccumulatorWithRegister(value_temp); |
| 1649 } | 1761 } |
| 1762 | |
| 1763 if (hole_check_required) { | |
| 1764 // Load destination to check for hole. | |
| 1765 Register value_temp = register_allocator()->NewRegister(); | |
| 1766 builder() | |
| 1767 ->StoreAccumulatorInRegister(value_temp) | |
| 1768 .LoadContextSlot(context_reg, variable->index()); | |
| 1769 | |
| 1770 if (mode == CONST_LEGACY && op == Token::INIT) { | |
| 1771 // Perform an intialization check for legacy constants. | |
| 1772 builder() | |
| 1773 ->JumpIfNotHole(&end_label) | |
| 1774 .LoadAccumulatorWithRegister(value_temp) | |
| 1775 .StoreContextSlot(context_reg, variable->index()) | |
| 1776 .Bind(&end_label); | |
| 1777 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 1778 // Break here because the value should not be stored unconditionally. | |
| 1779 // The above code performs the store conditionally. | |
| 1780 break; | |
| 1781 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
| 1782 DCHECK(!is_strict(language_mode())); | |
| 1783 // Ensure accumulator is in the correct state. | |
| 1784 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 1785 // Break here, non-initializing assignments to legacy constants are | |
| 1786 // ignored. | |
| 1787 break; | |
| 1788 } else { | |
| 1789 BuildHoleCheckForVariableAssignment(variable, op); | |
| 1790 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 1791 } | |
| 1792 } | |
| 1793 | |
| 1650 builder()->StoreContextSlot(context_reg, variable->index()); | 1794 builder()->StoreContextSlot(context_reg, variable->index()); |
| 1651 break; | 1795 break; |
| 1652 } | 1796 } |
| 1653 case VariableLocation::LOOKUP: { | 1797 case VariableLocation::LOOKUP: { |
| 1654 // TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for | 1798 if (mode == CONST_LEGACY && op == Token::INIT) { |
| 1655 // initializations of const declarations. | 1799 register_allocator()->PrepareForConsecutiveAllocations(3); |
| 1656 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 // Non-intializing assignments to legacy constants are ignored. | |
| 1815 DCHECK(!is_strict(language_mode())); | |
| 1816 } else { | |
| 1817 builder()->StoreLookupSlot(variable->name(), language_mode()); | |
| 1818 } | |
| 1657 break; | 1819 break; |
| 1658 } | 1820 } |
| 1659 } | 1821 } |
| 1660 } | 1822 } |
| 1661 | 1823 |
| 1662 | 1824 |
| 1663 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 1825 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 1664 DCHECK(expr->target()->IsValidReferenceExpression()); | 1826 DCHECK(expr->target()->IsValidReferenceExpression()); |
| 1665 Register object, key; | 1827 Register object, key; |
| 1666 Handle<String> name; | 1828 Handle<String> name; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1739 VisitForAccumulatorValue(expr->value()); | 1901 VisitForAccumulatorValue(expr->value()); |
| 1740 } | 1902 } |
| 1741 | 1903 |
| 1742 // Store the value. | 1904 // Store the value. |
| 1743 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 1905 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
| 1744 switch (assign_type) { | 1906 switch (assign_type) { |
| 1745 case VARIABLE: { | 1907 case VARIABLE: { |
| 1746 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. | 1908 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. |
| 1747 // Is the value in the accumulator safe? Yes, but scary. | 1909 // Is the value in the accumulator safe? Yes, but scary. |
| 1748 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1910 Variable* variable = expr->target()->AsVariableProxy()->var(); |
| 1749 VisitVariableAssignment(variable, slot); | 1911 VisitVariableAssignment(variable, expr->op(), slot); |
| 1750 break; | 1912 break; |
| 1751 } | 1913 } |
| 1752 case NAMED_PROPERTY: | 1914 case NAMED_PROPERTY: |
| 1753 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1915 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
| 1754 language_mode()); | 1916 language_mode()); |
| 1755 break; | 1917 break; |
| 1756 case KEYED_PROPERTY: | 1918 case KEYED_PROPERTY: |
| 1757 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 1919 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 1758 language_mode()); | 1920 language_mode()); |
| 1759 break; | 1921 break; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2163 } | 2325 } |
| 2164 | 2326 |
| 2165 // Perform +1/-1 operation. | 2327 // Perform +1/-1 operation. |
| 2166 builder()->CountOperation(expr->binary_op(), language_mode_strength()); | 2328 builder()->CountOperation(expr->binary_op(), language_mode_strength()); |
| 2167 | 2329 |
| 2168 // Store the value. | 2330 // Store the value. |
| 2169 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 2331 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
| 2170 switch (assign_type) { | 2332 switch (assign_type) { |
| 2171 case VARIABLE: { | 2333 case VARIABLE: { |
| 2172 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2334 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| 2173 VisitVariableAssignment(variable, feedback_slot); | 2335 VisitVariableAssignment(variable, expr->op(), feedback_slot); |
| 2174 break; | 2336 break; |
| 2175 } | 2337 } |
| 2176 case NAMED_PROPERTY: { | 2338 case NAMED_PROPERTY: { |
| 2177 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), | 2339 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), |
| 2178 language_mode()); | 2340 language_mode()); |
| 2179 break; | 2341 break; |
| 2180 } | 2342 } |
| 2181 case KEYED_PROPERTY: { | 2343 case KEYED_PROPERTY: { |
| 2182 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), | 2344 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), |
| 2183 language_mode()); | 2345 language_mode()); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2440 | 2602 |
| 2441 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); | 2603 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); |
| 2442 | 2604 |
| 2443 // Allocate and initialize a new arguments object and assign to the | 2605 // Allocate and initialize a new arguments object and assign to the |
| 2444 // {arguments} variable. | 2606 // {arguments} variable. |
| 2445 CreateArgumentsType type = | 2607 CreateArgumentsType type = |
| 2446 is_strict(language_mode()) || !info()->has_simple_parameters() | 2608 is_strict(language_mode()) || !info()->has_simple_parameters() |
| 2447 ? CreateArgumentsType::kUnmappedArguments | 2609 ? CreateArgumentsType::kUnmappedArguments |
| 2448 : CreateArgumentsType::kMappedArguments; | 2610 : CreateArgumentsType::kMappedArguments; |
| 2449 builder()->CreateArguments(type); | 2611 builder()->CreateArguments(type); |
| 2450 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 2612 VisitVariableAssignment(variable, Token::ASSIGN, |
| 2613 FeedbackVectorSlot::Invalid()); | |
| 2451 } | 2614 } |
| 2452 | 2615 |
| 2453 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest, int index) { | 2616 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest, int index) { |
| 2454 if (rest == nullptr) return; | 2617 if (rest == nullptr) return; |
| 2455 | 2618 |
| 2456 // Allocate and initialize a new arguments object and assign to the {rest} | 2619 // Allocate and initialize a new arguments object and assign to the {rest} |
| 2457 // variable. | 2620 // variable. |
| 2458 builder()->CreateRestArguments(index); | 2621 builder()->CreateRestArguments(index); |
| 2459 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); | 2622 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
| 2460 VisitVariableAssignment(rest, FeedbackVectorSlot::Invalid()); | 2623 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid()); |
| 2461 } | 2624 } |
| 2462 | 2625 |
| 2463 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { | 2626 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
| 2464 if (variable == nullptr) return; | 2627 if (variable == nullptr) return; |
| 2465 | 2628 |
| 2466 // TODO(rmcilroy): Remove once we have tests which exercise this code path. | 2629 // TODO(rmcilroy): Remove once we have tests which exercise this code path. |
| 2467 UNIMPLEMENTED(); | 2630 UNIMPLEMENTED(); |
| 2468 | 2631 |
| 2469 // Store the closure we were called with in the given variable. | 2632 // Store the closure we were called with in the given variable. |
| 2470 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2633 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 2471 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 2634 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 2472 } | 2635 } |
| 2473 | 2636 |
| 2474 | 2637 |
| 2475 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { | 2638 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
| 2476 if (variable == nullptr) return; | 2639 if (variable == nullptr) return; |
| 2477 | 2640 |
| 2478 // Store the new target we were called with in the given variable. | 2641 // Store the new target we were called with in the given variable. |
| 2479 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 2642 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
| 2480 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 2643 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 2481 } | 2644 } |
| 2482 | 2645 |
| 2483 | 2646 |
| 2484 void BytecodeGenerator::VisitFunctionClosureForContext() { | 2647 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 2485 AccumulatorResultScope accumulator_execution_result(this); | 2648 AccumulatorResultScope accumulator_execution_result(this); |
| 2486 Scope* closure_scope = execution_context()->scope()->ClosureScope(); | 2649 Scope* closure_scope = execution_context()->scope()->ClosureScope(); |
| 2487 if (closure_scope->is_script_scope() || | 2650 if (closure_scope->is_script_scope() || |
| 2488 closure_scope->is_module_scope()) { | 2651 closure_scope->is_module_scope()) { |
| 2489 // Contexts nested in the native context have a canonical empty function as | 2652 // Contexts nested in the native context have a canonical empty function as |
| 2490 // their closure, not the anonymous closure containing the global code. | 2653 // their closure, not the anonymous closure containing the global code. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2548 } | 2711 } |
| 2549 | 2712 |
| 2550 | 2713 |
| 2551 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2714 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2552 return info()->feedback_vector()->GetIndex(slot); | 2715 return info()->feedback_vector()->GetIndex(slot); |
| 2553 } | 2716 } |
| 2554 | 2717 |
| 2555 } // namespace interpreter | 2718 } // namespace interpreter |
| 2556 } // namespace internal | 2719 } // namespace internal |
| 2557 } // namespace v8 | 2720 } // namespace v8 |
| OLD | NEW |