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 LoadLookupSlotCallee/Receiver to get the Callee and Receiver | |
Michael Starzinger
2016/01/08 13:40:47
nit: Comment is outdated, also s/Callee/callee/ an
rmcilroy
2016/01/08 14:34:30
Done.
| |
1654 // Reuse the context and name arguments as the return registers (since | |
1655 // these are consecutive), and them move into callee and reciever | |
1656 // registers. | |
1657 builder() | |
1658 ->CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, context) | |
1659 .MoveRegister(context, callee) | |
1660 .MoveRegister(name, receiver); | |
1661 break; | |
1662 } | |
1663 // Fall through. | |
1664 } | |
1638 case Call::OTHER_CALL: { | 1665 case Call::OTHER_CALL: { |
1639 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1666 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
1640 VisitForAccumulatorValue(callee_expr); | 1667 VisitForAccumulatorValue(callee_expr); |
1641 builder()->StoreAccumulatorInRegister(callee); | 1668 builder()->StoreAccumulatorInRegister(callee); |
1642 break; | 1669 break; |
1643 } | 1670 } |
1644 case Call::NAMED_SUPER_PROPERTY_CALL: | 1671 case Call::NAMED_SUPER_PROPERTY_CALL: |
1645 case Call::KEYED_SUPER_PROPERTY_CALL: | 1672 case Call::KEYED_SUPER_PROPERTY_CALL: |
1646 case Call::LOOKUP_SLOT_CALL: | 1673 case Call::LOOKUP_SLOT_CALL: |
1647 case Call::SUPER_CALL: | 1674 case Call::SUPER_CALL: |
1648 case Call::POSSIBLY_EVAL_CALL: | |
1649 UNIMPLEMENTED(); | 1675 UNIMPLEMENTED(); |
1650 } | 1676 } |
1651 | 1677 |
1652 // Evaluate all arguments to the function call and store in sequential | 1678 // Evaluate all arguments to the function call and store in sequential |
1653 // registers. | 1679 // registers. |
1654 Register arg = VisitArguments(args); | 1680 Register arg = VisitArguments(args); |
1655 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); | 1681 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); |
1656 | 1682 |
1657 // TODO(rmcilroy): Deal with possible direct eval here? | 1683 // Resolve callee and receiver for a potential direct eval call. This block |
1684 // will mutate the callee and receiver values. | |
Michael Starzinger
2016/01/08 13:40:47
nit: This comment is outdated (also in the AstGrap
rmcilroy
2016/01/08 14:34:30
Done (also in AstGraphBuilder).
| |
1685 if (possibly_eval && args->length() > 0) { | |
1686 TemporaryRegisterScope temporary_register_scope(builder()); | |
1687 temporary_register_scope.PrepareForConsecutiveAllocations(5); | |
1688 Register callee_for_eval = | |
1689 temporary_register_scope.NextConsecutiveRegister(); | |
1690 Register source = temporary_register_scope.NextConsecutiveRegister(); | |
1691 Register function = temporary_register_scope.NextConsecutiveRegister(); | |
1692 Register language = temporary_register_scope.NextConsecutiveRegister(); | |
1693 Register position = temporary_register_scope.NextConsecutiveRegister(); | |
1694 | |
1695 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source | |
1696 // strings and function closure, and loading language and | |
1697 // position. | |
1698 builder() | |
1699 ->MoveRegister(callee, callee_for_eval) | |
1700 .MoveRegister(arg, source) | |
1701 .MoveRegister(Register::function_closure(), function) | |
1702 .LoadLiteral(Smi::FromInt(language_mode())) | |
1703 .StoreAccumulatorInRegister(language) | |
1704 .LoadLiteral( | |
1705 Smi::FromInt(execution_context()->scope()->start_position())) | |
1706 .StoreAccumulatorInRegister(position); | |
1707 | |
1708 // Call ResolvePossiblyDirectEval and modify the callee. | |
1709 builder() | |
1710 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5) | |
1711 .StoreAccumulatorInRegister(callee); | |
1712 } | |
1713 | |
1658 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 1714 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
1659 builder()->Call(callee, receiver, args->length(), | 1715 builder()->Call(callee, receiver, args->length(), |
1660 feedback_index(expr->CallFeedbackICSlot())); | 1716 feedback_index(expr->CallFeedbackICSlot())); |
1661 execution_result()->SetResultInAccumulator(); | 1717 execution_result()->SetResultInAccumulator(); |
1662 } | 1718 } |
1663 | 1719 |
1664 | 1720 |
1665 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 1721 void BytecodeGenerator::VisitCallNew(CallNew* expr) { |
1666 Register constructor = execution_result()->NewRegister(); | 1722 Register constructor = execution_result()->NewRegister(); |
1667 VisitForAccumulatorValue(expr->expression()); | 1723 VisitForAccumulatorValue(expr->expression()); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2045 Register::function_closure(), 1); | 2101 Register::function_closure(), 1); |
2046 } | 2102 } |
2047 execution_result()->SetResultInAccumulator(); | 2103 execution_result()->SetResultInAccumulator(); |
2048 } | 2104 } |
2049 | 2105 |
2050 | 2106 |
2051 void BytecodeGenerator::VisitBuildLocalActivationContext() { | 2107 void BytecodeGenerator::VisitBuildLocalActivationContext() { |
2052 Scope* scope = this->scope(); | 2108 Scope* scope = this->scope(); |
2053 | 2109 |
2054 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 2110 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
2055 UNIMPLEMENTED(); | 2111 Variable* variable = scope->receiver(); |
2112 Register receiver(builder()->Parameter(0)); | |
2113 // Context variable (at bottom of the context chain). | |
2114 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | |
2115 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( | |
2116 execution_context()->reg(), variable->index()); | |
2056 } | 2117 } |
2057 | 2118 |
2058 // Copy parameters into context if necessary. | 2119 // Copy parameters into context if necessary. |
2059 int num_parameters = scope->num_parameters(); | 2120 int num_parameters = scope->num_parameters(); |
2060 for (int i = 0; i < num_parameters; i++) { | 2121 for (int i = 0; i < num_parameters; i++) { |
2061 Variable* variable = scope->parameter(i); | 2122 Variable* variable = scope->parameter(i); |
2062 if (!variable->IsContextSlot()) continue; | 2123 if (!variable->IsContextSlot()) continue; |
2063 | 2124 |
2064 // The parameter indices are shifted by 1 (receiver is variable | 2125 // The parameter indices are shifted by 1 (receiver is variable |
2065 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 2126 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2225 } | 2286 } |
2226 | 2287 |
2227 | 2288 |
2228 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2289 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2229 return info()->feedback_vector()->GetIndex(slot); | 2290 return info()->feedback_vector()->GetIndex(slot); |
2230 } | 2291 } |
2231 | 2292 |
2232 } // namespace interpreter | 2293 } // namespace interpreter |
2233 } // namespace internal | 2294 } // namespace internal |
2234 } // namespace v8 | 2295 } // namespace v8 |
OLD | NEW |