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

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

Issue 1634153002: [Interpreter] Adds support for const/let variables to interpreter. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixed rebase errors. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/bytecode-register-allocator.h" 9 #include "src/interpreter/bytecode-register-allocator.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698