OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 __ mov(sp, fp); | 1562 __ mov(sp, fp); |
1563 __ MultiPop(fp.bit() | ra.bit()); | 1563 __ MultiPop(fp.bit() | ra.bit()); |
1564 __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize); | 1564 __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize); |
1565 __ Addu(sp, sp, t0); | 1565 __ Addu(sp, sp, t0); |
1566 // Adjust for the receiver. | 1566 // Adjust for the receiver. |
1567 __ Addu(sp, sp, Operand(kPointerSize)); | 1567 __ Addu(sp, sp, Operand(kPointerSize)); |
1568 } | 1568 } |
1569 | 1569 |
1570 | 1570 |
1571 // static | 1571 // static |
1572 void Builtins::Generate_CallFunction(MacroAssembler* masm) { | 1572 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
| 1573 ConvertReceiverMode mode) { |
1573 // ----------- S t a t e ------------- | 1574 // ----------- S t a t e ------------- |
1574 // -- a0 : the number of arguments (not including the receiver) | 1575 // -- a0 : the number of arguments (not including the receiver) |
1575 // -- a1 : the function to call (checked to be a JSFunction) | 1576 // -- a1 : the function to call (checked to be a JSFunction) |
1576 // ----------------------------------- | 1577 // ----------------------------------- |
| 1578 __ AssertFunction(a1); |
1577 | 1579 |
1578 Label convert, convert_global_proxy, convert_to_object, done_convert; | 1580 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
1579 __ AssertFunction(a1); | 1581 // Check that the function is not a "classConstructor". |
| 1582 Label class_constructor; |
1580 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1583 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
1581 | 1584 __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kFunctionKindByteOffset)); |
1582 { | 1585 __ And(at, a3, Operand(SharedFunctionInfo::kClassConstructorBitsWithinByte)); |
1583 Label non_class_constructor; | 1586 __ Branch(&class_constructor, ne, at, Operand(zero_reg)); |
1584 // Check whether the current function is a classConstructor. | |
1585 __ lbu(a3, | |
1586 FieldMemOperand(a2, SharedFunctionInfo::kFunctionKindByteOffset)); | |
1587 __ And(at, a3, | |
1588 Operand(SharedFunctionInfo::kClassConstructorBitsWithinByte)); | |
1589 __ Branch(&non_class_constructor, eq, at, Operand(zero_reg)); | |
1590 // Step: 2, If we call a classConstructor Function throw a TypeError. | |
1591 { | |
1592 FrameScope frame(masm, StackFrame::INTERNAL); | |
1593 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); | |
1594 } | |
1595 __ bind(&non_class_constructor); | |
1596 } | |
1597 | 1587 |
1598 // Enter the context of the function; ToObject has to run in the function | 1588 // Enter the context of the function; ToObject has to run in the function |
1599 // context, and we also need to take the global proxy from the function | 1589 // context, and we also need to take the global proxy from the function |
1600 // context in case of conversion. | 1590 // context in case of conversion. |
1601 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | |
1602 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == | 1591 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == |
1603 SharedFunctionInfo::kStrictModeByteOffset); | 1592 SharedFunctionInfo::kStrictModeByteOffset); |
1604 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 1593 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
1605 // We need to convert the receiver for non-native sloppy mode functions. | 1594 // We need to convert the receiver for non-native sloppy mode functions. |
| 1595 Label done_convert; |
1606 __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset)); | 1596 __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset)); |
1607 __ And(at, a3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) | | 1597 __ And(at, a3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) | |
1608 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); | 1598 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); |
1609 __ Branch(&done_convert, ne, at, Operand(zero_reg)); | 1599 __ Branch(&done_convert, ne, at, Operand(zero_reg)); |
1610 { | 1600 { |
1611 __ sll(at, a0, kPointerSizeLog2); | |
1612 __ addu(at, sp, at); | |
1613 __ lw(a3, MemOperand(at)); | |
1614 | |
1615 // ----------- S t a t e ------------- | 1601 // ----------- S t a t e ------------- |
1616 // -- a0 : the number of arguments (not including the receiver) | 1602 // -- a0 : the number of arguments (not including the receiver) |
1617 // -- a1 : the function to call (checked to be a JSFunction) | 1603 // -- a1 : the function to call (checked to be a JSFunction) |
1618 // -- a2 : the shared function info. | 1604 // -- a2 : the shared function info. |
1619 // -- a3 : the receiver | |
1620 // -- cp : the function context. | 1605 // -- cp : the function context. |
1621 // ----------------------------------- | 1606 // ----------------------------------- |
1622 | 1607 |
1623 Label convert_receiver; | 1608 if (mode == ConvertReceiverMode::kNullOrUndefined) { |
1624 __ JumpIfSmi(a3, &convert_to_object); | |
1625 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
1626 __ GetObjectType(a3, t0, t0); | |
1627 __ Branch(&done_convert, hs, t0, Operand(FIRST_JS_RECEIVER_TYPE)); | |
1628 __ JumpIfRoot(a3, Heap::kUndefinedValueRootIndex, &convert_global_proxy); | |
1629 __ JumpIfNotRoot(a3, Heap::kNullValueRootIndex, &convert_to_object); | |
1630 __ bind(&convert_global_proxy); | |
1631 { | |
1632 // Patch receiver to global proxy. | 1609 // Patch receiver to global proxy. |
1633 __ LoadGlobalProxy(a3); | 1610 __ LoadGlobalProxy(a3); |
| 1611 } else { |
| 1612 Label convert_to_object, convert_receiver; |
| 1613 __ sll(at, a0, kPointerSizeLog2); |
| 1614 __ addu(at, sp, at); |
| 1615 __ lw(a3, MemOperand(at)); |
| 1616 __ JumpIfSmi(a3, &convert_to_object); |
| 1617 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1618 __ GetObjectType(a3, t0, t0); |
| 1619 __ Branch(&done_convert, hs, t0, Operand(FIRST_JS_RECEIVER_TYPE)); |
| 1620 if (mode != ConvertReceiverMode::kNotNullOrUndefined) { |
| 1621 Label convert_global_proxy; |
| 1622 __ JumpIfRoot(a3, Heap::kUndefinedValueRootIndex, |
| 1623 &convert_global_proxy); |
| 1624 __ JumpIfNotRoot(a3, Heap::kNullValueRootIndex, &convert_to_object); |
| 1625 __ bind(&convert_global_proxy); |
| 1626 { |
| 1627 // Patch receiver to global proxy. |
| 1628 __ LoadGlobalProxy(a3); |
| 1629 } |
| 1630 __ Branch(&convert_receiver); |
| 1631 } |
| 1632 __ bind(&convert_to_object); |
| 1633 { |
| 1634 // Convert receiver using ToObject. |
| 1635 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1636 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1637 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1638 __ sll(a0, a0, kSmiTagSize); // Smi tagged. |
| 1639 __ Push(a0, a1); |
| 1640 __ mov(a0, a3); |
| 1641 ToObjectStub stub(masm->isolate()); |
| 1642 __ CallStub(&stub); |
| 1643 __ mov(a3, v0); |
| 1644 __ Pop(a0, a1); |
| 1645 __ sra(a0, a0, kSmiTagSize); // Un-tag. |
| 1646 } |
| 1647 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1648 __ bind(&convert_receiver); |
1634 } | 1649 } |
1635 __ Branch(&convert_receiver); | |
1636 __ bind(&convert_to_object); | |
1637 { | |
1638 // Convert receiver using ToObject. | |
1639 // TODO(bmeurer): Inline the allocation here to avoid building the frame | |
1640 // in the fast case? (fall back to AllocateInNewSpace?) | |
1641 FrameScope scope(masm, StackFrame::INTERNAL); | |
1642 __ sll(a0, a0, kSmiTagSize); // Smi tagged. | |
1643 __ Push(a0, a1); | |
1644 __ mov(a0, a3); | |
1645 ToObjectStub stub(masm->isolate()); | |
1646 __ CallStub(&stub); | |
1647 __ mov(a3, v0); | |
1648 __ Pop(a0, a1); | |
1649 __ sra(a0, a0, kSmiTagSize); // Un-tag. | |
1650 } | |
1651 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
1652 __ bind(&convert_receiver); | |
1653 __ sll(at, a0, kPointerSizeLog2); | 1650 __ sll(at, a0, kPointerSizeLog2); |
1654 __ addu(at, sp, at); | 1651 __ addu(at, sp, at); |
1655 __ sw(a3, MemOperand(at)); | 1652 __ sw(a3, MemOperand(at)); |
1656 } | 1653 } |
1657 __ bind(&done_convert); | 1654 __ bind(&done_convert); |
1658 | 1655 |
1659 // ----------- S t a t e ------------- | 1656 // ----------- S t a t e ------------- |
1660 // -- a0 : the number of arguments (not including the receiver) | 1657 // -- a0 : the number of arguments (not including the receiver) |
1661 // -- a1 : the function to call (checked to be a JSFunction) | 1658 // -- a1 : the function to call (checked to be a JSFunction) |
1662 // -- a2 : the shared function info. | 1659 // -- a2 : the shared function info. |
1663 // -- cp : the function context. | 1660 // -- cp : the function context. |
1664 // ----------------------------------- | 1661 // ----------------------------------- |
1665 | 1662 |
1666 __ lw(a2, | 1663 __ lw(a2, |
1667 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); | 1664 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); |
1668 __ sra(a2, a2, kSmiTagSize); // Un-tag. | 1665 __ sra(a2, a2, kSmiTagSize); // Un-tag. |
1669 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 1666 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
1670 ParameterCount actual(a0); | 1667 ParameterCount actual(a0); |
1671 ParameterCount expected(a2); | 1668 ParameterCount expected(a2); |
1672 __ InvokeCode(a3, expected, actual, JUMP_FUNCTION, NullCallWrapper()); | 1669 __ InvokeCode(a3, expected, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1670 |
| 1671 // The function is a "classConstructor", need to raise an exception. |
| 1672 __ bind(&class_constructor); |
| 1673 { |
| 1674 FrameScope frame(masm, StackFrame::INTERNAL); |
| 1675 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); |
| 1676 } |
1673 } | 1677 } |
1674 | 1678 |
1675 | 1679 |
1676 // static | 1680 // static |
1677 void Builtins::Generate_Call(MacroAssembler* masm) { | 1681 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
1678 // ----------- S t a t e ------------- | 1682 // ----------- S t a t e ------------- |
1679 // -- a0 : the number of arguments (not including the receiver) | 1683 // -- a0 : the number of arguments (not including the receiver) |
1680 // -- a1 : the target to call (can be any Object). | 1684 // -- a1 : the target to call (can be any Object). |
1681 // ----------------------------------- | 1685 // ----------------------------------- |
1682 | 1686 |
1683 Label non_callable, non_function, non_smi; | 1687 Label non_callable, non_function, non_smi; |
1684 __ JumpIfSmi(a1, &non_callable); | 1688 __ JumpIfSmi(a1, &non_callable); |
1685 __ bind(&non_smi); | 1689 __ bind(&non_smi); |
1686 __ GetObjectType(a1, t1, t2); | 1690 __ GetObjectType(a1, t1, t2); |
1687 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET, | 1691 __ Jump(masm->isolate()->builtins()->CallFunction(mode), |
1688 eq, t2, Operand(JS_FUNCTION_TYPE)); | 1692 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); |
1689 __ Branch(&non_function, ne, t2, Operand(JS_FUNCTION_PROXY_TYPE)); | 1693 __ Branch(&non_function, ne, t2, Operand(JS_FUNCTION_PROXY_TYPE)); |
1690 | 1694 |
1691 // 1. Call to function proxy. | 1695 // 1. Call to function proxy. |
1692 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. | 1696 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
1693 __ lw(a1, FieldMemOperand(a1, JSFunctionProxy::kCallTrapOffset)); | 1697 __ lw(a1, FieldMemOperand(a1, JSFunctionProxy::kCallTrapOffset)); |
1694 __ AssertNotSmi(a1); | 1698 __ AssertNotSmi(a1); |
1695 __ Branch(&non_smi); | 1699 __ Branch(&non_smi); |
1696 | 1700 |
1697 // 2. Call to something else, which might have a [[Call]] internal method (if | 1701 // 2. Call to something else, which might have a [[Call]] internal method (if |
1698 // not we raise an exception). | 1702 // not we raise an exception). |
1699 __ bind(&non_function); | 1703 __ bind(&non_function); |
1700 // Check if target has a [[Call]] internal method. | 1704 // Check if target has a [[Call]] internal method. |
1701 __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset)); | 1705 __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset)); |
1702 __ And(t1, t1, Operand(1 << Map::kIsCallable)); | 1706 __ And(t1, t1, Operand(1 << Map::kIsCallable)); |
1703 __ Branch(&non_callable, eq, t1, Operand(zero_reg)); | 1707 __ Branch(&non_callable, eq, t1, Operand(zero_reg)); |
1704 // Overwrite the original receiver with the (original) target. | 1708 // Overwrite the original receiver with the (original) target. |
1705 __ sll(at, a0, kPointerSizeLog2); | 1709 __ sll(at, a0, kPointerSizeLog2); |
1706 __ addu(at, sp, at); | 1710 __ addu(at, sp, at); |
1707 __ sw(a1, MemOperand(at)); | 1711 __ sw(a1, MemOperand(at)); |
1708 // Let the "call_as_function_delegate" take care of the rest. | 1712 // Let the "call_as_function_delegate" take care of the rest. |
1709 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1); | 1713 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1); |
1710 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1714 __ Jump(masm->isolate()->builtins()->CallFunction( |
| 1715 ConvertReceiverMode::kNotNullOrUndefined), |
| 1716 RelocInfo::CODE_TARGET); |
1711 | 1717 |
1712 // 3. Call to something that is not callable. | 1718 // 3. Call to something that is not callable. |
1713 __ bind(&non_callable); | 1719 __ bind(&non_callable); |
1714 { | 1720 { |
1715 FrameScope scope(masm, StackFrame::INTERNAL); | 1721 FrameScope scope(masm, StackFrame::INTERNAL); |
1716 __ Push(a1); | 1722 __ Push(a1); |
1717 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); | 1723 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); |
1718 } | 1724 } |
1719 } | 1725 } |
1720 | 1726 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1956 } | 1962 } |
1957 } | 1963 } |
1958 | 1964 |
1959 | 1965 |
1960 #undef __ | 1966 #undef __ |
1961 | 1967 |
1962 } // namespace internal | 1968 } // namespace internal |
1963 } // namespace v8 | 1969 } // namespace v8 |
1964 | 1970 |
1965 #endif // V8_TARGET_ARCH_MIPS | 1971 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |