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/control-flow-builders.h" | 9 #include "src/interpreter/control-flow-builders.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
(...skipping 1597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 // the semantics of the underlying call type. | 1608 // the semantics of the underlying call type. |
1609 Register callee = execution_result()->NewRegister(); | 1609 Register callee = execution_result()->NewRegister(); |
1610 | 1610 |
1611 // The receiver and arguments need to be allocated consecutively for | 1611 // The receiver and arguments need to be allocated consecutively for |
1612 // Call(). Future optimizations could avoid this there are no | 1612 // Call(). Future optimizations could avoid this there are no |
1613 // arguments or the receiver and arguments are already consecutive. | 1613 // arguments or the receiver and arguments are already consecutive. |
1614 ZoneList<Expression*>* args = expr->arguments(); | 1614 ZoneList<Expression*>* args = expr->arguments(); |
1615 execution_result()->PrepareForConsecutiveAllocations(args->length() + 1); | 1615 execution_result()->PrepareForConsecutiveAllocations(args->length() + 1); |
1616 Register receiver = execution_result()->NextConsecutiveRegister(); | 1616 Register receiver = execution_result()->NextConsecutiveRegister(); |
1617 | 1617 |
| 1618 bool possibly_eval = false; |
1618 switch (call_type) { | 1619 switch (call_type) { |
1619 case Call::NAMED_PROPERTY_CALL: | 1620 case Call::NAMED_PROPERTY_CALL: |
1620 case Call::KEYED_PROPERTY_CALL: { | 1621 case Call::KEYED_PROPERTY_CALL: { |
1621 Property* property = callee_expr->AsProperty(); | 1622 Property* property = callee_expr->AsProperty(); |
1622 VisitForAccumulatorValue(property->obj()); | 1623 VisitForAccumulatorValue(property->obj()); |
1623 builder()->StoreAccumulatorInRegister(receiver); | 1624 builder()->StoreAccumulatorInRegister(receiver); |
1624 VisitPropertyLoadForAccumulator(receiver, property); | 1625 VisitPropertyLoadForAccumulator(receiver, property); |
1625 builder()->StoreAccumulatorInRegister(callee); | 1626 builder()->StoreAccumulatorInRegister(callee); |
1626 break; | 1627 break; |
1627 } | 1628 } |
1628 case Call::GLOBAL_CALL: { | 1629 case Call::GLOBAL_CALL: { |
1629 // Receiver is undefined for global calls. | 1630 // Receiver is undefined for global calls. |
1630 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1631 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
1631 // Load callee as a global variable. | 1632 // Load callee as a global variable. |
1632 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 1633 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
1633 VisitVariableLoadForAccumulatorValue(proxy->var(), | 1634 VisitVariableLoadForAccumulatorValue(proxy->var(), |
1634 proxy->VariableFeedbackSlot()); | 1635 proxy->VariableFeedbackSlot()); |
1635 builder()->StoreAccumulatorInRegister(callee); | 1636 builder()->StoreAccumulatorInRegister(callee); |
1636 break; | 1637 break; |
1637 } | 1638 } |
| 1639 case Call::POSSIBLY_EVAL_CALL: { |
| 1640 possibly_eval = true; |
| 1641 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
| 1642 TemporaryRegisterScope temporary_register_scope(builder()); |
| 1643 temporary_register_scope.PrepareForConsecutiveAllocations(2); |
| 1644 Register context = temporary_register_scope.NextConsecutiveRegister(); |
| 1645 Register name = temporary_register_scope.NextConsecutiveRegister(); |
| 1646 |
| 1647 Variable* variable = callee_expr->AsVariableProxy()->var(); |
| 1648 builder() |
| 1649 ->MoveRegister(Register::function_context(), context) |
| 1650 .LoadLiteral(variable->name()) |
| 1651 .StoreAccumulatorInRegister(name); |
| 1652 |
| 1653 // Call LoadLookupSlot to get the callee and receiver. Reuse the context |
| 1654 // and name arguments as the return registers (since these are |
| 1655 // consecutive), and them move into callee and receiver registers. |
| 1656 builder() |
| 1657 ->CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, context) |
| 1658 .MoveRegister(context, callee) |
| 1659 .MoveRegister(name, receiver); |
| 1660 break; |
| 1661 } |
| 1662 // Fall through. |
| 1663 } |
1638 case Call::OTHER_CALL: { | 1664 case Call::OTHER_CALL: { |
1639 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1665 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
1640 VisitForAccumulatorValue(callee_expr); | 1666 VisitForAccumulatorValue(callee_expr); |
1641 builder()->StoreAccumulatorInRegister(callee); | 1667 builder()->StoreAccumulatorInRegister(callee); |
1642 break; | 1668 break; |
1643 } | 1669 } |
1644 case Call::NAMED_SUPER_PROPERTY_CALL: | 1670 case Call::NAMED_SUPER_PROPERTY_CALL: |
1645 case Call::KEYED_SUPER_PROPERTY_CALL: | 1671 case Call::KEYED_SUPER_PROPERTY_CALL: |
1646 case Call::LOOKUP_SLOT_CALL: | 1672 case Call::LOOKUP_SLOT_CALL: |
1647 case Call::SUPER_CALL: | 1673 case Call::SUPER_CALL: |
1648 case Call::POSSIBLY_EVAL_CALL: | |
1649 UNIMPLEMENTED(); | 1674 UNIMPLEMENTED(); |
1650 } | 1675 } |
1651 | 1676 |
1652 // Evaluate all arguments to the function call and store in sequential | 1677 // Evaluate all arguments to the function call and store in sequential |
1653 // registers. | 1678 // registers. |
1654 Register arg = VisitArguments(args); | 1679 Register arg = VisitArguments(args); |
1655 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); | 1680 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); |
1656 | 1681 |
1657 // TODO(rmcilroy): Deal with possible direct eval here? | 1682 // Resolve callee for a potential direct eval call. This block will mutate the |
| 1683 // callee value. |
| 1684 if (possibly_eval && args->length() > 0) { |
| 1685 TemporaryRegisterScope temporary_register_scope(builder()); |
| 1686 temporary_register_scope.PrepareForConsecutiveAllocations(5); |
| 1687 Register callee_for_eval = |
| 1688 temporary_register_scope.NextConsecutiveRegister(); |
| 1689 Register source = temporary_register_scope.NextConsecutiveRegister(); |
| 1690 Register function = temporary_register_scope.NextConsecutiveRegister(); |
| 1691 Register language = temporary_register_scope.NextConsecutiveRegister(); |
| 1692 Register position = temporary_register_scope.NextConsecutiveRegister(); |
| 1693 |
| 1694 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source |
| 1695 // strings and function closure, and loading language and |
| 1696 // position. |
| 1697 builder() |
| 1698 ->MoveRegister(callee, callee_for_eval) |
| 1699 .MoveRegister(arg, source) |
| 1700 .MoveRegister(Register::function_closure(), function) |
| 1701 .LoadLiteral(Smi::FromInt(language_mode())) |
| 1702 .StoreAccumulatorInRegister(language) |
| 1703 .LoadLiteral( |
| 1704 Smi::FromInt(execution_context()->scope()->start_position())) |
| 1705 .StoreAccumulatorInRegister(position); |
| 1706 |
| 1707 // Call ResolvePossiblyDirectEval and modify the callee. |
| 1708 builder() |
| 1709 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5) |
| 1710 .StoreAccumulatorInRegister(callee); |
| 1711 } |
| 1712 |
1658 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 1713 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
1659 builder()->Call(callee, receiver, args->length(), | 1714 builder()->Call(callee, receiver, args->length(), |
1660 feedback_index(expr->CallFeedbackICSlot())); | 1715 feedback_index(expr->CallFeedbackICSlot())); |
1661 execution_result()->SetResultInAccumulator(); | 1716 execution_result()->SetResultInAccumulator(); |
1662 } | 1717 } |
1663 | 1718 |
1664 | 1719 |
1665 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 1720 void BytecodeGenerator::VisitCallNew(CallNew* expr) { |
1666 Register constructor = execution_result()->NewRegister(); | 1721 Register constructor = execution_result()->NewRegister(); |
1667 VisitForAccumulatorValue(expr->expression()); | 1722 VisitForAccumulatorValue(expr->expression()); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2045 Register::function_closure(), 1); | 2100 Register::function_closure(), 1); |
2046 } | 2101 } |
2047 execution_result()->SetResultInAccumulator(); | 2102 execution_result()->SetResultInAccumulator(); |
2048 } | 2103 } |
2049 | 2104 |
2050 | 2105 |
2051 void BytecodeGenerator::VisitBuildLocalActivationContext() { | 2106 void BytecodeGenerator::VisitBuildLocalActivationContext() { |
2052 Scope* scope = this->scope(); | 2107 Scope* scope = this->scope(); |
2053 | 2108 |
2054 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 2109 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
2055 UNIMPLEMENTED(); | 2110 Variable* variable = scope->receiver(); |
| 2111 Register receiver(builder()->Parameter(0)); |
| 2112 // Context variable (at bottom of the context chain). |
| 2113 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 2114 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( |
| 2115 execution_context()->reg(), variable->index()); |
2056 } | 2116 } |
2057 | 2117 |
2058 // Copy parameters into context if necessary. | 2118 // Copy parameters into context if necessary. |
2059 int num_parameters = scope->num_parameters(); | 2119 int num_parameters = scope->num_parameters(); |
2060 for (int i = 0; i < num_parameters; i++) { | 2120 for (int i = 0; i < num_parameters; i++) { |
2061 Variable* variable = scope->parameter(i); | 2121 Variable* variable = scope->parameter(i); |
2062 if (!variable->IsContextSlot()) continue; | 2122 if (!variable->IsContextSlot()) continue; |
2063 | 2123 |
2064 // The parameter indices are shifted by 1 (receiver is variable | 2124 // The parameter indices are shifted by 1 (receiver is variable |
2065 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 2125 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2225 } | 2285 } |
2226 | 2286 |
2227 | 2287 |
2228 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2288 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2229 return info()->feedback_vector()->GetIndex(slot); | 2289 return info()->feedback_vector()->GetIndex(slot); |
2230 } | 2290 } |
2231 | 2291 |
2232 } // namespace interpreter | 2292 } // namespace interpreter |
2233 } // namespace internal | 2293 } // namespace internal |
2234 } // namespace v8 | 2294 } // namespace v8 |
OLD | NEW |