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

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: Refactored VisitVariableAssignment. 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 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 FeedbackVectorSlot slot) { 996 FeedbackVectorSlot slot) {
994 DCHECK(expr->IsValidReferenceExpression()); 997 DCHECK(expr->IsValidReferenceExpression());
995 998
996 // Evaluate assignment starting with the value to be stored in the 999 // Evaluate assignment starting with the value to be stored in the
997 // accumulator. 1000 // accumulator.
998 Property* property = expr->AsProperty(); 1001 Property* property = expr->AsProperty();
999 LhsKind assign_type = Property::GetAssignType(property); 1002 LhsKind assign_type = Property::GetAssignType(property);
1000 switch (assign_type) { 1003 switch (assign_type) {
1001 case VARIABLE: { 1004 case VARIABLE: {
1002 Variable* variable = expr->AsVariableProxy()->var(); 1005 Variable* variable = expr->AsVariableProxy()->var();
1003 VisitVariableAssignment(variable, slot); 1006 VisitVariableAssignment(variable, Token::ASSIGN, slot);
1004 break; 1007 break;
1005 } 1008 }
1006 case NAMED_PROPERTY: { 1009 case NAMED_PROPERTY: {
1007 RegisterAllocationScope register_scope(this); 1010 RegisterAllocationScope register_scope(this);
1008 Register value = register_allocator()->NewRegister(); 1011 Register value = register_allocator()->NewRegister();
1009 builder()->StoreAccumulatorInRegister(value); 1012 builder()->StoreAccumulatorInRegister(value);
1010 Register object = VisitForRegisterValue(property->obj()); 1013 Register object = VisitForRegisterValue(property->obj());
1011 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); 1014 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1012 builder()->LoadAccumulatorWithRegister(value); 1015 builder()->LoadAccumulatorWithRegister(value);
1013 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1016 builder()->StoreNamedProperty(object, name, feedback_index(slot),
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1498 builder()->LoadAccumulatorWithRegister(literal); 1501 builder()->LoadAccumulatorWithRegister(literal);
1499 } 1502 }
1500 execution_result()->SetResultInAccumulator(); 1503 execution_result()->SetResultInAccumulator();
1501 } 1504 }
1502 1505
1503 1506
1504 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 1507 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
1505 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1508 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1506 } 1509 }
1507 1510
1511 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1512 Handle<String> name) {
1513 if (mode == CONST_LEGACY) {
1514 BytecodeLabel end_label;
1515 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label);
1516 } else if (mode == LET || mode == CONST) {
1517 BuildThrowIfHole(name);
1518 }
1519 }
1508 1520
1509 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1521 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1510 FeedbackVectorSlot slot, 1522 FeedbackVectorSlot slot,
1511 TypeofMode typeof_mode) { 1523 TypeofMode typeof_mode) {
1524 VariableMode mode = variable->mode();
1512 switch (variable->location()) { 1525 switch (variable->location()) {
1513 case VariableLocation::LOCAL: { 1526 case VariableLocation::LOCAL: {
1514 Register source(Register(variable->index())); 1527 Register source(Register(variable->index()));
1515 builder()->LoadAccumulatorWithRegister(source); 1528 builder()->LoadAccumulatorWithRegister(source);
1529 BuildHoleCheckForVariableLoad(mode, variable->name());
1516 execution_result()->SetResultInAccumulator(); 1530 execution_result()->SetResultInAccumulator();
1517 break; 1531 break;
1518 } 1532 }
1519 case VariableLocation::PARAMETER: { 1533 case VariableLocation::PARAMETER: {
1520 // The parameter indices are shifted by 1 (receiver is variable 1534 // The parameter indices are shifted by 1 (receiver is variable
1521 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1535 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1522 Register source = builder()->Parameter(variable->index() + 1); 1536 Register source = builder()->Parameter(variable->index() + 1);
1523 builder()->LoadAccumulatorWithRegister(source); 1537 builder()->LoadAccumulatorWithRegister(source);
1538 BuildHoleCheckForVariableLoad(mode, variable->name());
1524 execution_result()->SetResultInAccumulator(); 1539 execution_result()->SetResultInAccumulator();
1525 break; 1540 break;
1526 } 1541 }
1527 case VariableLocation::GLOBAL: 1542 case VariableLocation::GLOBAL:
1528 case VariableLocation::UNALLOCATED: { 1543 case VariableLocation::UNALLOCATED: {
1529 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1544 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1530 language_mode(), typeof_mode); 1545 language_mode(), typeof_mode);
1531 execution_result()->SetResultInAccumulator(); 1546 execution_result()->SetResultInAccumulator();
1532 break; 1547 break;
1533 } 1548 }
(...skipping 12 matching lines...) Expand all
1546 // when this changes. 1561 // when this changes.
1547 builder() 1562 builder()
1548 ->LoadAccumulatorWithRegister(execution_context()->reg()) 1563 ->LoadAccumulatorWithRegister(execution_context()->reg())
1549 .StoreAccumulatorInRegister(context_reg); 1564 .StoreAccumulatorInRegister(context_reg);
1550 for (int i = 0; i < depth; ++i) { 1565 for (int i = 0; i < depth; ++i) {
1551 builder() 1566 builder()
1552 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1567 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1553 .StoreAccumulatorInRegister(context_reg); 1568 .StoreAccumulatorInRegister(context_reg);
1554 } 1569 }
1555 } 1570 }
1571
1556 builder()->LoadContextSlot(context_reg, variable->index()); 1572 builder()->LoadContextSlot(context_reg, variable->index());
1573 BuildHoleCheckForVariableLoad(mode, variable->name());
1557 execution_result()->SetResultInAccumulator(); 1574 execution_result()->SetResultInAccumulator();
1558 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
1559 // let variables.
1560 break; 1575 break;
1561 } 1576 }
1562 case VariableLocation::LOOKUP: { 1577 case VariableLocation::LOOKUP: {
1563 builder()->LoadLookupSlot(variable->name(), typeof_mode); 1578 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1564 execution_result()->SetResultInAccumulator(); 1579 execution_result()->SetResultInAccumulator();
1565 break; 1580 break;
1566 } 1581 }
1567 } 1582 }
1568 } 1583 }
1569 1584
1570 1585
1571 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( 1586 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1572 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1587 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1573 AccumulatorResultScope accumulator_result(this); 1588 AccumulatorResultScope accumulator_result(this);
1574 VisitVariableLoad(variable, slot, typeof_mode); 1589 VisitVariableLoad(variable, slot, typeof_mode);
1575 } 1590 }
1576 1591
1577 1592
1578 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( 1593 Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1579 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1594 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1580 RegisterResultScope register_scope(this); 1595 RegisterResultScope register_scope(this);
1581 VisitVariableLoad(variable, slot, typeof_mode); 1596 VisitVariableLoad(variable, slot, typeof_mode);
1582 return register_scope.ResultRegister(); 1597 return register_scope.ResultRegister();
1583 } 1598 }
1584 1599
1600 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1601 Register name_reg = register_allocator()->NewRegister();
1602 BytecodeLabel end_label;
rmcilroy 2016/02/03 12:28:26 nit - add a TODO that we will replace this with a
mythria 2016/02/04 10:28:52 Done.
1603 builder()
1604 ->JumpIfNotHole(&end_label)
1605 .LoadLiteral(name)
1606 .StoreAccumulatorInRegister(name_reg)
1607 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1608 .Bind(&end_label);
1609 }
1610
1611 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1612 Register name_reg = register_allocator()->NewRegister();
1613 BytecodeLabel end_label;
rmcilroy 2016/02/03 12:28:26 ditto
mythria 2016/02/04 10:28:52 Done.
1614 builder()
1615 ->JumpIfHole(&end_label)
1616 .LoadLiteral(name)
1617 .StoreAccumulatorInRegister(name_reg)
1618 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1619 .Bind(&end_label);
1620 }
1621
1622 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1623 Register name_reg = register_allocator()->NewRegister();
1624 BytecodeLabel else_label;
rmcilroy 2016/02/03 12:28:26 ditto
mythria 2016/02/04 10:28:52 Done.
1625 builder()
1626 ->JumpIfNotHole(&else_label)
1627 .LoadLiteral(name)
1628 .StoreAccumulatorInRegister(name_reg)
1629 .CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
1630 .Bind(&else_label)
1631 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1632 }
1633
1634 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
1635 Token::Value op) {
1636 VariableMode mode = variable->mode();
rmcilroy 2016/02/03 12:28:26 DCHECK not legacy const mode
mythria 2016/02/04 10:28:52 Done.
1637 if (mode == CONST && op != Token::INIT) {
1638 // Assigning to constant is not allowed.
1639 BuildThrowReassignConstant(variable->name());
1640 } else if (mode == LET && op != Token::INIT) {
1641 BuildThrowIfHole(variable->name());
rmcilroy 2016/02/03 12:28:26 nit - add comment
mythria 2016/02/04 10:28:52 Done.
1642 } else {
1643 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1644 // Perform an initialization check for 'this'. 'this' variable is the
1645 // only variable able to trigger bind operations outside the TDZ
1646 // via 'super' calls.
1647 BuildThrowIfNotHole(variable->name());
1648 }
1649 }
1585 1650
1586 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1651 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1652 Token::Value op,
1587 FeedbackVectorSlot slot) { 1653 FeedbackVectorSlot slot) {
1654 VariableMode mode = variable->mode();
1655 RegisterAllocationScope assignment_register_scope(this);
1656 BytecodeLabel end_label;
1657 bool hole_check_required =
1658 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) ||
1659 (mode == CONST && op != Token::INIT) ||
1660 (mode == CONST && op == Token::INIT && variable->is_this());
1588 switch (variable->location()) { 1661 switch (variable->location()) {
1662 case VariableLocation::PARAMETER:
1589 case VariableLocation::LOCAL: { 1663 case VariableLocation::LOCAL: {
1590 // TODO(rmcilroy): support const mode initialization. 1664 Register destination;
1591 Register destination(variable->index()); 1665 if (VariableLocation::PARAMETER == variable->location()) {
1666 destination = Register(builder()->Parameter(variable->index() + 1));
1667 } else {
1668 destination = Register(variable->index());
1669 }
1670
1671 if (hole_check_required) {
1672 // Load destination to check for hole.
1673 Register value_temp = register_allocator()->NewRegister();
1674 builder()
1675 ->StoreAccumulatorInRegister(value_temp)
1676 .LoadAccumulatorWithRegister(destination);
1677
1678 if (mode == CONST_LEGACY && op == Token::INIT) {
1679 builder()
1680 ->JumpIfNotHole(&end_label)
1681 .MoveRegister(value_temp, destination)
1682 .Bind(&end_label)
1683 .LoadAccumulatorWithRegister(value_temp);
1684 break;
rmcilroy 2016/02/03 12:28:26 nit - add comment on why this break is necessary
mythria 2016/02/04 10:28:52 Done.
1685 } else if (mode == CONST_LEGACY && op != Token::INIT) {
rmcilroy 2016/02/03 12:28:26 Could you drop this entire branch if you just made
mythria 2016/02/04 10:28:53 As discussed offline, I am not moving this because
1686 DCHECK(!is_strict(language_mode()));
1687 builder()->LoadAccumulatorWithRegister(value_temp);
rmcilroy 2016/02/03 12:28:26 nit - add a comment
mythria 2016/02/04 10:28:52 Done.
1688 break;
1689 } else {
1690 BuildHoleCheckForVariableAssignment(variable, op);
1691 builder()->LoadAccumulatorWithRegister(value_temp);
1692 }
1693 }
1694
1592 builder()->StoreAccumulatorInRegister(destination); 1695 builder()->StoreAccumulatorInRegister(destination);
1593 break; 1696 break;
1594 } 1697 }
1595 case VariableLocation::PARAMETER: {
1596 // The parameter indices are shifted by 1 (receiver is variable
1597 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1598 Register destination(builder()->Parameter(variable->index() + 1));
1599 builder()->StoreAccumulatorInRegister(destination);
1600 break;
1601 }
1602 case VariableLocation::GLOBAL: 1698 case VariableLocation::GLOBAL:
1603 case VariableLocation::UNALLOCATED: { 1699 case VariableLocation::UNALLOCATED: {
1604 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1700 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1605 language_mode()); 1701 language_mode());
1606 break; 1702 break;
1607 } 1703 }
1608 case VariableLocation::CONTEXT: { 1704 case VariableLocation::CONTEXT: {
1609 // TODO(rmcilroy): support const mode initialization.
1610 int depth = execution_context()->ContextChainDepth(variable->scope()); 1705 int depth = execution_context()->ContextChainDepth(variable->scope());
1611 ContextScope* context = execution_context()->Previous(depth); 1706 ContextScope* context = execution_context()->Previous(depth);
1612 Register context_reg; 1707 Register context_reg;
1708
1613 if (context) { 1709 if (context) {
1614 context_reg = context->reg(); 1710 context_reg = context->reg();
1615 } else { 1711 } else {
1616 Register value_temp = register_allocator()->NewRegister(); 1712 Register value_temp = register_allocator()->NewRegister();
1617 context_reg = register_allocator()->NewRegister(); 1713 context_reg = register_allocator()->NewRegister();
1618 // Walk the context chain to find the context at the given depth. 1714 // Walk the context chain to find the context at the given depth.
1619 // TODO(rmcilroy): Perform this work in a bytecode handler once we have 1715 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1620 // a generic mechanism for performing jumps in interpreter.cc. 1716 // a generic mechanism for performing jumps in interpreter.cc.
1621 // TODO(mythria): Also update bytecode graph builder with correct depth 1717 // TODO(mythria): Also update bytecode graph builder with correct depth
1622 // when this changes. 1718 // when this changes.
1623 builder() 1719 builder()
1624 ->StoreAccumulatorInRegister(value_temp) 1720 ->StoreAccumulatorInRegister(value_temp)
1625 .LoadAccumulatorWithRegister(execution_context()->reg()) 1721 .LoadAccumulatorWithRegister(execution_context()->reg())
1626 .StoreAccumulatorInRegister(context_reg); 1722 .StoreAccumulatorInRegister(context_reg);
1627 for (int i = 0; i < depth; ++i) { 1723 for (int i = 0; i < depth; ++i) {
1628 builder() 1724 builder()
1629 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1725 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1630 .StoreAccumulatorInRegister(context_reg); 1726 .StoreAccumulatorInRegister(context_reg);
1631 } 1727 }
1632 builder()->LoadAccumulatorWithRegister(value_temp); 1728 builder()->LoadAccumulatorWithRegister(value_temp);
1633 } 1729 }
1730
1731 if (hole_check_required) {
1732 // Load destination to check for hole.
1733 Register value_temp = register_allocator()->NewRegister();
1734 builder()
1735 ->StoreAccumulatorInRegister(value_temp)
1736 .LoadContextSlot(context_reg, variable->index());
1737
1738 if (mode == CONST_LEGACY && op == Token::INIT) {
1739 builder()
1740 ->JumpIfNotHole(&end_label)
1741 .LoadAccumulatorWithRegister(value_temp)
1742 .StoreContextSlot(context_reg, variable->index())
1743 .Bind(&end_label);
1744 builder()->LoadAccumulatorWithRegister(value_temp);
1745 break;
rmcilroy 2016/02/03 12:28:26 ditto
mythria 2016/02/04 10:28:52 Done.
1746 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1747 DCHECK(!is_strict(language_mode()));
rmcilroy 2016/02/03 12:28:26 Same comment
mythria 2016/02/04 10:28:52 Same as variable/parameter case earlier.
1748 builder()->LoadAccumulatorWithRegister(value_temp);
1749 break;
1750 } else {
1751 BuildHoleCheckForVariableAssignment(variable, op);
1752 builder()->LoadAccumulatorWithRegister(value_temp);
1753 }
1754 }
1755
1634 builder()->StoreContextSlot(context_reg, variable->index()); 1756 builder()->StoreContextSlot(context_reg, variable->index());
1635 break; 1757 break;
1636 } 1758 }
1637 case VariableLocation::LOOKUP: { 1759 case VariableLocation::LOOKUP: {
1638 // TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for 1760 if (mode == CONST_LEGACY && op == Token::INIT) {
1639 // initializations of const declarations. 1761 register_allocator()->PrepareForConsecutiveAllocations(3);
1640 builder()->StoreLookupSlot(variable->name(), language_mode()); 1762 Register value = register_allocator()->NextConsecutiveRegister();
1763 Register context = register_allocator()->NextConsecutiveRegister();
1764 Register name = register_allocator()->NextConsecutiveRegister();
1765
1766 // InitializeLegacyConstLookupSlot runtime call returns the 'value'
1767 // passed to it. So, accumulator will have its original contents when
1768 // runtime call returns.
1769 builder()
1770 ->StoreAccumulatorInRegister(value)
1771 .MoveRegister(execution_context()->reg(), context)
1772 .LoadLiteral(variable->name())
1773 .StoreAccumulatorInRegister(name)
1774 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3);
1775 } else if (mode == CONST_LEGACY && op != Token::INIT) {
rmcilroy 2016/02/03 12:28:26 ditto
mythria 2016/02/04 10:28:52 Same here.
1776 DCHECK(!is_strict(language_mode()));
1777 } else {
1778 builder()->StoreLookupSlot(variable->name(), language_mode());
1779 }
1641 break; 1780 break;
1642 } 1781 }
1643 } 1782 }
1644 } 1783 }
1645 1784
1646 1785
1647 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 1786 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
1648 DCHECK(expr->target()->IsValidReferenceExpression()); 1787 DCHECK(expr->target()->IsValidReferenceExpression());
1649 Register object, key; 1788 Register object, key;
1650 Handle<String> name; 1789 Handle<String> name;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 VisitForAccumulatorValue(expr->value()); 1862 VisitForAccumulatorValue(expr->value());
1724 } 1863 }
1725 1864
1726 // Store the value. 1865 // Store the value.
1727 FeedbackVectorSlot slot = expr->AssignmentSlot(); 1866 FeedbackVectorSlot slot = expr->AssignmentSlot();
1728 switch (assign_type) { 1867 switch (assign_type) {
1729 case VARIABLE: { 1868 case VARIABLE: {
1730 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. 1869 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
1731 // Is the value in the accumulator safe? Yes, but scary. 1870 // Is the value in the accumulator safe? Yes, but scary.
1732 Variable* variable = expr->target()->AsVariableProxy()->var(); 1871 Variable* variable = expr->target()->AsVariableProxy()->var();
1733 VisitVariableAssignment(variable, slot); 1872 VisitVariableAssignment(variable, expr->op(), slot);
1734 break; 1873 break;
1735 } 1874 }
1736 case NAMED_PROPERTY: 1875 case NAMED_PROPERTY:
1737 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1876 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1738 language_mode()); 1877 language_mode());
1739 break; 1878 break;
1740 case KEYED_PROPERTY: 1879 case KEYED_PROPERTY:
1741 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 1880 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1742 language_mode()); 1881 language_mode());
1743 break; 1882 break;
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 } 2288 }
2150 2289
2151 // Perform +1/-1 operation. 2290 // Perform +1/-1 operation.
2152 builder()->CountOperation(expr->binary_op(), language_mode_strength()); 2291 builder()->CountOperation(expr->binary_op(), language_mode_strength());
2153 2292
2154 // Store the value. 2293 // Store the value.
2155 FeedbackVectorSlot feedback_slot = expr->CountSlot(); 2294 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2156 switch (assign_type) { 2295 switch (assign_type) {
2157 case VARIABLE: { 2296 case VARIABLE: {
2158 Variable* variable = expr->expression()->AsVariableProxy()->var(); 2297 Variable* variable = expr->expression()->AsVariableProxy()->var();
2159 VisitVariableAssignment(variable, feedback_slot); 2298 VisitVariableAssignment(variable, expr->op(), feedback_slot);
2160 break; 2299 break;
2161 } 2300 }
2162 case NAMED_PROPERTY: { 2301 case NAMED_PROPERTY: {
2163 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), 2302 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot),
2164 language_mode()); 2303 language_mode());
2165 break; 2304 break;
2166 } 2305 }
2167 case KEYED_PROPERTY: { 2306 case KEYED_PROPERTY: {
2168 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), 2307 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot),
2169 language_mode()); 2308 language_mode());
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
2413 2552
2414 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); 2553 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
2415 2554
2416 // Allocate and initialize a new arguments object and assign to the 2555 // Allocate and initialize a new arguments object and assign to the
2417 // {arguments} variable. 2556 // {arguments} variable.
2418 CreateArgumentsType type = 2557 CreateArgumentsType type =
2419 is_strict(language_mode()) || !info()->has_simple_parameters() 2558 is_strict(language_mode()) || !info()->has_simple_parameters()
2420 ? CreateArgumentsType::kUnmappedArguments 2559 ? CreateArgumentsType::kUnmappedArguments
2421 : CreateArgumentsType::kMappedArguments; 2560 : CreateArgumentsType::kMappedArguments;
2422 builder()->CreateArguments(type); 2561 builder()->CreateArguments(type);
2423 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2562 VisitVariableAssignment(variable, Token::ASSIGN,
2563 FeedbackVectorSlot::Invalid());
2424 } 2564 }
2425 2565
2426 2566
2427 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { 2567 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
2428 if (variable == nullptr) return; 2568 if (variable == nullptr) return;
2429 2569
2430 // TODO(rmcilroy): Remove once we have tests which exercise this code path. 2570 // TODO(rmcilroy): Remove once we have tests which exercise this code path.
2431 UNIMPLEMENTED(); 2571 UNIMPLEMENTED();
2432 2572
2433 // Store the closure we were called with in the given variable. 2573 // Store the closure we were called with in the given variable.
2434 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2574 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2435 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2575 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2436 } 2576 }
2437 2577
2438 2578
2439 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { 2579 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
2440 if (variable == nullptr) return; 2580 if (variable == nullptr) return;
2441 2581
2442 // Store the new target we were called with in the given variable. 2582 // Store the new target we were called with in the given variable.
2443 builder()->LoadAccumulatorWithRegister(Register::new_target()); 2583 builder()->LoadAccumulatorWithRegister(Register::new_target());
2444 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2584 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
2445 } 2585 }
2446 2586
2447 2587
2448 void BytecodeGenerator::VisitFunctionClosureForContext() { 2588 void BytecodeGenerator::VisitFunctionClosureForContext() {
2449 AccumulatorResultScope accumulator_execution_result(this); 2589 AccumulatorResultScope accumulator_execution_result(this);
2450 Scope* closure_scope = execution_context()->scope()->ClosureScope(); 2590 Scope* closure_scope = execution_context()->scope()->ClosureScope();
2451 if (closure_scope->is_script_scope() || 2591 if (closure_scope->is_script_scope() ||
2452 closure_scope->is_module_scope()) { 2592 closure_scope->is_module_scope()) {
2453 // Contexts nested in the native context have a canonical empty function as 2593 // Contexts nested in the native context have a canonical empty function as
2454 // their closure, not the anonymous closure containing the global code. 2594 // their closure, not the anonymous closure containing the global code.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2506 } 2646 }
2507 2647
2508 2648
2509 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2649 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2510 return info()->feedback_vector()->GetIndex(slot); 2650 return info()->feedback_vector()->GetIndex(slot);
2511 } 2651 }
2512 2652
2513 } // namespace interpreter 2653 } // namespace interpreter
2514 } // namespace internal 2654 } // namespace internal
2515 } // namespace v8 2655 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698