Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1542 | 1542 |
| 1543 | 1543 |
| 1544 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1544 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1545 if (kind_ == Code::KEYED_CALL_IC) { | 1545 if (kind_ == Code::KEYED_CALL_IC) { |
| 1546 __ Cmp(rcx, name); | 1546 __ Cmp(rcx, name); |
| 1547 __ j(not_equal, miss); | 1547 __ j(not_equal, miss); |
| 1548 } | 1548 } |
| 1549 } | 1549 } |
| 1550 | 1550 |
| 1551 | 1551 |
| 1552 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | |
| 1553 Handle<JSObject> holder, | |
| 1554 Handle<Name> name, | |
| 1555 Label* miss) { | |
| 1556 ASSERT(holder->IsGlobalObject()); | |
| 1557 | |
| 1558 StackArgumentsAccessor args(rsp, arguments()); | |
| 1559 __ movq(rdx, args.GetReceiverOperand()); | |
| 1560 | |
| 1561 | |
| 1562 // Check that the maps haven't changed. | |
| 1563 __ JumpIfSmi(rdx, miss); | |
| 1564 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 1565 rbx, rax, rdi, name, miss); | |
| 1566 } | |
| 1567 | |
| 1568 | |
| 1569 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1552 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1570 Handle<Cell> cell, | 1553 Handle<Cell> cell, |
| 1571 Handle<JSFunction> function, | 1554 Handle<JSFunction> function, |
| 1572 Label* miss) { | 1555 Label* miss) { |
| 1573 // Get the value from the cell. | 1556 // Get the value from the cell. |
| 1574 __ Move(rdi, cell); | 1557 __ Move(rdi, cell); |
| 1575 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1558 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
| 1576 | 1559 |
| 1577 // Check that the cell contains the same function. | 1560 // Check that the cell contains the same function. |
| 1578 if (heap()->InNewSpace(*function)) { | 1561 if (heap()->InNewSpace(*function)) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1601 kind_, | 1584 kind_, |
| 1602 extra_state_); | 1585 extra_state_); |
| 1603 __ Jump(code, RelocInfo::CODE_TARGET); | 1586 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1604 } | 1587 } |
| 1605 | 1588 |
| 1606 | 1589 |
| 1607 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1590 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1608 Handle<JSObject> holder, | 1591 Handle<JSObject> holder, |
| 1609 PropertyIndex index, | 1592 PropertyIndex index, |
| 1610 Handle<Name> name) { | 1593 Handle<Name> name) { |
| 1611 // ----------- S t a t e ------------- | |
| 1612 // rcx : function name | |
| 1613 // rsp[0] : return address | |
| 1614 // rsp[8] : argument argc | |
| 1615 // rsp[16] : argument argc - 1 | |
| 1616 // ... | |
| 1617 // rsp[argc * 8] : argument 1 | |
| 1618 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 1619 // ----------------------------------- | |
| 1620 Label miss; | 1594 Label miss; |
| 1621 | 1595 |
| 1622 GenerateNameCheck(name, &miss); | 1596 Register reg = HandlerFrontendHeader( |
| 1623 | 1597 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1624 StackArgumentsAccessor args(rsp, arguments()); | |
| 1625 __ movq(rdx, args.GetReceiverOperand()); | |
| 1626 | |
| 1627 // Check that the receiver isn't a smi. | |
| 1628 __ JumpIfSmi(rdx, &miss); | |
| 1629 | |
| 1630 // Do the right check and compute the holder register. | |
| 1631 Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, | |
| 1632 holder, rbx, rax, rdi, name, &miss); | |
| 1633 | 1598 |
| 1634 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1599 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1635 index.translate(holder), Representation::Tagged()); | 1600 index.translate(holder), Representation::Tagged()); |
| 1636 | 1601 |
| 1637 // Check that the function really is a function. | 1602 // Check that the function really is a function. |
| 1638 __ JumpIfSmi(rdi, &miss); | 1603 __ JumpIfSmi(rdi, &miss); |
| 1639 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | 1604 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
| 1640 __ j(not_equal, &miss); | 1605 __ j(not_equal, &miss); |
| 1641 | 1606 |
| 1642 // Patch the receiver on the stack with the global proxy if | 1607 PatchGlobalProxy(object); |
| 1643 // necessary. | |
| 1644 if (object->IsGlobalObject()) { | |
| 1645 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 1646 __ movq(args.GetReceiverOperand(), rdx); | |
| 1647 } | |
| 1648 | 1608 |
| 1649 // Invoke the function. | 1609 // Invoke the function. |
| 1650 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1610 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1651 ? CALL_AS_FUNCTION | 1611 ? CALL_AS_FUNCTION |
| 1652 : CALL_AS_METHOD; | 1612 : CALL_AS_METHOD; |
| 1653 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 1613 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1654 NullCallWrapper(), call_kind); | 1614 NullCallWrapper(), call_kind); |
| 1655 | 1615 |
| 1656 // Handle call cache miss. | 1616 HandlerFrontendFooter(&miss); |
| 1657 __ bind(&miss); | |
| 1658 GenerateMissBranch(); | |
| 1659 | 1617 |
| 1660 // Return the generated code. | 1618 // Return the generated code. |
| 1661 return GetCode(Code::FAST, name); | 1619 return GetCode(Code::FAST, name); |
| 1662 } | 1620 } |
| 1663 | 1621 |
| 1664 | 1622 |
| 1665 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1623 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1666 Handle<Object> object, | 1624 Handle<Object> object, |
| 1667 Handle<JSObject> holder, | 1625 Handle<JSObject> holder, |
| 1668 Handle<Cell> cell, | 1626 Handle<Cell> cell, |
| 1669 Handle<JSFunction> function, | 1627 Handle<JSFunction> function, |
| 1670 Handle<String> name, | 1628 Handle<String> name, |
| 1671 Code::StubType type) { | 1629 Code::StubType type) { |
| 1672 Label miss; | 1630 Label miss; |
| 1673 | 1631 |
| 1674 // Check that function is still array | 1632 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1675 const int argc = arguments().immediate(); | 1633 if (!cell.is_null()) { |
| 1676 StackArgumentsAccessor args(rsp, argc); | |
| 1677 GenerateNameCheck(name, &miss); | |
| 1678 | |
| 1679 if (cell.is_null()) { | |
| 1680 __ movq(rdx, args.GetReceiverOperand()); | |
| 1681 | |
| 1682 // Check that the receiver isn't a smi. | |
| 1683 __ JumpIfSmi(rdx, &miss); | |
| 1684 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 1685 rbx, rax, rdi, name, &miss); | |
| 1686 } else { | |
| 1687 ASSERT(cell->value() == *function); | 1634 ASSERT(cell->value() == *function); |
| 1688 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 1689 &miss); | |
| 1690 GenerateLoadFunctionFromCell(cell, function, &miss); | 1635 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1691 } | 1636 } |
| 1692 | 1637 |
| 1693 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1638 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1694 site->SetElementsKind(GetInitialFastElementsKind()); | 1639 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1695 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1640 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1641 const int argc = arguments().immediate(); | |
| 1696 __ movq(rax, Immediate(argc)); | 1642 __ movq(rax, Immediate(argc)); |
| 1697 __ Move(rbx, site_feedback_cell); | 1643 __ Move(rbx, site_feedback_cell); |
| 1698 __ Move(rdi, function); | 1644 __ Move(rdi, function); |
| 1699 | 1645 |
| 1700 ArrayConstructorStub stub(isolate()); | 1646 ArrayConstructorStub stub(isolate()); |
| 1701 __ TailCallStub(&stub); | 1647 __ TailCallStub(&stub); |
| 1702 | 1648 |
| 1703 __ bind(&miss); | 1649 HandlerFrontendFooter(&miss); |
| 1704 GenerateMissBranch(); | |
| 1705 | 1650 |
| 1706 // Return the generated code. | 1651 // Return the generated code. |
| 1707 return GetCode(type, name); | 1652 return GetCode(type, name); |
| 1708 } | 1653 } |
| 1709 | 1654 |
| 1710 | 1655 |
| 1711 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1656 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1712 Handle<Object> object, | 1657 Handle<Object> object, |
| 1713 Handle<JSObject> holder, | 1658 Handle<JSObject> holder, |
| 1714 Handle<Cell> cell, | 1659 Handle<Cell> cell, |
| 1715 Handle<JSFunction> function, | 1660 Handle<JSFunction> function, |
| 1716 Handle<String> name, | 1661 Handle<String> name, |
| 1717 Code::StubType type) { | 1662 Code::StubType type) { |
| 1718 // ----------- S t a t e ------------- | 1663 // ----------- S t a t e ------------- |
| 1719 // -- rcx : name | 1664 // -- rcx : name |
| 1720 // -- rsp[0] : return address | 1665 // -- rsp[0] : return address |
| 1721 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1666 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1722 // -- ... | 1667 // -- ... |
| 1723 // -- rsp[(argc + 1) * 8] : receiver | 1668 // -- rsp[(argc + 1) * 8] : receiver |
| 1724 // ----------------------------------- | 1669 // ----------------------------------- |
| 1725 | 1670 |
| 1726 // If object is not an array or is observed, bail out to regular call. | 1671 // If object is not an array or is observed, bail out to regular call. |
| 1727 if (!object->IsJSArray() || | 1672 if (!object->IsJSArray() || |
| 1728 !cell.is_null() || | 1673 !cell.is_null() || |
| 1729 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1674 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1730 return Handle<Code>::null(); | 1675 return Handle<Code>::null(); |
| 1731 } | 1676 } |
| 1732 | 1677 |
| 1733 Label miss; | 1678 Label miss; |
| 1734 GenerateNameCheck(name, &miss); | 1679 |
| 1680 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 1735 | 1681 |
| 1736 const int argc = arguments().immediate(); | 1682 const int argc = arguments().immediate(); |
| 1737 StackArgumentsAccessor args(rsp, argc); | 1683 StackArgumentsAccessor args(rsp, argc); |
| 1738 __ movq(rdx, args.GetReceiverOperand()); | |
| 1739 | |
| 1740 // Check that the receiver isn't a smi. | |
| 1741 __ JumpIfSmi(rdx, &miss); | |
| 1742 | |
| 1743 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 1744 rbx, rax, rdi, name, &miss); | |
| 1745 | |
| 1746 if (argc == 0) { | 1684 if (argc == 0) { |
| 1747 // Noop, return the length. | 1685 // Noop, return the length. |
| 1748 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1686 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 1749 __ ret((argc + 1) * kPointerSize); | 1687 __ ret((argc + 1) * kPointerSize); |
| 1750 } else { | 1688 } else { |
| 1751 Label call_builtin; | 1689 Label call_builtin; |
| 1752 | 1690 |
| 1753 if (argc == 1) { // Otherwise fall through to call builtin. | 1691 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1754 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1692 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| 1755 | 1693 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1948 __ ret((argc + 1) * kPointerSize); | 1886 __ ret((argc + 1) * kPointerSize); |
| 1949 } | 1887 } |
| 1950 | 1888 |
| 1951 __ bind(&call_builtin); | 1889 __ bind(&call_builtin); |
| 1952 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1890 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1953 isolate()), | 1891 isolate()), |
| 1954 argc + 1, | 1892 argc + 1, |
| 1955 1); | 1893 1); |
| 1956 } | 1894 } |
| 1957 | 1895 |
| 1958 __ bind(&miss); | 1896 HandlerFrontendFooter(&miss); |
| 1959 GenerateMissBranch(); | |
| 1960 | 1897 |
| 1961 // Return the generated code. | 1898 // Return the generated code. |
| 1962 return GetCode(type, name); | 1899 return GetCode(type, name); |
| 1963 } | 1900 } |
| 1964 | 1901 |
| 1965 | 1902 |
| 1966 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1903 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1967 Handle<Object> object, | 1904 Handle<Object> object, |
| 1968 Handle<JSObject> holder, | 1905 Handle<JSObject> holder, |
| 1969 Handle<Cell> cell, | 1906 Handle<Cell> cell, |
| 1970 Handle<JSFunction> function, | 1907 Handle<JSFunction> function, |
| 1971 Handle<String> name, | 1908 Handle<String> name, |
| 1972 Code::StubType type) { | 1909 Code::StubType type) { |
| 1973 // ----------- S t a t e ------------- | |
| 1974 // -- rcx : name | |
| 1975 // -- rsp[0] : return address | |
| 1976 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 1977 // -- ... | |
| 1978 // -- rsp[(argc + 1) * 8] : receiver | |
| 1979 // ----------------------------------- | |
| 1980 | |
| 1981 // If object is not an array or is observed, bail out to regular call. | 1910 // If object is not an array or is observed, bail out to regular call. |
| 1982 if (!object->IsJSArray() || | 1911 if (!object->IsJSArray() || |
| 1983 !cell.is_null() || | 1912 !cell.is_null() || |
| 1984 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1913 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1985 return Handle<Code>::null(); | 1914 return Handle<Code>::null(); |
| 1986 } | 1915 } |
| 1987 | 1916 |
| 1988 Label miss, return_undefined, call_builtin; | 1917 Label miss, return_undefined, call_builtin; |
| 1989 GenerateNameCheck(name, &miss); | |
| 1990 | 1918 |
| 1991 const int argc = arguments().immediate(); | 1919 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1992 StackArgumentsAccessor args(rsp, argc); | |
| 1993 __ movq(rdx, args.GetReceiverOperand()); | |
| 1994 | |
| 1995 // Check that the receiver isn't a smi. | |
| 1996 __ JumpIfSmi(rdx, &miss); | |
| 1997 | |
| 1998 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 1999 rbx, rax, rdi, name, &miss); | |
| 2000 | 1920 |
| 2001 // Get the elements array of the object. | 1921 // Get the elements array of the object. |
| 2002 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1922 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 2003 | 1923 |
| 2004 // Check that the elements are in fast mode and writable. | 1924 // Check that the elements are in fast mode and writable. |
| 2005 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1925 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
| 2006 Heap::kFixedArrayMapRootIndex); | 1926 Heap::kFixedArrayMapRootIndex); |
| 2007 __ j(not_equal, &call_builtin); | 1927 __ j(not_equal, &call_builtin); |
| 2008 | 1928 |
| 2009 // Get the array's length into rcx and calculate new length. | 1929 // Get the array's length into rcx and calculate new length. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2022 __ j(equal, &call_builtin); | 1942 __ j(equal, &call_builtin); |
| 2023 | 1943 |
| 2024 // Set the array's length. | 1944 // Set the array's length. |
| 2025 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); | 1945 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); |
| 2026 | 1946 |
| 2027 // Fill with the hole and return original value. | 1947 // Fill with the hole and return original value. |
| 2028 __ movq(FieldOperand(rbx, | 1948 __ movq(FieldOperand(rbx, |
| 2029 rcx, times_pointer_size, | 1949 rcx, times_pointer_size, |
| 2030 FixedArray::kHeaderSize), | 1950 FixedArray::kHeaderSize), |
| 2031 r9); | 1951 r9); |
| 1952 const int argc = arguments().immediate(); | |
| 2032 __ ret((argc + 1) * kPointerSize); | 1953 __ ret((argc + 1) * kPointerSize); |
| 2033 | 1954 |
| 2034 __ bind(&return_undefined); | 1955 __ bind(&return_undefined); |
| 2035 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1956 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 2036 __ ret((argc + 1) * kPointerSize); | 1957 __ ret((argc + 1) * kPointerSize); |
| 2037 | 1958 |
| 2038 __ bind(&call_builtin); | 1959 __ bind(&call_builtin); |
| 2039 __ TailCallExternalReference( | 1960 __ TailCallExternalReference( |
| 2040 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1961 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 2041 argc + 1, | 1962 argc + 1, |
| 2042 1); | 1963 1); |
| 2043 | 1964 |
| 2044 __ bind(&miss); | 1965 HandlerFrontendFooter(&miss); |
| 2045 GenerateMissBranch(); | |
| 2046 | 1966 |
| 2047 // Return the generated code. | 1967 // Return the generated code. |
| 2048 return GetCode(type, name); | 1968 return GetCode(type, name); |
| 2049 } | 1969 } |
| 2050 | 1970 |
| 2051 | 1971 |
| 2052 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 1972 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2053 Handle<Object> object, | 1973 Handle<Object> object, |
| 2054 Handle<JSObject> holder, | 1974 Handle<JSObject> holder, |
| 2055 Handle<Cell> cell, | 1975 Handle<Cell> cell, |
| 2056 Handle<JSFunction> function, | 1976 Handle<JSFunction> function, |
| 2057 Handle<String> name, | 1977 Handle<String> name, |
| 2058 Code::StubType type) { | 1978 Code::StubType type) { |
| 2059 // ----------- S t a t e ------------- | |
| 2060 // -- rcx : function name | |
| 2061 // -- rsp[0] : return address | |
| 2062 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2063 // -- ... | |
| 2064 // -- rsp[(argc + 1) * 8] : receiver | |
| 2065 // ----------------------------------- | |
| 2066 | |
| 2067 // If object is not a string, bail out to regular call. | 1979 // If object is not a string, bail out to regular call. |
| 2068 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1980 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2069 | 1981 |
| 2070 const int argc = arguments().immediate(); | |
| 2071 StackArgumentsAccessor args(rsp, argc); | |
| 2072 | |
| 2073 Label miss; | 1982 Label miss; |
| 2074 Label name_miss; | 1983 Label name_miss; |
| 2075 Label index_out_of_range; | 1984 Label index_out_of_range; |
| 2076 Label* index_out_of_range_label = &index_out_of_range; | 1985 Label* index_out_of_range_label = &index_out_of_range; |
| 2077 if (kind_ == Code::CALL_IC && | 1986 if (kind_ == Code::CALL_IC && |
| 2078 (CallICBase::StringStubState::decode(extra_state_) == | 1987 (CallICBase::StringStubState::decode(extra_state_) == |
| 2079 DEFAULT_STRING_STUB)) { | 1988 DEFAULT_STRING_STUB)) { |
| 2080 index_out_of_range_label = &miss; | 1989 index_out_of_range_label = &miss; |
| 2081 } | 1990 } |
| 2082 GenerateNameCheck(name, &name_miss); | |
| 2083 | 1991 |
| 2084 // Check that the maps starting from the prototype haven't changed. | 1992 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2085 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2086 Context::STRING_FUNCTION_INDEX, | |
| 2087 rax, | |
| 2088 &miss); | |
| 2089 ASSERT(!object.is_identical_to(holder)); | |
| 2090 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2091 CheckPrototypes( | |
| 2092 IC::CurrentTypeOf(prototype, isolate()), | |
| 2093 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2094 | 1993 |
| 2095 Register receiver = rbx; | 1994 Register receiver = rbx; |
| 2096 Register index = rdi; | 1995 Register index = rdi; |
| 2097 Register result = rax; | 1996 Register result = rax; |
| 1997 const int argc = arguments().immediate(); | |
| 1998 StackArgumentsAccessor args(rsp, argc); | |
| 1999 | |
| 2098 __ movq(receiver, args.GetReceiverOperand()); | 2000 __ movq(receiver, args.GetReceiverOperand()); |
| 2099 if (argc > 0) { | 2001 if (argc > 0) { |
| 2100 __ movq(index, args.GetArgumentOperand(1)); | 2002 __ movq(index, args.GetArgumentOperand(1)); |
| 2101 } else { | 2003 } else { |
| 2102 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2004 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2103 } | 2005 } |
| 2104 | 2006 |
| 2105 StringCharCodeAtGenerator generator(receiver, | 2007 StringCharCodeAtGenerator generator(receiver, |
| 2106 index, | 2008 index, |
| 2107 result, | 2009 result, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2132 } | 2034 } |
| 2133 | 2035 |
| 2134 | 2036 |
| 2135 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2037 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2136 Handle<Object> object, | 2038 Handle<Object> object, |
| 2137 Handle<JSObject> holder, | 2039 Handle<JSObject> holder, |
| 2138 Handle<Cell> cell, | 2040 Handle<Cell> cell, |
| 2139 Handle<JSFunction> function, | 2041 Handle<JSFunction> function, |
| 2140 Handle<String> name, | 2042 Handle<String> name, |
| 2141 Code::StubType type) { | 2043 Code::StubType type) { |
| 2142 // ----------- S t a t e ------------- | |
| 2143 // -- rcx : function name | |
| 2144 // -- rsp[0] : return address | |
| 2145 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2146 // -- ... | |
| 2147 // -- rsp[(argc + 1) * 8] : receiver | |
| 2148 // ----------------------------------- | |
| 2149 | |
| 2150 // If object is not a string, bail out to regular call. | 2044 // If object is not a string, bail out to regular call. |
| 2151 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2045 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2152 | 2046 |
| 2153 const int argc = arguments().immediate(); | 2047 const int argc = arguments().immediate(); |
| 2154 StackArgumentsAccessor args(rsp, argc); | 2048 StackArgumentsAccessor args(rsp, argc); |
| 2155 | 2049 |
| 2156 Label miss; | 2050 Label miss; |
| 2157 Label name_miss; | 2051 Label name_miss; |
| 2158 Label index_out_of_range; | 2052 Label index_out_of_range; |
| 2159 Label* index_out_of_range_label = &index_out_of_range; | 2053 Label* index_out_of_range_label = &index_out_of_range; |
| 2160 if (kind_ == Code::CALL_IC && | 2054 if (kind_ == Code::CALL_IC && |
| 2161 (CallICBase::StringStubState::decode(extra_state_) == | 2055 (CallICBase::StringStubState::decode(extra_state_) == |
| 2162 DEFAULT_STRING_STUB)) { | 2056 DEFAULT_STRING_STUB)) { |
| 2163 index_out_of_range_label = &miss; | 2057 index_out_of_range_label = &miss; |
| 2164 } | 2058 } |
| 2165 GenerateNameCheck(name, &name_miss); | |
| 2166 | 2059 |
| 2167 // Check that the maps starting from the prototype haven't changed. | 2060 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2168 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2169 Context::STRING_FUNCTION_INDEX, | |
| 2170 rax, | |
| 2171 &miss); | |
| 2172 ASSERT(!object.is_identical_to(holder)); | |
| 2173 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2174 CheckPrototypes( | |
| 2175 IC::CurrentTypeOf(prototype, isolate()), | |
| 2176 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2177 | 2061 |
| 2178 Register receiver = rax; | 2062 Register receiver = rax; |
| 2179 Register index = rdi; | 2063 Register index = rdi; |
| 2180 Register scratch = rdx; | 2064 Register scratch = rdx; |
| 2181 Register result = rax; | 2065 Register result = rax; |
| 2182 __ movq(receiver, args.GetReceiverOperand()); | 2066 __ movq(receiver, args.GetReceiverOperand()); |
| 2183 if (argc > 0) { | 2067 if (argc > 0) { |
| 2184 __ movq(index, args.GetArgumentOperand(1)); | 2068 __ movq(index, args.GetArgumentOperand(1)); |
| 2185 } else { | 2069 } else { |
| 2186 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2070 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 2216 } | 2100 } |
| 2217 | 2101 |
| 2218 | 2102 |
| 2219 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2103 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2220 Handle<Object> object, | 2104 Handle<Object> object, |
| 2221 Handle<JSObject> holder, | 2105 Handle<JSObject> holder, |
| 2222 Handle<Cell> cell, | 2106 Handle<Cell> cell, |
| 2223 Handle<JSFunction> function, | 2107 Handle<JSFunction> function, |
| 2224 Handle<String> name, | 2108 Handle<String> name, |
| 2225 Code::StubType type) { | 2109 Code::StubType type) { |
| 2226 // ----------- S t a t e ------------- | |
| 2227 // -- rcx : function name | |
| 2228 // -- rsp[0] : return address | |
| 2229 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2230 // -- ... | |
| 2231 // -- rsp[(argc + 1) * 8] : receiver | |
| 2232 // ----------------------------------- | |
| 2233 | |
| 2234 // If the object is not a JSObject or we got an unexpected number of | 2110 // If the object is not a JSObject or we got an unexpected number of |
| 2235 // arguments, bail out to the regular call. | 2111 // arguments, bail out to the regular call. |
| 2236 const int argc = arguments().immediate(); | 2112 const int argc = arguments().immediate(); |
| 2237 StackArgumentsAccessor args(rsp, argc); | 2113 StackArgumentsAccessor args(rsp, argc); |
| 2238 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2114 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2239 | 2115 |
| 2240 Label miss; | 2116 Label miss; |
| 2241 GenerateNameCheck(name, &miss); | |
| 2242 | 2117 |
| 2243 if (cell.is_null()) { | 2118 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2244 __ movq(rdx, args.GetReceiverOperand()); | 2119 if (!cell.is_null()) { |
| 2245 __ JumpIfSmi(rdx, &miss); | |
| 2246 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 2247 rbx, rax, rdi, name, &miss); | |
| 2248 } else { | |
| 2249 ASSERT(cell->value() == *function); | 2120 ASSERT(cell->value() == *function); |
| 2250 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2251 &miss); | |
| 2252 GenerateLoadFunctionFromCell(cell, function, &miss); | 2121 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2253 } | 2122 } |
| 2254 | 2123 |
| 2255 // Load the char code argument. | 2124 // Load the char code argument. |
| 2256 Register code = rbx; | 2125 Register code = rbx; |
| 2257 __ movq(code, args.GetArgumentOperand(1)); | 2126 __ movq(code, args.GetArgumentOperand(1)); |
| 2258 | 2127 |
| 2259 // Check the code is a smi. | 2128 // Check the code is a smi. |
| 2260 Label slow; | 2129 Label slow; |
| 2261 __ JumpIfNotSmi(code, &slow); | 2130 __ JumpIfNotSmi(code, &slow); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2273 // Tail call the full function. We do not have to patch the receiver | 2142 // Tail call the full function. We do not have to patch the receiver |
| 2274 // because the function makes no use of it. | 2143 // because the function makes no use of it. |
| 2275 __ bind(&slow); | 2144 __ bind(&slow); |
| 2276 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2145 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2277 ? CALL_AS_FUNCTION | 2146 ? CALL_AS_FUNCTION |
| 2278 : CALL_AS_METHOD; | 2147 : CALL_AS_METHOD; |
| 2279 ParameterCount expected(function); | 2148 ParameterCount expected(function); |
| 2280 __ InvokeFunction(function, expected, arguments(), | 2149 __ InvokeFunction(function, expected, arguments(), |
| 2281 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2150 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2282 | 2151 |
| 2283 __ bind(&miss); | 2152 HandlerFrontendFooter(&miss); |
| 2284 // rcx: function name. | |
| 2285 GenerateMissBranch(); | |
| 2286 | 2153 |
| 2287 // Return the generated code. | 2154 // Return the generated code. |
| 2288 return GetCode(type, name); | 2155 return GetCode(type, name); |
| 2289 } | 2156 } |
| 2290 | 2157 |
| 2291 | 2158 |
| 2292 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2159 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2293 Handle<Object> object, | 2160 Handle<Object> object, |
| 2294 Handle<JSObject> holder, | 2161 Handle<JSObject> holder, |
| 2295 Handle<Cell> cell, | 2162 Handle<Cell> cell, |
| 2296 Handle<JSFunction> function, | 2163 Handle<JSFunction> function, |
| 2297 Handle<String> name, | 2164 Handle<String> name, |
| 2298 Code::StubType type) { | 2165 Code::StubType type) { |
| 2299 // ----------- S t a t e ------------- | |
| 2300 // -- rcx : name | |
| 2301 // -- rsp[0] : return address | |
| 2302 // -- rsp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2303 // -- ... | |
| 2304 // -- rsp[(argc + 1) * 4] : receiver | |
| 2305 // ----------------------------------- | |
| 2306 const int argc = arguments().immediate(); | 2166 const int argc = arguments().immediate(); |
| 2307 StackArgumentsAccessor args(rsp, argc); | 2167 StackArgumentsAccessor args(rsp, argc); |
| 2308 | 2168 |
| 2309 // If the object is not a JSObject or we got an unexpected number of | 2169 // If the object is not a JSObject or we got an unexpected number of |
| 2310 // arguments, bail out to the regular call. | 2170 // arguments, bail out to the regular call. |
| 2311 if (!object->IsJSObject() || argc != 1) { | 2171 if (!object->IsJSObject() || argc != 1) { |
| 2312 return Handle<Code>::null(); | 2172 return Handle<Code>::null(); |
| 2313 } | 2173 } |
| 2314 | 2174 |
| 2315 Label miss; | 2175 Label miss, slow; |
| 2316 GenerateNameCheck(name, &miss); | |
| 2317 | 2176 |
| 2318 if (cell.is_null()) { | 2177 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2319 __ movq(rdx, args.GetReceiverOperand()); | 2178 if (!cell.is_null()) { |
| 2320 | |
| 2321 STATIC_ASSERT(kSmiTag == 0); | |
| 2322 __ JumpIfSmi(rdx, &miss); | |
| 2323 | |
| 2324 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 2325 rbx, rax, rdi, name, &miss); | |
| 2326 } else { | |
| 2327 ASSERT(cell->value() == *function); | 2179 ASSERT(cell->value() == *function); |
| 2328 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2329 &miss); | |
| 2330 GenerateLoadFunctionFromCell(cell, function, &miss); | 2180 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2331 } | 2181 } |
| 2332 | 2182 |
| 2333 // Load the (only) argument into rax. | 2183 // Load the (only) argument into rax. |
| 2334 __ movq(rax, args.GetArgumentOperand(1)); | 2184 __ movq(rax, args.GetArgumentOperand(1)); |
| 2335 | 2185 |
| 2336 // Check if the argument is a smi. | 2186 // Check if the argument is a smi. |
| 2337 Label smi; | 2187 Label smi; |
| 2338 STATIC_ASSERT(kSmiTag == 0); | 2188 STATIC_ASSERT(kSmiTag == 0); |
| 2339 __ JumpIfSmi(rax, &smi); | 2189 __ JumpIfSmi(rax, &smi); |
| 2340 | 2190 |
| 2341 // Check if the argument is a heap number and load its value into xmm0. | 2191 // Check if the argument is a heap number and load its value into xmm0. |
| 2342 Label slow; | |
| 2343 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | 2192 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
| 2344 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | 2193 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 2345 | 2194 |
| 2346 // Check if the argument is strictly positive. Note this also discards NaN. | 2195 // Check if the argument is strictly positive. Note this also discards NaN. |
| 2347 __ xorpd(xmm1, xmm1); | 2196 __ xorpd(xmm1, xmm1); |
| 2348 __ ucomisd(xmm0, xmm1); | 2197 __ ucomisd(xmm0, xmm1); |
| 2349 __ j(below_equal, &slow); | 2198 __ j(below_equal, &slow); |
| 2350 | 2199 |
| 2351 // Do a truncating conversion. | 2200 // Do a truncating conversion. |
| 2352 __ cvttsd2si(rax, xmm0); | 2201 __ cvttsd2si(rax, xmm0); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2401 __ movq(rax, args.GetArgumentOperand(1)); | 2250 __ movq(rax, args.GetArgumentOperand(1)); |
| 2402 __ ret(2 * kPointerSize); | 2251 __ ret(2 * kPointerSize); |
| 2403 | 2252 |
| 2404 // Tail call the full function. We do not have to patch the receiver | 2253 // Tail call the full function. We do not have to patch the receiver |
| 2405 // because the function makes no use of it. | 2254 // because the function makes no use of it. |
| 2406 __ bind(&slow); | 2255 __ bind(&slow); |
| 2407 ParameterCount expected(function); | 2256 ParameterCount expected(function); |
| 2408 __ InvokeFunction(function, expected, arguments(), | 2257 __ InvokeFunction(function, expected, arguments(), |
| 2409 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2258 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
| 2410 | 2259 |
| 2411 __ bind(&miss); | 2260 HandlerFrontendFooter(&miss); |
| 2412 // rcx: function name. | |
| 2413 GenerateMissBranch(); | |
| 2414 | 2261 |
| 2415 // Return the generated code. | 2262 // Return the generated code. |
| 2416 return GetCode(type, name); | 2263 return GetCode(type, name); |
| 2417 } | 2264 } |
| 2418 | 2265 |
| 2419 | 2266 |
| 2420 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2267 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2421 Handle<Object> object, | 2268 Handle<Object> object, |
| 2422 Handle<JSObject> holder, | 2269 Handle<JSObject> holder, |
| 2423 Handle<Cell> cell, | 2270 Handle<Cell> cell, |
| 2424 Handle<JSFunction> function, | 2271 Handle<JSFunction> function, |
| 2425 Handle<String> name, | 2272 Handle<String> name, |
| 2426 Code::StubType type) { | 2273 Code::StubType type) { |
| 2427 // ----------- S t a t e ------------- | |
| 2428 // -- rcx : function name | |
| 2429 // -- rsp[0] : return address | |
| 2430 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2431 // -- ... | |
| 2432 // -- rsp[(argc + 1) * 8] : receiver | |
| 2433 // ----------------------------------- | |
| 2434 | |
| 2435 // If the object is not a JSObject or we got an unexpected number of | 2274 // If the object is not a JSObject or we got an unexpected number of |
| 2436 // arguments, bail out to the regular call. | 2275 // arguments, bail out to the regular call. |
| 2437 const int argc = arguments().immediate(); | 2276 const int argc = arguments().immediate(); |
| 2438 StackArgumentsAccessor args(rsp, argc); | 2277 StackArgumentsAccessor args(rsp, argc); |
| 2439 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2278 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2440 | 2279 |
| 2441 Label miss; | 2280 Label miss; |
| 2442 GenerateNameCheck(name, &miss); | |
| 2443 | 2281 |
| 2444 if (cell.is_null()) { | 2282 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2445 __ movq(rdx, args.GetReceiverOperand()); | 2283 if (!cell.is_null()) { |
| 2446 __ JumpIfSmi(rdx, &miss); | |
| 2447 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | |
| 2448 rbx, rax, rdi, name, &miss); | |
| 2449 } else { | |
| 2450 ASSERT(cell->value() == *function); | 2284 ASSERT(cell->value() == *function); |
| 2451 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2452 &miss); | |
| 2453 GenerateLoadFunctionFromCell(cell, function, &miss); | 2285 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2454 } | 2286 } |
| 2287 | |
| 2455 // Load the (only) argument into rax. | 2288 // Load the (only) argument into rax. |
| 2456 __ movq(rax, args.GetArgumentOperand(1)); | 2289 __ movq(rax, args.GetArgumentOperand(1)); |
| 2457 | 2290 |
| 2458 // Check if the argument is a smi. | 2291 // Check if the argument is a smi. |
| 2459 Label not_smi; | 2292 Label not_smi; |
| 2460 STATIC_ASSERT(kSmiTag == 0); | 2293 STATIC_ASSERT(kSmiTag == 0); |
| 2461 __ JumpIfNotSmi(rax, ¬_smi); | 2294 __ JumpIfNotSmi(rax, ¬_smi); |
| 2462 | 2295 |
| 2463 // Branchless abs implementation, refer to below: | 2296 // Branchless abs implementation, refer to below: |
| 2464 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs | 2297 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2506 // Tail call the full function. We do not have to patch the receiver | 2339 // Tail call the full function. We do not have to patch the receiver |
| 2507 // because the function makes no use of it. | 2340 // because the function makes no use of it. |
| 2508 __ bind(&slow); | 2341 __ bind(&slow); |
| 2509 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2342 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2510 ? CALL_AS_FUNCTION | 2343 ? CALL_AS_FUNCTION |
| 2511 : CALL_AS_METHOD; | 2344 : CALL_AS_METHOD; |
| 2512 ParameterCount expected(function); | 2345 ParameterCount expected(function); |
| 2513 __ InvokeFunction(function, expected, arguments(), | 2346 __ InvokeFunction(function, expected, arguments(), |
| 2514 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2347 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2515 | 2348 |
| 2516 __ bind(&miss); | 2349 HandlerFrontendFooter(&miss); |
| 2517 // rcx: function name. | |
| 2518 GenerateMissBranch(); | |
| 2519 | 2350 |
| 2520 // Return the generated code. | 2351 // Return the generated code. |
| 2521 return GetCode(type, name); | 2352 return GetCode(type, name); |
| 2522 } | 2353 } |
| 2523 | 2354 |
| 2524 | 2355 |
| 2525 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2356 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2526 const CallOptimization& optimization, | 2357 const CallOptimization& optimization, |
| 2527 Handle<Object> object, | 2358 Handle<Object> object, |
| 2528 Handle<JSObject> holder, | 2359 Handle<JSObject> holder, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2583 Label success; | 2414 Label success; |
| 2584 // Check that the object is a boolean. | 2415 // Check that the object is a boolean. |
| 2585 __ CompareRoot(object, Heap::kTrueValueRootIndex); | 2416 __ CompareRoot(object, Heap::kTrueValueRootIndex); |
| 2586 __ j(equal, &success); | 2417 __ j(equal, &success); |
| 2587 __ CompareRoot(object, Heap::kFalseValueRootIndex); | 2418 __ CompareRoot(object, Heap::kFalseValueRootIndex); |
| 2588 __ j(not_equal, miss); | 2419 __ j(not_equal, miss); |
| 2589 __ bind(&success); | 2420 __ bind(&success); |
| 2590 } | 2421 } |
| 2591 | 2422 |
| 2592 | 2423 |
| 2593 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2424 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2594 Handle<JSObject> holder, | 2425 if (object->IsGlobalObject()) { |
| 2595 Handle<Name> name, | 2426 StackArgumentsAccessor args(rsp, arguments()); |
| 2596 CheckType check) { | 2427 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2597 // ----------- S t a t e ------------- | 2428 __ movq(args.GetReceiverOperand(), rdx); |
| 2598 // rcx : function name | 2429 } |
| 2599 // rsp[0] : return address | 2430 } |
| 2600 // rsp[8] : argument argc | 2431 |
| 2601 // rsp[16] : argument argc - 1 | 2432 |
| 2602 // ... | 2433 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2603 // rsp[argc * 8] : argument 1 | 2434 Handle<JSObject> holder, |
| 2604 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2435 Handle<Name> name, |
| 2605 // ----------------------------------- | 2436 CheckType check, |
| 2606 Label miss; | 2437 Label* miss) { |
| 2607 GenerateNameCheck(name, &miss); | 2438 GenerateNameCheck(name, miss); |
| 2439 | |
| 2440 Register reg = rdx; | |
| 2608 | 2441 |
| 2609 StackArgumentsAccessor args(rsp, arguments()); | 2442 StackArgumentsAccessor args(rsp, arguments()); |
| 2610 __ movq(rdx, args.GetReceiverOperand()); | 2443 __ movq(reg, args.GetReceiverOperand()); |
| 2611 | 2444 |
| 2612 // Check that the receiver isn't a smi. | 2445 // Check that the receiver isn't a smi. |
| 2613 if (check != NUMBER_CHECK) { | 2446 if (check != NUMBER_CHECK) { |
| 2614 __ JumpIfSmi(rdx, &miss); | 2447 __ JumpIfSmi(reg, miss); |
| 2615 } | 2448 } |
| 2616 | 2449 |
| 2617 // Make sure that it's okay not to patch the on stack receiver | 2450 // Make sure that it's okay not to patch the on stack receiver |
| 2618 // unless we're doing a receiver map check. | 2451 // unless we're doing a receiver map check. |
| 2619 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2452 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2620 | 2453 |
| 2621 Counters* counters = isolate()->counters(); | 2454 Counters* counters = isolate()->counters(); |
| 2622 switch (check) { | 2455 switch (check) { |
| 2623 case RECEIVER_MAP_CHECK: | 2456 case RECEIVER_MAP_CHECK: |
| 2624 __ IncrementCounter(counters->call_const(), 1); | 2457 __ IncrementCounter(counters->call_const(), 1); |
| 2625 | 2458 |
| 2626 // Check that the maps haven't changed. | 2459 // Check that the maps haven't changed. |
| 2627 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, | 2460 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder, |
| 2628 rbx, rax, rdi, name, &miss); | 2461 rbx, rax, rdi, name, miss); |
| 2629 | |
| 2630 // Patch the receiver on the stack with the global proxy if | |
| 2631 // necessary. | |
| 2632 if (object->IsGlobalObject()) { | |
| 2633 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2634 __ movq(args.GetReceiverOperand(), rdx); | |
| 2635 } | |
| 2636 break; | 2462 break; |
| 2637 | 2463 |
| 2638 case STRING_CHECK: { | 2464 case STRING_CHECK: { |
| 2639 // Check that the object is a string. | 2465 // Check that the object is a string. |
| 2640 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); | 2466 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax); |
| 2641 __ j(above_equal, &miss); | 2467 __ j(above_equal, miss); |
| 2642 // Check that the maps starting from the prototype haven't changed. | 2468 // Check that the maps starting from the prototype haven't changed. |
| 2643 GenerateDirectLoadGlobalFunctionPrototype( | 2469 GenerateDirectLoadGlobalFunctionPrototype( |
| 2644 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); | 2470 masm(), Context::STRING_FUNCTION_INDEX, rax, miss); |
| 2645 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2646 CheckPrototypes( | |
| 2647 IC::CurrentTypeOf(prototype, isolate()), | |
| 2648 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2649 break; | 2471 break; |
| 2650 } | 2472 } |
| 2651 case SYMBOL_CHECK: { | 2473 case SYMBOL_CHECK: { |
| 2652 // Check that the object is a symbol. | 2474 // Check that the object is a symbol. |
| 2653 __ CmpObjectType(rdx, SYMBOL_TYPE, rax); | 2475 __ CmpObjectType(reg, SYMBOL_TYPE, rax); |
| 2654 __ j(not_equal, &miss); | 2476 __ j(not_equal, miss); |
| 2655 // Check that the maps starting from the prototype haven't changed. | 2477 // Check that the maps starting from the prototype haven't changed. |
| 2656 GenerateDirectLoadGlobalFunctionPrototype( | 2478 GenerateDirectLoadGlobalFunctionPrototype( |
| 2657 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss); | 2479 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss); |
| 2658 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2659 CheckPrototypes( | |
| 2660 IC::CurrentTypeOf(prototype, isolate()), | |
| 2661 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2662 break; | 2480 break; |
| 2663 } | 2481 } |
| 2664 case NUMBER_CHECK: { | 2482 case NUMBER_CHECK: { |
| 2665 Label fast; | 2483 Label fast; |
| 2666 // Check that the object is a smi or a heap number. | 2484 // Check that the object is a smi or a heap number. |
| 2667 __ JumpIfSmi(rdx, &fast); | 2485 __ JumpIfSmi(reg, &fast); |
| 2668 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); | 2486 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax); |
| 2669 __ j(not_equal, &miss); | 2487 __ j(not_equal, miss); |
| 2670 __ bind(&fast); | 2488 __ bind(&fast); |
| 2671 // Check that the maps starting from the prototype haven't changed. | 2489 // Check that the maps starting from the prototype haven't changed. |
| 2672 GenerateDirectLoadGlobalFunctionPrototype( | 2490 GenerateDirectLoadGlobalFunctionPrototype( |
| 2673 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); | 2491 masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss); |
| 2674 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2675 CheckPrototypes( | |
| 2676 IC::CurrentTypeOf(prototype, isolate()), | |
| 2677 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2678 break; | 2492 break; |
| 2679 } | 2493 } |
| 2680 case BOOLEAN_CHECK: { | 2494 case BOOLEAN_CHECK: { |
| 2681 GenerateBooleanCheck(rdx, &miss); | 2495 GenerateBooleanCheck(reg, miss); |
| 2682 // Check that the maps starting from the prototype haven't changed. | 2496 // Check that the maps starting from the prototype haven't changed. |
| 2683 GenerateDirectLoadGlobalFunctionPrototype( | 2497 GenerateDirectLoadGlobalFunctionPrototype( |
| 2684 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); | 2498 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss); |
| 2685 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2686 CheckPrototypes( | |
| 2687 IC::CurrentTypeOf(prototype, isolate()), | |
| 2688 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2689 break; | 2499 break; |
| 2690 } | 2500 } |
| 2691 } | 2501 } |
| 2692 | 2502 |
| 2693 Label success; | 2503 if (check != RECEIVER_MAP_CHECK) { |
| 2694 __ jmp(&success); | 2504 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2505 reg = CheckPrototypes( | |
| 2506 IC::CurrentTypeOf(prototype, isolate()), | |
| 2507 rax, holder, rbx, rdx, rdi, name, miss); | |
| 2508 } | |
| 2695 | 2509 |
| 2696 // Handle call cache miss. | 2510 return reg; |
| 2697 __ bind(&miss); | |
| 2698 GenerateMissBranch(); | |
| 2699 | |
| 2700 __ bind(&success); | |
| 2701 } | 2511 } |
| 2702 | 2512 |
| 2703 | 2513 |
| 2704 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2514 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| 2705 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2515 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2706 ? CALL_AS_FUNCTION | 2516 ? CALL_AS_FUNCTION |
| 2707 : CALL_AS_METHOD; | 2517 : CALL_AS_METHOD; |
| 2708 ParameterCount expected(function); | 2518 ParameterCount expected(function); |
| 2709 __ InvokeFunction(function, expected, arguments(), | 2519 __ InvokeFunction(function, expected, arguments(), |
| 2710 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2520 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2711 } | 2521 } |
| 2712 | 2522 |
| 2713 | 2523 |
| 2714 Handle<Code> CallStubCompiler::CompileCallConstant( | 2524 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2715 Handle<Object> object, | 2525 Handle<Object> object, |
| 2716 Handle<JSObject> holder, | 2526 Handle<JSObject> holder, |
| 2717 Handle<Name> name, | 2527 Handle<Name> name, |
| 2718 CheckType check, | 2528 CheckType check, |
| 2719 Handle<JSFunction> function) { | 2529 Handle<JSFunction> function) { |
| 2720 if (HasCustomCallGenerator(function)) { | 2530 if (HasCustomCallGenerator(function)) { |
| 2721 Handle<Code> code = CompileCustomCall(object, holder, | 2531 Handle<Code> code = CompileCustomCall(object, holder, |
| 2722 Handle<PropertyCell>::null(), | 2532 Handle<PropertyCell>::null(), |
| 2723 function, Handle<String>::cast(name), | 2533 function, Handle<String>::cast(name), |
| 2724 Code::FAST); | 2534 Code::FAST); |
| 2725 // A null handle means bail out to the regular compiler code below. | 2535 // A null handle means bail out to the regular compiler code below. |
| 2726 if (!code.is_null()) return code; | 2536 if (!code.is_null()) return code; |
| 2727 } | 2537 } |
| 2728 | 2538 |
| 2729 CompileHandlerFrontend(object, holder, name, check); | 2539 Label miss; |
| 2540 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2541 PatchGlobalProxy(object); | |
| 2730 CompileHandlerBackend(function); | 2542 CompileHandlerBackend(function); |
| 2543 HandlerFrontendFooter(&miss); | |
| 2731 | 2544 |
| 2732 // Return the generated code. | 2545 // Return the generated code. |
| 2733 return GetCode(function); | 2546 return GetCode(function); |
| 2734 } | 2547 } |
| 2735 | 2548 |
| 2736 | 2549 |
| 2737 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2550 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2738 Handle<JSObject> holder, | 2551 Handle<JSObject> holder, |
| 2739 Handle<Name> name) { | 2552 Handle<Name> name) { |
| 2740 // ----------- S t a t e ------------- | |
| 2741 // rcx : function name | |
| 2742 // rsp[0] : return address | |
| 2743 // rsp[8] : argument argc | |
| 2744 // rsp[16] : argument argc - 1 | |
| 2745 // ... | |
| 2746 // rsp[argc * 8] : argument 1 | |
| 2747 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 2748 // ----------------------------------- | |
| 2749 Label miss; | 2553 Label miss; |
| 2750 GenerateNameCheck(name, &miss); | 2554 GenerateNameCheck(name, &miss); |
| 2751 | 2555 |
| 2752 | |
| 2753 LookupResult lookup(isolate()); | 2556 LookupResult lookup(isolate()); |
| 2754 LookupPostInterceptor(holder, name, &lookup); | 2557 LookupPostInterceptor(holder, name, &lookup); |
| 2755 | 2558 |
| 2756 // Get the receiver from the stack. | 2559 // Get the receiver from the stack. |
| 2757 StackArgumentsAccessor args(rsp, arguments()); | 2560 StackArgumentsAccessor args(rsp, arguments()); |
| 2758 __ movq(rdx, args.GetReceiverOperand()); | 2561 __ movq(rdx, args.GetReceiverOperand()); |
| 2759 | 2562 |
| 2760 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2563 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
| 2761 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, | 2564 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
| 2762 &miss); | 2565 &miss); |
| 2763 | 2566 |
| 2764 // Restore receiver. | 2567 // Restore receiver. |
| 2765 __ movq(rdx, args.GetReceiverOperand()); | 2568 __ movq(rdx, args.GetReceiverOperand()); |
| 2766 | 2569 |
| 2767 // Check that the function really is a function. | 2570 // Check that the function really is a function. |
| 2768 __ JumpIfSmi(rax, &miss); | 2571 __ JumpIfSmi(rax, &miss); |
| 2769 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 2572 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2770 __ j(not_equal, &miss); | 2573 __ j(not_equal, &miss); |
| 2771 | 2574 |
| 2772 // Patch the receiver on the stack with the global proxy if | 2575 // Patch the receiver on the stack with the global proxy if |
| 2773 // necessary. | 2576 // necessary. |
| 2774 if (object->IsGlobalObject()) { | 2577 if (object->IsGlobalObject()) { |
|
Igor Sheludko
2013/11/28 12:54:27
Looks like PatchGlobalProxy(object);
| |
| 2775 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2578 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2776 __ movq(args.GetReceiverOperand(), rdx); | 2579 __ movq(args.GetReceiverOperand(), rdx); |
| 2777 } | 2580 } |
| 2778 | 2581 |
| 2779 // Invoke the function. | 2582 // Invoke the function. |
| 2780 __ movq(rdi, rax); | 2583 __ movq(rdi, rax); |
| 2781 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2584 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2782 ? CALL_AS_FUNCTION | 2585 ? CALL_AS_FUNCTION |
| 2783 : CALL_AS_METHOD; | 2586 : CALL_AS_METHOD; |
| 2784 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 2587 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2785 NullCallWrapper(), call_kind); | 2588 NullCallWrapper(), call_kind); |
| 2786 | 2589 |
| 2787 // Handle load cache miss. | 2590 // Handle load cache miss. |
| 2788 __ bind(&miss); | 2591 __ bind(&miss); |
| 2789 GenerateMissBranch(); | 2592 GenerateMissBranch(); |
| 2790 | 2593 |
| 2791 // Return the generated code. | 2594 // Return the generated code. |
| 2792 return GetCode(Code::FAST, name); | 2595 return GetCode(Code::FAST, name); |
| 2793 } | 2596 } |
| 2794 | 2597 |
| 2795 | 2598 |
| 2796 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2599 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2797 Handle<JSObject> object, | 2600 Handle<JSObject> object, |
| 2798 Handle<GlobalObject> holder, | 2601 Handle<GlobalObject> holder, |
| 2799 Handle<PropertyCell> cell, | 2602 Handle<PropertyCell> cell, |
| 2800 Handle<JSFunction> function, | 2603 Handle<JSFunction> function, |
| 2801 Handle<Name> name) { | 2604 Handle<Name> name) { |
| 2802 // ----------- S t a t e ------------- | |
| 2803 // rcx : function name | |
| 2804 // rsp[0] : return address | |
| 2805 // rsp[8] : argument argc | |
| 2806 // rsp[16] : argument argc - 1 | |
| 2807 // ... | |
| 2808 // rsp[argc * 8] : argument 1 | |
| 2809 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 2810 // ----------------------------------- | |
| 2811 | |
| 2812 if (HasCustomCallGenerator(function)) { | 2605 if (HasCustomCallGenerator(function)) { |
| 2813 Handle<Code> code = CompileCustomCall( | 2606 Handle<Code> code = CompileCustomCall( |
| 2814 object, holder, cell, function, Handle<String>::cast(name), | 2607 object, holder, cell, function, Handle<String>::cast(name), |
| 2815 Code::NORMAL); | 2608 Code::NORMAL); |
| 2816 // A null handle means bail out to the regular compiler code below. | 2609 // A null handle means bail out to the regular compiler code below. |
| 2817 if (!code.is_null()) return code; | 2610 if (!code.is_null()) return code; |
| 2818 } | 2611 } |
| 2819 | 2612 |
| 2820 Label miss; | 2613 Label miss; |
| 2821 GenerateNameCheck(name, &miss); | 2614 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2822 | |
| 2823 StackArgumentsAccessor args(rsp, arguments()); | |
| 2824 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
| 2825 GenerateLoadFunctionFromCell(cell, function, &miss); | 2615 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2826 | 2616 PatchGlobalProxy(object); |
| 2827 // Patch the receiver on the stack with the global proxy. | |
| 2828 if (object->IsGlobalObject()) { | |
| 2829 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2830 __ movq(args.GetReceiverOperand(), rdx); | |
| 2831 } | |
| 2832 | 2617 |
| 2833 // Set up the context (function already in rdi). | 2618 // Set up the context (function already in rdi). |
| 2834 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2619 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2835 | 2620 |
| 2836 // Jump to the cached code (tail call). | 2621 // Jump to the cached code (tail call). |
| 2837 Counters* counters = isolate()->counters(); | 2622 Counters* counters = isolate()->counters(); |
| 2838 __ IncrementCounter(counters->call_global_inline(), 1); | 2623 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2839 ParameterCount expected(function->shared()->formal_parameter_count()); | 2624 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2840 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2625 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2841 ? CALL_AS_FUNCTION | 2626 ? CALL_AS_FUNCTION |
| 2842 : CALL_AS_METHOD; | 2627 : CALL_AS_METHOD; |
| 2843 // We call indirectly through the code field in the function to | 2628 // We call indirectly through the code field in the function to |
| 2844 // allow recompilation to take effect without changing any of the | 2629 // allow recompilation to take effect without changing any of the |
| 2845 // call sites. | 2630 // call sites. |
| 2846 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2631 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2847 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | 2632 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2848 NullCallWrapper(), call_kind); | 2633 NullCallWrapper(), call_kind); |
| 2849 | 2634 |
| 2850 // Handle call cache miss. | 2635 HandlerFrontendFooter(&miss); |
| 2851 __ bind(&miss); | |
| 2852 __ IncrementCounter(counters->call_global_inline_miss(), 1); | |
| 2853 GenerateMissBranch(); | |
| 2854 | 2636 |
| 2855 // Return the generated code. | 2637 // Return the generated code. |
| 2856 return GetCode(Code::NORMAL, name); | 2638 return GetCode(Code::NORMAL, name); |
| 2857 } | 2639 } |
| 2858 | 2640 |
| 2859 | 2641 |
| 2860 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2642 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2861 Handle<JSObject> object, | 2643 Handle<JSObject> object, |
| 2862 Handle<JSObject> holder, | 2644 Handle<JSObject> holder, |
| 2863 Handle<Name> name, | 2645 Handle<Name> name, |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3227 // ----------------------------------- | 3009 // ----------------------------------- |
| 3228 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3010 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3229 } | 3011 } |
| 3230 | 3012 |
| 3231 | 3013 |
| 3232 #undef __ | 3014 #undef __ |
| 3233 | 3015 |
| 3234 } } // namespace v8::internal | 3016 } } // namespace v8::internal |
| 3235 | 3017 |
| 3236 #endif // V8_TARGET_ARCH_X64 | 3018 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |