Mercurial > hg > graal-jvmci-8
comparison src/share/vm/oops/constMethod.cpp @ 7462:ade95d680b42
8004728: Add hotspot support for parameter reflection
Summary: Add hotspot support for parameter reflection
Reviewed-by: acorn, jrose, coleenp
Contributed-by: eric.mccorkle@oracle.com
author | coleenp |
---|---|
date | Tue, 08 Jan 2013 14:01:36 -0500 |
parents | b2dbd323c668 |
children | 16fb9f942703 |
comparison
equal
deleted
inserted
replaced
7460:6c3f47d964f3 | 7462:ade95d680b42 |
---|---|
37 int byte_code_size, | 37 int byte_code_size, |
38 int compressed_line_number_size, | 38 int compressed_line_number_size, |
39 int localvariable_table_length, | 39 int localvariable_table_length, |
40 int exception_table_length, | 40 int exception_table_length, |
41 int checked_exceptions_length, | 41 int checked_exceptions_length, |
42 int method_parameters_length, | |
42 u2 generic_signature_index, | 43 u2 generic_signature_index, |
43 MethodType method_type, | 44 MethodType method_type, |
44 TRAPS) { | 45 TRAPS) { |
45 int size = ConstMethod::size(byte_code_size, | 46 int size = ConstMethod::size(byte_code_size, |
46 compressed_line_number_size, | 47 compressed_line_number_size, |
47 localvariable_table_length, | 48 localvariable_table_length, |
48 exception_table_length, | 49 exception_table_length, |
49 checked_exceptions_length, | 50 checked_exceptions_length, |
50 generic_signature_index); | 51 method_parameters_length, |
52 generic_signature_index); | |
51 return new (loader_data, size, true, THREAD) ConstMethod( | 53 return new (loader_data, size, true, THREAD) ConstMethod( |
52 byte_code_size, compressed_line_number_size, localvariable_table_length, | 54 byte_code_size, compressed_line_number_size, localvariable_table_length, |
53 exception_table_length, checked_exceptions_length, generic_signature_index, | 55 exception_table_length, checked_exceptions_length, |
56 method_parameters_length, generic_signature_index, | |
54 method_type, size); | 57 method_type, size); |
55 } | 58 } |
56 | 59 |
57 ConstMethod::ConstMethod(int byte_code_size, | 60 ConstMethod::ConstMethod(int byte_code_size, |
58 int compressed_line_number_size, | 61 int compressed_line_number_size, |
59 int localvariable_table_length, | 62 int localvariable_table_length, |
60 int exception_table_length, | 63 int exception_table_length, |
61 int checked_exceptions_length, | 64 int checked_exceptions_length, |
65 int method_parameters_length, | |
62 u2 generic_signature_index, | 66 u2 generic_signature_index, |
63 MethodType method_type, | 67 MethodType method_type, |
64 int size) { | 68 int size) { |
65 | 69 |
66 No_Safepoint_Verifier no_safepoint; | 70 No_Safepoint_Verifier no_safepoint; |
72 set_constMethod_size(size); | 76 set_constMethod_size(size); |
73 set_inlined_tables_length(generic_signature_index, | 77 set_inlined_tables_length(generic_signature_index, |
74 checked_exceptions_length, | 78 checked_exceptions_length, |
75 compressed_line_number_size, | 79 compressed_line_number_size, |
76 localvariable_table_length, | 80 localvariable_table_length, |
77 exception_table_length); | 81 exception_table_length, |
82 method_parameters_length); | |
78 set_method_type(method_type); | 83 set_method_type(method_type); |
79 assert(this->size() == size, "wrong size for object"); | 84 assert(this->size() == size, "wrong size for object"); |
80 } | 85 } |
81 | 86 |
82 | 87 |
90 } | 95 } |
91 | 96 |
92 // How big must this constMethodObject be? | 97 // How big must this constMethodObject be? |
93 | 98 |
94 int ConstMethod::size(int code_size, | 99 int ConstMethod::size(int code_size, |
95 int compressed_line_number_size, | 100 int compressed_line_number_size, |
96 int local_variable_table_length, | 101 int local_variable_table_length, |
97 int exception_table_length, | 102 int exception_table_length, |
98 int checked_exceptions_length, | 103 int checked_exceptions_length, |
99 u2 generic_signature_index) { | 104 int method_parameters_length, |
105 u2 generic_signature_index) { | |
100 int extra_bytes = code_size; | 106 int extra_bytes = code_size; |
101 if (compressed_line_number_size > 0) { | 107 if (compressed_line_number_size > 0) { |
102 extra_bytes += compressed_line_number_size; | 108 extra_bytes += compressed_line_number_size; |
103 } | 109 } |
104 if (checked_exceptions_length > 0) { | 110 if (checked_exceptions_length > 0) { |
114 extra_bytes += sizeof(u2); | 120 extra_bytes += sizeof(u2); |
115 extra_bytes += exception_table_length * sizeof(ExceptionTableElement); | 121 extra_bytes += exception_table_length * sizeof(ExceptionTableElement); |
116 } | 122 } |
117 if (generic_signature_index != 0) { | 123 if (generic_signature_index != 0) { |
118 extra_bytes += sizeof(u2); | 124 extra_bytes += sizeof(u2); |
125 } | |
126 if (method_parameters_length > 0) { | |
127 extra_bytes += sizeof(u2); | |
128 extra_bytes += method_parameters_length * sizeof(MethodParametersElement); | |
119 } | 129 } |
120 int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; | 130 int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; |
121 return align_object_size(header_size() + extra_words); | 131 return align_object_size(header_size() + extra_words); |
122 } | 132 } |
123 | 133 |
141 } | 151 } |
142 | 152 |
143 u2* ConstMethod::checked_exceptions_length_addr() const { | 153 u2* ConstMethod::checked_exceptions_length_addr() const { |
144 // Located immediately before the generic signature index. | 154 // Located immediately before the generic signature index. |
145 assert(has_checked_exceptions(), "called only if table is present"); | 155 assert(has_checked_exceptions(), "called only if table is present"); |
156 if(has_method_parameters()) { | |
157 // If method parameters present, locate immediately before them. | |
158 return (u2*)method_parameters_start() - 1; | |
159 } else { | |
160 // Else, the exception table is at the end of the constMethod. | |
161 return has_generic_signature() ? (last_u2_element() - 1) : | |
162 last_u2_element(); | |
163 } | |
164 } | |
165 | |
166 u2* ConstMethod::method_parameters_length_addr() const { | |
167 assert(has_method_parameters(), "called only if table is present"); | |
146 return has_generic_signature() ? (last_u2_element() - 1) : | 168 return has_generic_signature() ? (last_u2_element() - 1) : |
147 last_u2_element(); | 169 last_u2_element(); |
148 } | 170 } |
149 | 171 |
150 u2* ConstMethod::exception_table_length_addr() const { | 172 u2* ConstMethod::exception_table_length_addr() const { |
151 assert(has_exception_handler(), "called only if table is present"); | 173 assert(has_exception_handler(), "called only if table is present"); |
152 if (has_checked_exceptions()) { | 174 if (has_checked_exceptions()) { |
153 // If checked_exception present, locate immediately before them. | 175 // If checked_exception present, locate immediately before them. |
154 return (u2*) checked_exceptions_start() - 1; | 176 return (u2*) checked_exceptions_start() - 1; |
155 } else { | 177 } else { |
156 // Else, the exception table is at the end of the constMethod or | 178 if(has_method_parameters()) { |
157 // immediately before the generic signature index. | 179 // If method parameters present, locate immediately before them. |
180 return (u2*)method_parameters_start() - 1; | |
181 } else { | |
182 // Else, the exception table is at the end of the constMethod. | |
158 return has_generic_signature() ? (last_u2_element() - 1) : | 183 return has_generic_signature() ? (last_u2_element() - 1) : |
159 last_u2_element(); | 184 last_u2_element(); |
185 } | |
160 } | 186 } |
161 } | 187 } |
162 | 188 |
163 u2* ConstMethod::localvariable_table_length_addr() const { | 189 u2* ConstMethod::localvariable_table_length_addr() const { |
164 assert(has_localvariable_table(), "called only if table is present"); | 190 assert(has_localvariable_table(), "called only if table is present"); |
168 } else { | 194 } else { |
169 if (has_checked_exceptions()) { | 195 if (has_checked_exceptions()) { |
170 // If checked_exception present, locate immediately before them. | 196 // If checked_exception present, locate immediately before them. |
171 return (u2*) checked_exceptions_start() - 1; | 197 return (u2*) checked_exceptions_start() - 1; |
172 } else { | 198 } else { |
173 // Else, the linenumber table is at the end of the constMethod or | 199 if(has_method_parameters()) { |
174 // immediately before the generic signature index. | 200 // If method parameters present, locate immediately before them. |
201 return (u2*)method_parameters_start() - 1; | |
202 } else { | |
203 // Else, the exception table is at the end of the constMethod. | |
175 return has_generic_signature() ? (last_u2_element() - 1) : | 204 return has_generic_signature() ? (last_u2_element() - 1) : |
176 last_u2_element(); | 205 last_u2_element(); |
177 } | 206 } |
207 } | |
178 } | 208 } |
179 } | 209 } |
180 | 210 |
181 // Update the flags to indicate the presence of these optional fields. | 211 // Update the flags to indicate the presence of these optional fields. |
182 void ConstMethod::set_inlined_tables_length(u2 generic_signature_index, | 212 void ConstMethod::set_inlined_tables_length(u2 generic_signature_index, |
183 int checked_exceptions_len, | 213 int checked_exceptions_len, |
184 int compressed_line_number_size, | 214 int compressed_line_number_size, |
185 int localvariable_table_len, | 215 int localvariable_table_len, |
186 int exception_table_len) { | 216 int exception_table_len, |
187 // Must be done in the order below, otherwise length_addr accessors | 217 int method_parameters_len) { |
188 // will not work. Only set bit in header if length is positive. | |
189 assert(_flags == 0, "Error"); | 218 assert(_flags == 0, "Error"); |
190 if (compressed_line_number_size > 0) { | 219 if (compressed_line_number_size > 0) |
191 _flags |= _has_linenumber_table; | 220 _flags |= _has_linenumber_table; |
192 } | 221 if (generic_signature_index != 0) |
193 if (generic_signature_index != 0) { | |
194 _flags |= _has_generic_signature; | 222 _flags |= _has_generic_signature; |
223 if (method_parameters_len > 0) | |
224 _flags |= _has_method_parameters; | |
225 if (checked_exceptions_len > 0) | |
226 _flags |= _has_checked_exceptions; | |
227 if (exception_table_len > 0) | |
228 _flags |= _has_exception_table; | |
229 if (localvariable_table_len > 0) | |
230 _flags |= _has_localvariable_table; | |
231 | |
232 // This code is extremely brittle and should possibly be revised. | |
233 // The *_length_addr functions walk backwards through the | |
234 // constMethod data, using each of the length indexes ahead of them, | |
235 // as well as the flags variable. Therefore, the indexes must be | |
236 // initialized in reverse order, or else they will compute the wrong | |
237 // offsets. Moving the initialization of _flags into a separate | |
238 // block solves *half* of the problem, but the following part will | |
239 // still break if the order is not exactly right. | |
240 // | |
241 // Also, the servicability agent needs to be informed anytime | |
242 // anything is added here. It might be advisable to have some sort | |
243 // of indication of this inline. | |
244 if (generic_signature_index != 0) | |
195 *(generic_signature_index_addr()) = generic_signature_index; | 245 *(generic_signature_index_addr()) = generic_signature_index; |
196 } | 246 // New data should probably go here. |
197 if (checked_exceptions_len > 0) { | 247 if (method_parameters_len > 0) |
198 _flags |= _has_checked_exceptions; | 248 *(method_parameters_length_addr()) = method_parameters_len; |
249 if (checked_exceptions_len > 0) | |
199 *(checked_exceptions_length_addr()) = checked_exceptions_len; | 250 *(checked_exceptions_length_addr()) = checked_exceptions_len; |
200 } | 251 if (exception_table_len > 0) |
201 if (exception_table_len > 0) { | |
202 _flags |= _has_exception_table; | |
203 *(exception_table_length_addr()) = exception_table_len; | 252 *(exception_table_length_addr()) = exception_table_len; |
204 } | 253 if (localvariable_table_len > 0) |
205 if (localvariable_table_len > 0) { | |
206 _flags |= _has_localvariable_table; | |
207 *(localvariable_table_length_addr()) = localvariable_table_len; | 254 *(localvariable_table_length_addr()) = localvariable_table_len; |
208 } | 255 } |
256 | |
257 int ConstMethod::method_parameters_length() const { | |
258 return has_method_parameters() ? *(method_parameters_length_addr()) : 0; | |
259 } | |
260 | |
261 MethodParametersElement* ConstMethod::method_parameters_start() const { | |
262 u2* addr = method_parameters_length_addr(); | |
263 u2 length = *addr; | |
264 assert(length > 0, "should only be called if table is present"); | |
265 addr -= length * sizeof(MethodParametersElement) / sizeof(u2); | |
266 return (MethodParametersElement*) addr; | |
209 } | 267 } |
210 | 268 |
211 | 269 |
212 int ConstMethod::checked_exceptions_length() const { | 270 int ConstMethod::checked_exceptions_length() const { |
213 return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0; | 271 return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0; |
296 } | 354 } |
297 compressed_table_end += stream.position(); | 355 compressed_table_end += stream.position(); |
298 } | 356 } |
299 guarantee(compressed_table_end <= m_end, "invalid method layout"); | 357 guarantee(compressed_table_end <= m_end, "invalid method layout"); |
300 // Verify checked exceptions, exception table and local variable tables | 358 // Verify checked exceptions, exception table and local variable tables |
359 if (has_method_parameters()) { | |
360 u2* addr = method_parameters_length_addr(); | |
361 guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); | |
362 } | |
301 if (has_checked_exceptions()) { | 363 if (has_checked_exceptions()) { |
302 u2* addr = checked_exceptions_length_addr(); | 364 u2* addr = checked_exceptions_length_addr(); |
303 guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); | 365 guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); |
304 } | 366 } |
305 if (has_exception_handler()) { | 367 if (has_exception_handler()) { |
316 uncompressed_table_start = (u2*) localvariable_table_start(); | 378 uncompressed_table_start = (u2*) localvariable_table_start(); |
317 } else if (has_exception_handler()) { | 379 } else if (has_exception_handler()) { |
318 uncompressed_table_start = (u2*) exception_table_start(); | 380 uncompressed_table_start = (u2*) exception_table_start(); |
319 } else if (has_checked_exceptions()) { | 381 } else if (has_checked_exceptions()) { |
320 uncompressed_table_start = (u2*) checked_exceptions_start(); | 382 uncompressed_table_start = (u2*) checked_exceptions_start(); |
383 } else if (has_method_parameters()) { | |
384 uncompressed_table_start = (u2*) method_parameters_start(); | |
321 } else { | 385 } else { |
322 uncompressed_table_start = (u2*) m_end; | 386 uncompressed_table_start = (u2*) m_end; |
323 } | 387 } |
324 int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end; | 388 int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end; |
325 int max_gap = align_object_size(1)*BytesPerWord; | 389 int max_gap = align_object_size(1)*BytesPerWord; |