Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
| 9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
| 10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 711 decl->fun(), info()->script(), info()); | 711 decl->fun(), info()->script(), info()); |
| 712 // Check for stack-overflow exception. | 712 // Check for stack-overflow exception. |
| 713 if (function.is_null()) return SetStackOverflow(); | 713 if (function.is_null()) return SetStackOverflow(); |
| 714 globals()->push_back(variable->name()); | 714 globals()->push_back(variable->name()); |
| 715 globals()->push_back(function); | 715 globals()->push_back(function); |
| 716 break; | 716 break; |
| 717 } | 717 } |
| 718 case VariableLocation::PARAMETER: | 718 case VariableLocation::PARAMETER: |
| 719 case VariableLocation::LOCAL: { | 719 case VariableLocation::LOCAL: { |
| 720 VisitForAccumulatorValue(decl->fun()); | 720 VisitForAccumulatorValue(decl->fun()); |
| 721 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); | 721 DCHECK(variable->mode() == LET || variable->mode() == VAR || |
| 722 variable->mode() == CONST); | |
| 723 VisitVariableAssignment(variable, Token::INIT, | |
| 724 FeedbackVectorSlot::Invalid()); | |
| 722 break; | 725 break; |
| 723 } | 726 } |
| 724 case VariableLocation::CONTEXT: { | 727 case VariableLocation::CONTEXT: { |
| 725 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 728 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 726 VisitForAccumulatorValue(decl->fun()); | 729 VisitForAccumulatorValue(decl->fun()); |
| 727 builder()->StoreContextSlot(execution_context()->reg(), | 730 builder()->StoreContextSlot(execution_context()->reg(), |
| 728 variable->index()); | 731 variable->index()); |
| 729 break; | 732 break; |
| 730 } | 733 } |
| 731 case VariableLocation::LOOKUP: { | 734 case VariableLocation::LOOKUP: { |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |