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