Mercurial > hg > truffle
comparison src/cpu/ppc/vm/interp_masm_ppc_64.cpp @ 20710:c5e86c5cd22e
8066964: ppc64: argument and return type profiling, fix problem with popframe
Reviewed-by: roland, kvn
author | goetz |
---|---|
date | Fri, 12 Dec 2014 08:48:56 +0100 |
parents | f6bde7889409 |
children |
comparison
equal
deleted
inserted
replaced
20709:28f116adb50c | 20710:c5e86c5cd22e |
---|---|
543 // Index check | 543 // Index check |
544 lwz(Rlength, arrayOopDesc::length_offset_in_bytes(), Rarray); | 544 lwz(Rlength, arrayOopDesc::length_offset_in_bytes(), Rarray); |
545 cmplw(CCR0, Rindex, Rlength); | 545 cmplw(CCR0, Rindex, Rlength); |
546 sldi(RsxtIndex, RsxtIndex, index_shift); | 546 sldi(RsxtIndex, RsxtIndex, index_shift); |
547 blt(CCR0, LnotOOR); | 547 blt(CCR0, LnotOOR); |
548 // Index should be in R17_tos, array should be in R4_ARG2. | |
549 mr(R17_tos, Rindex); | |
550 mr(R4_ARG2, Rarray); | |
548 load_dispatch_table(Rtmp, (address*)Interpreter::_throw_ArrayIndexOutOfBoundsException_entry); | 551 load_dispatch_table(Rtmp, (address*)Interpreter::_throw_ArrayIndexOutOfBoundsException_entry); |
549 mtctr(Rtmp); | 552 mtctr(Rtmp); |
550 bctr(); | 553 bctr(); |
551 | 554 |
552 if (!ImplicitNullChecks) { | 555 if (!ImplicitNullChecks) { |
1677 if (start_row > 0) { | 1680 if (start_row > 0) { |
1678 b(done); | 1681 b(done); |
1679 } | 1682 } |
1680 } | 1683 } |
1681 | 1684 |
1685 // Argument and return type profilig. | |
1686 // kills: tmp, tmp2, R0, CR0, CR1 | |
1687 void InterpreterMacroAssembler::profile_obj_type(Register obj, Register mdo_addr_base, | |
1688 RegisterOrConstant mdo_addr_offs, Register tmp, Register tmp2) { | |
1689 Label do_nothing, do_update; | |
1690 | |
1691 // tmp2 = obj is allowed | |
1692 assert_different_registers(obj, mdo_addr_base, tmp, R0); | |
1693 assert_different_registers(tmp2, mdo_addr_base, tmp, R0); | |
1694 const Register klass = tmp2; | |
1695 | |
1696 verify_oop(obj); | |
1697 | |
1698 ld(tmp, mdo_addr_offs, mdo_addr_base); | |
1699 | |
1700 // Set null_seen if obj is 0. | |
1701 cmpdi(CCR0, obj, 0); | |
1702 ori(R0, tmp, TypeEntries::null_seen); | |
1703 beq(CCR0, do_update); | |
1704 | |
1705 load_klass(klass, obj); | |
1706 | |
1707 clrrdi(R0, tmp, exact_log2(-TypeEntries::type_klass_mask)); | |
1708 // Basically same as andi(R0, tmp, TypeEntries::type_klass_mask); | |
1709 cmpd(CCR1, R0, klass); | |
1710 // Klass seen before, nothing to do (regardless of unknown bit). | |
1711 //beq(CCR1, do_nothing); | |
1712 | |
1713 andi_(R0, klass, TypeEntries::type_unknown); | |
1714 // Already unknown. Nothing to do anymore. | |
1715 //bne(CCR0, do_nothing); | |
1716 crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne | |
1717 beq(CCR0, do_nothing); | |
1718 | |
1719 clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask)); | |
1720 orr(R0, klass, tmp); // Combine klass and null_seen bit (only used if (tmp & type_mask)==0). | |
1721 beq(CCR0, do_update); // First time here. Set profile type. | |
1722 | |
1723 // Different than before. Cannot keep accurate profile. | |
1724 ori(R0, tmp, TypeEntries::type_unknown); | |
1725 | |
1726 bind(do_update); | |
1727 // update profile | |
1728 std(R0, mdo_addr_offs, mdo_addr_base); | |
1729 | |
1730 align(32, 12); | |
1731 bind(do_nothing); | |
1732 } | |
1733 | |
1734 void InterpreterMacroAssembler::profile_arguments_type(Register callee, Register tmp1, Register tmp2, bool is_virtual) { | |
1735 if (!ProfileInterpreter) { | |
1736 return; | |
1737 } | |
1738 | |
1739 assert_different_registers(callee, tmp1, tmp2, R28_mdx); | |
1740 | |
1741 if (MethodData::profile_arguments() || MethodData::profile_return()) { | |
1742 Label profile_continue; | |
1743 | |
1744 test_method_data_pointer(profile_continue); | |
1745 | |
1746 int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size()); | |
1747 | |
1748 lbz(tmp1, in_bytes(DataLayout::tag_offset()) - off_to_start, R28_mdx); | |
1749 cmpwi(CCR0, tmp1, is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag); | |
1750 bne(CCR0, profile_continue); | |
1751 | |
1752 if (MethodData::profile_arguments()) { | |
1753 Label done; | |
1754 int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset()); | |
1755 add(R28_mdx, off_to_args, R28_mdx); | |
1756 | |
1757 for (int i = 0; i < TypeProfileArgsLimit; i++) { | |
1758 if (i > 0 || MethodData::profile_return()) { | |
1759 // If return value type is profiled we may have no argument to profile. | |
1760 ld(tmp1, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args, R28_mdx); | |
1761 cmpdi(CCR0, tmp1, (i+1)*TypeStackSlotEntries::per_arg_count()); | |
1762 addi(tmp1, tmp1, -i*TypeStackSlotEntries::per_arg_count()); | |
1763 blt(CCR0, done); | |
1764 } | |
1765 ld(tmp1, in_bytes(Method::const_offset()), callee); | |
1766 lhz(tmp1, in_bytes(ConstMethod::size_of_parameters_offset()), tmp1); | |
1767 // Stack offset o (zero based) from the start of the argument | |
1768 // list, for n arguments translates into offset n - o - 1 from | |
1769 // the end of the argument list. But there's an extra slot at | |
1770 // the top of the stack. So the offset is n - o from Lesp. | |
1771 ld(tmp2, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args, R28_mdx); | |
1772 subf(tmp1, tmp2, tmp1); | |
1773 | |
1774 sldi(tmp1, tmp1, Interpreter::logStackElementSize); | |
1775 ldx(tmp1, tmp1, R15_esp); | |
1776 | |
1777 profile_obj_type(tmp1, R28_mdx, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args, tmp2, tmp1); | |
1778 | |
1779 int to_add = in_bytes(TypeStackSlotEntries::per_arg_size()); | |
1780 addi(R28_mdx, R28_mdx, to_add); | |
1781 off_to_args += to_add; | |
1782 } | |
1783 | |
1784 if (MethodData::profile_return()) { | |
1785 ld(tmp1, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args, R28_mdx); | |
1786 addi(tmp1, tmp1, -TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count()); | |
1787 } | |
1788 | |
1789 bind(done); | |
1790 | |
1791 if (MethodData::profile_return()) { | |
1792 // We're right after the type profile for the last | |
1793 // argument. tmp1 is the number of cells left in the | |
1794 // CallTypeData/VirtualCallTypeData to reach its end. Non null | |
1795 // if there's a return to profile. | |
1796 assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type"); | |
1797 sldi(tmp1, tmp1, exact_log2(DataLayout::cell_size)); | |
1798 add(R28_mdx, tmp1, R28_mdx); | |
1799 } | |
1800 } else { | |
1801 assert(MethodData::profile_return(), "either profile call args or call ret"); | |
1802 update_mdp_by_constant(in_bytes(TypeEntriesAtCall::return_only_size())); | |
1803 } | |
1804 | |
1805 // Mdp points right after the end of the | |
1806 // CallTypeData/VirtualCallTypeData, right after the cells for the | |
1807 // return value type if there's one. | |
1808 align(32, 12); | |
1809 bind(profile_continue); | |
1810 } | |
1811 } | |
1812 | |
1813 void InterpreterMacroAssembler::profile_return_type(Register ret, Register tmp1, Register tmp2) { | |
1814 assert_different_registers(ret, tmp1, tmp2); | |
1815 if (ProfileInterpreter && MethodData::profile_return()) { | |
1816 Label profile_continue; | |
1817 | |
1818 test_method_data_pointer(profile_continue); | |
1819 | |
1820 if (MethodData::profile_return_jsr292_only()) { | |
1821 // If we don't profile all invoke bytecodes we must make sure | |
1822 // it's a bytecode we indeed profile. We can't go back to the | |
1823 // begining of the ProfileData we intend to update to check its | |
1824 // type because we're right after it and we don't known its | |
1825 // length. | |
1826 lbz(tmp1, 0, R14_bcp); | |
1827 lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method); | |
1828 cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic); | |
1829 cmpwi(CCR1, tmp1, Bytecodes::_invokehandle); | |
1830 cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); | |
1831 cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm); | |
1832 cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); | |
1833 bne(CCR0, profile_continue); | |
1834 } | |
1835 | |
1836 profile_obj_type(ret, R28_mdx, -in_bytes(ReturnTypeEntry::size()), tmp1, tmp2); | |
1837 | |
1838 align(32, 12); | |
1839 bind(profile_continue); | |
1840 } | |
1841 } | |
1842 | |
1843 void InterpreterMacroAssembler::profile_parameters_type(Register tmp1, Register tmp2, Register tmp3, Register tmp4) { | |
1844 if (ProfileInterpreter && MethodData::profile_parameters()) { | |
1845 Label profile_continue, done; | |
1846 | |
1847 test_method_data_pointer(profile_continue); | |
1848 | |
1849 // Load the offset of the area within the MDO used for | |
1850 // parameters. If it's negative we're not profiling any parameters. | |
1851 lwz(tmp1, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()), R28_mdx); | |
1852 cmpwi(CCR0, tmp1, 0); | |
1853 blt(CCR0, profile_continue); | |
1854 | |
1855 // Compute a pointer to the area for parameters from the offset | |
1856 // and move the pointer to the slot for the last | |
1857 // parameters. Collect profiling from last parameter down. | |
1858 // mdo start + parameters offset + array length - 1 | |
1859 | |
1860 // Pointer to the parameter area in the MDO. | |
1861 const Register mdp = tmp1; | |
1862 add(mdp, tmp1, R28_mdx); | |
1863 | |
1864 // Pffset of the current profile entry to update. | |
1865 const Register entry_offset = tmp2; | |
1866 // entry_offset = array len in number of cells | |
1867 ld(entry_offset, in_bytes(ArrayData::array_len_offset()), mdp); | |
1868 | |
1869 int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0)); | |
1870 assert(off_base % DataLayout::cell_size == 0, "should be a number of cells"); | |
1871 | |
1872 // entry_offset (number of cells) = array len - size of 1 entry + offset of the stack slot field | |
1873 addi(entry_offset, entry_offset, -TypeStackSlotEntries::per_arg_count() + (off_base / DataLayout::cell_size)); | |
1874 // entry_offset in bytes | |
1875 sldi(entry_offset, entry_offset, exact_log2(DataLayout::cell_size)); | |
1876 | |
1877 Label loop; | |
1878 align(32, 12); | |
1879 bind(loop); | |
1880 | |
1881 // Load offset on the stack from the slot for this parameter. | |
1882 ld(tmp3, entry_offset, mdp); | |
1883 sldi(tmp3, tmp3, Interpreter::logStackElementSize); | |
1884 neg(tmp3, tmp3); | |
1885 // Read the parameter from the local area. | |
1886 ldx(tmp3, tmp3, R18_locals); | |
1887 | |
1888 // Make entry_offset now point to the type field for this parameter. | |
1889 int type_base = in_bytes(ParametersTypeData::type_offset(0)); | |
1890 assert(type_base > off_base, "unexpected"); | |
1891 addi(entry_offset, entry_offset, type_base - off_base); | |
1892 | |
1893 // Profile the parameter. | |
1894 profile_obj_type(tmp3, mdp, entry_offset, tmp4, tmp3); | |
1895 | |
1896 // Go to next parameter. | |
1897 int delta = TypeStackSlotEntries::per_arg_count() * DataLayout::cell_size + (type_base - off_base); | |
1898 cmpdi(CCR0, entry_offset, off_base + delta); | |
1899 addi(entry_offset, entry_offset, -delta); | |
1900 bge(CCR0, loop); | |
1901 | |
1902 align(32, 12); | |
1903 bind(profile_continue); | |
1904 } | |
1905 } | |
1906 | |
1682 // Add a InterpMonitorElem to stack (see frame_sparc.hpp). | 1907 // Add a InterpMonitorElem to stack (see frame_sparc.hpp). |
1683 void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Register Rtemp1, Register Rtemp2) { | 1908 void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Register Rtemp1, Register Rtemp2) { |
1684 | 1909 |
1685 // Very-local scratch registers. | 1910 // Very-local scratch registers. |
1686 const Register esp = Rtemp1; | 1911 const Register esp = Rtemp1; |
2038 const int log2_bytecode_size_limit = 16; | 2263 const int log2_bytecode_size_limit = 16; |
2039 srdi_(Rtmp, reg, log2_bytecode_size_limit); | 2264 srdi_(Rtmp, reg, log2_bytecode_size_limit); |
2040 bne(CCR0, test); | 2265 bne(CCR0, test); |
2041 | 2266 |
2042 address fd = CAST_FROM_FN_PTR(address, verify_return_address); | 2267 address fd = CAST_FROM_FN_PTR(address, verify_return_address); |
2043 unsigned int nbytes_save = 10*8; // 10 volatile gprs | 2268 const int nbytes_save = 11*8; // volatile gprs except R0 |
2044 | 2269 save_volatile_gprs(R1_SP, -nbytes_save); // except R0 |
2045 save_LR_CR(Rtmp); | 2270 save_LR_CR(Rtmp); // Save in old frame. |
2046 push_frame_reg_args(nbytes_save, Rtmp); | 2271 push_frame_reg_args(nbytes_save, Rtmp); |
2047 save_volatile_gprs(R1_SP, 112); // except R0 | |
2048 | 2272 |
2049 load_const_optimized(Rtmp, fd, R0); | 2273 load_const_optimized(Rtmp, fd, R0); |
2050 mr_if_needed(R4_ARG2, reg); | 2274 mr_if_needed(R4_ARG2, reg); |
2051 mr(R3_ARG1, R19_method); | 2275 mr(R3_ARG1, R19_method); |
2052 call_c(Rtmp); // call C | 2276 call_c(Rtmp); // call C |
2053 | 2277 |
2054 restore_volatile_gprs(R1_SP, 112); // except R0 | |
2055 pop_frame(); | 2278 pop_frame(); |
2056 restore_LR_CR(Rtmp); | 2279 restore_LR_CR(Rtmp); |
2280 restore_volatile_gprs(R1_SP, -nbytes_save); // except R0 | |
2057 b(skip); | 2281 b(skip); |
2058 | 2282 |
2059 // Perform a more elaborate out-of-line call. | 2283 // Perform a more elaborate out-of-line call. |
2060 // Not an address; verify it: | 2284 // Not an address; verify it: |
2061 bind(test); | 2285 bind(test); |