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

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: rebased the patch Created 4 years, 11 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 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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 builder()->LoadAccumulatorWithRegister(literal); 1499 builder()->LoadAccumulatorWithRegister(literal);
1498 } 1500 }
1499 execution_result()->SetResultInAccumulator(); 1501 execution_result()->SetResultInAccumulator();
1500 } 1502 }
1501 1503
1502 1504
1503 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 1505 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
1504 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1506 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1505 } 1507 }
1506 1508
1509 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1510 Handle<String> name) {
1511 if (mode == CONST_LEGACY) {
1512 BytecodeLabel end_label;
1513 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label);
rmcilroy 2016/01/26 14:37:28 Newlines between builder operations (throughout).
mythria 2016/02/01 10:02:18 I added newlines. cl format removes them. Shall I
rmcilroy 2016/02/03 12:28:25 I think we should override this if possible, it is
1514 } else if (mode == LET || mode == CONST) {
1515 BuildThrowIfHole(name);
1516 }
1517 }
1507 1518
1508 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1519 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1509 FeedbackVectorSlot slot, 1520 FeedbackVectorSlot slot,
1510 TypeofMode typeof_mode) { 1521 TypeofMode typeof_mode) {
1522 VariableMode mode = variable->mode();
1511 switch (variable->location()) { 1523 switch (variable->location()) {
1512 case VariableLocation::LOCAL: { 1524 case VariableLocation::LOCAL: {
1513 Register source(Register(variable->index())); 1525 Register source(Register(variable->index()));
1514 builder()->LoadAccumulatorWithRegister(source); 1526 builder()->LoadAccumulatorWithRegister(source);
1527 BuildHoleCheckForVariableLoad(mode, variable->name());
1515 execution_result()->SetResultInAccumulator(); 1528 execution_result()->SetResultInAccumulator();
1516 break; 1529 break;
1517 } 1530 }
1518 case VariableLocation::PARAMETER: { 1531 case VariableLocation::PARAMETER: {
1519 // The parameter indices are shifted by 1 (receiver is variable 1532 // The parameter indices are shifted by 1 (receiver is variable
1520 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1533 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1521 Register source = builder()->Parameter(variable->index() + 1); 1534 Register source = builder()->Parameter(variable->index() + 1);
1522 builder()->LoadAccumulatorWithRegister(source); 1535 builder()->LoadAccumulatorWithRegister(source);
1536 BuildHoleCheckForVariableLoad(mode, variable->name());
1523 execution_result()->SetResultInAccumulator(); 1537 execution_result()->SetResultInAccumulator();
1524 break; 1538 break;
1525 } 1539 }
1526 case VariableLocation::GLOBAL: 1540 case VariableLocation::GLOBAL:
1527 case VariableLocation::UNALLOCATED: { 1541 case VariableLocation::UNALLOCATED: {
1528 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1542 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1529 language_mode(), typeof_mode); 1543 language_mode(), typeof_mode);
1530 execution_result()->SetResultInAccumulator(); 1544 execution_result()->SetResultInAccumulator();
1531 break; 1545 break;
1532 } 1546 }
(...skipping 12 matching lines...) Expand all
1545 // when this changes. 1559 // when this changes.
1546 builder() 1560 builder()
1547 ->LoadAccumulatorWithRegister(execution_context()->reg()) 1561 ->LoadAccumulatorWithRegister(execution_context()->reg())
1548 .StoreAccumulatorInRegister(context_reg); 1562 .StoreAccumulatorInRegister(context_reg);
1549 for (int i = 0; i < depth; ++i) { 1563 for (int i = 0; i < depth; ++i) {
1550 builder() 1564 builder()
1551 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1565 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1552 .StoreAccumulatorInRegister(context_reg); 1566 .StoreAccumulatorInRegister(context_reg);
1553 } 1567 }
1554 } 1568 }
1569
1555 builder()->LoadContextSlot(context_reg, variable->index()); 1570 builder()->LoadContextSlot(context_reg, variable->index());
1571 BuildHoleCheckForVariableLoad(mode, variable->name());
1556 execution_result()->SetResultInAccumulator(); 1572 execution_result()->SetResultInAccumulator();
1557 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
1558 // let variables.
1559 break; 1573 break;
1560 } 1574 }
1561 case VariableLocation::LOOKUP: { 1575 case VariableLocation::LOOKUP: {
1562 builder()->LoadLookupSlot(variable->name(), typeof_mode); 1576 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1563 execution_result()->SetResultInAccumulator(); 1577 execution_result()->SetResultInAccumulator();
1564 break; 1578 break;
1565 } 1579 }
1566 } 1580 }
1567 } 1581 }
1568 1582
1569 1583
1570 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( 1584 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1571 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1585 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1572 AccumulatorResultScope accumulator_result(this); 1586 AccumulatorResultScope accumulator_result(this);
1573 VisitVariableLoad(variable, slot, typeof_mode); 1587 VisitVariableLoad(variable, slot, typeof_mode);
1574 } 1588 }
1575 1589
1576 1590
1577 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( 1591 Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1578 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1592 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1579 RegisterResultScope register_scope(this); 1593 RegisterResultScope register_scope(this);
1580 VisitVariableLoad(variable, slot, typeof_mode); 1594 VisitVariableLoad(variable, slot, typeof_mode);
1581 return register_scope.ResultRegister(); 1595 return register_scope.ResultRegister();
1582 } 1596 }
1583 1597
1598 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1599 Register name_reg = register_allocator()->NewRegister();
1600 BytecodeLabel end_label;
1601 builder()
1602 ->JumpIfNotHole(&end_label)
1603 .LoadLiteral(name)
1604 .StoreAccumulatorInRegister(name_reg)
1605 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1606 .Bind(&end_label);
1607 }
1608
1609 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1610 Register name_reg = register_allocator()->NewRegister();
1611 BytecodeLabel end_label;
1612 builder()
1613 ->JumpIfHole(&end_label)
1614 .LoadLiteral(name)
1615 .StoreAccumulatorInRegister(name_reg)
1616 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1617 .Bind(&end_label);
1618 }
1619
1620 void BytecodeGenerator::BuildThrowReassignConstant(Register destination,
1621 Handle<String> name) {
1622 Register name_reg = register_allocator()->NewRegister();
1623 BytecodeLabel else_label;
1624 builder()
1625 ->LoadLiteral(name)
1626 .StoreAccumulatorInRegister(name_reg)
1627 .LoadAccumulatorWithRegister(destination)
1628 .JumpIfNotHole(&else_label)
1629 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1630 .Bind(&else_label)
1631 .CallRuntime(Runtime::kThrowConstAssignError, name_reg, 1);
1632 }
1633
1634 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
rmcilroy 2016/01/26 14:37:28 Could we merge both BuildThrowReassignConstant (an
mythria 2016/02/01 10:02:18 Done.
1635 Register name_reg = register_allocator()->NewRegister();
1636 BytecodeLabel else_label;
1637 builder()
1638 ->JumpIfNotHole(&else_label)
1639 .LoadLiteral(name)
rmcilroy 2016/01/26 14:37:28 Move LoadLiteral / StoreAccumulatorInRegister(name
mythria 2016/02/01 10:02:18 For throwing const reassign error, we don't need t
1640 .StoreAccumulatorInRegister(name_reg)
1641 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1642 .Bind(&else_label)
1643 .LoadLiteral(name)
1644 .StoreAccumulatorInRegister(name_reg)
1645 .CallRuntime(Runtime::kThrowConstAssignError, name_reg, 1);
1646 }
1584 1647
1585 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1648 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1649 Token::Value op,
1586 FeedbackVectorSlot slot) { 1650 FeedbackVectorSlot slot) {
1651 VariableMode mode = variable->mode();
1652 RegisterAllocationScope assignment_register_scope(this);
1653 BytecodeLabel end_label;
1654 bool hole_check_required =
1655 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) ||
1656 (mode == CONST && op != Token::INIT) ||
1657 (mode == CONST && op == Token::INIT && variable->is_this());
1587 switch (variable->location()) { 1658 switch (variable->location()) {
1659 case VariableLocation::PARAMETER:
1588 case VariableLocation::LOCAL: { 1660 case VariableLocation::LOCAL: {
1589 // TODO(rmcilroy): support const mode initialization. 1661 Register destination;
1590 Register destination(variable->index()); 1662 if (VariableLocation::PARAMETER == variable->location()) {
1591 builder()->StoreAccumulatorInRegister(destination); 1663 destination = Register(builder()->Parameter(variable->index() + 1));
1592 break; 1664 } else {
1593 } 1665 destination = Register(variable->index());
1594 case VariableLocation::PARAMETER: { 1666 }
1595 // The parameter indices are shifted by 1 (receiver is variable 1667
1596 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1668 if (!hole_check_required) {
1597 Register destination(builder()->Parameter(variable->index() + 1)); 1669 builder()->StoreAccumulatorInRegister(destination);
1598 builder()->StoreAccumulatorInRegister(destination); 1670 } else if (mode == CONST && op != Token::INIT) {
rmcilroy 2016/01/26 14:37:28 As discussed, could you merge the code to do the h
mythria 2016/02/01 10:02:18 Done. I did not pull const_legacy && Token::Init t
1671 // Assigning to constant is not allowed. Throw an appropriate
1672 // exception. Accumulator is not restored back.
1673 BuildThrowReassignConstant(destination, variable->name());
1674 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1675 // TODO(mythria): Find a test case for strict mode legacy constants.
rmcilroy 2016/01/26 14:37:28 Legacy const doesn't exist for strict mode, right?
mythria 2016/02/01 10:02:18 Done. Yes, it was a old comment. Retained the DCHE
1676 DCHECK(!is_strict(language_mode()));
1677 } else {
1678 // Store accumulator to a temporary register and load destination to
1679 // perform hole check.
1680 BytecodeLabel end_label;
1681 Register value_temp = register_allocator()->NewRegister();
1682 builder()
1683 ->StoreAccumulatorInRegister(value_temp)
1684 .LoadAccumulatorWithRegister(destination);
1685 if (mode == CONST_LEGACY && op == Token::INIT) {
1686 // If the destination is already initialized silently ignore this
1687 // assignment. Restore the accumulator.
1688 builder()
1689 ->JumpIfNotHole(&end_label)
1690 .MoveRegister(value_temp, destination)
1691 .Bind(&end_label)
1692 .LoadAccumulatorWithRegister(value_temp);
1693 } else if (mode == LET && op != Token::INIT) {
1694 BuildThrowIfHole(variable->name());
1695 // Move does not help here, because accumulator should be restored to
1696 // value_temp as well.
1697 builder()
1698 ->LoadAccumulatorWithRegister(value_temp)
1699 .StoreAccumulatorInRegister(destination);
1700 } else {
1701 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1702 // Perform an initialization check for 'this'. 'this' variable is the
1703 // only variable being able to trigger bind operations outside the TDZ
1704 // via 'super' calls.
1705 BuildThrowIfNotHole(variable->name());
1706 builder()
1707 ->LoadAccumulatorWithRegister(value_temp)
1708 .StoreAccumulatorInRegister(destination);
1709 }
1710 }
1599 break; 1711 break;
1600 } 1712 }
1601 case VariableLocation::GLOBAL: 1713 case VariableLocation::GLOBAL:
1602 case VariableLocation::UNALLOCATED: { 1714 case VariableLocation::UNALLOCATED: {
1603 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1715 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1604 language_mode()); 1716 language_mode());
1605 break; 1717 break;
1606 } 1718 }
1607 case VariableLocation::CONTEXT: { 1719 case VariableLocation::CONTEXT: {
1608 // TODO(rmcilroy): support const mode initialization.
1609 int depth = execution_context()->ContextChainDepth(variable->scope()); 1720 int depth = execution_context()->ContextChainDepth(variable->scope());
1610 ContextScope* context = execution_context()->Previous(depth); 1721 ContextScope* context = execution_context()->Previous(depth);
1611 Register context_reg; 1722 Register context_reg;
1723 Register value_temp;
1724 bool value_in_accumulator = true;
rmcilroy 2016/01/26 14:37:28 Let's not try to be smart with "value_in_accumulat
mythria 2016/02/01 10:02:18 Done.
1725
1612 if (context) { 1726 if (context) {
1613 context_reg = context->reg(); 1727 context_reg = context->reg();
1614 } else { 1728 } else {
1615 Register value_temp = register_allocator()->NewRegister(); 1729 value_temp = register_allocator()->NewRegister();
1616 context_reg = register_allocator()->NewRegister(); 1730 context_reg = register_allocator()->NewRegister();
1617 // Walk the context chain to find the context at the given depth. 1731 // Walk the context chain to find the context at the given depth.
1618 // TODO(rmcilroy): Perform this work in a bytecode handler once we have 1732 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1619 // a generic mechanism for performing jumps in interpreter.cc. 1733 // a generic mechanism for performing jumps in interpreter.cc.
1620 // TODO(mythria): Also update bytecode graph builder with correct depth 1734 // TODO(mythria): Also update bytecode graph builder with correct depth
1621 // when this changes. 1735 // when this changes.
1622 builder() 1736 builder()
1623 ->StoreAccumulatorInRegister(value_temp) 1737 ->StoreAccumulatorInRegister(value_temp)
1624 .LoadAccumulatorWithRegister(execution_context()->reg()) 1738 .LoadAccumulatorWithRegister(execution_context()->reg())
1625 .StoreAccumulatorInRegister(context_reg); 1739 .StoreAccumulatorInRegister(context_reg);
1626 for (int i = 0; i < depth; ++i) { 1740 for (int i = 0; i < depth; ++i) {
1627 builder() 1741 builder()
1628 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1742 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1629 .StoreAccumulatorInRegister(context_reg); 1743 .StoreAccumulatorInRegister(context_reg);
1630 } 1744 }
1631 builder()->LoadAccumulatorWithRegister(value_temp); 1745 value_in_accumulator = false;
1632 } 1746 }
1633 builder()->StoreContextSlot(context_reg, variable->index()); 1747
1748 if (!hole_check_required) {
1749 if (!value_in_accumulator) {
1750 builder()->LoadAccumulatorWithRegister(value_temp);
1751 }
1752 builder()->StoreContextSlot(context_reg, variable->index());
1753 } else if (mode == CONST && op != Token::INIT) {
1754 // Assigning to constant is not allowed. Throw an appropriate
1755 // exception. Accumulator is not restored back.
1756 builder()->LoadContextSlot(context_reg, variable->index());
1757 BuildThrowReassignConstant(variable->name());
1758 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1759 // TODO(mythria): Find a test case for strict mode legacy constants.
rmcilroy 2016/01/26 14:37:28 ditto.
mythria 2016/02/01 10:02:18 Done.
1760 DCHECK(!is_strict(language_mode()));
1761 // Accumulator has to be restored back.
1762 if (!value_in_accumulator) {
1763 builder()->LoadAccumulatorWithRegister(value_temp);
1764 }
1765 } else {
1766 // Store accumulator to a temporary register and load destination to
1767 // perform hole check.
1768 if (value_in_accumulator) {
1769 value_temp = register_allocator()->NewRegister();
1770 builder()->StoreAccumulatorInRegister(value_temp);
1771 }
1772 builder()->LoadContextSlot(context_reg, variable->index());
1773 BytecodeLabel end_label;
1774 if (mode == CONST_LEGACY && op == Token::INIT) {
1775 // If the destination is already initialized silently ignore this
1776 // assignment and restore back the accumulator.
rmcilroy 2016/01/26 14:37:28 Not sure what "restore back the accumulator" means
mythria 2016/02/01 10:02:18 Done.
1777 builder()
1778 ->JumpIfNotHole(&end_label)
1779 .LoadAccumulatorWithRegister(value_temp)
1780 .StoreContextSlot(context_reg, variable->index())
1781 .Bind(&end_label)
1782 .LoadAccumulatorWithRegister(value_temp);
1783 } else if (mode == LET && op != Token::INIT) {
1784 BuildThrowIfHole(variable->name());
1785 builder()
1786 ->LoadAccumulatorWithRegister(value_temp)
1787 .StoreContextSlot(context_reg, variable->index());
1788 } else {
1789 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1790 // Perform an initialization check for 'this'. 'this' variable is the
1791 // only variable being able to trigger bind operations outside the TDZ
rmcilroy 2016/01/26 14:37:28 /s/variable being able/variable able
mythria 2016/02/01 10:02:18 Done.
1792 // via 'super' calls.
1793 BuildThrowIfNotHole(variable->name());
1794 builder()
1795 ->LoadAccumulatorWithRegister(value_temp)
1796 .StoreContextSlot(context_reg, variable->index());
1797 }
1798 }
1634 break; 1799 break;
1635 } 1800 }
1636 case VariableLocation::LOOKUP: { 1801 case VariableLocation::LOOKUP: {
1637 // TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for 1802 if (mode == CONST_LEGACY && op == Token::INIT) {
1638 // initializations of const declarations. 1803 register_allocator()->PrepareForConsecutiveAllocations(3);
1639 builder()->StoreLookupSlot(variable->name(), language_mode()); 1804 Register value = register_allocator()->NextConsecutiveRegister();
1805 Register context = register_allocator()->NextConsecutiveRegister();
1806 Register name = register_allocator()->NextConsecutiveRegister();
1807
1808 // InitializeLegacyConstLookupSlot runtime call returns the 'value'
1809 // passed to it. So, accumulator will have its original contents when
1810 // runtime call returns.
1811 builder()
1812 ->StoreAccumulatorInRegister(value)
1813 .MoveRegister(execution_context()->reg(), context)
1814 .LoadLiteral(variable->name())
1815 .StoreAccumulatorInRegister(name)
1816 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3);
1817 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1818 // TODO(mythria): Find a test case for strict mode. We should throw in
1819 // strict mode.
1820 DCHECK(!is_strict(language_mode()));
1821 } else {
1822 builder()->StoreLookupSlot(variable->name(), language_mode());
1823 }
1640 break; 1824 break;
1641 } 1825 }
1642 } 1826 }
1643 } 1827 }
1644 1828
1645 1829
1646 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 1830 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
1647 DCHECK(expr->target()->IsValidReferenceExpression()); 1831 DCHECK(expr->target()->IsValidReferenceExpression());
1648 Register object, key; 1832 Register object, key;
1649 Handle<String> name; 1833 Handle<String> name;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 VisitForAccumulatorValue(expr->value()); 1906 VisitForAccumulatorValue(expr->value());
1723 } 1907 }
1724 1908
1725 // Store the value. 1909 // Store the value.
1726 FeedbackVectorSlot slot = expr->AssignmentSlot(); 1910 FeedbackVectorSlot slot = expr->AssignmentSlot();
1727 switch (assign_type) { 1911 switch (assign_type) {
1728 case VARIABLE: { 1912 case VARIABLE: {
1729 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. 1913 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
1730 // Is the value in the accumulator safe? Yes, but scary. 1914 // Is the value in the accumulator safe? Yes, but scary.
1731 Variable* variable = expr->target()->AsVariableProxy()->var(); 1915 Variable* variable = expr->target()->AsVariableProxy()->var();
1732 VisitVariableAssignment(variable, slot); 1916 VisitVariableAssignment(variable, expr->op(), slot);
1733 break; 1917 break;
1734 } 1918 }
1735 case NAMED_PROPERTY: 1919 case NAMED_PROPERTY:
1736 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1920 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1737 language_mode()); 1921 language_mode());
1738 break; 1922 break;
1739 case KEYED_PROPERTY: 1923 case KEYED_PROPERTY:
1740 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 1924 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1741 language_mode()); 1925 language_mode());
1742 break; 1926 break;
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 } 2332 }
2149 2333
2150 // Perform +1/-1 operation. 2334 // Perform +1/-1 operation.
2151 builder()->CountOperation(expr->binary_op(), language_mode_strength()); 2335 builder()->CountOperation(expr->binary_op(), language_mode_strength());
2152 2336
2153 // Store the value. 2337 // Store the value.
2154 FeedbackVectorSlot feedback_slot = expr->CountSlot(); 2338 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2155 switch (assign_type) { 2339 switch (assign_type) {
2156 case VARIABLE: { 2340 case VARIABLE: {
2157 Variable* variable = expr->expression()->AsVariableProxy()->var(); 2341 Variable* variable = expr->expression()->AsVariableProxy()->var();
2158 VisitVariableAssignment(variable, feedback_slot); 2342 VisitVariableAssignment(variable, expr->op(), feedback_slot);
2159 break; 2343 break;
2160 } 2344 }
2161 case NAMED_PROPERTY: { 2345 case NAMED_PROPERTY: {
2162 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), 2346 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot),
2163 language_mode()); 2347 language_mode());
2164 break; 2348 break;
2165 } 2349 }
2166 case KEYED_PROPERTY: { 2350 case KEYED_PROPERTY: {
2167 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), 2351 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot),
2168 language_mode()); 2352 language_mode());
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
2412 2596
2413 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); 2597 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
2414 2598
2415 // Allocate and initialize a new arguments object and assign to the 2599 // Allocate and initialize a new arguments object and assign to the
2416 // {arguments} variable. 2600 // {arguments} variable.
2417 CreateArgumentsType type = 2601 CreateArgumentsType type =
2418 is_strict(language_mode()) || !info()->has_simple_parameters() 2602 is_strict(language_mode()) || !info()->has_simple_parameters()
2419 ? CreateArgumentsType::kUnmappedArguments 2603 ? CreateArgumentsType::kUnmappedArguments
2420 : CreateArgumentsType::kMappedArguments; 2604 : CreateArgumentsType::kMappedArguments;
2421 builder()->CreateArguments(type); 2605 builder()->CreateArguments(type);
2422 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2606 VisitVariableAssignment(variable, Token::ASSIGN,
2607 FeedbackVectorSlot::Invalid());
2423 } 2608 }
2424 2609
2425 2610
2426 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { 2611 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
2427 if (variable == nullptr) return; 2612 if (variable == nullptr) return;
2428 2613
2429 // TODO(rmcilroy): Remove once we have tests which exercise this code path. 2614 // TODO(rmcilroy): Remove once we have tests which exercise this code path.
2430 UNIMPLEMENTED(); 2615 UNIMPLEMENTED();
2431 2616
2432 // Store the closure we were called with in the given variable. 2617 // Store the closure we were called with in the given variable.
2433 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2618 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2434 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2619 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2435 } 2620 }
2436 2621
2437 2622
2438 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { 2623 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
2439 if (variable == nullptr) return; 2624 if (variable == nullptr) return;
2440 2625
2441 // Store the new target we were called with in the given variable. 2626 // Store the new target we were called with in the given variable.
2442 builder()->LoadAccumulatorWithRegister(Register::new_target()); 2627 builder()->LoadAccumulatorWithRegister(Register::new_target());
2443 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2628 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2444 } 2629 }
2445 2630
2446 2631
2447 void BytecodeGenerator::VisitFunctionClosureForContext() { 2632 void BytecodeGenerator::VisitFunctionClosureForContext() {
2448 AccumulatorResultScope accumulator_execution_result(this); 2633 AccumulatorResultScope accumulator_execution_result(this);
2449 Scope* closure_scope = execution_context()->scope()->ClosureScope(); 2634 Scope* closure_scope = execution_context()->scope()->ClosureScope();
2450 if (closure_scope->is_script_scope() || 2635 if (closure_scope->is_script_scope() ||
2451 closure_scope->is_module_scope()) { 2636 closure_scope->is_module_scope()) {
2452 // Contexts nested in the native context have a canonical empty function as 2637 // Contexts nested in the native context have a canonical empty function as
2453 // their closure, not the anonymous closure containing the global code. 2638 // their closure, not the anonymous closure containing the global code.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2505 } 2690 }
2506 2691
2507 2692
2508 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2693 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2509 return info()->feedback_vector()->GetIndex(slot); 2694 return info()->feedback_vector()->GetIndex(slot);
2510 } 2695 }
2511 2696
2512 } // namespace interpreter 2697 } // namespace interpreter
2513 } // namespace internal 2698 } // namespace internal
2514 } // namespace v8 2699 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698