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

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: 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
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698