OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
(...skipping 1536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 1547 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
1548 kPointerSize))); | 1548 kPointerSize))); |
1549 __ Mov(jssp, fp); | 1549 __ Mov(jssp, fp); |
1550 __ Pop(fp, lr); | 1550 __ Pop(fp, lr); |
1551 __ DropBySMI(x10, kXRegSize); | 1551 __ DropBySMI(x10, kXRegSize); |
1552 __ Drop(1); | 1552 __ Drop(1); |
1553 } | 1553 } |
1554 | 1554 |
1555 | 1555 |
1556 // static | 1556 // static |
1557 void Builtins::Generate_CallFunction(MacroAssembler* masm) { | 1557 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
| 1558 ConvertReceiverMode mode) { |
1558 // ----------- S t a t e ------------- | 1559 // ----------- S t a t e ------------- |
1559 // -- x0 : the number of arguments (not including the receiver) | 1560 // -- x0 : the number of arguments (not including the receiver) |
1560 // -- x1 : the function to call (checked to be a JSFunction) | 1561 // -- x1 : the function to call (checked to be a JSFunction) |
1561 // ----------------------------------- | 1562 // ----------------------------------- |
1562 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | |
1563 | |
1564 Label convert, convert_global_proxy, convert_to_object, done_convert; | |
1565 __ AssertFunction(x1); | 1563 __ AssertFunction(x1); |
1566 | 1564 |
| 1565 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| 1566 // Check that function is not a "classConstructor". |
| 1567 Label class_constructor; |
1567 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | 1568 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
1568 { | 1569 __ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset)); |
1569 Label non_class_constructor; | 1570 __ TestAndBranchIfAnySet( |
1570 // Check whether the current function is a classConstructor | 1571 w3, (1 << SharedFunctionInfo::kIsDefaultConstructor) | |
1571 __ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset)); | 1572 (1 << SharedFunctionInfo::kIsSubclassConstructor) | |
1572 __ TestAndBranchIfAllClear( | 1573 (1 << SharedFunctionInfo::kIsBaseConstructor), |
1573 w3, (1 << SharedFunctionInfo::kIsDefaultConstructor) | | 1574 &class_constructor); |
1574 (1 << SharedFunctionInfo::kIsSubclassConstructor) | | |
1575 (1 << SharedFunctionInfo::kIsBaseConstructor), | |
1576 &non_class_constructor); | |
1577 // Step: 2, If we call a classConstructor Function throw a TypeError. | |
1578 { | |
1579 FrameScope frame(masm, StackFrame::INTERNAL); | |
1580 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); | |
1581 } | |
1582 __ bind(&non_class_constructor); | |
1583 } | |
1584 | 1575 |
1585 // Enter the context of the function; ToObject has to run in the function | 1576 // Enter the context of the function; ToObject has to run in the function |
1586 // context, and we also need to take the global proxy from the function | 1577 // context, and we also need to take the global proxy from the function |
1587 // context in case of conversion. | 1578 // context in case of conversion. |
1588 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); | 1579 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); |
1589 // We need to convert the receiver for non-native sloppy mode functions. | 1580 // We need to convert the receiver for non-native sloppy mode functions. |
| 1581 Label done_convert; |
1590 __ TestAndBranchIfAnySet(w3, | 1582 __ TestAndBranchIfAnySet(w3, |
1591 (1 << SharedFunctionInfo::kNative) | | 1583 (1 << SharedFunctionInfo::kNative) | |
1592 (1 << SharedFunctionInfo::kStrictModeFunction), | 1584 (1 << SharedFunctionInfo::kStrictModeFunction), |
1593 &done_convert); | 1585 &done_convert); |
1594 { | 1586 { |
1595 __ Peek(x3, Operand(x0, LSL, kXRegSizeLog2)); | |
1596 | |
1597 // ----------- S t a t e ------------- | 1587 // ----------- S t a t e ------------- |
1598 // -- x0 : the number of arguments (not including the receiver) | 1588 // -- x0 : the number of arguments (not including the receiver) |
1599 // -- x1 : the function to call (checked to be a JSFunction) | 1589 // -- x1 : the function to call (checked to be a JSFunction) |
1600 // -- x2 : the shared function info. | 1590 // -- x2 : the shared function info. |
1601 // -- x3 : the receiver | |
1602 // -- cp : the function context. | 1591 // -- cp : the function context. |
1603 // ----------------------------------- | 1592 // ----------------------------------- |
1604 | 1593 |
1605 Label convert_receiver; | 1594 if (mode == ConvertReceiverMode::kNullOrUndefined) { |
1606 __ JumpIfSmi(x3, &convert_to_object); | |
1607 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
1608 __ CompareObjectType(x3, x4, x4, FIRST_JS_RECEIVER_TYPE); | |
1609 __ B(hs, &done_convert); | |
1610 __ JumpIfRoot(x3, Heap::kUndefinedValueRootIndex, &convert_global_proxy); | |
1611 __ JumpIfNotRoot(x3, Heap::kNullValueRootIndex, &convert_to_object); | |
1612 __ Bind(&convert_global_proxy); | |
1613 { | |
1614 // Patch receiver to global proxy. | 1595 // Patch receiver to global proxy. |
1615 __ LoadGlobalProxy(x3); | 1596 __ LoadGlobalProxy(x3); |
| 1597 } else { |
| 1598 Label convert_to_object, convert_receiver; |
| 1599 __ Peek(x3, Operand(x0, LSL, kXRegSizeLog2)); |
| 1600 __ JumpIfSmi(x3, &convert_to_object); |
| 1601 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1602 __ CompareObjectType(x3, x4, x4, FIRST_JS_RECEIVER_TYPE); |
| 1603 __ B(hs, &done_convert); |
| 1604 if (mode != ConvertReceiverMode::kNotNullOrUndefined) { |
| 1605 Label convert_global_proxy; |
| 1606 __ JumpIfRoot(x3, Heap::kUndefinedValueRootIndex, |
| 1607 &convert_global_proxy); |
| 1608 __ JumpIfNotRoot(x3, Heap::kNullValueRootIndex, &convert_to_object); |
| 1609 __ Bind(&convert_global_proxy); |
| 1610 { |
| 1611 // Patch receiver to global proxy. |
| 1612 __ LoadGlobalProxy(x3); |
| 1613 } |
| 1614 __ B(&convert_receiver); |
| 1615 } |
| 1616 __ Bind(&convert_to_object); |
| 1617 { |
| 1618 // Convert receiver using ToObject. |
| 1619 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1620 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1621 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1622 __ SmiTag(x0); |
| 1623 __ Push(x0, x1); |
| 1624 __ Mov(x0, x3); |
| 1625 ToObjectStub stub(masm->isolate()); |
| 1626 __ CallStub(&stub); |
| 1627 __ Mov(x3, x0); |
| 1628 __ Pop(x1, x0); |
| 1629 __ SmiUntag(x0); |
| 1630 } |
| 1631 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
| 1632 __ Bind(&convert_receiver); |
1616 } | 1633 } |
1617 __ B(&convert_receiver); | |
1618 __ Bind(&convert_to_object); | |
1619 { | |
1620 // Convert receiver using ToObject. | |
1621 // TODO(bmeurer): Inline the allocation here to avoid building the frame | |
1622 // in the fast case? (fall back to AllocateInNewSpace?) | |
1623 FrameScope scope(masm, StackFrame::INTERNAL); | |
1624 __ SmiTag(x0); | |
1625 __ Push(x0, x1); | |
1626 __ Mov(x0, x3); | |
1627 ToObjectStub stub(masm->isolate()); | |
1628 __ CallStub(&stub); | |
1629 __ Mov(x3, x0); | |
1630 __ Pop(x1, x0); | |
1631 __ SmiUntag(x0); | |
1632 } | |
1633 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | |
1634 __ Bind(&convert_receiver); | |
1635 __ Poke(x3, Operand(x0, LSL, kXRegSizeLog2)); | 1634 __ Poke(x3, Operand(x0, LSL, kXRegSizeLog2)); |
1636 } | 1635 } |
1637 __ Bind(&done_convert); | 1636 __ Bind(&done_convert); |
1638 | 1637 |
1639 // ----------- S t a t e ------------- | 1638 // ----------- S t a t e ------------- |
1640 // -- x0 : the number of arguments (not including the receiver) | 1639 // -- x0 : the number of arguments (not including the receiver) |
1641 // -- x1 : the function to call (checked to be a JSFunction) | 1640 // -- x1 : the function to call (checked to be a JSFunction) |
1642 // -- x2 : the shared function info. | 1641 // -- x2 : the shared function info. |
1643 // -- cp : the function context. | 1642 // -- cp : the function context. |
1644 // ----------------------------------- | 1643 // ----------------------------------- |
1645 | 1644 |
1646 __ Ldrsw( | 1645 __ Ldrsw( |
1647 x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset)); | 1646 x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset)); |
1648 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); | 1647 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); |
1649 ParameterCount actual(x0); | 1648 ParameterCount actual(x0); |
1650 ParameterCount expected(x2); | 1649 ParameterCount expected(x2); |
1651 __ InvokeCode(x3, expected, actual, JUMP_FUNCTION, NullCallWrapper()); | 1650 __ InvokeCode(x3, expected, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1651 |
| 1652 // The function is a "classConstructor", need to raise an exception. |
| 1653 __ bind(&class_constructor); |
| 1654 { |
| 1655 FrameScope frame(masm, StackFrame::INTERNAL); |
| 1656 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); |
| 1657 } |
1652 } | 1658 } |
1653 | 1659 |
1654 | 1660 |
1655 // static | 1661 // static |
1656 void Builtins::Generate_Call(MacroAssembler* masm) { | 1662 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
1657 // ----------- S t a t e ------------- | 1663 // ----------- S t a t e ------------- |
1658 // -- x0 : the number of arguments (not including the receiver) | 1664 // -- x0 : the number of arguments (not including the receiver) |
1659 // -- x1 : the target to call (can be any Object). | 1665 // -- x1 : the target to call (can be any Object). |
1660 // ----------------------------------- | 1666 // ----------------------------------- |
1661 | 1667 |
1662 Label non_callable, non_function, non_smi; | 1668 Label non_callable, non_function, non_smi; |
1663 __ JumpIfSmi(x1, &non_callable); | 1669 __ JumpIfSmi(x1, &non_callable); |
1664 __ Bind(&non_smi); | 1670 __ Bind(&non_smi); |
1665 __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE); | 1671 __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE); |
1666 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET, | 1672 __ Jump(masm->isolate()->builtins()->CallFunction(mode), |
1667 eq); | 1673 RelocInfo::CODE_TARGET, eq); |
1668 __ Cmp(x5, JS_FUNCTION_PROXY_TYPE); | 1674 __ Cmp(x5, JS_FUNCTION_PROXY_TYPE); |
1669 __ B(ne, &non_function); | 1675 __ B(ne, &non_function); |
1670 | 1676 |
1671 // 1. Call to function proxy. | 1677 // 1. Call to function proxy. |
1672 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. | 1678 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
1673 __ Ldr(x1, FieldMemOperand(x1, JSFunctionProxy::kCallTrapOffset)); | 1679 __ Ldr(x1, FieldMemOperand(x1, JSFunctionProxy::kCallTrapOffset)); |
1674 __ AssertNotSmi(x1); | 1680 __ AssertNotSmi(x1); |
1675 __ B(&non_smi); | 1681 __ B(&non_smi); |
1676 | 1682 |
1677 // 2. Call to something else, which might have a [[Call]] internal method (if | 1683 // 2. Call to something else, which might have a [[Call]] internal method (if |
1678 // not we raise an exception). | 1684 // not we raise an exception). |
1679 __ Bind(&non_function); | 1685 __ Bind(&non_function); |
1680 // Check if target has a [[Call]] internal method. | 1686 // Check if target has a [[Call]] internal method. |
1681 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); | 1687 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); |
1682 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &non_callable); | 1688 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &non_callable); |
1683 // Overwrite the original receiver with the (original) target. | 1689 // Overwrite the original receiver with the (original) target. |
1684 __ Poke(x1, Operand(x0, LSL, kXRegSizeLog2)); | 1690 __ Poke(x1, Operand(x0, LSL, kXRegSizeLog2)); |
1685 // Let the "call_as_function_delegate" take care of the rest. | 1691 // Let the "call_as_function_delegate" take care of the rest. |
1686 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, x1); | 1692 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, x1); |
1687 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1693 __ Jump(masm->isolate()->builtins()->CallFunction( |
| 1694 ConvertReceiverMode::kNotNullOrUndefined), |
| 1695 RelocInfo::CODE_TARGET); |
1688 | 1696 |
1689 // 3. Call to something that is not callable. | 1697 // 3. Call to something that is not callable. |
1690 __ bind(&non_callable); | 1698 __ bind(&non_callable); |
1691 { | 1699 { |
1692 FrameScope scope(masm, StackFrame::INTERNAL); | 1700 FrameScope scope(masm, StackFrame::INTERNAL); |
1693 __ Push(x1); | 1701 __ Push(x1); |
1694 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); | 1702 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); |
1695 } | 1703 } |
1696 } | 1704 } |
1697 | 1705 |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2017 } | 2025 } |
2018 } | 2026 } |
2019 | 2027 |
2020 | 2028 |
2021 #undef __ | 2029 #undef __ |
2022 | 2030 |
2023 } // namespace internal | 2031 } // namespace internal |
2024 } // namespace v8 | 2032 } // namespace v8 |
2025 | 2033 |
2026 #endif // V8_TARGET_ARCH_ARM | 2034 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |