Mercurial > hg > graal-jvmci-8
comparison src/share/vm/oops/methodData.hpp @ 12962:5ccbab1c69f3
8026251: New type profiling points: parameters to methods
Summary: x86 interpreter and c1 type profiling for parameters on method entries
Reviewed-by: kvn, twisti
author | roland |
---|---|
date | Tue, 22 Oct 2013 09:51:47 +0200 |
parents | ce0cc25bc5e2 |
children | 6e1826d5c23e 2b8e28fdf503 |
comparison
equal
deleted
inserted
replaced
12961:4748b3308cda | 12962:5ccbab1c69f3 |
---|---|
117 ret_data_tag, | 117 ret_data_tag, |
118 branch_data_tag, | 118 branch_data_tag, |
119 multi_branch_data_tag, | 119 multi_branch_data_tag, |
120 arg_info_data_tag, | 120 arg_info_data_tag, |
121 call_type_data_tag, | 121 call_type_data_tag, |
122 virtual_call_type_data_tag | 122 virtual_call_type_data_tag, |
123 parameters_type_data_tag | |
123 }; | 124 }; |
124 | 125 |
125 enum { | 126 enum { |
126 // The _struct._flags word is formatted as [trap_state:4 | flags:4]. | 127 // The _struct._flags word is formatted as [trap_state:4 | flags:4]. |
127 // The trap state breaks down further as [recompile:1 | reason:3]. | 128 // The trap state breaks down further as [recompile:1 | reason:3]. |
262 class JumpData; | 263 class JumpData; |
263 class BranchData; | 264 class BranchData; |
264 class ArrayData; | 265 class ArrayData; |
265 class MultiBranchData; | 266 class MultiBranchData; |
266 class ArgInfoData; | 267 class ArgInfoData; |
268 class ParametersTypeData; | |
267 | 269 |
268 // ProfileData | 270 // ProfileData |
269 // | 271 // |
270 // A ProfileData object is created to refer to a section of profiling | 272 // A ProfileData object is created to refer to a section of profiling |
271 // data in a structured way. | 273 // data in a structured way. |
395 virtual bool is_ArrayData() const { return false; } | 397 virtual bool is_ArrayData() const { return false; } |
396 virtual bool is_MultiBranchData() const { return false; } | 398 virtual bool is_MultiBranchData() const { return false; } |
397 virtual bool is_ArgInfoData() const { return false; } | 399 virtual bool is_ArgInfoData() const { return false; } |
398 virtual bool is_CallTypeData() const { return false; } | 400 virtual bool is_CallTypeData() const { return false; } |
399 virtual bool is_VirtualCallTypeData()const { return false; } | 401 virtual bool is_VirtualCallTypeData()const { return false; } |
402 virtual bool is_ParametersTypeData() const { return false; } | |
400 | 403 |
401 | 404 |
402 BitData* as_BitData() const { | 405 BitData* as_BitData() const { |
403 assert(is_BitData(), "wrong type"); | 406 assert(is_BitData(), "wrong type"); |
404 return is_BitData() ? (BitData*) this : NULL; | 407 return is_BitData() ? (BitData*) this : NULL; |
444 return is_CallTypeData() ? (CallTypeData*)this : NULL; | 447 return is_CallTypeData() ? (CallTypeData*)this : NULL; |
445 } | 448 } |
446 VirtualCallTypeData* as_VirtualCallTypeData() const { | 449 VirtualCallTypeData* as_VirtualCallTypeData() const { |
447 assert(is_VirtualCallTypeData(), "wrong type"); | 450 assert(is_VirtualCallTypeData(), "wrong type"); |
448 return is_VirtualCallTypeData() ? (VirtualCallTypeData*)this : NULL; | 451 return is_VirtualCallTypeData() ? (VirtualCallTypeData*)this : NULL; |
452 } | |
453 ParametersTypeData* as_ParametersTypeData() const { | |
454 assert(is_ParametersTypeData(), "wrong type"); | |
455 return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL; | |
449 } | 456 } |
450 | 457 |
451 | 458 |
452 // Subclass specific initialization | 459 // Subclass specific initialization |
453 virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {} | 460 virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {} |
765 public: | 772 public: |
766 | 773 |
767 TypeStackSlotEntries(int base_off, int nb_entries) | 774 TypeStackSlotEntries(int base_off, int nb_entries) |
768 : TypeEntries(base_off), _number_of_entries(nb_entries) {} | 775 : TypeEntries(base_off), _number_of_entries(nb_entries) {} |
769 | 776 |
770 static int compute_cell_count(Symbol* signature, int max); | 777 static int compute_cell_count(Symbol* signature, bool include_receiver, int max); |
771 | 778 |
772 void post_initialize(Symbol* signature, bool has_receiver); | 779 void post_initialize(Symbol* signature, bool has_receiver, bool include_receiver); |
773 | 780 |
774 // offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries | 781 // offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries |
775 static int stack_slot_local_offset(int i) { | 782 static int stack_slot_local_offset(int i) { |
776 return i * per_arg_cell_count + stack_slot_entry; | 783 return i * per_arg_cell_count + stack_slot_entry; |
777 } | 784 } |
944 | 951 |
945 void check_number_of_arguments(int total) { | 952 void check_number_of_arguments(int total) { |
946 assert(number_of_arguments() == total, "should be set in DataLayout::initialize"); | 953 assert(number_of_arguments() == total, "should be set in DataLayout::initialize"); |
947 } | 954 } |
948 | 955 |
949 protected: | |
950 // An entry for a return value takes less space than an entry for an | |
951 // argument so if the number of cells exceeds the number of cells | |
952 // needed for an argument, this object contains type information for | |
953 // at least one argument. | |
954 bool has_arguments() const { | |
955 bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count(); | |
956 assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments"); | |
957 return res; | |
958 } | |
959 | |
960 public: | 956 public: |
961 CallTypeData(DataLayout* layout) : | 957 CallTypeData(DataLayout* layout) : |
962 CounterData(layout), | 958 CounterData(layout), |
963 _args(CounterData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()), | 959 _args(CounterData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()), |
964 _ret(cell_count() - ReturnTypeEntry::static_cell_count()) | 960 _ret(cell_count() - ReturnTypeEntry::static_cell_count()) |
1013 | 1009 |
1014 void set_return_type(Klass* k) { | 1010 void set_return_type(Klass* k) { |
1015 assert(has_return(), "no return!"); | 1011 assert(has_return(), "no return!"); |
1016 intptr_t current = _ret.type(); | 1012 intptr_t current = _ret.type(); |
1017 _ret.set_type(TypeEntries::with_status(k, current)); | 1013 _ret.set_type(TypeEntries::with_status(k, current)); |
1014 } | |
1015 | |
1016 // An entry for a return value takes less space than an entry for an | |
1017 // argument so if the number of cells exceeds the number of cells | |
1018 // needed for an argument, this object contains type information for | |
1019 // at least one argument. | |
1020 bool has_arguments() const { | |
1021 bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count(); | |
1022 assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments"); | |
1023 return res; | |
1018 } | 1024 } |
1019 | 1025 |
1020 // An entry for a return value takes less space than an entry for an | 1026 // An entry for a return value takes less space than an entry for an |
1021 // argument, so if the remainder of the number of cells divided by | 1027 // argument, so if the remainder of the number of cells divided by |
1022 // the number of cells for an argument is not null, a return value | 1028 // the number of cells for an argument is not null, a return value |
1211 | 1217 |
1212 void check_number_of_arguments(int total) { | 1218 void check_number_of_arguments(int total) { |
1213 assert(number_of_arguments() == total, "should be set in DataLayout::initialize"); | 1219 assert(number_of_arguments() == total, "should be set in DataLayout::initialize"); |
1214 } | 1220 } |
1215 | 1221 |
1216 protected: | |
1217 // An entry for a return value takes less space than an entry for an | |
1218 // argument so if the number of cells exceeds the number of cells | |
1219 // needed for an argument, this object contains type information for | |
1220 // at least one argument. | |
1221 bool has_arguments() const { | |
1222 bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count(); | |
1223 assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments"); | |
1224 return res; | |
1225 } | |
1226 | |
1227 public: | 1222 public: |
1228 VirtualCallTypeData(DataLayout* layout) : | 1223 VirtualCallTypeData(DataLayout* layout) : |
1229 VirtualCallData(layout), | 1224 VirtualCallData(layout), |
1230 _args(VirtualCallData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()), | 1225 _args(VirtualCallData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()), |
1231 _ret(cell_count() - ReturnTypeEntry::static_cell_count()) | 1226 _ret(cell_count() - ReturnTypeEntry::static_cell_count()) |
1289 // the number of cells for an argument is not null, a return value | 1284 // the number of cells for an argument is not null, a return value |
1290 // is profiled in this object. | 1285 // is profiled in this object. |
1291 bool has_return() const { | 1286 bool has_return() const { |
1292 bool res = (cell_count_no_header() % TypeStackSlotEntries::per_arg_count()) != 0; | 1287 bool res = (cell_count_no_header() % TypeStackSlotEntries::per_arg_count()) != 0; |
1293 assert (!res || TypeEntriesAtCall::return_profiling_enabled(), "no profiling of return values"); | 1288 assert (!res || TypeEntriesAtCall::return_profiling_enabled(), "no profiling of return values"); |
1289 return res; | |
1290 } | |
1291 | |
1292 // An entry for a return value takes less space than an entry for an | |
1293 // argument so if the number of cells exceeds the number of cells | |
1294 // needed for an argument, this object contains type information for | |
1295 // at least one argument. | |
1296 bool has_arguments() const { | |
1297 bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count(); | |
1298 assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments"); | |
1294 return res; | 1299 return res; |
1295 } | 1300 } |
1296 | 1301 |
1297 // Code generation support | 1302 // Code generation support |
1298 static ByteSize args_data_offset() { | 1303 static ByteSize args_data_offset() { |
1658 } | 1663 } |
1659 | 1664 |
1660 #ifndef PRODUCT | 1665 #ifndef PRODUCT |
1661 void print_data_on(outputStream* st) const; | 1666 void print_data_on(outputStream* st) const; |
1662 #endif | 1667 #endif |
1668 }; | |
1669 | |
1670 // ParametersTypeData | |
1671 // | |
1672 // A ParametersTypeData is used to access profiling information about | |
1673 // types of parameters to a method | |
1674 class ParametersTypeData : public ArrayData { | |
1675 | |
1676 private: | |
1677 TypeStackSlotEntries _parameters; | |
1678 | |
1679 static int stack_slot_local_offset(int i) { | |
1680 assert_profiling_enabled(); | |
1681 return array_start_off_set + TypeStackSlotEntries::stack_slot_local_offset(i); | |
1682 } | |
1683 | |
1684 static int type_local_offset(int i) { | |
1685 assert_profiling_enabled(); | |
1686 return array_start_off_set + TypeStackSlotEntries::type_local_offset(i); | |
1687 } | |
1688 | |
1689 static bool profiling_enabled(); | |
1690 static void assert_profiling_enabled() { | |
1691 assert(profiling_enabled(), "method parameters profiling should be on"); | |
1692 } | |
1693 | |
1694 public: | |
1695 ParametersTypeData(DataLayout* layout) : ArrayData(layout), _parameters(1, number_of_parameters()) { | |
1696 assert(layout->tag() == DataLayout::parameters_type_data_tag, "wrong type"); | |
1697 // Some compilers (VC++) don't want this passed in member initialization list | |
1698 _parameters.set_profile_data(this); | |
1699 } | |
1700 | |
1701 static int compute_cell_count(Method* m); | |
1702 | |
1703 virtual bool is_ParametersTypeData() const { return true; } | |
1704 | |
1705 virtual void post_initialize(BytecodeStream* stream, MethodData* mdo); | |
1706 | |
1707 int number_of_parameters() const { | |
1708 return array_len() / TypeStackSlotEntries::per_arg_count(); | |
1709 } | |
1710 | |
1711 const TypeStackSlotEntries* parameters() const { return &_parameters; } | |
1712 | |
1713 uint stack_slot(int i) const { | |
1714 return _parameters.stack_slot(i); | |
1715 } | |
1716 | |
1717 void set_type(int i, Klass* k) { | |
1718 intptr_t current = _parameters.type(i); | |
1719 _parameters.set_type(i, TypeEntries::with_status((intptr_t)k, current)); | |
1720 } | |
1721 | |
1722 virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) { | |
1723 _parameters.clean_weak_klass_links(is_alive_closure); | |
1724 } | |
1725 | |
1726 #ifndef PRODUCT | |
1727 virtual void print_data_on(outputStream* st) const; | |
1728 #endif | |
1729 | |
1730 static ByteSize stack_slot_offset(int i) { | |
1731 return cell_offset(stack_slot_local_offset(i)); | |
1732 } | |
1733 | |
1734 static ByteSize type_offset(int i) { | |
1735 return cell_offset(type_local_offset(i)); | |
1736 } | |
1663 }; | 1737 }; |
1664 | 1738 |
1665 // MethodData* | 1739 // MethodData* |
1666 // | 1740 // |
1667 // A MethodData* holds information which has been collected about | 1741 // A MethodData* holds information which has been collected about |
1771 bool _would_profile; | 1845 bool _would_profile; |
1772 | 1846 |
1773 // Size of _data array in bytes. (Excludes header and extra_data fields.) | 1847 // Size of _data array in bytes. (Excludes header and extra_data fields.) |
1774 int _data_size; | 1848 int _data_size; |
1775 | 1849 |
1850 // data index for the area dedicated to parameters. -1 if no | |
1851 // parameter profiling. | |
1852 int _parameters_type_data_di; | |
1853 | |
1776 // Beginning of the data entries | 1854 // Beginning of the data entries |
1777 intptr_t _data[1]; | 1855 intptr_t _data[1]; |
1778 | 1856 |
1779 // Helper for size computation | 1857 // Helper for size computation |
1780 static int compute_data_size(BytecodeStream* stream); | 1858 static int compute_data_size(BytecodeStream* stream); |
1840 static bool profile_all_arguments(); | 1918 static bool profile_all_arguments(); |
1841 static bool profile_arguments_for_invoke(methodHandle m, int bci); | 1919 static bool profile_arguments_for_invoke(methodHandle m, int bci); |
1842 static int profile_return_flag(); | 1920 static int profile_return_flag(); |
1843 static bool profile_all_return(); | 1921 static bool profile_all_return(); |
1844 static bool profile_return_for_invoke(methodHandle m, int bci); | 1922 static bool profile_return_for_invoke(methodHandle m, int bci); |
1923 static int profile_parameters_flag(); | |
1924 static bool profile_parameters_jsr292_only(); | |
1925 static bool profile_all_parameters(); | |
1845 | 1926 |
1846 public: | 1927 public: |
1847 static int header_size() { | 1928 static int header_size() { |
1848 return sizeof(MethodData)/wordSize; | 1929 return sizeof(MethodData)/wordSize; |
1849 } | 1930 } |
2046 if (decompile_count() > (uint)PerMethodRecompilationCutoff) { | 2127 if (decompile_count() > (uint)PerMethodRecompilationCutoff) { |
2047 method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff"); | 2128 method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff"); |
2048 } | 2129 } |
2049 } | 2130 } |
2050 | 2131 |
2132 // Return pointer to area dedicated to parameters in MDO | |
2133 ParametersTypeData* parameters_type_data() const { | |
2134 return _parameters_type_data_di != -1 ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL; | |
2135 } | |
2136 | |
2137 int parameters_type_data_di() const { | |
2138 assert(_parameters_type_data_di != -1, "no args type data"); | |
2139 return _parameters_type_data_di; | |
2140 } | |
2141 | |
2051 // Support for code generation | 2142 // Support for code generation |
2052 static ByteSize data_offset() { | 2143 static ByteSize data_offset() { |
2053 return byte_offset_of(MethodData, _data[0]); | 2144 return byte_offset_of(MethodData, _data[0]); |
2054 } | 2145 } |
2055 | 2146 |
2056 static ByteSize invocation_counter_offset() { | 2147 static ByteSize invocation_counter_offset() { |
2057 return byte_offset_of(MethodData, _invocation_counter); | 2148 return byte_offset_of(MethodData, _invocation_counter); |
2058 } | 2149 } |
2059 static ByteSize backedge_counter_offset() { | 2150 static ByteSize backedge_counter_offset() { |
2060 return byte_offset_of(MethodData, _backedge_counter); | 2151 return byte_offset_of(MethodData, _backedge_counter); |
2152 } | |
2153 | |
2154 static ByteSize parameters_type_data_di_offset() { | |
2155 return byte_offset_of(MethodData, _parameters_type_data_di); | |
2061 } | 2156 } |
2062 | 2157 |
2063 // Deallocation support - no pointer fields to deallocate | 2158 // Deallocation support - no pointer fields to deallocate |
2064 void deallocate_contents(ClassLoaderData* loader_data) {} | 2159 void deallocate_contents(ClassLoaderData* loader_data) {} |
2065 | 2160 |
2081 | 2176 |
2082 // verification | 2177 // verification |
2083 void verify_on(outputStream* st); | 2178 void verify_on(outputStream* st); |
2084 void verify_data_on(outputStream* st); | 2179 void verify_data_on(outputStream* st); |
2085 | 2180 |
2181 static bool profile_parameters_for_method(methodHandle m); | |
2086 static bool profile_arguments(); | 2182 static bool profile_arguments(); |
2087 static bool profile_return(); | 2183 static bool profile_return(); |
2184 static bool profile_parameters(); | |
2088 static bool profile_return_jsr292_only(); | 2185 static bool profile_return_jsr292_only(); |
2089 }; | 2186 }; |
2090 | 2187 |
2091 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP | 2188 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP |