1 | /* |
2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "classfile/altHashing.hpp" |
27 | #include "classfile/classLoaderData.inline.hpp" |
28 | #include "classfile/javaClasses.inline.hpp" |
29 | #include "classfile/moduleEntry.hpp" |
30 | #include "classfile/stringTable.hpp" |
31 | #include "classfile/symbolTable.hpp" |
32 | #include "classfile/vmSymbols.hpp" |
33 | #include "code/debugInfo.hpp" |
34 | #include "code/dependencyContext.hpp" |
35 | #include "code/pcDesc.hpp" |
36 | #include "interpreter/interpreter.hpp" |
37 | #include "interpreter/linkResolver.hpp" |
38 | #include "logging/log.hpp" |
39 | #include "logging/logStream.hpp" |
40 | #include "memory/heapShared.inline.hpp" |
41 | #include "memory/metaspaceShared.hpp" |
42 | #include "memory/oopFactory.hpp" |
43 | #include "memory/resourceArea.hpp" |
44 | #include "memory/universe.hpp" |
45 | #include "oops/fieldStreams.hpp" |
46 | #include "oops/instanceKlass.hpp" |
47 | #include "oops/instanceMirrorKlass.hpp" |
48 | #include "oops/klass.hpp" |
49 | #include "oops/method.inline.hpp" |
50 | #include "oops/objArrayOop.inline.hpp" |
51 | #include "oops/oop.inline.hpp" |
52 | #include "oops/symbol.hpp" |
53 | #include "oops/typeArrayOop.inline.hpp" |
54 | #include "prims/jvmtiExport.hpp" |
55 | #include "prims/resolvedMethodTable.hpp" |
56 | #include "runtime/fieldDescriptor.inline.hpp" |
57 | #include "runtime/frame.inline.hpp" |
58 | #include "runtime/handles.inline.hpp" |
59 | #include "runtime/interfaceSupport.inline.hpp" |
60 | #include "runtime/java.hpp" |
61 | #include "runtime/javaCalls.hpp" |
62 | #include "runtime/jniHandles.inline.hpp" |
63 | #include "runtime/safepoint.hpp" |
64 | #include "runtime/safepointVerifiers.hpp" |
65 | #include "runtime/thread.inline.hpp" |
66 | #include "runtime/vframe.inline.hpp" |
67 | #include "utilities/align.hpp" |
68 | #include "utilities/preserveException.hpp" |
69 | #include "utilities/utf8.hpp" |
70 | #if INCLUDE_JVMCI |
71 | #include "jvmci/jvmciJavaClasses.hpp" |
72 | #endif |
73 | |
74 | #define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \ |
75 | klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum); |
76 | |
77 | #if INCLUDE_CDS |
78 | #define INJECTED_FIELD_SERIALIZE_OFFSET(klass, name, signature, may_be_java) \ |
79 | f->do_u4((u4*)&_##name##_offset); |
80 | #endif |
81 | |
82 | #define DECLARE_INJECTED_FIELD(klass, name, signature, may_be_java) \ |
83 | { SystemDictionary::WK_KLASS_ENUM_NAME(klass), vmSymbols::VM_SYMBOL_ENUM_NAME(name##_name), vmSymbols::VM_SYMBOL_ENUM_NAME(signature), may_be_java }, |
84 | |
85 | InjectedField JavaClasses::_injected_fields[] = { |
86 | ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD) |
87 | }; |
88 | |
89 | int JavaClasses::compute_injected_offset(InjectedFieldID id) { |
90 | return _injected_fields[id].compute_offset(); |
91 | } |
92 | |
93 | InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) { |
94 | *field_count = 0; |
95 | |
96 | vmSymbols::SID sid = vmSymbols::find_sid(class_name); |
97 | if (sid == vmSymbols::NO_SID) { |
98 | // Only well known classes can inject fields |
99 | return NULL; |
100 | } |
101 | |
102 | int count = 0; |
103 | int start = -1; |
104 | |
105 | #define LOOKUP_INJECTED_FIELD(klass, name, signature, may_be_java) \ |
106 | if (sid == vmSymbols::VM_SYMBOL_ENUM_NAME(klass)) { \ |
107 | count++; \ |
108 | if (start == -1) start = klass##_##name##_enum; \ |
109 | } |
110 | ALL_INJECTED_FIELDS(LOOKUP_INJECTED_FIELD); |
111 | #undef LOOKUP_INJECTED_FIELD |
112 | |
113 | if (start != -1) { |
114 | *field_count = count; |
115 | return _injected_fields + start; |
116 | } |
117 | return NULL; |
118 | } |
119 | |
120 | |
121 | // Helpful routine for computing field offsets at run time rather than hardcoding them |
122 | // Finds local fields only, including static fields. Static field offsets are from the |
123 | // beginning of the mirror. |
124 | static void compute_offset(int &dest_offset, |
125 | InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol, |
126 | bool is_static = false) { |
127 | fieldDescriptor fd; |
128 | if (ik == NULL) { |
129 | ResourceMark rm; |
130 | log_error(class)("Mismatch JDK version for field: %s type: %s" , name_symbol->as_C_string(), signature_symbol->as_C_string()); |
131 | vm_exit_during_initialization("Invalid layout of well-known class" ); |
132 | } |
133 | |
134 | if (!ik->find_local_field(name_symbol, signature_symbol, &fd) || fd.is_static() != is_static) { |
135 | ResourceMark rm; |
136 | log_error(class)("Invalid layout of %s field: %s type: %s" , ik->external_name(), |
137 | name_symbol->as_C_string(), signature_symbol->as_C_string()); |
138 | #ifndef PRODUCT |
139 | // Prints all fields and offsets |
140 | Log(class) lt; |
141 | LogStream ls(lt.error()); |
142 | ik->print_on(&ls); |
143 | #endif //PRODUCT |
144 | vm_exit_during_initialization("Invalid layout of well-known class: use -Xlog:class+load=info to see the origin of the problem class" ); |
145 | } |
146 | dest_offset = fd.offset(); |
147 | } |
148 | |
149 | // Overloading to pass name as a string. |
150 | static void compute_offset(int& dest_offset, InstanceKlass* ik, |
151 | const char* name_string, Symbol* signature_symbol, |
152 | bool is_static = false) { |
153 | TempNewSymbol name = SymbolTable::probe(name_string, (int)strlen(name_string)); |
154 | if (name == NULL) { |
155 | ResourceMark rm; |
156 | log_error(class)("Name %s should be in the SymbolTable since its class is loaded" , name_string); |
157 | vm_exit_during_initialization("Invalid layout of well-known class" , ik->external_name()); |
158 | } |
159 | compute_offset(dest_offset, ik, name, signature_symbol, is_static); |
160 | } |
161 | |
162 | int java_lang_String::value_offset = 0; |
163 | int java_lang_String::hash_offset = 0; |
164 | int java_lang_String::hashIsZero_offset = 0; |
165 | int java_lang_String::coder_offset = 0; |
166 | |
167 | bool java_lang_String::initialized = false; |
168 | |
169 | bool java_lang_String::is_instance(oop obj) { |
170 | return is_instance_inlined(obj); |
171 | } |
172 | |
173 | #if INCLUDE_CDS |
174 | #define FIELD_SERIALIZE_OFFSET(offset, klass, name, signature, is_static) \ |
175 | f->do_u4((u4*)&offset) |
176 | #endif |
177 | |
178 | #define FIELD_COMPUTE_OFFSET(offset, klass, name, signature, is_static) \ |
179 | compute_offset(offset, klass, name, vmSymbols::signature(), is_static) |
180 | |
181 | #define STRING_FIELDS_DO(macro) \ |
182 | macro(value_offset, k, vmSymbols::value_name(), byte_array_signature, false); \ |
183 | macro(hash_offset, k, "hash", int_signature, false); \ |
184 | macro(hashIsZero_offset, k, "hashIsZero", bool_signature, false); \ |
185 | macro(coder_offset, k, "coder", byte_signature, false); |
186 | |
187 | void java_lang_String::compute_offsets() { |
188 | if (initialized) { |
189 | return; |
190 | } |
191 | |
192 | InstanceKlass* k = SystemDictionary::String_klass(); |
193 | STRING_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
194 | |
195 | initialized = true; |
196 | } |
197 | |
198 | #if INCLUDE_CDS |
199 | void java_lang_String::serialize_offsets(SerializeClosure* f) { |
200 | STRING_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
201 | f->do_bool(&initialized); |
202 | } |
203 | #endif |
204 | |
205 | class CompactStringsFixup : public FieldClosure { |
206 | private: |
207 | bool _value; |
208 | |
209 | public: |
210 | CompactStringsFixup(bool value) : _value(value) {} |
211 | |
212 | void do_field(fieldDescriptor* fd) { |
213 | if (fd->name() == vmSymbols::compact_strings_name()) { |
214 | oop mirror = fd->field_holder()->java_mirror(); |
215 | assert(fd->field_holder() == SystemDictionary::String_klass(), "Should be String" ); |
216 | assert(mirror != NULL, "String must have mirror already" ); |
217 | mirror->bool_field_put(fd->offset(), _value); |
218 | } |
219 | } |
220 | }; |
221 | |
222 | void java_lang_String::set_compact_strings(bool value) { |
223 | CompactStringsFixup fix(value); |
224 | SystemDictionary::String_klass()->do_local_static_fields(&fix); |
225 | } |
226 | |
227 | Handle java_lang_String::basic_create(int length, bool is_latin1, TRAPS) { |
228 | assert(initialized, "Must be initialized" ); |
229 | assert(CompactStrings || !is_latin1, "Must be UTF16 without CompactStrings" ); |
230 | |
231 | // Create the String object first, so there's a chance that the String |
232 | // and the char array it points to end up in the same cache line. |
233 | oop obj; |
234 | obj = SystemDictionary::String_klass()->allocate_instance(CHECK_NH); |
235 | |
236 | // Create the char array. The String object must be handlized here |
237 | // because GC can happen as a result of the allocation attempt. |
238 | Handle h_obj(THREAD, obj); |
239 | int arr_length = is_latin1 ? length : length << 1; // 2 bytes per UTF16. |
240 | typeArrayOop buffer = oopFactory::new_byteArray(arr_length, CHECK_NH);; |
241 | |
242 | // Point the String at the char array |
243 | obj = h_obj(); |
244 | set_value(obj, buffer); |
245 | // No need to zero the offset, allocation zero'ed the entire String object |
246 | set_coder(obj, is_latin1 ? CODER_LATIN1 : CODER_UTF16); |
247 | return h_obj; |
248 | } |
249 | |
250 | Handle java_lang_String::create_from_unicode(const jchar* unicode, int length, TRAPS) { |
251 | bool is_latin1 = CompactStrings && UNICODE::is_latin1(unicode, length); |
252 | Handle h_obj = basic_create(length, is_latin1, CHECK_NH); |
253 | typeArrayOop buffer = value(h_obj()); |
254 | assert(TypeArrayKlass::cast(buffer->klass())->element_type() == T_BYTE, "only byte[]" ); |
255 | if (is_latin1) { |
256 | for (int index = 0; index < length; index++) { |
257 | buffer->byte_at_put(index, (jbyte)unicode[index]); |
258 | } |
259 | } else { |
260 | for (int index = 0; index < length; index++) { |
261 | buffer->char_at_put(index, unicode[index]); |
262 | } |
263 | } |
264 | |
265 | #ifdef ASSERT |
266 | { |
267 | ResourceMark rm; |
268 | char* expected = UNICODE::as_utf8(unicode, length); |
269 | char* actual = as_utf8_string(h_obj()); |
270 | if (strcmp(expected, actual) != 0) { |
271 | tty->print_cr("Unicode conversion failure: %s --> %s" , expected, actual); |
272 | ShouldNotReachHere(); |
273 | } |
274 | } |
275 | #endif |
276 | |
277 | return h_obj; |
278 | } |
279 | |
280 | oop java_lang_String::create_oop_from_unicode(const jchar* unicode, int length, TRAPS) { |
281 | Handle h_obj = create_from_unicode(unicode, length, CHECK_0); |
282 | return h_obj(); |
283 | } |
284 | |
285 | Handle java_lang_String::create_from_str(const char* utf8_str, TRAPS) { |
286 | if (utf8_str == NULL) { |
287 | return Handle(); |
288 | } |
289 | bool has_multibyte, is_latin1; |
290 | int length = UTF8::unicode_length(utf8_str, is_latin1, has_multibyte); |
291 | if (!CompactStrings) { |
292 | has_multibyte = true; |
293 | is_latin1 = false; |
294 | } |
295 | |
296 | Handle h_obj = basic_create(length, is_latin1, CHECK_NH); |
297 | if (length > 0) { |
298 | if (!has_multibyte) { |
299 | const jbyte* src = reinterpret_cast<const jbyte*>(utf8_str); |
300 | ArrayAccess<>::arraycopy_from_native(src, value(h_obj()), typeArrayOopDesc::element_offset<jbyte>(0), length); |
301 | } else if (is_latin1) { |
302 | UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length); |
303 | } else { |
304 | UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length); |
305 | } |
306 | } |
307 | |
308 | #ifdef ASSERT |
309 | // This check is too strict because the input string is not necessarily valid UTF8. |
310 | // For example, it may be created with arbitrary content via jni_NewStringUTF. |
311 | /* |
312 | { |
313 | ResourceMark rm; |
314 | const char* expected = utf8_str; |
315 | char* actual = as_utf8_string(h_obj()); |
316 | if (strcmp(expected, actual) != 0) { |
317 | tty->print_cr("String conversion failure: %s --> %s", expected, actual); |
318 | ShouldNotReachHere(); |
319 | } |
320 | } |
321 | */ |
322 | #endif |
323 | |
324 | return h_obj; |
325 | } |
326 | |
327 | oop java_lang_String::create_oop_from_str(const char* utf8_str, TRAPS) { |
328 | Handle h_obj = create_from_str(utf8_str, CHECK_0); |
329 | return h_obj(); |
330 | } |
331 | |
332 | Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) { |
333 | const char* utf8_str = (char*)symbol->bytes(); |
334 | int utf8_len = symbol->utf8_length(); |
335 | |
336 | bool has_multibyte, is_latin1; |
337 | int length = UTF8::unicode_length(utf8_str, utf8_len, is_latin1, has_multibyte); |
338 | if (!CompactStrings) { |
339 | has_multibyte = true; |
340 | is_latin1 = false; |
341 | } |
342 | |
343 | Handle h_obj = basic_create(length, is_latin1, CHECK_NH); |
344 | if (length > 0) { |
345 | if (!has_multibyte) { |
346 | const jbyte* src = reinterpret_cast<const jbyte*>(utf8_str); |
347 | ArrayAccess<>::arraycopy_from_native(src, value(h_obj()), typeArrayOopDesc::element_offset<jbyte>(0), length); |
348 | } else if (is_latin1) { |
349 | UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length); |
350 | } else { |
351 | UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length); |
352 | } |
353 | } |
354 | |
355 | #ifdef ASSERT |
356 | { |
357 | ResourceMark rm; |
358 | const char* expected = symbol->as_utf8(); |
359 | char* actual = as_utf8_string(h_obj()); |
360 | if (strncmp(expected, actual, utf8_len) != 0) { |
361 | tty->print_cr("Symbol conversion failure: %s --> %s" , expected, actual); |
362 | ShouldNotReachHere(); |
363 | } |
364 | } |
365 | #endif |
366 | |
367 | return h_obj; |
368 | } |
369 | |
370 | // Converts a C string to a Java String based on current encoding |
371 | Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRAPS) { |
372 | assert(str != NULL, "bad arguments" ); |
373 | |
374 | typedef jstring (*to_java_string_fn_t)(JNIEnv*, const char *); |
375 | static to_java_string_fn_t _to_java_string_fn = NULL; |
376 | |
377 | if (_to_java_string_fn == NULL) { |
378 | void *lib_handle = os::native_java_library(); |
379 | _to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, os::dll_lookup(lib_handle, "NewStringPlatform" )); |
380 | if (_to_java_string_fn == NULL) { |
381 | fatal("NewStringPlatform missing" ); |
382 | } |
383 | } |
384 | |
385 | jstring js = NULL; |
386 | { JavaThread* thread = (JavaThread*)THREAD; |
387 | assert(thread->is_Java_thread(), "must be java thread" ); |
388 | HandleMark hm(thread); |
389 | ThreadToNativeFromVM ttn(thread); |
390 | js = (_to_java_string_fn)(thread->jni_environment(), str); |
391 | } |
392 | return Handle(THREAD, JNIHandles::resolve(js)); |
393 | } |
394 | |
395 | // Converts a Java String to a native C string that can be used for |
396 | // native OS calls. |
397 | char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) { |
398 | typedef char* (*to_platform_string_fn_t)(JNIEnv*, jstring, bool*); |
399 | static to_platform_string_fn_t _to_platform_string_fn = NULL; |
400 | |
401 | if (_to_platform_string_fn == NULL) { |
402 | void *lib_handle = os::native_java_library(); |
403 | _to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, os::dll_lookup(lib_handle, "GetStringPlatformChars" )); |
404 | if (_to_platform_string_fn == NULL) { |
405 | fatal("GetStringPlatformChars missing" ); |
406 | } |
407 | } |
408 | |
409 | char *native_platform_string; |
410 | { JavaThread* thread = (JavaThread*)THREAD; |
411 | assert(thread->is_Java_thread(), "must be java thread" ); |
412 | JNIEnv *env = thread->jni_environment(); |
413 | jstring js = (jstring) JNIHandles::make_local(env, java_string()); |
414 | bool is_copy; |
415 | HandleMark hm(thread); |
416 | ThreadToNativeFromVM ttn(thread); |
417 | native_platform_string = (_to_platform_string_fn)(env, js, &is_copy); |
418 | assert(is_copy == JNI_TRUE, "is_copy value changed" ); |
419 | JNIHandles::destroy_local(js); |
420 | } |
421 | return native_platform_string; |
422 | } |
423 | |
424 | Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS) { |
425 | oop obj = java_string(); |
426 | // Typical usage is to convert all '/' to '.' in string. |
427 | typeArrayOop value = java_lang_String::value(obj); |
428 | int length = java_lang_String::length(obj, value); |
429 | bool is_latin1 = java_lang_String::is_latin1(obj); |
430 | |
431 | // First check if any from_char exist |
432 | int index; // Declared outside, used later |
433 | for (index = 0; index < length; index++) { |
434 | jchar c = !is_latin1 ? value->char_at(index) : |
435 | ((jchar) value->byte_at(index)) & 0xff; |
436 | if (c == from_char) { |
437 | break; |
438 | } |
439 | } |
440 | if (index == length) { |
441 | // No from_char, so do not copy. |
442 | return java_string; |
443 | } |
444 | |
445 | // Check if result string will be latin1 |
446 | bool to_is_latin1 = false; |
447 | |
448 | // Replacement char must be latin1 |
449 | if (CompactStrings && UNICODE::is_latin1(to_char)) { |
450 | if (is_latin1) { |
451 | // Source string is latin1 as well |
452 | to_is_latin1 = true; |
453 | } else if (!UNICODE::is_latin1(from_char)) { |
454 | // We are replacing an UTF16 char. Scan string to |
455 | // check if result can be latin1 encoded. |
456 | to_is_latin1 = true; |
457 | for (index = 0; index < length; index++) { |
458 | jchar c = value->char_at(index); |
459 | if (c != from_char && !UNICODE::is_latin1(c)) { |
460 | to_is_latin1 = false; |
461 | break; |
462 | } |
463 | } |
464 | } |
465 | } |
466 | |
467 | // Create new UNICODE (or byte) buffer. Must handlize value because GC |
468 | // may happen during String and char array creation. |
469 | typeArrayHandle h_value(THREAD, value); |
470 | Handle string = basic_create(length, to_is_latin1, CHECK_NH); |
471 | typeArrayOop from_buffer = h_value(); |
472 | typeArrayOop to_buffer = java_lang_String::value(string()); |
473 | |
474 | // Copy contents |
475 | for (index = 0; index < length; index++) { |
476 | jchar c = (!is_latin1) ? from_buffer->char_at(index) : |
477 | ((jchar) from_buffer->byte_at(index)) & 0xff; |
478 | if (c == from_char) { |
479 | c = to_char; |
480 | } |
481 | if (!to_is_latin1) { |
482 | to_buffer->char_at_put(index, c); |
483 | } else { |
484 | to_buffer->byte_at_put(index, (jbyte) c); |
485 | } |
486 | } |
487 | return string; |
488 | } |
489 | |
490 | jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) { |
491 | typeArrayOop value = java_lang_String::value(java_string); |
492 | length = java_lang_String::length(java_string, value); |
493 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
494 | |
495 | jchar* result = NEW_RESOURCE_ARRAY_RETURN_NULL(jchar, length); |
496 | if (result != NULL) { |
497 | if (!is_latin1) { |
498 | for (int index = 0; index < length; index++) { |
499 | result[index] = value->char_at(index); |
500 | } |
501 | } else { |
502 | for (int index = 0; index < length; index++) { |
503 | result[index] = ((jchar) value->byte_at(index)) & 0xff; |
504 | } |
505 | } |
506 | } else { |
507 | THROW_MSG_0(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string" ); |
508 | } |
509 | return result; |
510 | } |
511 | |
512 | unsigned int java_lang_String::hash_code(oop java_string) { |
513 | // The hash and hashIsZero fields are subject to a benign data race, |
514 | // making it crucial to ensure that any observable result of the |
515 | // calculation in this method stays correct under any possible read of |
516 | // these fields. Necessary restrictions to allow this to be correct |
517 | // without explicit memory fences or similar concurrency primitives is |
518 | // that we can ever only write to one of these two fields for a given |
519 | // String instance, and that the computation is idempotent and derived |
520 | // from immutable state |
521 | assert(initialized && (hash_offset > 0) && (hashIsZero_offset > 0), "Must be initialized" ); |
522 | if (java_lang_String::hash_is_set(java_string)) { |
523 | return java_string->int_field(hash_offset); |
524 | } |
525 | |
526 | typeArrayOop value = java_lang_String::value(java_string); |
527 | int length = java_lang_String::length(java_string, value); |
528 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
529 | |
530 | unsigned int hash = 0; |
531 | if (length > 0) { |
532 | if (is_latin1) { |
533 | hash = java_lang_String::hash_code(value->byte_at_addr(0), length); |
534 | } else { |
535 | hash = java_lang_String::hash_code(value->char_at_addr(0), length); |
536 | } |
537 | } |
538 | |
539 | if (hash != 0) { |
540 | java_string->int_field_put(hash_offset, hash); |
541 | } else { |
542 | java_string->bool_field_put(hashIsZero_offset, true); |
543 | } |
544 | return hash; |
545 | } |
546 | |
547 | char* java_lang_String::as_quoted_ascii(oop java_string) { |
548 | typeArrayOop value = java_lang_String::value(java_string); |
549 | int length = java_lang_String::length(java_string, value); |
550 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
551 | |
552 | if (length == 0) return NULL; |
553 | |
554 | char* result; |
555 | int result_length; |
556 | if (!is_latin1) { |
557 | jchar* base = value->char_at_addr(0); |
558 | result_length = UNICODE::quoted_ascii_length(base, length) + 1; |
559 | result = NEW_RESOURCE_ARRAY(char, result_length); |
560 | UNICODE::as_quoted_ascii(base, length, result, result_length); |
561 | } else { |
562 | jbyte* base = value->byte_at_addr(0); |
563 | result_length = UNICODE::quoted_ascii_length(base, length) + 1; |
564 | result = NEW_RESOURCE_ARRAY(char, result_length); |
565 | UNICODE::as_quoted_ascii(base, length, result, result_length); |
566 | } |
567 | assert(result_length >= length + 1, "must not be shorter" ); |
568 | assert(result_length == (int)strlen(result) + 1, "must match" ); |
569 | return result; |
570 | } |
571 | |
572 | Symbol* java_lang_String::as_symbol(oop java_string) { |
573 | typeArrayOop value = java_lang_String::value(java_string); |
574 | int length = java_lang_String::length(java_string, value); |
575 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
576 | if (!is_latin1) { |
577 | jchar* base = (length == 0) ? NULL : value->char_at_addr(0); |
578 | Symbol* sym = SymbolTable::new_symbol(base, length); |
579 | return sym; |
580 | } else { |
581 | ResourceMark rm; |
582 | jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); |
583 | const char* base = UNICODE::as_utf8(position, length); |
584 | Symbol* sym = SymbolTable::new_symbol(base, length); |
585 | return sym; |
586 | } |
587 | } |
588 | |
589 | Symbol* java_lang_String::as_symbol_or_null(oop java_string) { |
590 | typeArrayOop value = java_lang_String::value(java_string); |
591 | int length = java_lang_String::length(java_string, value); |
592 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
593 | if (!is_latin1) { |
594 | jchar* base = (length == 0) ? NULL : value->char_at_addr(0); |
595 | return SymbolTable::probe_unicode(base, length); |
596 | } else { |
597 | ResourceMark rm; |
598 | jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); |
599 | const char* base = UNICODE::as_utf8(position, length); |
600 | return SymbolTable::probe(base, length); |
601 | } |
602 | } |
603 | |
604 | int java_lang_String::utf8_length(oop java_string, typeArrayOop value) { |
605 | assert(value_equals(value, java_lang_String::value(java_string)), |
606 | "value must be same as java_lang_String::value(java_string)" ); |
607 | int length = java_lang_String::length(java_string, value); |
608 | if (length == 0) { |
609 | return 0; |
610 | } |
611 | if (!java_lang_String::is_latin1(java_string)) { |
612 | return UNICODE::utf8_length(value->char_at_addr(0), length); |
613 | } else { |
614 | return UNICODE::utf8_length(value->byte_at_addr(0), length); |
615 | } |
616 | } |
617 | |
618 | int java_lang_String::utf8_length(oop java_string) { |
619 | typeArrayOop value = java_lang_String::value(java_string); |
620 | return utf8_length(java_string, value); |
621 | } |
622 | |
623 | char* java_lang_String::as_utf8_string(oop java_string) { |
624 | typeArrayOop value = java_lang_String::value(java_string); |
625 | int length = java_lang_String::length(java_string, value); |
626 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
627 | if (!is_latin1) { |
628 | jchar* position = (length == 0) ? NULL : value->char_at_addr(0); |
629 | return UNICODE::as_utf8(position, length); |
630 | } else { |
631 | jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); |
632 | return UNICODE::as_utf8(position, length); |
633 | } |
634 | } |
635 | |
636 | char* java_lang_String::as_utf8_string(oop java_string, typeArrayOop value, char* buf, int buflen) { |
637 | assert(value_equals(value, java_lang_String::value(java_string)), |
638 | "value must be same as java_lang_String::value(java_string)" ); |
639 | int length = java_lang_String::length(java_string, value); |
640 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
641 | if (!is_latin1) { |
642 | jchar* position = (length == 0) ? NULL : value->char_at_addr(0); |
643 | return UNICODE::as_utf8(position, length, buf, buflen); |
644 | } else { |
645 | jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0); |
646 | return UNICODE::as_utf8(position, length, buf, buflen); |
647 | } |
648 | } |
649 | |
650 | char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) { |
651 | typeArrayOop value = java_lang_String::value(java_string); |
652 | return as_utf8_string(java_string, value, buf, buflen); |
653 | } |
654 | |
655 | char* java_lang_String::as_utf8_string(oop java_string, int start, int len) { |
656 | typeArrayOop value = java_lang_String::value(java_string); |
657 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
658 | assert(start + len <= java_lang_String::length(java_string), "just checking" ); |
659 | if (!is_latin1) { |
660 | jchar* position = value->char_at_addr(start); |
661 | return UNICODE::as_utf8(position, len); |
662 | } else { |
663 | jbyte* position = value->byte_at_addr(start); |
664 | return UNICODE::as_utf8(position, len); |
665 | } |
666 | } |
667 | |
668 | char* java_lang_String::as_utf8_string(oop java_string, typeArrayOop value, int start, int len, char* buf, int buflen) { |
669 | assert(value_equals(value, java_lang_String::value(java_string)), |
670 | "value must be same as java_lang_String::value(java_string)" ); |
671 | assert(start + len <= java_lang_String::length(java_string), "just checking" ); |
672 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
673 | if (!is_latin1) { |
674 | jchar* position = value->char_at_addr(start); |
675 | return UNICODE::as_utf8(position, len, buf, buflen); |
676 | } else { |
677 | jbyte* position = value->byte_at_addr(start); |
678 | return UNICODE::as_utf8(position, len, buf, buflen); |
679 | } |
680 | } |
681 | |
682 | bool java_lang_String::equals(oop java_string, const jchar* chars, int len) { |
683 | assert(java_string->klass() == SystemDictionary::String_klass(), |
684 | "must be java_string" ); |
685 | typeArrayOop value = java_lang_String::value_no_keepalive(java_string); |
686 | int length = java_lang_String::length(java_string, value); |
687 | if (length != len) { |
688 | return false; |
689 | } |
690 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
691 | if (!is_latin1) { |
692 | for (int i = 0; i < len; i++) { |
693 | if (value->char_at(i) != chars[i]) { |
694 | return false; |
695 | } |
696 | } |
697 | } else { |
698 | for (int i = 0; i < len; i++) { |
699 | if ((((jchar) value->byte_at(i)) & 0xff) != chars[i]) { |
700 | return false; |
701 | } |
702 | } |
703 | } |
704 | return true; |
705 | } |
706 | |
707 | bool java_lang_String::equals(oop str1, oop str2) { |
708 | assert(str1->klass() == SystemDictionary::String_klass(), |
709 | "must be java String" ); |
710 | assert(str2->klass() == SystemDictionary::String_klass(), |
711 | "must be java String" ); |
712 | typeArrayOop value1 = java_lang_String::value_no_keepalive(str1); |
713 | bool is_latin1 = java_lang_String::is_latin1(str1); |
714 | typeArrayOop value2 = java_lang_String::value_no_keepalive(str2); |
715 | bool is_latin2 = java_lang_String::is_latin1(str2); |
716 | |
717 | if (is_latin1 != is_latin2) { |
718 | // Strings with different coders are never equal. |
719 | return false; |
720 | } |
721 | return value_equals(value1, value2); |
722 | } |
723 | |
724 | void java_lang_String::print(oop java_string, outputStream* st) { |
725 | assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string" ); |
726 | typeArrayOop value = java_lang_String::value_no_keepalive(java_string); |
727 | |
728 | if (value == NULL) { |
729 | // This can happen if, e.g., printing a String |
730 | // object before its initializer has been called |
731 | st->print("NULL" ); |
732 | return; |
733 | } |
734 | |
735 | int length = java_lang_String::length(java_string, value); |
736 | bool is_latin1 = java_lang_String::is_latin1(java_string); |
737 | |
738 | st->print("\"" ); |
739 | for (int index = 0; index < length; index++) { |
740 | st->print("%c" , (!is_latin1) ? value->char_at(index) : |
741 | ((jchar) value->byte_at(index)) & 0xff ); |
742 | } |
743 | st->print("\"" ); |
744 | } |
745 | |
746 | |
747 | static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) { |
748 | assert(mirror.not_null() && fd->is_static(), "just checking" ); |
749 | if (fd->has_initial_value()) { |
750 | BasicType t = fd->field_type(); |
751 | switch (t) { |
752 | case T_BYTE: |
753 | mirror()->byte_field_put(fd->offset(), fd->int_initial_value()); |
754 | break; |
755 | case T_BOOLEAN: |
756 | mirror()->bool_field_put(fd->offset(), fd->int_initial_value()); |
757 | break; |
758 | case T_CHAR: |
759 | mirror()->char_field_put(fd->offset(), fd->int_initial_value()); |
760 | break; |
761 | case T_SHORT: |
762 | mirror()->short_field_put(fd->offset(), fd->int_initial_value()); |
763 | break; |
764 | case T_INT: |
765 | mirror()->int_field_put(fd->offset(), fd->int_initial_value()); |
766 | break; |
767 | case T_FLOAT: |
768 | mirror()->float_field_put(fd->offset(), fd->float_initial_value()); |
769 | break; |
770 | case T_DOUBLE: |
771 | mirror()->double_field_put(fd->offset(), fd->double_initial_value()); |
772 | break; |
773 | case T_LONG: |
774 | mirror()->long_field_put(fd->offset(), fd->long_initial_value()); |
775 | break; |
776 | case T_OBJECT: |
777 | { |
778 | assert(fd->signature() == vmSymbols::string_signature(), |
779 | "just checking" ); |
780 | if (DumpSharedSpaces && HeapShared::is_archived_object(mirror())) { |
781 | // Archive the String field and update the pointer. |
782 | oop s = mirror()->obj_field(fd->offset()); |
783 | oop archived_s = StringTable::create_archived_string(s, CHECK); |
784 | mirror()->obj_field_put(fd->offset(), archived_s); |
785 | } else { |
786 | oop string = fd->string_initial_value(CHECK); |
787 | mirror()->obj_field_put(fd->offset(), string); |
788 | } |
789 | } |
790 | break; |
791 | default: |
792 | THROW_MSG(vmSymbols::java_lang_ClassFormatError(), |
793 | "Illegal ConstantValue attribute in class file" ); |
794 | } |
795 | } |
796 | } |
797 | |
798 | |
799 | void java_lang_Class::fixup_mirror(Klass* k, TRAPS) { |
800 | assert(InstanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already" ); |
801 | |
802 | // If the offset was read from the shared archive, it was fixed up already |
803 | if (!k->is_shared()) { |
804 | if (k->is_instance_klass()) { |
805 | // During bootstrap, java.lang.Class wasn't loaded so static field |
806 | // offsets were computed without the size added it. Go back and |
807 | // update all the static field offsets to included the size. |
808 | for (JavaFieldStream fs(InstanceKlass::cast(k)); !fs.done(); fs.next()) { |
809 | if (fs.access_flags().is_static()) { |
810 | int real_offset = fs.offset() + InstanceMirrorKlass::offset_of_static_fields(); |
811 | fs.set_offset(real_offset); |
812 | } |
813 | } |
814 | } |
815 | } |
816 | |
817 | if (k->is_shared() && k->has_raw_archived_mirror()) { |
818 | if (HeapShared::open_archive_heap_region_mapped()) { |
819 | bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK); |
820 | assert(present, "Missing archived mirror for %s" , k->external_name()); |
821 | return; |
822 | } else { |
823 | k->set_java_mirror_handle(NULL); |
824 | k->clear_has_raw_archived_mirror(); |
825 | } |
826 | } |
827 | create_mirror(k, Handle(), Handle(), Handle(), CHECK); |
828 | } |
829 | |
830 | void java_lang_Class::initialize_mirror_fields(Klass* k, |
831 | Handle mirror, |
832 | Handle protection_domain, |
833 | TRAPS) { |
834 | // Allocate a simple java object for a lock. |
835 | // This needs to be a java object because during class initialization |
836 | // it can be held across a java call. |
837 | typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK); |
838 | set_init_lock(mirror(), r); |
839 | |
840 | // Set protection domain also |
841 | set_protection_domain(mirror(), protection_domain()); |
842 | |
843 | // Initialize static fields |
844 | InstanceKlass::cast(k)->do_local_static_fields(&initialize_static_field, mirror, CHECK); |
845 | } |
846 | |
847 | // Set the java.lang.Module module field in the java_lang_Class mirror |
848 | void java_lang_Class::set_mirror_module_field(Klass* k, Handle mirror, Handle module, TRAPS) { |
849 | if (module.is_null()) { |
850 | // During startup, the module may be NULL only if java.base has not been defined yet. |
851 | // Put the class on the fixup_module_list to patch later when the java.lang.Module |
852 | // for java.base is known. But note that since we captured the NULL module another |
853 | // thread may have completed that initialization. |
854 | |
855 | bool javabase_was_defined = false; |
856 | { |
857 | MutexLocker m1(Module_lock, THREAD); |
858 | // Keep list of classes needing java.base module fixup |
859 | if (!ModuleEntryTable::javabase_defined()) { |
860 | assert(k->java_mirror() != NULL, "Class's mirror is null" ); |
861 | k->class_loader_data()->inc_keep_alive(); |
862 | assert(fixup_module_field_list() != NULL, "fixup_module_field_list not initialized" ); |
863 | fixup_module_field_list()->push(k); |
864 | } else { |
865 | javabase_was_defined = true; |
866 | } |
867 | } |
868 | |
869 | // If java.base was already defined then patch this particular class with java.base. |
870 | if (javabase_was_defined) { |
871 | ModuleEntry *javabase_entry = ModuleEntryTable::javabase_moduleEntry(); |
872 | assert(javabase_entry != NULL && javabase_entry->module() != NULL, |
873 | "Setting class module field, " JAVA_BASE_NAME " should be defined" ); |
874 | Handle javabase_handle(THREAD, javabase_entry->module()); |
875 | set_module(mirror(), javabase_handle()); |
876 | } |
877 | } else { |
878 | assert(Universe::is_module_initialized() || |
879 | (ModuleEntryTable::javabase_defined() && |
880 | (oopDesc::equals(module(), ModuleEntryTable::javabase_moduleEntry()->module()))), |
881 | "Incorrect java.lang.Module specification while creating mirror" ); |
882 | set_module(mirror(), module()); |
883 | } |
884 | } |
885 | |
886 | // Statically allocate fixup lists because they always get created. |
887 | void java_lang_Class::allocate_fixup_lists() { |
888 | GrowableArray<Klass*>* mirror_list = |
889 | new (ResourceObj::C_HEAP, mtClass) GrowableArray<Klass*>(40, true); |
890 | set_fixup_mirror_list(mirror_list); |
891 | |
892 | GrowableArray<Klass*>* module_list = |
893 | new (ResourceObj::C_HEAP, mtModule) GrowableArray<Klass*>(500, true); |
894 | set_fixup_module_field_list(module_list); |
895 | } |
896 | |
897 | void java_lang_Class::create_mirror(Klass* k, Handle class_loader, |
898 | Handle module, Handle protection_domain, TRAPS) { |
899 | assert(k != NULL, "Use create_basic_type_mirror for primitive types" ); |
900 | assert(k->java_mirror() == NULL, "should only assign mirror once" ); |
901 | |
902 | // Use this moment of initialization to cache modifier_flags also, |
903 | // to support Class.getModifiers(). Instance classes recalculate |
904 | // the cached flags after the class file is parsed, but before the |
905 | // class is put into the system dictionary. |
906 | int computed_modifiers = k->compute_modifier_flags(CHECK); |
907 | k->set_modifier_flags(computed_modifiers); |
908 | // Class_klass has to be loaded because it is used to allocate |
909 | // the mirror. |
910 | if (SystemDictionary::Class_klass_loaded()) { |
911 | // Allocate mirror (java.lang.Class instance) |
912 | oop mirror_oop = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK); |
913 | Handle mirror(THREAD, mirror_oop); |
914 | Handle comp_mirror; |
915 | |
916 | // Setup indirection from mirror->klass |
917 | java_lang_Class::set_klass(mirror(), k); |
918 | |
919 | InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass()); |
920 | assert(oop_size(mirror()) == mk->instance_size(k), "should have been set" ); |
921 | |
922 | java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror())); |
923 | |
924 | // It might also have a component mirror. This mirror must already exist. |
925 | if (k->is_array_klass()) { |
926 | if (k->is_typeArray_klass()) { |
927 | BasicType type = TypeArrayKlass::cast(k)->element_type(); |
928 | comp_mirror = Handle(THREAD, Universe::java_mirror(type)); |
929 | } else { |
930 | assert(k->is_objArray_klass(), "Must be" ); |
931 | Klass* element_klass = ObjArrayKlass::cast(k)->element_klass(); |
932 | assert(element_klass != NULL, "Must have an element klass" ); |
933 | comp_mirror = Handle(THREAD, element_klass->java_mirror()); |
934 | } |
935 | assert(comp_mirror() != NULL, "must have a mirror" ); |
936 | |
937 | // Two-way link between the array klass and its component mirror: |
938 | // (array_klass) k -> mirror -> component_mirror -> array_klass -> k |
939 | set_component_mirror(mirror(), comp_mirror()); |
940 | // See below for ordering dependencies between field array_klass in component mirror |
941 | // and java_mirror in this klass. |
942 | } else { |
943 | assert(k->is_instance_klass(), "Must be" ); |
944 | |
945 | initialize_mirror_fields(k, mirror, protection_domain, THREAD); |
946 | if (HAS_PENDING_EXCEPTION) { |
947 | // If any of the fields throws an exception like OOM remove the klass field |
948 | // from the mirror so GC doesn't follow it after the klass has been deallocated. |
949 | // This mirror looks like a primitive type, which logically it is because it |
950 | // it represents no class. |
951 | java_lang_Class::set_klass(mirror(), NULL); |
952 | return; |
953 | } |
954 | } |
955 | |
956 | // set the classLoader field in the java_lang_Class instance |
957 | assert(oopDesc::equals(class_loader(), k->class_loader()), "should be same" ); |
958 | set_class_loader(mirror(), class_loader()); |
959 | |
960 | // Setup indirection from klass->mirror |
961 | // after any exceptions can happen during allocations. |
962 | k->set_java_mirror(mirror); |
963 | |
964 | // Set the module field in the java_lang_Class instance. This must be done |
965 | // after the mirror is set. |
966 | set_mirror_module_field(k, mirror, module, THREAD); |
967 | |
968 | if (comp_mirror() != NULL) { |
969 | // Set after k->java_mirror() is published, because compiled code running |
970 | // concurrently doesn't expect a k to have a null java_mirror. |
971 | release_set_array_klass(comp_mirror(), k); |
972 | } |
973 | } else { |
974 | assert(fixup_mirror_list() != NULL, "fixup_mirror_list not initialized" ); |
975 | fixup_mirror_list()->push(k); |
976 | } |
977 | } |
978 | |
979 | #if INCLUDE_CDS_JAVA_HEAP |
980 | // Clears mirror fields. Static final fields with initial values are reloaded |
981 | // from constant pool. The object identity hash is in the object header and is |
982 | // not affected. |
983 | class ResetMirrorField: public FieldClosure { |
984 | private: |
985 | Handle _m; |
986 | |
987 | public: |
988 | ResetMirrorField(Handle mirror) : _m(mirror) {} |
989 | |
990 | void do_field(fieldDescriptor* fd) { |
991 | assert(DumpSharedSpaces, "dump time only" ); |
992 | assert(_m.not_null(), "Mirror cannot be NULL" ); |
993 | |
994 | if (fd->is_static() && fd->has_initial_value()) { |
995 | initialize_static_field(fd, _m, Thread::current()); |
996 | return; |
997 | } |
998 | |
999 | BasicType ft = fd->field_type(); |
1000 | switch (ft) { |
1001 | case T_BYTE: |
1002 | _m()->byte_field_put(fd->offset(), 0); |
1003 | break; |
1004 | case T_CHAR: |
1005 | _m()->char_field_put(fd->offset(), 0); |
1006 | break; |
1007 | case T_DOUBLE: |
1008 | _m()->double_field_put(fd->offset(), 0); |
1009 | break; |
1010 | case T_FLOAT: |
1011 | _m()->float_field_put(fd->offset(), 0); |
1012 | break; |
1013 | case T_INT: |
1014 | _m()->int_field_put(fd->offset(), 0); |
1015 | break; |
1016 | case T_LONG: |
1017 | _m()->long_field_put(fd->offset(), 0); |
1018 | break; |
1019 | case T_SHORT: |
1020 | _m()->short_field_put(fd->offset(), 0); |
1021 | break; |
1022 | case T_BOOLEAN: |
1023 | _m()->bool_field_put(fd->offset(), false); |
1024 | break; |
1025 | case T_ARRAY: |
1026 | case T_OBJECT: { |
1027 | // It might be useful to cache the String field, but |
1028 | // for now just clear out any reference field |
1029 | oop o = _m()->obj_field(fd->offset()); |
1030 | _m()->obj_field_put(fd->offset(), NULL); |
1031 | break; |
1032 | } |
1033 | default: |
1034 | ShouldNotReachHere(); |
1035 | break; |
1036 | } |
1037 | } |
1038 | }; |
1039 | |
1040 | void java_lang_Class::archive_basic_type_mirrors(TRAPS) { |
1041 | assert(HeapShared::is_heap_object_archiving_allowed(), |
1042 | "HeapShared::is_heap_object_archiving_allowed() must be true" ); |
1043 | |
1044 | for (int t = 0; t <= T_VOID; t++) { |
1045 | oop m = Universe::_mirrors[t]; |
1046 | if (m != NULL) { |
1047 | // Update the field at _array_klass_offset to point to the relocated array klass. |
1048 | oop archived_m = HeapShared::archive_heap_object(m, THREAD); |
1049 | assert(archived_m != NULL, "sanity" ); |
1050 | Klass *ak = (Klass*)(archived_m->metadata_field(_array_klass_offset)); |
1051 | assert(ak != NULL || t == T_VOID, "should not be NULL" ); |
1052 | if (ak != NULL) { |
1053 | Klass *reloc_ak = MetaspaceShared::get_relocated_klass(ak); |
1054 | archived_m->metadata_field_put(_array_klass_offset, reloc_ak); |
1055 | } |
1056 | |
1057 | // Clear the fields. Just to be safe |
1058 | Klass *k = m->klass(); |
1059 | Handle archived_mirror_h(THREAD, archived_m); |
1060 | ResetMirrorField reset(archived_mirror_h); |
1061 | InstanceKlass::cast(k)->do_nonstatic_fields(&reset); |
1062 | |
1063 | log_trace(cds, heap, mirror)( |
1064 | "Archived %s mirror object from " PTR_FORMAT " ==> " PTR_FORMAT, |
1065 | type2name((BasicType)t), p2i(Universe::_mirrors[t]), p2i(archived_m)); |
1066 | |
1067 | Universe::_mirrors[t] = archived_m; |
1068 | } |
1069 | } |
1070 | |
1071 | assert(Universe::_mirrors[T_INT] != NULL && |
1072 | Universe::_mirrors[T_FLOAT] != NULL && |
1073 | Universe::_mirrors[T_DOUBLE] != NULL && |
1074 | Universe::_mirrors[T_BYTE] != NULL && |
1075 | Universe::_mirrors[T_BOOLEAN] != NULL && |
1076 | Universe::_mirrors[T_CHAR] != NULL && |
1077 | Universe::_mirrors[T_LONG] != NULL && |
1078 | Universe::_mirrors[T_SHORT] != NULL && |
1079 | Universe::_mirrors[T_VOID] != NULL, "sanity" ); |
1080 | |
1081 | Universe::set_int_mirror(Universe::_mirrors[T_INT]); |
1082 | Universe::set_float_mirror(Universe::_mirrors[T_FLOAT]); |
1083 | Universe::set_double_mirror(Universe::_mirrors[T_DOUBLE]); |
1084 | Universe::set_byte_mirror(Universe::_mirrors[T_BYTE]); |
1085 | Universe::set_bool_mirror(Universe::_mirrors[T_BOOLEAN]); |
1086 | Universe::set_char_mirror(Universe::_mirrors[T_CHAR]); |
1087 | Universe::set_long_mirror(Universe::_mirrors[T_LONG]); |
1088 | Universe::set_short_mirror(Universe::_mirrors[T_SHORT]); |
1089 | Universe::set_void_mirror(Universe::_mirrors[T_VOID]); |
1090 | } |
1091 | |
1092 | // |
1093 | // After the mirror object is successfully archived, the archived |
1094 | // klass is set with _has_archived_raw_mirror flag. |
1095 | // |
1096 | // The _has_archived_raw_mirror flag is cleared at runtime when the |
1097 | // archived mirror is restored. If archived java heap data cannot |
1098 | // be used at runtime, new mirror object is created for the shared |
1099 | // class. The _has_archived_raw_mirror is cleared also during the process. |
1100 | oop java_lang_Class::archive_mirror(Klass* k, TRAPS) { |
1101 | assert(HeapShared::is_heap_object_archiving_allowed(), |
1102 | "HeapShared::is_heap_object_archiving_allowed() must be true" ); |
1103 | |
1104 | // Mirror is already archived |
1105 | if (k->has_raw_archived_mirror()) { |
1106 | assert(k->archived_java_mirror_raw() != NULL, "no archived mirror" ); |
1107 | return k->archived_java_mirror_raw(); |
1108 | } |
1109 | |
1110 | // No mirror |
1111 | oop mirror = k->java_mirror(); |
1112 | if (mirror == NULL) { |
1113 | return NULL; |
1114 | } |
1115 | |
1116 | if (k->is_instance_klass()) { |
1117 | InstanceKlass *ik = InstanceKlass::cast(k); |
1118 | assert(ik->signers() == NULL, "class with signer should have been excluded" ); |
1119 | |
1120 | if (!(ik->is_shared_boot_class() || ik->is_shared_platform_class() || |
1121 | ik->is_shared_app_class())) { |
1122 | // Archiving mirror for classes from non-builtin loaders is not |
1123 | // supported. Clear the _java_mirror within the archived class. |
1124 | k->set_java_mirror_handle(NULL); |
1125 | return NULL; |
1126 | } |
1127 | } |
1128 | |
1129 | // Now start archiving the mirror object |
1130 | oop archived_mirror = HeapShared::archive_heap_object(mirror, THREAD); |
1131 | if (archived_mirror == NULL) { |
1132 | return NULL; |
1133 | } |
1134 | |
1135 | archived_mirror = process_archived_mirror(k, mirror, archived_mirror, THREAD); |
1136 | if (archived_mirror == NULL) { |
1137 | return NULL; |
1138 | } |
1139 | |
1140 | k->set_archived_java_mirror_raw(archived_mirror); |
1141 | |
1142 | k->set_has_raw_archived_mirror(); |
1143 | |
1144 | ResourceMark rm; |
1145 | log_trace(cds, heap, mirror)( |
1146 | "Archived %s mirror object from " PTR_FORMAT " ==> " PTR_FORMAT, |
1147 | k->external_name(), p2i(mirror), p2i(archived_mirror)); |
1148 | |
1149 | return archived_mirror; |
1150 | } |
1151 | |
1152 | // The process is based on create_mirror(). |
1153 | oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror, |
1154 | oop archived_mirror, |
1155 | Thread *THREAD) { |
1156 | // Clear nonstatic fields in archived mirror. Some of the fields will be set |
1157 | // to archived metadata and objects below. |
1158 | Klass *c = archived_mirror->klass(); |
1159 | Handle archived_mirror_h(THREAD, archived_mirror); |
1160 | ResetMirrorField reset(archived_mirror_h); |
1161 | InstanceKlass::cast(c)->do_nonstatic_fields(&reset); |
1162 | |
1163 | if (k->is_array_klass()) { |
1164 | oop archived_comp_mirror; |
1165 | if (k->is_typeArray_klass()) { |
1166 | // The primitive type mirrors are already archived. Get the archived mirror. |
1167 | oop comp_mirror = java_lang_Class::component_mirror(mirror); |
1168 | archived_comp_mirror = HeapShared::find_archived_heap_object(comp_mirror); |
1169 | assert(archived_comp_mirror != NULL, "Must be" ); |
1170 | } else { |
1171 | assert(k->is_objArray_klass(), "Must be" ); |
1172 | Klass* element_klass = ObjArrayKlass::cast(k)->element_klass(); |
1173 | assert(element_klass != NULL, "Must have an element klass" ); |
1174 | archived_comp_mirror = archive_mirror(element_klass, THREAD); |
1175 | if (archived_comp_mirror == NULL) { |
1176 | return NULL; |
1177 | } |
1178 | } |
1179 | java_lang_Class::set_component_mirror(archived_mirror, archived_comp_mirror); |
1180 | } else { |
1181 | assert(k->is_instance_klass(), "Must be" ); |
1182 | |
1183 | // Reset local static fields in the mirror |
1184 | InstanceKlass::cast(k)->do_local_static_fields(&reset); |
1185 | |
1186 | java_lang_Class:set_init_lock(archived_mirror, NULL); |
1187 | |
1188 | set_protection_domain(archived_mirror, NULL); |
1189 | } |
1190 | |
1191 | // clear class loader and mirror_module_field |
1192 | set_class_loader(archived_mirror, NULL); |
1193 | set_module(archived_mirror, NULL); |
1194 | |
1195 | // The archived mirror's field at _klass_offset is still pointing to the original |
1196 | // klass. Updated the field in the archived mirror to point to the relocated |
1197 | // klass in the archive. |
1198 | Klass *reloc_k = MetaspaceShared::get_relocated_klass(as_Klass(mirror)); |
1199 | log_debug(cds, heap, mirror)( |
1200 | "Relocate mirror metadata field at _klass_offset from " PTR_FORMAT " ==> " PTR_FORMAT, |
1201 | p2i(as_Klass(mirror)), p2i(reloc_k)); |
1202 | archived_mirror->metadata_field_put(_klass_offset, reloc_k); |
1203 | |
1204 | // The field at _array_klass_offset is pointing to the original one dimension |
1205 | // higher array klass if exists. Relocate the pointer. |
1206 | Klass *arr = array_klass_acquire(mirror); |
1207 | if (arr != NULL) { |
1208 | Klass *reloc_arr = MetaspaceShared::get_relocated_klass(arr); |
1209 | log_debug(cds, heap, mirror)( |
1210 | "Relocate mirror metadata field at _array_klass_offset from " PTR_FORMAT " ==> " PTR_FORMAT, |
1211 | p2i(arr), p2i(reloc_arr)); |
1212 | archived_mirror->metadata_field_put(_array_klass_offset, reloc_arr); |
1213 | } |
1214 | return archived_mirror; |
1215 | } |
1216 | |
1217 | // Returns true if the mirror is updated, false if no archived mirror |
1218 | // data is present. After the archived mirror object is restored, the |
1219 | // shared klass' _has_raw_archived_mirror flag is cleared. |
1220 | bool java_lang_Class::restore_archived_mirror(Klass *k, |
1221 | Handle class_loader, Handle module, |
1222 | Handle protection_domain, TRAPS) { |
1223 | // Postpone restoring archived mirror until java.lang.Class is loaded. Please |
1224 | // see more details in SystemDictionary::resolve_well_known_classes(). |
1225 | if (!SystemDictionary::Class_klass_loaded()) { |
1226 | assert(fixup_mirror_list() != NULL, "fixup_mirror_list not initialized" ); |
1227 | fixup_mirror_list()->push(k); |
1228 | return true; |
1229 | } |
1230 | |
1231 | oop m = HeapShared::materialize_archived_object(k->archived_java_mirror_raw_narrow()); |
1232 | |
1233 | if (m == NULL) { |
1234 | return false; |
1235 | } |
1236 | |
1237 | log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m)); |
1238 | |
1239 | // mirror is archived, restore |
1240 | assert(HeapShared::is_archived_object(m), "must be archived mirror object" ); |
1241 | Handle mirror(THREAD, m); |
1242 | |
1243 | if (!k->is_array_klass()) { |
1244 | // - local static final fields with initial values were initialized at dump time |
1245 | |
1246 | // create the init_lock |
1247 | typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_(false)); |
1248 | set_init_lock(mirror(), r); |
1249 | |
1250 | if (protection_domain.not_null()) { |
1251 | set_protection_domain(mirror(), protection_domain()); |
1252 | } |
1253 | } |
1254 | |
1255 | assert(class_loader() == k->class_loader(), "should be same" ); |
1256 | if (class_loader.not_null()) { |
1257 | set_class_loader(mirror(), class_loader()); |
1258 | } |
1259 | |
1260 | k->set_java_mirror(mirror); |
1261 | k->clear_has_raw_archived_mirror(); |
1262 | |
1263 | set_mirror_module_field(k, mirror, module, THREAD); |
1264 | |
1265 | ResourceMark rm; |
1266 | log_trace(cds, heap, mirror)( |
1267 | "Restored %s archived mirror " PTR_FORMAT, k->external_name(), p2i(mirror())); |
1268 | |
1269 | return true; |
1270 | } |
1271 | #endif // INCLUDE_CDS_JAVA_HEAP |
1272 | |
1273 | void java_lang_Class::fixup_module_field(Klass* k, Handle module) { |
1274 | assert(_module_offset != 0, "must have been computed already" ); |
1275 | java_lang_Class::set_module(k->java_mirror(), module()); |
1276 | } |
1277 | |
1278 | int java_lang_Class::oop_size(oop java_class) { |
1279 | assert(_oop_size_offset != 0, "must be set" ); |
1280 | int size = java_class->int_field(_oop_size_offset); |
1281 | assert(size > 0, "Oop size must be greater than zero, not %d" , size); |
1282 | return size; |
1283 | } |
1284 | |
1285 | |
1286 | void java_lang_Class::set_oop_size(HeapWord* java_class, int size) { |
1287 | assert(_oop_size_offset != 0, "must be set" ); |
1288 | assert(size > 0, "Oop size must be greater than zero, not %d" , size); |
1289 | *(int*)(((char*)java_class) + _oop_size_offset) = size; |
1290 | } |
1291 | |
1292 | int java_lang_Class::static_oop_field_count(oop java_class) { |
1293 | assert(_static_oop_field_count_offset != 0, "must be set" ); |
1294 | return java_class->int_field(_static_oop_field_count_offset); |
1295 | } |
1296 | |
1297 | int java_lang_Class::static_oop_field_count_raw(oop java_class) { |
1298 | assert(_static_oop_field_count_offset != 0, "must be set" ); |
1299 | return java_class->int_field_raw(_static_oop_field_count_offset); |
1300 | } |
1301 | |
1302 | void java_lang_Class::set_static_oop_field_count(oop java_class, int size) { |
1303 | assert(_static_oop_field_count_offset != 0, "must be set" ); |
1304 | java_class->int_field_put(_static_oop_field_count_offset, size); |
1305 | } |
1306 | |
1307 | oop java_lang_Class::protection_domain(oop java_class) { |
1308 | assert(_protection_domain_offset != 0, "must be set" ); |
1309 | return java_class->obj_field(_protection_domain_offset); |
1310 | } |
1311 | void java_lang_Class::set_protection_domain(oop java_class, oop pd) { |
1312 | assert(_protection_domain_offset != 0, "must be set" ); |
1313 | java_class->obj_field_put(_protection_domain_offset, pd); |
1314 | } |
1315 | |
1316 | void java_lang_Class::set_component_mirror(oop java_class, oop comp_mirror) { |
1317 | assert(_component_mirror_offset != 0, "must be set" ); |
1318 | java_class->obj_field_put(_component_mirror_offset, comp_mirror); |
1319 | } |
1320 | oop java_lang_Class::component_mirror(oop java_class) { |
1321 | assert(_component_mirror_offset != 0, "must be set" ); |
1322 | return java_class->obj_field(_component_mirror_offset); |
1323 | } |
1324 | |
1325 | oop java_lang_Class::init_lock(oop java_class) { |
1326 | assert(_init_lock_offset != 0, "must be set" ); |
1327 | return java_class->obj_field(_init_lock_offset); |
1328 | } |
1329 | void java_lang_Class::set_init_lock(oop java_class, oop init_lock) { |
1330 | assert(_init_lock_offset != 0, "must be set" ); |
1331 | java_class->obj_field_put(_init_lock_offset, init_lock); |
1332 | } |
1333 | |
1334 | objArrayOop java_lang_Class::signers(oop java_class) { |
1335 | assert(_signers_offset != 0, "must be set" ); |
1336 | return (objArrayOop)java_class->obj_field(_signers_offset); |
1337 | } |
1338 | void java_lang_Class::set_signers(oop java_class, objArrayOop signers) { |
1339 | assert(_signers_offset != 0, "must be set" ); |
1340 | java_class->obj_field_put(_signers_offset, (oop)signers); |
1341 | } |
1342 | |
1343 | |
1344 | void java_lang_Class::set_class_loader(oop java_class, oop loader) { |
1345 | // jdk7 runs Queens in bootstrapping and jdk8-9 has no coordinated pushes yet. |
1346 | if (_class_loader_offset != 0) { |
1347 | java_class->obj_field_put(_class_loader_offset, loader); |
1348 | } |
1349 | } |
1350 | |
1351 | oop java_lang_Class::class_loader(oop java_class) { |
1352 | assert(_class_loader_offset != 0, "must be set" ); |
1353 | return java_class->obj_field(_class_loader_offset); |
1354 | } |
1355 | |
1356 | oop java_lang_Class::module(oop java_class) { |
1357 | assert(_module_offset != 0, "must be set" ); |
1358 | return java_class->obj_field(_module_offset); |
1359 | } |
1360 | |
1361 | void java_lang_Class::set_module(oop java_class, oop module) { |
1362 | assert(_module_offset != 0, "must be set" ); |
1363 | java_class->obj_field_put(_module_offset, module); |
1364 | } |
1365 | |
1366 | oop java_lang_Class::name(Handle java_class, TRAPS) { |
1367 | assert(_name_offset != 0, "must be set" ); |
1368 | oop o = java_class->obj_field(_name_offset); |
1369 | if (o == NULL) { |
1370 | o = StringTable::intern(java_lang_Class::as_external_name(java_class()), THREAD); |
1371 | java_class->obj_field_put(_name_offset, o); |
1372 | } |
1373 | return o; |
1374 | } |
1375 | |
1376 | oop java_lang_Class::source_file(oop java_class) { |
1377 | assert(_source_file_offset != 0, "must be set" ); |
1378 | return java_class->obj_field(_source_file_offset); |
1379 | } |
1380 | |
1381 | void java_lang_Class::set_source_file(oop java_class, oop source_file) { |
1382 | assert(_source_file_offset != 0, "must be set" ); |
1383 | java_class->obj_field_put(_source_file_offset, source_file); |
1384 | } |
1385 | |
1386 | oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { |
1387 | // This should be improved by adding a field at the Java level or by |
1388 | // introducing a new VM klass (see comment in ClassFileParser) |
1389 | oop java_class = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(NULL, CHECK_0); |
1390 | if (type != T_VOID) { |
1391 | Klass* aklass = Universe::typeArrayKlassObj(type); |
1392 | assert(aklass != NULL, "correct bootstrap" ); |
1393 | release_set_array_klass(java_class, aklass); |
1394 | } |
1395 | #ifdef ASSERT |
1396 | InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(SystemDictionary::Class_klass()); |
1397 | assert(java_lang_Class::static_oop_field_count(java_class) == 0, "should have been zeroed by allocation" ); |
1398 | #endif |
1399 | return java_class; |
1400 | } |
1401 | |
1402 | |
1403 | Klass* java_lang_Class::as_Klass(oop java_class) { |
1404 | //%note memory_2 |
1405 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1406 | Klass* k = ((Klass*)java_class->metadata_field(_klass_offset)); |
1407 | assert(k == NULL || k->is_klass(), "type check" ); |
1408 | return k; |
1409 | } |
1410 | |
1411 | Klass* java_lang_Class::as_Klass_raw(oop java_class) { |
1412 | //%note memory_2 |
1413 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1414 | Klass* k = ((Klass*)java_class->metadata_field_raw(_klass_offset)); |
1415 | assert(k == NULL || k->is_klass(), "type check" ); |
1416 | return k; |
1417 | } |
1418 | |
1419 | |
1420 | void java_lang_Class::set_klass(oop java_class, Klass* klass) { |
1421 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1422 | java_class->metadata_field_put(_klass_offset, klass); |
1423 | } |
1424 | |
1425 | |
1426 | void java_lang_Class::print_signature(oop java_class, outputStream* st) { |
1427 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1428 | Symbol* name = NULL; |
1429 | bool is_instance = false; |
1430 | if (is_primitive(java_class)) { |
1431 | name = vmSymbols::type_signature(primitive_type(java_class)); |
1432 | } else { |
1433 | Klass* k = as_Klass(java_class); |
1434 | is_instance = k->is_instance_klass(); |
1435 | name = k->name(); |
1436 | } |
1437 | if (name == NULL) { |
1438 | st->print("<null>" ); |
1439 | return; |
1440 | } |
1441 | if (is_instance) st->print("L" ); |
1442 | st->write((char*) name->base(), (int) name->utf8_length()); |
1443 | if (is_instance) st->print(";" ); |
1444 | } |
1445 | |
1446 | Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found) { |
1447 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1448 | Symbol* name; |
1449 | if (is_primitive(java_class)) { |
1450 | name = vmSymbols::type_signature(primitive_type(java_class)); |
1451 | // Because this can create a new symbol, the caller has to decrement |
1452 | // the refcount, so make adjustment here and below for symbols returned |
1453 | // that are not created or incremented due to a successful lookup. |
1454 | name->increment_refcount(); |
1455 | } else { |
1456 | Klass* k = as_Klass(java_class); |
1457 | if (!k->is_instance_klass()) { |
1458 | name = k->name(); |
1459 | name->increment_refcount(); |
1460 | } else { |
1461 | ResourceMark rm; |
1462 | const char* sigstr = k->signature_name(); |
1463 | int siglen = (int) strlen(sigstr); |
1464 | if (!intern_if_not_found) { |
1465 | name = SymbolTable::probe(sigstr, siglen); |
1466 | } else { |
1467 | name = SymbolTable::new_symbol(sigstr, siglen); |
1468 | } |
1469 | } |
1470 | } |
1471 | return name; |
1472 | } |
1473 | |
1474 | // Returns the Java name for this Java mirror (Resource allocated) |
1475 | // See Klass::external_name(). |
1476 | // For primitive type Java mirrors, its type name is returned. |
1477 | const char* java_lang_Class::as_external_name(oop java_class) { |
1478 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1479 | const char* name = NULL; |
1480 | if (is_primitive(java_class)) { |
1481 | name = type2name(primitive_type(java_class)); |
1482 | } else { |
1483 | name = as_Klass(java_class)->external_name(); |
1484 | } |
1485 | if (name == NULL) { |
1486 | name = "<null>" ; |
1487 | } |
1488 | return name; |
1489 | } |
1490 | |
1491 | Klass* java_lang_Class::array_klass_acquire(oop java_class) { |
1492 | Klass* k = ((Klass*)java_class->metadata_field_acquire(_array_klass_offset)); |
1493 | assert(k == NULL || k->is_klass() && k->is_array_klass(), "should be array klass" ); |
1494 | return k; |
1495 | } |
1496 | |
1497 | |
1498 | void java_lang_Class::release_set_array_klass(oop java_class, Klass* klass) { |
1499 | assert(klass->is_klass() && klass->is_array_klass(), "should be array klass" ); |
1500 | java_class->release_metadata_field_put(_array_klass_offset, klass); |
1501 | } |
1502 | |
1503 | |
1504 | BasicType java_lang_Class::primitive_type(oop java_class) { |
1505 | assert(java_lang_Class::is_primitive(java_class), "just checking" ); |
1506 | Klass* ak = ((Klass*)java_class->metadata_field(_array_klass_offset)); |
1507 | BasicType type = T_VOID; |
1508 | if (ak != NULL) { |
1509 | // Note: create_basic_type_mirror above initializes ak to a non-null value. |
1510 | type = ArrayKlass::cast(ak)->element_type(); |
1511 | } else { |
1512 | assert(oopDesc::equals(java_class, Universe::void_mirror()), "only valid non-array primitive" ); |
1513 | } |
1514 | assert(oopDesc::equals(Universe::java_mirror(type), java_class), "must be consistent" ); |
1515 | return type; |
1516 | } |
1517 | |
1518 | BasicType java_lang_Class::as_BasicType(oop java_class, Klass** reference_klass) { |
1519 | assert(java_lang_Class::is_instance(java_class), "must be a Class object" ); |
1520 | if (is_primitive(java_class)) { |
1521 | if (reference_klass != NULL) |
1522 | (*reference_klass) = NULL; |
1523 | return primitive_type(java_class); |
1524 | } else { |
1525 | if (reference_klass != NULL) |
1526 | (*reference_klass) = as_Klass(java_class); |
1527 | return T_OBJECT; |
1528 | } |
1529 | } |
1530 | |
1531 | |
1532 | oop java_lang_Class::primitive_mirror(BasicType t) { |
1533 | oop mirror = Universe::java_mirror(t); |
1534 | assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class" ); |
1535 | assert(java_lang_Class::is_primitive(mirror), "must be primitive" ); |
1536 | return mirror; |
1537 | } |
1538 | |
1539 | bool java_lang_Class::offsets_computed = false; |
1540 | int java_lang_Class::classRedefinedCount_offset = -1; |
1541 | |
1542 | #define CLASS_FIELDS_DO(macro) \ |
1543 | macro(classRedefinedCount_offset, k, "classRedefinedCount", int_signature, false) ; \ |
1544 | macro(_class_loader_offset, k, "classLoader", classloader_signature, false); \ |
1545 | macro(_component_mirror_offset, k, "componentType", class_signature, false); \ |
1546 | macro(_module_offset, k, "module", module_signature, false); \ |
1547 | macro(_name_offset, k, "name", string_signature, false); \ |
1548 | |
1549 | void java_lang_Class::compute_offsets() { |
1550 | if (offsets_computed) { |
1551 | return; |
1552 | } |
1553 | |
1554 | offsets_computed = true; |
1555 | |
1556 | InstanceKlass* k = SystemDictionary::Class_klass(); |
1557 | CLASS_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
1558 | |
1559 | // Init lock is a C union with component_mirror. Only instanceKlass mirrors have |
1560 | // init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops |
1561 | // GC treats them the same. |
1562 | _init_lock_offset = _component_mirror_offset; |
1563 | |
1564 | CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
1565 | } |
1566 | |
1567 | #if INCLUDE_CDS |
1568 | void java_lang_Class::serialize_offsets(SerializeClosure* f) { |
1569 | f->do_bool(&offsets_computed); |
1570 | f->do_u4((u4*)&_init_lock_offset); |
1571 | |
1572 | CLASS_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
1573 | |
1574 | CLASS_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
1575 | } |
1576 | #endif |
1577 | |
1578 | int java_lang_Class::classRedefinedCount(oop the_class_mirror) { |
1579 | if (classRedefinedCount_offset == -1) { |
1580 | // If we don't have an offset for it then just return -1 as a marker. |
1581 | return -1; |
1582 | } |
1583 | |
1584 | return the_class_mirror->int_field(classRedefinedCount_offset); |
1585 | } |
1586 | |
1587 | void java_lang_Class::set_classRedefinedCount(oop the_class_mirror, int value) { |
1588 | if (classRedefinedCount_offset == -1) { |
1589 | // If we don't have an offset for it then nothing to set. |
1590 | return; |
1591 | } |
1592 | |
1593 | the_class_mirror->int_field_put(classRedefinedCount_offset, value); |
1594 | } |
1595 | |
1596 | |
1597 | // Note: JDK1.1 and before had a privateInfo_offset field which was used for the |
1598 | // platform thread structure, and a eetop offset which was used for thread |
1599 | // local storage (and unused by the HotSpot VM). In JDK1.2 the two structures |
1600 | // merged, so in the HotSpot VM we just use the eetop field for the thread |
1601 | // instead of the privateInfo_offset. |
1602 | // |
1603 | // Note: The stackSize field is only present starting in 1.4. |
1604 | |
1605 | int java_lang_Thread::_name_offset = 0; |
1606 | int java_lang_Thread::_group_offset = 0; |
1607 | int java_lang_Thread::_contextClassLoader_offset = 0; |
1608 | int java_lang_Thread::_inheritedAccessControlContext_offset = 0; |
1609 | int java_lang_Thread::_priority_offset = 0; |
1610 | int java_lang_Thread::_eetop_offset = 0; |
1611 | int java_lang_Thread::_daemon_offset = 0; |
1612 | int java_lang_Thread::_stillborn_offset = 0; |
1613 | int java_lang_Thread::_stackSize_offset = 0; |
1614 | int java_lang_Thread::_tid_offset = 0; |
1615 | int java_lang_Thread::_thread_status_offset = 0; |
1616 | int java_lang_Thread::_park_blocker_offset = 0; |
1617 | |
1618 | #define THREAD_FIELDS_DO(macro) \ |
1619 | macro(_name_offset, k, vmSymbols::name_name(), string_signature, false); \ |
1620 | macro(_group_offset, k, vmSymbols::group_name(), threadgroup_signature, false); \ |
1621 | macro(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), classloader_signature, false); \ |
1622 | macro(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), accesscontrolcontext_signature, false); \ |
1623 | macro(_priority_offset, k, vmSymbols::priority_name(), int_signature, false); \ |
1624 | macro(_daemon_offset, k, vmSymbols::daemon_name(), bool_signature, false); \ |
1625 | macro(_eetop_offset, k, "eetop", long_signature, false); \ |
1626 | macro(_stillborn_offset, k, "stillborn", bool_signature, false); \ |
1627 | macro(_stackSize_offset, k, "stackSize", long_signature, false); \ |
1628 | macro(_tid_offset, k, "tid", long_signature, false); \ |
1629 | macro(_thread_status_offset, k, "threadStatus", int_signature, false); \ |
1630 | macro(_park_blocker_offset, k, "parkBlocker", object_signature, false) |
1631 | |
1632 | void java_lang_Thread::compute_offsets() { |
1633 | assert(_group_offset == 0, "offsets should be initialized only once" ); |
1634 | |
1635 | InstanceKlass* k = SystemDictionary::Thread_klass(); |
1636 | THREAD_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
1637 | } |
1638 | |
1639 | #if INCLUDE_CDS |
1640 | void java_lang_Thread::serialize_offsets(SerializeClosure* f) { |
1641 | THREAD_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
1642 | } |
1643 | #endif |
1644 | |
1645 | JavaThread* java_lang_Thread::thread(oop java_thread) { |
1646 | return (JavaThread*)java_thread->address_field(_eetop_offset); |
1647 | } |
1648 | |
1649 | |
1650 | void java_lang_Thread::set_thread(oop java_thread, JavaThread* thread) { |
1651 | java_thread->address_field_put(_eetop_offset, (address)thread); |
1652 | } |
1653 | |
1654 | |
1655 | oop java_lang_Thread::name(oop java_thread) { |
1656 | return java_thread->obj_field(_name_offset); |
1657 | } |
1658 | |
1659 | |
1660 | void java_lang_Thread::set_name(oop java_thread, oop name) { |
1661 | java_thread->obj_field_put(_name_offset, name); |
1662 | } |
1663 | |
1664 | |
1665 | ThreadPriority java_lang_Thread::priority(oop java_thread) { |
1666 | return (ThreadPriority)java_thread->int_field(_priority_offset); |
1667 | } |
1668 | |
1669 | |
1670 | void java_lang_Thread::set_priority(oop java_thread, ThreadPriority priority) { |
1671 | java_thread->int_field_put(_priority_offset, priority); |
1672 | } |
1673 | |
1674 | |
1675 | oop java_lang_Thread::threadGroup(oop java_thread) { |
1676 | return java_thread->obj_field(_group_offset); |
1677 | } |
1678 | |
1679 | |
1680 | bool java_lang_Thread::is_stillborn(oop java_thread) { |
1681 | return java_thread->bool_field(_stillborn_offset) != 0; |
1682 | } |
1683 | |
1684 | |
1685 | // We never have reason to turn the stillborn bit off |
1686 | void java_lang_Thread::set_stillborn(oop java_thread) { |
1687 | java_thread->bool_field_put(_stillborn_offset, true); |
1688 | } |
1689 | |
1690 | |
1691 | bool java_lang_Thread::is_alive(oop java_thread) { |
1692 | JavaThread* thr = java_lang_Thread::thread(java_thread); |
1693 | return (thr != NULL); |
1694 | } |
1695 | |
1696 | |
1697 | bool java_lang_Thread::is_daemon(oop java_thread) { |
1698 | return java_thread->bool_field(_daemon_offset) != 0; |
1699 | } |
1700 | |
1701 | |
1702 | void java_lang_Thread::set_daemon(oop java_thread) { |
1703 | java_thread->bool_field_put(_daemon_offset, true); |
1704 | } |
1705 | |
1706 | oop java_lang_Thread::context_class_loader(oop java_thread) { |
1707 | return java_thread->obj_field(_contextClassLoader_offset); |
1708 | } |
1709 | |
1710 | oop java_lang_Thread::inherited_access_control_context(oop java_thread) { |
1711 | return java_thread->obj_field(_inheritedAccessControlContext_offset); |
1712 | } |
1713 | |
1714 | |
1715 | jlong java_lang_Thread::stackSize(oop java_thread) { |
1716 | return java_thread->long_field(_stackSize_offset); |
1717 | } |
1718 | |
1719 | // Write the thread status value to threadStatus field in java.lang.Thread java class. |
1720 | void java_lang_Thread::set_thread_status(oop java_thread, |
1721 | java_lang_Thread::ThreadStatus status) { |
1722 | java_thread->int_field_put(_thread_status_offset, status); |
1723 | } |
1724 | |
1725 | // Read thread status value from threadStatus field in java.lang.Thread java class. |
1726 | java_lang_Thread::ThreadStatus java_lang_Thread::get_thread_status(oop java_thread) { |
1727 | // Make sure the caller is operating on behalf of the VM or is |
1728 | // running VM code (state == _thread_in_vm). |
1729 | assert(Threads_lock->owned_by_self() || Thread::current()->is_VM_thread() || |
1730 | JavaThread::current()->thread_state() == _thread_in_vm, |
1731 | "Java Thread is not running in vm" ); |
1732 | return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset); |
1733 | } |
1734 | |
1735 | |
1736 | jlong java_lang_Thread::thread_id(oop java_thread) { |
1737 | return java_thread->long_field(_tid_offset); |
1738 | } |
1739 | |
1740 | oop java_lang_Thread::park_blocker(oop java_thread) { |
1741 | return java_thread->obj_field(_park_blocker_offset); |
1742 | } |
1743 | |
1744 | const char* java_lang_Thread::thread_status_name(oop java_thread) { |
1745 | ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset); |
1746 | switch (status) { |
1747 | case NEW : return "NEW" ; |
1748 | case RUNNABLE : return "RUNNABLE" ; |
1749 | case SLEEPING : return "TIMED_WAITING (sleeping)" ; |
1750 | case IN_OBJECT_WAIT : return "WAITING (on object monitor)" ; |
1751 | case IN_OBJECT_WAIT_TIMED : return "TIMED_WAITING (on object monitor)" ; |
1752 | case PARKED : return "WAITING (parking)" ; |
1753 | case PARKED_TIMED : return "TIMED_WAITING (parking)" ; |
1754 | case BLOCKED_ON_MONITOR_ENTER : return "BLOCKED (on object monitor)" ; |
1755 | case TERMINATED : return "TERMINATED" ; |
1756 | default : return "UNKNOWN" ; |
1757 | }; |
1758 | } |
1759 | int java_lang_ThreadGroup::_parent_offset = 0; |
1760 | int java_lang_ThreadGroup::_name_offset = 0; |
1761 | int java_lang_ThreadGroup::_threads_offset = 0; |
1762 | int java_lang_ThreadGroup::_groups_offset = 0; |
1763 | int java_lang_ThreadGroup::_maxPriority_offset = 0; |
1764 | int java_lang_ThreadGroup::_destroyed_offset = 0; |
1765 | int java_lang_ThreadGroup::_daemon_offset = 0; |
1766 | int java_lang_ThreadGroup::_nthreads_offset = 0; |
1767 | int java_lang_ThreadGroup::_ngroups_offset = 0; |
1768 | |
1769 | oop java_lang_ThreadGroup::parent(oop java_thread_group) { |
1770 | assert(oopDesc::is_oop(java_thread_group), "thread group must be oop" ); |
1771 | return java_thread_group->obj_field(_parent_offset); |
1772 | } |
1773 | |
1774 | // ("name as oop" accessor is not necessary) |
1775 | |
1776 | const char* java_lang_ThreadGroup::name(oop java_thread_group) { |
1777 | oop name = java_thread_group->obj_field(_name_offset); |
1778 | // ThreadGroup.name can be null |
1779 | if (name != NULL) { |
1780 | return java_lang_String::as_utf8_string(name); |
1781 | } |
1782 | return NULL; |
1783 | } |
1784 | |
1785 | int java_lang_ThreadGroup::nthreads(oop java_thread_group) { |
1786 | assert(oopDesc::is_oop(java_thread_group), "thread group must be oop" ); |
1787 | return java_thread_group->int_field(_nthreads_offset); |
1788 | } |
1789 | |
1790 | objArrayOop java_lang_ThreadGroup::threads(oop java_thread_group) { |
1791 | oop threads = java_thread_group->obj_field(_threads_offset); |
1792 | assert(threads != NULL, "threadgroups should have threads" ); |
1793 | assert(threads->is_objArray(), "just checking" ); // Todo: Add better type checking code |
1794 | return objArrayOop(threads); |
1795 | } |
1796 | |
1797 | int java_lang_ThreadGroup::ngroups(oop java_thread_group) { |
1798 | assert(oopDesc::is_oop(java_thread_group), "thread group must be oop" ); |
1799 | return java_thread_group->int_field(_ngroups_offset); |
1800 | } |
1801 | |
1802 | objArrayOop java_lang_ThreadGroup::groups(oop java_thread_group) { |
1803 | oop groups = java_thread_group->obj_field(_groups_offset); |
1804 | assert(groups == NULL || groups->is_objArray(), "just checking" ); // Todo: Add better type checking code |
1805 | return objArrayOop(groups); |
1806 | } |
1807 | |
1808 | ThreadPriority java_lang_ThreadGroup::maxPriority(oop java_thread_group) { |
1809 | assert(oopDesc::is_oop(java_thread_group), "thread group must be oop" ); |
1810 | return (ThreadPriority) java_thread_group->int_field(_maxPriority_offset); |
1811 | } |
1812 | |
1813 | bool java_lang_ThreadGroup::is_destroyed(oop java_thread_group) { |
1814 | assert(oopDesc::is_oop(java_thread_group), "thread group must be oop" ); |
1815 | return java_thread_group->bool_field(_destroyed_offset) != 0; |
1816 | } |
1817 | |
1818 | bool java_lang_ThreadGroup::is_daemon(oop java_thread_group) { |
1819 | assert(oopDesc::is_oop(java_thread_group), "thread group must be oop" ); |
1820 | return java_thread_group->bool_field(_daemon_offset) != 0; |
1821 | } |
1822 | |
1823 | #define THREADGROUP_FIELDS_DO(macro) \ |
1824 | macro(_parent_offset, k, vmSymbols::parent_name(), threadgroup_signature, false); \ |
1825 | macro(_name_offset, k, vmSymbols::name_name(), string_signature, false); \ |
1826 | macro(_threads_offset, k, vmSymbols::threads_name(), thread_array_signature, false); \ |
1827 | macro(_groups_offset, k, vmSymbols::groups_name(), threadgroup_array_signature, false); \ |
1828 | macro(_maxPriority_offset, k, vmSymbols::maxPriority_name(), int_signature, false); \ |
1829 | macro(_destroyed_offset, k, vmSymbols::destroyed_name(), bool_signature, false); \ |
1830 | macro(_daemon_offset, k, vmSymbols::daemon_name(), bool_signature, false); \ |
1831 | macro(_nthreads_offset, k, vmSymbols::nthreads_name(), int_signature, false); \ |
1832 | macro(_ngroups_offset, k, vmSymbols::ngroups_name(), int_signature, false) |
1833 | |
1834 | void java_lang_ThreadGroup::compute_offsets() { |
1835 | assert(_parent_offset == 0, "offsets should be initialized only once" ); |
1836 | |
1837 | InstanceKlass* k = SystemDictionary::ThreadGroup_klass(); |
1838 | THREADGROUP_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
1839 | } |
1840 | |
1841 | #if INCLUDE_CDS |
1842 | void java_lang_ThreadGroup::serialize_offsets(SerializeClosure* f) { |
1843 | THREADGROUP_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
1844 | } |
1845 | #endif |
1846 | |
1847 | #define THROWABLE_FIELDS_DO(macro) \ |
1848 | macro(backtrace_offset, k, "backtrace", object_signature, false); \ |
1849 | macro(detailMessage_offset, k, "detailMessage", string_signature, false); \ |
1850 | macro(stackTrace_offset, k, "stackTrace", java_lang_StackTraceElement_array, false); \ |
1851 | macro(depth_offset, k, "depth", int_signature, false); \ |
1852 | macro(static_unassigned_stacktrace_offset, k, "UNASSIGNED_STACK", java_lang_StackTraceElement_array, true) |
1853 | |
1854 | void java_lang_Throwable::compute_offsets() { |
1855 | InstanceKlass* k = SystemDictionary::Throwable_klass(); |
1856 | THROWABLE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
1857 | } |
1858 | |
1859 | #if INCLUDE_CDS |
1860 | void java_lang_Throwable::serialize_offsets(SerializeClosure* f) { |
1861 | THROWABLE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
1862 | } |
1863 | #endif |
1864 | |
1865 | oop java_lang_Throwable::unassigned_stacktrace() { |
1866 | InstanceKlass* ik = SystemDictionary::Throwable_klass(); |
1867 | oop base = ik->static_field_base_raw(); |
1868 | return base->obj_field(static_unassigned_stacktrace_offset); |
1869 | } |
1870 | |
1871 | oop java_lang_Throwable::backtrace(oop throwable) { |
1872 | return throwable->obj_field_acquire(backtrace_offset); |
1873 | } |
1874 | |
1875 | |
1876 | void java_lang_Throwable::set_backtrace(oop throwable, oop value) { |
1877 | throwable->release_obj_field_put(backtrace_offset, value); |
1878 | } |
1879 | |
1880 | int java_lang_Throwable::depth(oop throwable) { |
1881 | return throwable->int_field(depth_offset); |
1882 | } |
1883 | |
1884 | void java_lang_Throwable::set_depth(oop throwable, int value) { |
1885 | throwable->int_field_put(depth_offset, value); |
1886 | } |
1887 | |
1888 | oop java_lang_Throwable::message(oop throwable) { |
1889 | return throwable->obj_field(detailMessage_offset); |
1890 | } |
1891 | |
1892 | |
1893 | // Return Symbol for detailed_message or NULL |
1894 | Symbol* java_lang_Throwable::detail_message(oop throwable) { |
1895 | PRESERVE_EXCEPTION_MARK; // Keep original exception |
1896 | oop detailed_message = java_lang_Throwable::message(throwable); |
1897 | if (detailed_message != NULL) { |
1898 | return java_lang_String::as_symbol(detailed_message); |
1899 | } |
1900 | return NULL; |
1901 | } |
1902 | |
1903 | void java_lang_Throwable::set_message(oop throwable, oop value) { |
1904 | throwable->obj_field_put(detailMessage_offset, value); |
1905 | } |
1906 | |
1907 | |
1908 | void java_lang_Throwable::set_stacktrace(oop throwable, oop st_element_array) { |
1909 | throwable->obj_field_put(stackTrace_offset, st_element_array); |
1910 | } |
1911 | |
1912 | void java_lang_Throwable::clear_stacktrace(oop throwable) { |
1913 | set_stacktrace(throwable, NULL); |
1914 | } |
1915 | |
1916 | |
1917 | void java_lang_Throwable::print(oop throwable, outputStream* st) { |
1918 | ResourceMark rm; |
1919 | Klass* k = throwable->klass(); |
1920 | assert(k != NULL, "just checking" ); |
1921 | st->print("%s" , k->external_name()); |
1922 | oop msg = message(throwable); |
1923 | if (msg != NULL) { |
1924 | st->print(": %s" , java_lang_String::as_utf8_string(msg)); |
1925 | } |
1926 | } |
1927 | |
1928 | // After this many redefines, the stack trace is unreliable. |
1929 | const int MAX_VERSION = USHRT_MAX; |
1930 | |
1931 | static inline bool version_matches(Method* method, int version) { |
1932 | assert(version < MAX_VERSION, "version is too big" ); |
1933 | return method != NULL && (method->constants()->version() == version); |
1934 | } |
1935 | |
1936 | |
1937 | // This class provides a simple wrapper over the internal structure of |
1938 | // exception backtrace to insulate users of the backtrace from needing |
1939 | // to know what it looks like. |
1940 | class BacktraceBuilder: public StackObj { |
1941 | friend class BacktraceIterator; |
1942 | private: |
1943 | Handle _backtrace; |
1944 | objArrayOop _head; |
1945 | typeArrayOop _methods; |
1946 | typeArrayOop _bcis; |
1947 | objArrayOop _mirrors; |
1948 | typeArrayOop _names; // needed to insulate method name against redefinition |
1949 | int _index; |
1950 | NoSafepointVerifier _nsv; |
1951 | |
1952 | enum { |
1953 | trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1954 | trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1955 | trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
1956 | trace_names_offset = java_lang_Throwable::trace_names_offset, |
1957 | trace_next_offset = java_lang_Throwable::trace_next_offset, |
1958 | trace_size = java_lang_Throwable::trace_size, |
1959 | trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1960 | }; |
1961 | |
1962 | // get info out of chunks |
1963 | static typeArrayOop get_methods(objArrayHandle chunk) { |
1964 | typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); |
1965 | assert(methods != NULL, "method array should be initialized in backtrace" ); |
1966 | return methods; |
1967 | } |
1968 | static typeArrayOop get_bcis(objArrayHandle chunk) { |
1969 | typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); |
1970 | assert(bcis != NULL, "bci array should be initialized in backtrace" ); |
1971 | return bcis; |
1972 | } |
1973 | static objArrayOop get_mirrors(objArrayHandle chunk) { |
1974 | objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); |
1975 | assert(mirrors != NULL, "mirror array should be initialized in backtrace" ); |
1976 | return mirrors; |
1977 | } |
1978 | static typeArrayOop get_names(objArrayHandle chunk) { |
1979 | typeArrayOop names = typeArrayOop(chunk->obj_at(trace_names_offset)); |
1980 | assert(names != NULL, "names array should be initialized in backtrace" ); |
1981 | return names; |
1982 | } |
1983 | |
1984 | public: |
1985 | |
1986 | // constructor for new backtrace |
1987 | BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL) { |
1988 | expand(CHECK); |
1989 | _backtrace = Handle(THREAD, _head); |
1990 | _index = 0; |
1991 | } |
1992 | |
1993 | BacktraceBuilder(Thread* thread, objArrayHandle backtrace) { |
1994 | _methods = get_methods(backtrace); |
1995 | _bcis = get_bcis(backtrace); |
1996 | _mirrors = get_mirrors(backtrace); |
1997 | _names = get_names(backtrace); |
1998 | assert(_methods->length() == _bcis->length() && |
1999 | _methods->length() == _mirrors->length() && |
2000 | _mirrors->length() == _names->length(), |
2001 | "method and source information arrays should match" ); |
2002 | |
2003 | // head is the preallocated backtrace |
2004 | _head = backtrace(); |
2005 | _backtrace = Handle(thread, _head); |
2006 | _index = 0; |
2007 | } |
2008 | |
2009 | void expand(TRAPS) { |
2010 | objArrayHandle old_head(THREAD, _head); |
2011 | PauseNoSafepointVerifier pnsv(&_nsv); |
2012 | |
2013 | objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); |
2014 | objArrayHandle new_head(THREAD, head); |
2015 | |
2016 | typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK); |
2017 | typeArrayHandle new_methods(THREAD, methods); |
2018 | |
2019 | typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); |
2020 | typeArrayHandle new_bcis(THREAD, bcis); |
2021 | |
2022 | objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
2023 | objArrayHandle new_mirrors(THREAD, mirrors); |
2024 | |
2025 | typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK); |
2026 | typeArrayHandle new_names(THREAD, names); |
2027 | |
2028 | if (!old_head.is_null()) { |
2029 | old_head->obj_at_put(trace_next_offset, new_head()); |
2030 | } |
2031 | new_head->obj_at_put(trace_methods_offset, new_methods()); |
2032 | new_head->obj_at_put(trace_bcis_offset, new_bcis()); |
2033 | new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); |
2034 | new_head->obj_at_put(trace_names_offset, new_names()); |
2035 | |
2036 | _head = new_head(); |
2037 | _methods = new_methods(); |
2038 | _bcis = new_bcis(); |
2039 | _mirrors = new_mirrors(); |
2040 | _names = new_names(); |
2041 | _index = 0; |
2042 | } |
2043 | |
2044 | oop backtrace() { |
2045 | return _backtrace(); |
2046 | } |
2047 | |
2048 | inline void push(Method* method, int bci, TRAPS) { |
2049 | // Smear the -1 bci to 0 since the array only holds unsigned |
2050 | // shorts. The later line number lookup would just smear the -1 |
2051 | // to a 0 even if it could be recorded. |
2052 | if (bci == SynchronizationEntryBCI) bci = 0; |
2053 | |
2054 | if (_index >= trace_chunk_size) { |
2055 | methodHandle mhandle(THREAD, method); |
2056 | expand(CHECK); |
2057 | method = mhandle(); |
2058 | } |
2059 | |
2060 | _methods->ushort_at_put(_index, method->orig_method_idnum()); |
2061 | _bcis->int_at_put(_index, Backtrace::merge_bci_and_version(bci, method->constants()->version())); |
2062 | |
2063 | // Note:this doesn't leak symbols because the mirror in the backtrace keeps the |
2064 | // klass owning the symbols alive so their refcounts aren't decremented. |
2065 | Symbol* name = method->name(); |
2066 | _names->symbol_at_put(_index, name); |
2067 | |
2068 | // We need to save the mirrors in the backtrace to keep the class |
2069 | // from being unloaded while we still have this stack trace. |
2070 | assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror" ); |
2071 | _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
2072 | _index++; |
2073 | } |
2074 | |
2075 | }; |
2076 | |
2077 | struct BacktraceElement : public StackObj { |
2078 | int _method_id; |
2079 | int _bci; |
2080 | int _version; |
2081 | Symbol* _name; |
2082 | Handle _mirror; |
2083 | BacktraceElement(Handle mirror, int mid, int version, int bci, Symbol* name) : |
2084 | _method_id(mid), _bci(bci), _version(version), _name(name), _mirror(mirror) {} |
2085 | }; |
2086 | |
2087 | class BacktraceIterator : public StackObj { |
2088 | int _index; |
2089 | objArrayHandle _result; |
2090 | objArrayHandle _mirrors; |
2091 | typeArrayHandle _methods; |
2092 | typeArrayHandle _bcis; |
2093 | typeArrayHandle _names; |
2094 | |
2095 | void init(objArrayHandle result, Thread* thread) { |
2096 | // Get method id, bci, version and mirror from chunk |
2097 | _result = result; |
2098 | if (_result.not_null()) { |
2099 | _methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result)); |
2100 | _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result)); |
2101 | _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result)); |
2102 | _names = typeArrayHandle(thread, BacktraceBuilder::get_names(_result)); |
2103 | _index = 0; |
2104 | } |
2105 | } |
2106 | public: |
2107 | BacktraceIterator(objArrayHandle result, Thread* thread) { |
2108 | init(result, thread); |
2109 | assert(_methods.is_null() || _methods->length() == java_lang_Throwable::trace_chunk_size, "lengths don't match" ); |
2110 | } |
2111 | |
2112 | BacktraceElement next(Thread* thread) { |
2113 | BacktraceElement e (Handle(thread, _mirrors->obj_at(_index)), |
2114 | _methods->ushort_at(_index), |
2115 | Backtrace::version_at(_bcis->int_at(_index)), |
2116 | Backtrace::bci_at(_bcis->int_at(_index)), |
2117 | _names->symbol_at(_index)); |
2118 | _index++; |
2119 | |
2120 | if (_index >= java_lang_Throwable::trace_chunk_size) { |
2121 | int next_offset = java_lang_Throwable::trace_next_offset; |
2122 | // Get next chunk |
2123 | objArrayHandle result (thread, objArrayOop(_result->obj_at(next_offset))); |
2124 | init(result, thread); |
2125 | } |
2126 | return e; |
2127 | } |
2128 | |
2129 | bool repeat() { |
2130 | return _result.not_null() && _mirrors->obj_at(_index) != NULL; |
2131 | } |
2132 | }; |
2133 | |
2134 | |
2135 | // Print stack trace element to resource allocated buffer |
2136 | static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id, |
2137 | int version, int bci, Symbol* name) { |
2138 | ResourceMark rm; |
2139 | |
2140 | // Get strings and string lengths |
2141 | InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
2142 | const char* klass_name = holder->external_name(); |
2143 | int buf_len = (int)strlen(klass_name); |
2144 | |
2145 | char* method_name = name->as_C_string(); |
2146 | buf_len += (int)strlen(method_name); |
2147 | |
2148 | char* source_file_name = NULL; |
2149 | Symbol* source = Backtrace::get_source_file_name(holder, version); |
2150 | if (source != NULL) { |
2151 | source_file_name = source->as_C_string(); |
2152 | buf_len += (int)strlen(source_file_name); |
2153 | } |
2154 | |
2155 | char *module_name = NULL, *module_version = NULL; |
2156 | ModuleEntry* module = holder->module(); |
2157 | if (module->is_named()) { |
2158 | module_name = module->name()->as_C_string(); |
2159 | buf_len += (int)strlen(module_name); |
2160 | if (module->version() != NULL) { |
2161 | module_version = module->version()->as_C_string(); |
2162 | buf_len += (int)strlen(module_version); |
2163 | } |
2164 | } |
2165 | |
2166 | // Allocate temporary buffer with extra space for formatting and line number |
2167 | char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); |
2168 | |
2169 | // Print stack trace line in buffer |
2170 | sprintf(buf, "\tat %s.%s(" , klass_name, method_name); |
2171 | |
2172 | // Print module information |
2173 | if (module_name != NULL) { |
2174 | if (module_version != NULL) { |
2175 | sprintf(buf + (int)strlen(buf), "%s@%s/" , module_name, module_version); |
2176 | } else { |
2177 | sprintf(buf + (int)strlen(buf), "%s/" , module_name); |
2178 | } |
2179 | } |
2180 | |
2181 | // The method can be NULL if the requested class version is gone |
2182 | Method* method = holder->method_with_orig_idnum(method_id, version); |
2183 | if (!version_matches(method, version)) { |
2184 | strcat(buf, "Redefined)" ); |
2185 | } else { |
2186 | int line_number = Backtrace::get_line_number(method, bci); |
2187 | if (line_number == -2) { |
2188 | strcat(buf, "Native Method)" ); |
2189 | } else { |
2190 | if (source_file_name != NULL && (line_number != -1)) { |
2191 | // Sourcename and linenumber |
2192 | sprintf(buf + (int)strlen(buf), "%s:%d)" , source_file_name, line_number); |
2193 | } else if (source_file_name != NULL) { |
2194 | // Just sourcename |
2195 | sprintf(buf + (int)strlen(buf), "%s)" , source_file_name); |
2196 | } else { |
2197 | // Neither sourcename nor linenumber |
2198 | sprintf(buf + (int)strlen(buf), "Unknown Source)" ); |
2199 | } |
2200 | CompiledMethod* nm = method->code(); |
2201 | if (WizardMode && nm != NULL) { |
2202 | sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")" , (intptr_t)nm); |
2203 | } |
2204 | } |
2205 | } |
2206 | |
2207 | st->print_cr("%s" , buf); |
2208 | } |
2209 | |
2210 | void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { |
2211 | Handle mirror (Thread::current(), method->method_holder()->java_mirror()); |
2212 | int method_id = method->orig_method_idnum(); |
2213 | int version = method->constants()->version(); |
2214 | print_stack_element_to_stream(st, mirror, method_id, version, bci, method->name()); |
2215 | } |
2216 | |
2217 | /** |
2218 | * Print the throwable message and its stack trace plus all causes by walking the |
2219 | * cause chain. The output looks the same as of Throwable.printStackTrace(). |
2220 | */ |
2221 | void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) { |
2222 | // First, print the message. |
2223 | print(throwable(), st); |
2224 | st->cr(); |
2225 | |
2226 | // Now print the stack trace. |
2227 | Thread* THREAD = Thread::current(); |
2228 | while (throwable.not_null()) { |
2229 | objArrayHandle result (THREAD, objArrayOop(backtrace(throwable()))); |
2230 | if (result.is_null()) { |
2231 | st->print_raw_cr("\t<<no stack trace available>>" ); |
2232 | return; |
2233 | } |
2234 | BacktraceIterator iter(result, THREAD); |
2235 | |
2236 | while (iter.repeat()) { |
2237 | BacktraceElement bte = iter.next(THREAD); |
2238 | print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._name); |
2239 | } |
2240 | { |
2241 | // Call getCause() which doesn't necessarily return the _cause field. |
2242 | EXCEPTION_MARK; |
2243 | JavaValue cause(T_OBJECT); |
2244 | JavaCalls::call_virtual(&cause, |
2245 | throwable, |
2246 | throwable->klass(), |
2247 | vmSymbols::getCause_name(), |
2248 | vmSymbols::void_throwable_signature(), |
2249 | THREAD); |
2250 | // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. |
2251 | if (HAS_PENDING_EXCEPTION) { |
2252 | CLEAR_PENDING_EXCEPTION; |
2253 | throwable = Handle(); |
2254 | } else { |
2255 | throwable = Handle(THREAD, (oop) cause.get_jobject()); |
2256 | if (throwable.not_null()) { |
2257 | st->print("Caused by: " ); |
2258 | print(throwable(), st); |
2259 | st->cr(); |
2260 | } |
2261 | } |
2262 | } |
2263 | } |
2264 | } |
2265 | |
2266 | /** |
2267 | * Print the throwable stack trace by calling the Java method java.lang.Throwable.printStackTrace(). |
2268 | */ |
2269 | void java_lang_Throwable::java_printStackTrace(Handle throwable, TRAPS) { |
2270 | assert(throwable->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected" ); |
2271 | JavaValue result(T_VOID); |
2272 | JavaCalls::call_virtual(&result, |
2273 | throwable, |
2274 | SystemDictionary::Throwable_klass(), |
2275 | vmSymbols::printStackTrace_name(), |
2276 | vmSymbols::void_method_signature(), |
2277 | THREAD); |
2278 | } |
2279 | |
2280 | void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS) { |
2281 | if (!StackTraceInThrowable) return; |
2282 | ResourceMark rm(THREAD); |
2283 | |
2284 | // Start out by clearing the backtrace for this object, in case the VM |
2285 | // runs out of memory while allocating the stack trace |
2286 | set_backtrace(throwable(), NULL); |
2287 | // Clear lazily constructed Java level stacktrace if refilling occurs |
2288 | // This is unnecessary in 1.7+ but harmless |
2289 | clear_stacktrace(throwable()); |
2290 | |
2291 | int max_depth = MaxJavaStackTraceDepth; |
2292 | JavaThread* thread = (JavaThread*)THREAD; |
2293 | |
2294 | BacktraceBuilder bt(CHECK); |
2295 | |
2296 | // If there is no Java frame just return the method that was being called |
2297 | // with bci 0 |
2298 | if (!thread->has_last_Java_frame()) { |
2299 | if (max_depth >= 1 && method() != NULL) { |
2300 | bt.push(method(), 0, CHECK); |
2301 | log_info(stacktrace)("%s, %d" , throwable->klass()->external_name(), 1); |
2302 | set_depth(throwable(), 1); |
2303 | set_backtrace(throwable(), bt.backtrace()); |
2304 | } |
2305 | return; |
2306 | } |
2307 | |
2308 | // Instead of using vframe directly, this version of fill_in_stack_trace |
2309 | // basically handles everything by hand. This significantly improved the |
2310 | // speed of this method call up to 28.5% on Solaris sparc. 27.1% on Windows. |
2311 | // See bug 6333838 for more details. |
2312 | // The "ASSERT" here is to verify this method generates the exactly same stack |
2313 | // trace as utilizing vframe. |
2314 | #ifdef ASSERT |
2315 | vframeStream st(thread); |
2316 | methodHandle st_method(THREAD, st.method()); |
2317 | #endif |
2318 | int total_count = 0; |
2319 | RegisterMap map(thread, false); |
2320 | int decode_offset = 0; |
2321 | CompiledMethod* nm = NULL; |
2322 | bool skip_fillInStackTrace_check = false; |
2323 | bool skip_throwableInit_check = false; |
2324 | bool skip_hidden = !ShowHiddenFrames; |
2325 | |
2326 | for (frame fr = thread->last_frame(); max_depth == 0 || max_depth != total_count;) { |
2327 | Method* method = NULL; |
2328 | int bci = 0; |
2329 | |
2330 | // Compiled java method case. |
2331 | if (decode_offset != 0) { |
2332 | DebugInfoReadStream stream(nm, decode_offset); |
2333 | decode_offset = stream.read_int(); |
2334 | method = (Method*)nm->metadata_at(stream.read_int()); |
2335 | bci = stream.read_bci(); |
2336 | } else { |
2337 | if (fr.is_first_frame()) break; |
2338 | address pc = fr.pc(); |
2339 | if (fr.is_interpreted_frame()) { |
2340 | address bcp = fr.interpreter_frame_bcp(); |
2341 | method = fr.interpreter_frame_method(); |
2342 | bci = method->bci_from(bcp); |
2343 | fr = fr.sender(&map); |
2344 | } else { |
2345 | CodeBlob* cb = fr.cb(); |
2346 | // HMMM QQQ might be nice to have frame return nm as NULL if cb is non-NULL |
2347 | // but non nmethod |
2348 | fr = fr.sender(&map); |
2349 | if (cb == NULL || !cb->is_compiled()) { |
2350 | continue; |
2351 | } |
2352 | nm = cb->as_compiled_method(); |
2353 | if (nm->method()->is_native()) { |
2354 | method = nm->method(); |
2355 | bci = 0; |
2356 | } else { |
2357 | PcDesc* pd = nm->pc_desc_at(pc); |
2358 | decode_offset = pd->scope_decode_offset(); |
2359 | // if decode_offset is not equal to 0, it will execute the |
2360 | // "compiled java method case" at the beginning of the loop. |
2361 | continue; |
2362 | } |
2363 | } |
2364 | } |
2365 | #ifdef ASSERT |
2366 | assert(st_method() == method && st.bci() == bci, |
2367 | "Wrong stack trace" ); |
2368 | st.next(); |
2369 | // vframeStream::method isn't GC-safe so store off a copy |
2370 | // of the Method* in case we GC. |
2371 | if (!st.at_end()) { |
2372 | st_method = st.method(); |
2373 | } |
2374 | #endif |
2375 | |
2376 | // the format of the stacktrace will be: |
2377 | // - 1 or more fillInStackTrace frames for the exception class (skipped) |
2378 | // - 0 or more <init> methods for the exception class (skipped) |
2379 | // - rest of the stack |
2380 | |
2381 | if (!skip_fillInStackTrace_check) { |
2382 | if (method->name() == vmSymbols::fillInStackTrace_name() && |
2383 | throwable->is_a(method->method_holder())) { |
2384 | continue; |
2385 | } |
2386 | else { |
2387 | skip_fillInStackTrace_check = true; // gone past them all |
2388 | } |
2389 | } |
2390 | if (!skip_throwableInit_check) { |
2391 | assert(skip_fillInStackTrace_check, "logic error in backtrace filtering" ); |
2392 | |
2393 | // skip <init> methods of the exception class and superclasses |
2394 | // This is simlar to classic VM. |
2395 | if (method->name() == vmSymbols::object_initializer_name() && |
2396 | throwable->is_a(method->method_holder())) { |
2397 | continue; |
2398 | } else { |
2399 | // there are none or we've seen them all - either way stop checking |
2400 | skip_throwableInit_check = true; |
2401 | } |
2402 | } |
2403 | if (method->is_hidden()) { |
2404 | if (skip_hidden) continue; |
2405 | } |
2406 | bt.push(method, bci, CHECK); |
2407 | total_count++; |
2408 | } |
2409 | |
2410 | log_info(stacktrace)("%s, %d" , throwable->klass()->external_name(), total_count); |
2411 | |
2412 | // Put completed stack trace into throwable object |
2413 | set_backtrace(throwable(), bt.backtrace()); |
2414 | set_depth(throwable(), total_count); |
2415 | } |
2416 | |
2417 | void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method) { |
2418 | // No-op if stack trace is disabled |
2419 | if (!StackTraceInThrowable) { |
2420 | return; |
2421 | } |
2422 | |
2423 | // Disable stack traces for some preallocated out of memory errors |
2424 | if (!Universe::should_fill_in_stack_trace(throwable)) { |
2425 | return; |
2426 | } |
2427 | |
2428 | PRESERVE_EXCEPTION_MARK; |
2429 | |
2430 | JavaThread* thread = JavaThread::active(); |
2431 | fill_in_stack_trace(throwable, method, thread); |
2432 | // ignore exceptions thrown during stack trace filling |
2433 | CLEAR_PENDING_EXCEPTION; |
2434 | } |
2435 | |
2436 | void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { |
2437 | // Allocate stack trace - backtrace is created but not filled in |
2438 | |
2439 | // No-op if stack trace is disabled |
2440 | if (!StackTraceInThrowable) return; |
2441 | BacktraceBuilder bt(CHECK); // creates a backtrace |
2442 | set_backtrace(throwable(), bt.backtrace()); |
2443 | } |
2444 | |
2445 | |
2446 | void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle throwable) { |
2447 | // Fill in stack trace into preallocated backtrace (no GC) |
2448 | |
2449 | // No-op if stack trace is disabled |
2450 | if (!StackTraceInThrowable) return; |
2451 | |
2452 | assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check" ); |
2453 | |
2454 | JavaThread* THREAD = JavaThread::current(); |
2455 | |
2456 | objArrayHandle backtrace (THREAD, (objArrayOop)java_lang_Throwable::backtrace(throwable())); |
2457 | assert(backtrace.not_null(), "backtrace should have been preallocated" ); |
2458 | |
2459 | ResourceMark rm(THREAD); |
2460 | vframeStream st(THREAD); |
2461 | |
2462 | BacktraceBuilder bt(THREAD, backtrace); |
2463 | |
2464 | // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init |
2465 | // methods as preallocated errors aren't created by "java" code. |
2466 | |
2467 | // fill in as much stack trace as possible |
2468 | int chunk_count = 0; |
2469 | for (;!st.at_end(); st.next()) { |
2470 | bt.push(st.method(), st.bci(), CHECK); |
2471 | chunk_count++; |
2472 | |
2473 | // Bail-out for deep stacks |
2474 | if (chunk_count >= trace_chunk_size) break; |
2475 | } |
2476 | set_depth(throwable(), chunk_count); |
2477 | log_info(stacktrace)("%s, %d" , throwable->klass()->external_name(), chunk_count); |
2478 | |
2479 | // We support the Throwable immutability protocol defined for Java 7. |
2480 | java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); |
2481 | assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized" ); |
2482 | } |
2483 | |
2484 | void java_lang_Throwable::get_stack_trace_elements(Handle throwable, |
2485 | objArrayHandle stack_trace_array_h, TRAPS) { |
2486 | |
2487 | if (throwable.is_null() || stack_trace_array_h.is_null()) { |
2488 | THROW(vmSymbols::java_lang_NullPointerException()); |
2489 | } |
2490 | |
2491 | assert(stack_trace_array_h->is_objArray(), "Stack trace array should be an array of StackTraceElenent" ); |
2492 | |
2493 | if (stack_trace_array_h->length() != depth(throwable())) { |
2494 | THROW(vmSymbols::java_lang_IndexOutOfBoundsException()); |
2495 | } |
2496 | |
2497 | objArrayHandle result(THREAD, objArrayOop(backtrace(throwable()))); |
2498 | BacktraceIterator iter(result, THREAD); |
2499 | |
2500 | int index = 0; |
2501 | while (iter.repeat()) { |
2502 | BacktraceElement bte = iter.next(THREAD); |
2503 | |
2504 | Handle stack_trace_element(THREAD, stack_trace_array_h->obj_at(index++)); |
2505 | |
2506 | if (stack_trace_element.is_null()) { |
2507 | THROW(vmSymbols::java_lang_NullPointerException()); |
2508 | } |
2509 | |
2510 | InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(bte._mirror())); |
2511 | methodHandle method (THREAD, holder->method_with_orig_idnum(bte._method_id, bte._version)); |
2512 | |
2513 | java_lang_StackTraceElement::fill_in(stack_trace_element, holder, |
2514 | method, |
2515 | bte._version, |
2516 | bte._bci, |
2517 | bte._name, CHECK); |
2518 | } |
2519 | } |
2520 | |
2521 | oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { |
2522 | // Allocate java.lang.StackTraceElement instance |
2523 | InstanceKlass* k = SystemDictionary::StackTraceElement_klass(); |
2524 | assert(k != NULL, "must be loaded in 1.4+" ); |
2525 | if (k->should_be_initialized()) { |
2526 | k->initialize(CHECK_0); |
2527 | } |
2528 | |
2529 | Handle element = k->allocate_instance_handle(CHECK_0); |
2530 | |
2531 | int version = method->constants()->version(); |
2532 | fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0); |
2533 | return element(); |
2534 | } |
2535 | |
2536 | void java_lang_StackTraceElement::fill_in(Handle element, |
2537 | InstanceKlass* holder, const methodHandle& method, |
2538 | int version, int bci, Symbol* name, TRAPS) { |
2539 | assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check" ); |
2540 | |
2541 | ResourceMark rm(THREAD); |
2542 | HandleMark hm(THREAD); |
2543 | |
2544 | // Fill in class name |
2545 | Handle java_class(THREAD, holder->java_mirror()); |
2546 | oop classname = java_lang_Class::name(java_class, CHECK); |
2547 | java_lang_StackTraceElement::set_declaringClass(element(), classname); |
2548 | java_lang_StackTraceElement::set_declaringClassObject(element(), java_class()); |
2549 | |
2550 | oop loader = holder->class_loader(); |
2551 | if (loader != NULL) { |
2552 | oop loader_name = java_lang_ClassLoader::name(loader); |
2553 | if (loader_name != NULL) |
2554 | java_lang_StackTraceElement::set_classLoaderName(element(), loader_name); |
2555 | } |
2556 | |
2557 | // Fill in method name |
2558 | oop methodname = StringTable::intern(name, CHECK); |
2559 | java_lang_StackTraceElement::set_methodName(element(), methodname); |
2560 | |
2561 | // Fill in module name and version |
2562 | ModuleEntry* module = holder->module(); |
2563 | if (module->is_named()) { |
2564 | oop module_name = StringTable::intern(module->name(), CHECK); |
2565 | java_lang_StackTraceElement::set_moduleName(element(), module_name); |
2566 | oop module_version; |
2567 | if (module->version() != NULL) { |
2568 | module_version = StringTable::intern(module->version(), CHECK); |
2569 | } else { |
2570 | module_version = NULL; |
2571 | } |
2572 | java_lang_StackTraceElement::set_moduleVersion(element(), module_version); |
2573 | } |
2574 | |
2575 | if (method() == NULL || !version_matches(method(), version)) { |
2576 | // The method was redefined, accurate line number information isn't available |
2577 | java_lang_StackTraceElement::set_fileName(element(), NULL); |
2578 | java_lang_StackTraceElement::set_lineNumber(element(), -1); |
2579 | } else { |
2580 | // Fill in source file name and line number. |
2581 | Symbol* source = Backtrace::get_source_file_name(holder, version); |
2582 | oop source_file = java_lang_Class::source_file(java_class()); |
2583 | if (source != NULL) { |
2584 | // Class was not redefined. We can trust its cache if set, |
2585 | // else we have to initialize it. |
2586 | if (source_file == NULL) { |
2587 | source_file = StringTable::intern(source, CHECK); |
2588 | java_lang_Class::set_source_file(java_class(), source_file); |
2589 | } |
2590 | } else { |
2591 | // Class was redefined. Dump the cache if it was set. |
2592 | if (source_file != NULL) { |
2593 | source_file = NULL; |
2594 | java_lang_Class::set_source_file(java_class(), source_file); |
2595 | } |
2596 | if (ShowHiddenFrames) { |
2597 | source = vmSymbols::unknown_class_name(); |
2598 | source_file = StringTable::intern(source, CHECK); |
2599 | } |
2600 | } |
2601 | java_lang_StackTraceElement::set_fileName(element(), source_file); |
2602 | |
2603 | int line_number = Backtrace::get_line_number(method, bci); |
2604 | java_lang_StackTraceElement::set_lineNumber(element(), line_number); |
2605 | } |
2606 | } |
2607 | |
2608 | #if INCLUDE_JVMCI |
2609 | void java_lang_StackTraceElement::decode(Handle mirror, methodHandle method, int bci, Symbol*& methodname, Symbol*& filename, int& line_number) { |
2610 | int method_id = method->orig_method_idnum(); |
2611 | int cpref = method->name_index(); |
2612 | decode(mirror, method_id, method->constants()->version(), bci, cpref, methodname, filename, line_number); |
2613 | } |
2614 | |
2615 | void java_lang_StackTraceElement::decode(Handle mirror, int method_id, int version, int bci, int cpref, Symbol*& methodname, Symbol*& filename, int& line_number) { |
2616 | // Fill in class name |
2617 | InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
2618 | Method* method = holder->method_with_orig_idnum(method_id, version); |
2619 | |
2620 | // The method can be NULL if the requested class version is gone |
2621 | Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); |
2622 | |
2623 | // Fill in method name |
2624 | methodname = sym; |
2625 | |
2626 | if (!version_matches(method, version)) { |
2627 | // If the method was redefined, accurate line number information isn't available |
2628 | filename = NULL; |
2629 | line_number = -1; |
2630 | } else { |
2631 | // Fill in source file name and line number. |
2632 | // Use a specific ik version as a holder since the mirror might |
2633 | // refer to a version that is now obsolete and no longer accessible |
2634 | // via the previous versions list. |
2635 | holder = holder->get_klass_version(version); |
2636 | assert(holder != NULL, "sanity check" ); |
2637 | Symbol* source = holder->source_file_name(); |
2638 | if (ShowHiddenFrames && source == NULL) { |
2639 | source = vmSymbols::unknown_class_name(); |
2640 | } |
2641 | filename = source; |
2642 | line_number = Backtrace::get_line_number(method, bci); |
2643 | } |
2644 | } |
2645 | #endif // INCLUDE_JVMCI |
2646 | |
2647 | Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { |
2648 | HandleMark hm(THREAD); |
2649 | Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); |
2650 | Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); |
2651 | // we should expand MemberName::name when Throwable uses StackTrace |
2652 | // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); |
2653 | return method; |
2654 | } |
2655 | |
2656 | void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS) { |
2657 | // set Method* or mid/cpref |
2658 | HandleMark hm(THREAD); |
2659 | Handle mname(Thread::current(), stackFrame->obj_field(_memberName_offset)); |
2660 | InstanceKlass* ik = method->method_holder(); |
2661 | CallInfo info(method(), ik, CHECK); |
2662 | MethodHandles::init_method_MemberName(mname, info); |
2663 | // set bci |
2664 | java_lang_StackFrameInfo::set_bci(stackFrame(), bci); |
2665 | // method may be redefined; store the version |
2666 | int version = method->constants()->version(); |
2667 | assert((jushort)version == version, "version should be short" ); |
2668 | java_lang_StackFrameInfo::set_version(stackFrame(), (short)version); |
2669 | } |
2670 | |
2671 | void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) { |
2672 | ResourceMark rm(THREAD); |
2673 | HandleMark hm(THREAD); |
2674 | Handle mname(THREAD, stackFrame->obj_field(java_lang_StackFrameInfo::_memberName_offset)); |
2675 | Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname())); |
2676 | InstanceKlass* holder = InstanceKlass::cast(clazz); |
2677 | Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK); |
2678 | |
2679 | short version = stackFrame->short_field(_version_offset); |
2680 | short bci = stackFrame->short_field(_bci_offset); |
2681 | Symbol* name = method->name(); |
2682 | java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, CHECK); |
2683 | } |
2684 | |
2685 | #define STACKFRAMEINFO_FIELDS_DO(macro) \ |
2686 | macro(_memberName_offset, k, "memberName", object_signature, false); \ |
2687 | macro(_bci_offset, k, "bci", short_signature, false) |
2688 | |
2689 | void java_lang_StackFrameInfo::compute_offsets() { |
2690 | InstanceKlass* k = SystemDictionary::StackFrameInfo_klass(); |
2691 | STACKFRAMEINFO_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
2692 | STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
2693 | } |
2694 | |
2695 | #if INCLUDE_CDS |
2696 | void java_lang_StackFrameInfo::serialize_offsets(SerializeClosure* f) { |
2697 | STACKFRAMEINFO_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
2698 | STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
2699 | } |
2700 | #endif |
2701 | |
2702 | #define LIVESTACKFRAMEINFO_FIELDS_DO(macro) \ |
2703 | macro(_monitors_offset, k, "monitors", object_array_signature, false); \ |
2704 | macro(_locals_offset, k, "locals", object_array_signature, false); \ |
2705 | macro(_operands_offset, k, "operands", object_array_signature, false); \ |
2706 | macro(_mode_offset, k, "mode", int_signature, false) |
2707 | |
2708 | void java_lang_LiveStackFrameInfo::compute_offsets() { |
2709 | InstanceKlass* k = SystemDictionary::LiveStackFrameInfo_klass(); |
2710 | LIVESTACKFRAMEINFO_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
2711 | } |
2712 | |
2713 | #if INCLUDE_CDS |
2714 | void java_lang_LiveStackFrameInfo::serialize_offsets(SerializeClosure* f) { |
2715 | LIVESTACKFRAMEINFO_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
2716 | } |
2717 | #endif |
2718 | |
2719 | #define ACCESSIBLEOBJECT_FIELDS_DO(macro) \ |
2720 | macro(override_offset, k, "override", bool_signature, false) |
2721 | |
2722 | void java_lang_reflect_AccessibleObject::compute_offsets() { |
2723 | InstanceKlass* k = SystemDictionary::reflect_AccessibleObject_klass(); |
2724 | ACCESSIBLEOBJECT_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
2725 | } |
2726 | |
2727 | #if INCLUDE_CDS |
2728 | void java_lang_reflect_AccessibleObject::serialize_offsets(SerializeClosure* f) { |
2729 | ACCESSIBLEOBJECT_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
2730 | } |
2731 | #endif |
2732 | |
2733 | jboolean java_lang_reflect_AccessibleObject::override(oop reflect) { |
2734 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2735 | return (jboolean) reflect->bool_field(override_offset); |
2736 | } |
2737 | |
2738 | void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean value) { |
2739 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2740 | reflect->bool_field_put(override_offset, (int) value); |
2741 | } |
2742 | |
2743 | #define METHOD_FIELDS_DO(macro) \ |
2744 | macro(clazz_offset, k, vmSymbols::clazz_name(), class_signature, false); \ |
2745 | macro(name_offset, k, vmSymbols::name_name(), string_signature, false); \ |
2746 | macro(returnType_offset, k, vmSymbols::returnType_name(), class_signature, false); \ |
2747 | macro(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), class_array_signature, false); \ |
2748 | macro(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), class_array_signature, false); \ |
2749 | macro(slot_offset, k, vmSymbols::slot_name(), int_signature, false); \ |
2750 | macro(modifiers_offset, k, vmSymbols::modifiers_name(), int_signature, false); \ |
2751 | macro(signature_offset, k, vmSymbols::signature_name(), string_signature, false); \ |
2752 | macro(annotations_offset, k, vmSymbols::annotations_name(), byte_array_signature, false); \ |
2753 | macro(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), byte_array_signature, false); \ |
2754 | macro(annotation_default_offset, k, vmSymbols::annotation_default_name(), byte_array_signature, false); |
2755 | |
2756 | void java_lang_reflect_Method::compute_offsets() { |
2757 | InstanceKlass* k = SystemDictionary::reflect_Method_klass(); |
2758 | METHOD_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
2759 | } |
2760 | |
2761 | #if INCLUDE_CDS |
2762 | void java_lang_reflect_Method::serialize_offsets(SerializeClosure* f) { |
2763 | METHOD_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
2764 | } |
2765 | #endif |
2766 | |
2767 | Handle java_lang_reflect_Method::create(TRAPS) { |
2768 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2769 | Klass* klass = SystemDictionary::reflect_Method_klass(); |
2770 | // This class is eagerly initialized during VM initialization, since we keep a refence |
2771 | // to one of the methods |
2772 | assert(InstanceKlass::cast(klass)->is_initialized(), "must be initialized" ); |
2773 | return InstanceKlass::cast(klass)->allocate_instance_handle(THREAD); |
2774 | } |
2775 | |
2776 | oop java_lang_reflect_Method::clazz(oop reflect) { |
2777 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2778 | return reflect->obj_field(clazz_offset); |
2779 | } |
2780 | |
2781 | void java_lang_reflect_Method::set_clazz(oop reflect, oop value) { |
2782 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2783 | reflect->obj_field_put(clazz_offset, value); |
2784 | } |
2785 | |
2786 | int java_lang_reflect_Method::slot(oop reflect) { |
2787 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2788 | return reflect->int_field(slot_offset); |
2789 | } |
2790 | |
2791 | void java_lang_reflect_Method::set_slot(oop reflect, int value) { |
2792 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2793 | reflect->int_field_put(slot_offset, value); |
2794 | } |
2795 | |
2796 | void java_lang_reflect_Method::set_name(oop method, oop value) { |
2797 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2798 | method->obj_field_put(name_offset, value); |
2799 | } |
2800 | |
2801 | oop java_lang_reflect_Method::return_type(oop method) { |
2802 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2803 | return method->obj_field(returnType_offset); |
2804 | } |
2805 | |
2806 | void java_lang_reflect_Method::set_return_type(oop method, oop value) { |
2807 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2808 | method->obj_field_put(returnType_offset, value); |
2809 | } |
2810 | |
2811 | oop java_lang_reflect_Method::parameter_types(oop method) { |
2812 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2813 | return method->obj_field(parameterTypes_offset); |
2814 | } |
2815 | |
2816 | void java_lang_reflect_Method::set_parameter_types(oop method, oop value) { |
2817 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2818 | method->obj_field_put(parameterTypes_offset, value); |
2819 | } |
2820 | |
2821 | void java_lang_reflect_Method::set_exception_types(oop method, oop value) { |
2822 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2823 | method->obj_field_put(exceptionTypes_offset, value); |
2824 | } |
2825 | |
2826 | void java_lang_reflect_Method::set_modifiers(oop method, int value) { |
2827 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2828 | method->int_field_put(modifiers_offset, value); |
2829 | } |
2830 | |
2831 | void java_lang_reflect_Method::set_signature(oop method, oop value) { |
2832 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2833 | method->obj_field_put(signature_offset, value); |
2834 | } |
2835 | |
2836 | void java_lang_reflect_Method::set_annotations(oop method, oop value) { |
2837 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2838 | method->obj_field_put(annotations_offset, value); |
2839 | } |
2840 | |
2841 | void java_lang_reflect_Method::set_parameter_annotations(oop method, oop value) { |
2842 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2843 | method->obj_field_put(parameter_annotations_offset, value); |
2844 | } |
2845 | |
2846 | void java_lang_reflect_Method::set_annotation_default(oop method, oop value) { |
2847 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2848 | method->obj_field_put(annotation_default_offset, value); |
2849 | } |
2850 | |
2851 | #define CONSTRUCTOR_FIELDS_DO(macro) \ |
2852 | macro(clazz_offset, k, vmSymbols::clazz_name(), class_signature, false); \ |
2853 | macro(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), class_array_signature, false); \ |
2854 | macro(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), class_array_signature, false); \ |
2855 | macro(slot_offset, k, vmSymbols::slot_name(), int_signature, false); \ |
2856 | macro(modifiers_offset, k, vmSymbols::modifiers_name(), int_signature, false); \ |
2857 | macro(signature_offset, k, vmSymbols::signature_name(), string_signature, false); \ |
2858 | macro(annotations_offset, k, vmSymbols::annotations_name(), byte_array_signature, false); \ |
2859 | macro(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), byte_array_signature, false); |
2860 | |
2861 | void java_lang_reflect_Constructor::compute_offsets() { |
2862 | InstanceKlass* k = SystemDictionary::reflect_Constructor_klass(); |
2863 | CONSTRUCTOR_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
2864 | } |
2865 | |
2866 | #if INCLUDE_CDS |
2867 | void java_lang_reflect_Constructor::serialize_offsets(SerializeClosure* f) { |
2868 | CONSTRUCTOR_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
2869 | } |
2870 | #endif |
2871 | |
2872 | Handle java_lang_reflect_Constructor::create(TRAPS) { |
2873 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2874 | Symbol* name = vmSymbols::java_lang_reflect_Constructor(); |
2875 | Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); |
2876 | InstanceKlass* ik = InstanceKlass::cast(k); |
2877 | // Ensure it is initialized |
2878 | ik->initialize(CHECK_NH); |
2879 | return ik->allocate_instance_handle(THREAD); |
2880 | } |
2881 | |
2882 | oop java_lang_reflect_Constructor::clazz(oop reflect) { |
2883 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2884 | return reflect->obj_field(clazz_offset); |
2885 | } |
2886 | |
2887 | void java_lang_reflect_Constructor::set_clazz(oop reflect, oop value) { |
2888 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2889 | reflect->obj_field_put(clazz_offset, value); |
2890 | } |
2891 | |
2892 | oop java_lang_reflect_Constructor::parameter_types(oop constructor) { |
2893 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2894 | return constructor->obj_field(parameterTypes_offset); |
2895 | } |
2896 | |
2897 | void java_lang_reflect_Constructor::set_parameter_types(oop constructor, oop value) { |
2898 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2899 | constructor->obj_field_put(parameterTypes_offset, value); |
2900 | } |
2901 | |
2902 | void java_lang_reflect_Constructor::set_exception_types(oop constructor, oop value) { |
2903 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2904 | constructor->obj_field_put(exceptionTypes_offset, value); |
2905 | } |
2906 | |
2907 | int java_lang_reflect_Constructor::slot(oop reflect) { |
2908 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2909 | return reflect->int_field(slot_offset); |
2910 | } |
2911 | |
2912 | void java_lang_reflect_Constructor::set_slot(oop reflect, int value) { |
2913 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2914 | reflect->int_field_put(slot_offset, value); |
2915 | } |
2916 | |
2917 | void java_lang_reflect_Constructor::set_modifiers(oop constructor, int value) { |
2918 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2919 | constructor->int_field_put(modifiers_offset, value); |
2920 | } |
2921 | |
2922 | void java_lang_reflect_Constructor::set_signature(oop constructor, oop value) { |
2923 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2924 | constructor->obj_field_put(signature_offset, value); |
2925 | } |
2926 | |
2927 | void java_lang_reflect_Constructor::set_annotations(oop constructor, oop value) { |
2928 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2929 | constructor->obj_field_put(annotations_offset, value); |
2930 | } |
2931 | |
2932 | void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop value) { |
2933 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2934 | method->obj_field_put(parameter_annotations_offset, value); |
2935 | } |
2936 | |
2937 | #define FIELD_FIELDS_DO(macro) \ |
2938 | macro(clazz_offset, k, vmSymbols::clazz_name(), class_signature, false); \ |
2939 | macro(name_offset, k, vmSymbols::name_name(), string_signature, false); \ |
2940 | macro(type_offset, k, vmSymbols::type_name(), class_signature, false); \ |
2941 | macro(slot_offset, k, vmSymbols::slot_name(), int_signature, false); \ |
2942 | macro(modifiers_offset, k, vmSymbols::modifiers_name(), int_signature, false); \ |
2943 | macro(signature_offset, k, vmSymbols::signature_name(), string_signature, false); \ |
2944 | macro(annotations_offset, k, vmSymbols::annotations_name(), byte_array_signature, false); |
2945 | |
2946 | void java_lang_reflect_Field::compute_offsets() { |
2947 | InstanceKlass* k = SystemDictionary::reflect_Field_klass(); |
2948 | FIELD_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
2949 | } |
2950 | |
2951 | #if INCLUDE_CDS |
2952 | void java_lang_reflect_Field::serialize_offsets(SerializeClosure* f) { |
2953 | FIELD_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
2954 | } |
2955 | #endif |
2956 | |
2957 | Handle java_lang_reflect_Field::create(TRAPS) { |
2958 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2959 | Symbol* name = vmSymbols::java_lang_reflect_Field(); |
2960 | Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); |
2961 | InstanceKlass* ik = InstanceKlass::cast(k); |
2962 | // Ensure it is initialized |
2963 | ik->initialize(CHECK_NH); |
2964 | return ik->allocate_instance_handle(THREAD); |
2965 | } |
2966 | |
2967 | oop java_lang_reflect_Field::clazz(oop reflect) { |
2968 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2969 | return reflect->obj_field(clazz_offset); |
2970 | } |
2971 | |
2972 | void java_lang_reflect_Field::set_clazz(oop reflect, oop value) { |
2973 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2974 | reflect->obj_field_put(clazz_offset, value); |
2975 | } |
2976 | |
2977 | oop java_lang_reflect_Field::name(oop field) { |
2978 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2979 | return field->obj_field(name_offset); |
2980 | } |
2981 | |
2982 | void java_lang_reflect_Field::set_name(oop field, oop value) { |
2983 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2984 | field->obj_field_put(name_offset, value); |
2985 | } |
2986 | |
2987 | oop java_lang_reflect_Field::type(oop field) { |
2988 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2989 | return field->obj_field(type_offset); |
2990 | } |
2991 | |
2992 | void java_lang_reflect_Field::set_type(oop field, oop value) { |
2993 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2994 | field->obj_field_put(type_offset, value); |
2995 | } |
2996 | |
2997 | int java_lang_reflect_Field::slot(oop reflect) { |
2998 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
2999 | return reflect->int_field(slot_offset); |
3000 | } |
3001 | |
3002 | void java_lang_reflect_Field::set_slot(oop reflect, int value) { |
3003 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3004 | reflect->int_field_put(slot_offset, value); |
3005 | } |
3006 | |
3007 | int java_lang_reflect_Field::modifiers(oop field) { |
3008 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3009 | return field->int_field(modifiers_offset); |
3010 | } |
3011 | |
3012 | void java_lang_reflect_Field::set_modifiers(oop field, int value) { |
3013 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3014 | field->int_field_put(modifiers_offset, value); |
3015 | } |
3016 | |
3017 | void java_lang_reflect_Field::set_signature(oop field, oop value) { |
3018 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3019 | field->obj_field_put(signature_offset, value); |
3020 | } |
3021 | |
3022 | void java_lang_reflect_Field::set_annotations(oop field, oop value) { |
3023 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3024 | field->obj_field_put(annotations_offset, value); |
3025 | } |
3026 | |
3027 | #define CONSTANTPOOL_FIELDS_DO(macro) \ |
3028 | macro(_oop_offset, k, "constantPoolOop", object_signature, false) |
3029 | |
3030 | void reflect_ConstantPool::compute_offsets() { |
3031 | InstanceKlass* k = SystemDictionary::reflect_ConstantPool_klass(); |
3032 | // The field is called ConstantPool* in the sun.reflect.ConstantPool class. |
3033 | CONSTANTPOOL_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3034 | } |
3035 | |
3036 | #if INCLUDE_CDS |
3037 | void reflect_ConstantPool::serialize_offsets(SerializeClosure* f) { |
3038 | CONSTANTPOOL_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3039 | } |
3040 | #endif |
3041 | |
3042 | #define PARAMETER_FIELDS_DO(macro) \ |
3043 | macro(name_offset, k, vmSymbols::name_name(), string_signature, false); \ |
3044 | macro(modifiers_offset, k, vmSymbols::modifiers_name(), int_signature, false); \ |
3045 | macro(index_offset, k, vmSymbols::index_name(), int_signature, false); \ |
3046 | macro(executable_offset, k, vmSymbols::executable_name(), executable_signature, false) |
3047 | |
3048 | void java_lang_reflect_Parameter::compute_offsets() { |
3049 | InstanceKlass* k = SystemDictionary::reflect_Parameter_klass(); |
3050 | PARAMETER_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3051 | } |
3052 | |
3053 | #if INCLUDE_CDS |
3054 | void java_lang_reflect_Parameter::serialize_offsets(SerializeClosure* f) { |
3055 | PARAMETER_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3056 | } |
3057 | #endif |
3058 | |
3059 | Handle java_lang_reflect_Parameter::create(TRAPS) { |
3060 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3061 | Symbol* name = vmSymbols::java_lang_reflect_Parameter(); |
3062 | Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); |
3063 | InstanceKlass* ik = InstanceKlass::cast(k); |
3064 | // Ensure it is initialized |
3065 | ik->initialize(CHECK_NH); |
3066 | return ik->allocate_instance_handle(THREAD); |
3067 | } |
3068 | |
3069 | oop java_lang_reflect_Parameter::name(oop param) { |
3070 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3071 | return param->obj_field(name_offset); |
3072 | } |
3073 | |
3074 | void java_lang_reflect_Parameter::set_name(oop param, oop value) { |
3075 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3076 | param->obj_field_put(name_offset, value); |
3077 | } |
3078 | |
3079 | int java_lang_reflect_Parameter::modifiers(oop param) { |
3080 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3081 | return param->int_field(modifiers_offset); |
3082 | } |
3083 | |
3084 | void java_lang_reflect_Parameter::set_modifiers(oop param, int value) { |
3085 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3086 | param->int_field_put(modifiers_offset, value); |
3087 | } |
3088 | |
3089 | int java_lang_reflect_Parameter::index(oop param) { |
3090 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3091 | return param->int_field(index_offset); |
3092 | } |
3093 | |
3094 | void java_lang_reflect_Parameter::set_index(oop param, int value) { |
3095 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3096 | param->int_field_put(index_offset, value); |
3097 | } |
3098 | |
3099 | oop java_lang_reflect_Parameter::executable(oop param) { |
3100 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3101 | return param->obj_field(executable_offset); |
3102 | } |
3103 | |
3104 | void java_lang_reflect_Parameter::set_executable(oop param, oop value) { |
3105 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3106 | param->obj_field_put(executable_offset, value); |
3107 | } |
3108 | |
3109 | |
3110 | int java_lang_Module::loader_offset; |
3111 | int java_lang_Module::name_offset; |
3112 | int java_lang_Module::_module_entry_offset = -1; |
3113 | |
3114 | Handle java_lang_Module::create(Handle loader, Handle module_name, TRAPS) { |
3115 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3116 | return JavaCalls::construct_new_instance(SystemDictionary::Module_klass(), |
3117 | vmSymbols::java_lang_module_init_signature(), |
3118 | loader, module_name, CHECK_NH); |
3119 | } |
3120 | |
3121 | #define MODULE_FIELDS_DO(macro) \ |
3122 | macro(loader_offset, k, vmSymbols::loader_name(), classloader_signature, false); \ |
3123 | macro(name_offset, k, vmSymbols::name_name(), string_signature, false) |
3124 | |
3125 | void java_lang_Module::compute_offsets() { |
3126 | InstanceKlass* k = SystemDictionary::Module_klass(); |
3127 | MODULE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3128 | MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
3129 | } |
3130 | |
3131 | #if INCLUDE_CDS |
3132 | void java_lang_Module::serialize_offsets(SerializeClosure* f) { |
3133 | MODULE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3134 | MODULE_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
3135 | } |
3136 | #endif |
3137 | |
3138 | oop java_lang_Module::loader(oop module) { |
3139 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3140 | return module->obj_field(loader_offset); |
3141 | } |
3142 | |
3143 | void java_lang_Module::set_loader(oop module, oop value) { |
3144 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3145 | module->obj_field_put(loader_offset, value); |
3146 | } |
3147 | |
3148 | oop java_lang_Module::name(oop module) { |
3149 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3150 | return module->obj_field(name_offset); |
3151 | } |
3152 | |
3153 | void java_lang_Module::set_name(oop module, oop value) { |
3154 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3155 | module->obj_field_put(name_offset, value); |
3156 | } |
3157 | |
3158 | ModuleEntry* java_lang_Module::module_entry(oop module) { |
3159 | assert(_module_entry_offset != -1, "Uninitialized module_entry_offset" ); |
3160 | assert(module != NULL, "module can't be null" ); |
3161 | assert(oopDesc::is_oop(module), "module must be oop" ); |
3162 | |
3163 | ModuleEntry* module_entry = (ModuleEntry*)module->address_field(_module_entry_offset); |
3164 | if (module_entry == NULL) { |
3165 | // If the inject field containing the ModuleEntry* is null then return the |
3166 | // class loader's unnamed module. |
3167 | oop loader = java_lang_Module::loader(module); |
3168 | Handle h_loader = Handle(Thread::current(), loader); |
3169 | ClassLoaderData* loader_cld = SystemDictionary::register_loader(h_loader); |
3170 | return loader_cld->unnamed_module(); |
3171 | } |
3172 | return module_entry; |
3173 | } |
3174 | |
3175 | void java_lang_Module::set_module_entry(oop module, ModuleEntry* module_entry) { |
3176 | assert(_module_entry_offset != -1, "Uninitialized module_entry_offset" ); |
3177 | assert(module != NULL, "module can't be null" ); |
3178 | assert(oopDesc::is_oop(module), "module must be oop" ); |
3179 | module->address_field_put(_module_entry_offset, (address)module_entry); |
3180 | } |
3181 | |
3182 | Handle reflect_ConstantPool::create(TRAPS) { |
3183 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3184 | InstanceKlass* k = SystemDictionary::reflect_ConstantPool_klass(); |
3185 | // Ensure it is initialized |
3186 | k->initialize(CHECK_NH); |
3187 | return k->allocate_instance_handle(THREAD); |
3188 | } |
3189 | |
3190 | |
3191 | void reflect_ConstantPool::set_cp(oop reflect, ConstantPool* value) { |
3192 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3193 | oop mirror = value->pool_holder()->java_mirror(); |
3194 | // Save the mirror to get back the constant pool. |
3195 | reflect->obj_field_put(_oop_offset, mirror); |
3196 | } |
3197 | |
3198 | ConstantPool* reflect_ConstantPool::get_cp(oop reflect) { |
3199 | assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem" ); |
3200 | |
3201 | oop mirror = reflect->obj_field(_oop_offset); |
3202 | Klass* k = java_lang_Class::as_Klass(mirror); |
3203 | assert(k->is_instance_klass(), "Must be" ); |
3204 | |
3205 | // Get the constant pool back from the klass. Since class redefinition |
3206 | // merges the new constant pool into the old, this is essentially the |
3207 | // same constant pool as the original. If constant pool merging is |
3208 | // no longer done in the future, this will have to change to save |
3209 | // the original. |
3210 | return InstanceKlass::cast(k)->constants(); |
3211 | } |
3212 | |
3213 | #define UNSAFESTATICFIELDACCESSORIMPL_FIELDS_DO(macro) \ |
3214 | macro(_base_offset, k, "base", object_signature, false) |
3215 | |
3216 | void reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() { |
3217 | InstanceKlass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(); |
3218 | UNSAFESTATICFIELDACCESSORIMPL_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3219 | } |
3220 | |
3221 | #if INCLUDE_CDS |
3222 | void reflect_UnsafeStaticFieldAccessorImpl::serialize_offsets(SerializeClosure* f) { |
3223 | UNSAFESTATICFIELDACCESSORIMPL_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3224 | } |
3225 | #endif |
3226 | |
3227 | oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) { |
3228 | Klass* k = SystemDictionary::box_klass(type); |
3229 | if (k == NULL) return NULL; |
3230 | InstanceKlass* ik = InstanceKlass::cast(k); |
3231 | if (!ik->is_initialized()) ik->initialize(CHECK_0); |
3232 | return ik->allocate_instance(THREAD); |
3233 | } |
3234 | |
3235 | |
3236 | oop java_lang_boxing_object::create(BasicType type, jvalue* value, TRAPS) { |
3237 | oop box = initialize_and_allocate(type, CHECK_0); |
3238 | if (box == NULL) return NULL; |
3239 | switch (type) { |
3240 | case T_BOOLEAN: |
3241 | box->bool_field_put(value_offset, value->z); |
3242 | break; |
3243 | case T_CHAR: |
3244 | box->char_field_put(value_offset, value->c); |
3245 | break; |
3246 | case T_FLOAT: |
3247 | box->float_field_put(value_offset, value->f); |
3248 | break; |
3249 | case T_DOUBLE: |
3250 | box->double_field_put(long_value_offset, value->d); |
3251 | break; |
3252 | case T_BYTE: |
3253 | box->byte_field_put(value_offset, value->b); |
3254 | break; |
3255 | case T_SHORT: |
3256 | box->short_field_put(value_offset, value->s); |
3257 | break; |
3258 | case T_INT: |
3259 | box->int_field_put(value_offset, value->i); |
3260 | break; |
3261 | case T_LONG: |
3262 | box->long_field_put(long_value_offset, value->j); |
3263 | break; |
3264 | default: |
3265 | return NULL; |
3266 | } |
3267 | return box; |
3268 | } |
3269 | |
3270 | |
3271 | BasicType java_lang_boxing_object::basic_type(oop box) { |
3272 | if (box == NULL) return T_ILLEGAL; |
3273 | BasicType type = SystemDictionary::box_klass_type(box->klass()); |
3274 | if (type == T_OBJECT) // 'unknown' value returned by SD::bkt |
3275 | return T_ILLEGAL; |
3276 | return type; |
3277 | } |
3278 | |
3279 | |
3280 | BasicType java_lang_boxing_object::get_value(oop box, jvalue* value) { |
3281 | BasicType type = SystemDictionary::box_klass_type(box->klass()); |
3282 | switch (type) { |
3283 | case T_BOOLEAN: |
3284 | value->z = box->bool_field(value_offset); |
3285 | break; |
3286 | case T_CHAR: |
3287 | value->c = box->char_field(value_offset); |
3288 | break; |
3289 | case T_FLOAT: |
3290 | value->f = box->float_field(value_offset); |
3291 | break; |
3292 | case T_DOUBLE: |
3293 | value->d = box->double_field(long_value_offset); |
3294 | break; |
3295 | case T_BYTE: |
3296 | value->b = box->byte_field(value_offset); |
3297 | break; |
3298 | case T_SHORT: |
3299 | value->s = box->short_field(value_offset); |
3300 | break; |
3301 | case T_INT: |
3302 | value->i = box->int_field(value_offset); |
3303 | break; |
3304 | case T_LONG: |
3305 | value->j = box->long_field(long_value_offset); |
3306 | break; |
3307 | default: |
3308 | return T_ILLEGAL; |
3309 | } // end switch |
3310 | return type; |
3311 | } |
3312 | |
3313 | |
3314 | BasicType java_lang_boxing_object::set_value(oop box, jvalue* value) { |
3315 | BasicType type = SystemDictionary::box_klass_type(box->klass()); |
3316 | switch (type) { |
3317 | case T_BOOLEAN: |
3318 | box->bool_field_put(value_offset, value->z); |
3319 | break; |
3320 | case T_CHAR: |
3321 | box->char_field_put(value_offset, value->c); |
3322 | break; |
3323 | case T_FLOAT: |
3324 | box->float_field_put(value_offset, value->f); |
3325 | break; |
3326 | case T_DOUBLE: |
3327 | box->double_field_put(long_value_offset, value->d); |
3328 | break; |
3329 | case T_BYTE: |
3330 | box->byte_field_put(value_offset, value->b); |
3331 | break; |
3332 | case T_SHORT: |
3333 | box->short_field_put(value_offset, value->s); |
3334 | break; |
3335 | case T_INT: |
3336 | box->int_field_put(value_offset, value->i); |
3337 | break; |
3338 | case T_LONG: |
3339 | box->long_field_put(long_value_offset, value->j); |
3340 | break; |
3341 | default: |
3342 | return T_ILLEGAL; |
3343 | } // end switch |
3344 | return type; |
3345 | } |
3346 | |
3347 | |
3348 | void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* st) { |
3349 | switch (type) { |
3350 | case T_BOOLEAN: st->print("%s" , value->z ? "true" : "false" ); break; |
3351 | case T_CHAR: st->print("%d" , value->c); break; |
3352 | case T_BYTE: st->print("%d" , value->b); break; |
3353 | case T_SHORT: st->print("%d" , value->s); break; |
3354 | case T_INT: st->print("%d" , value->i); break; |
3355 | case T_LONG: st->print(JLONG_FORMAT, value->j); break; |
3356 | case T_FLOAT: st->print("%f" , value->f); break; |
3357 | case T_DOUBLE: st->print("%lf" , value->d); break; |
3358 | default: st->print("type %d?" , type); break; |
3359 | } |
3360 | } |
3361 | |
3362 | // Support for java_lang_ref_Reference |
3363 | |
3364 | bool java_lang_ref_Reference::is_referent_field(oop obj, ptrdiff_t offset) { |
3365 | assert(obj != NULL, "sanity" ); |
3366 | if (offset != java_lang_ref_Reference::referent_offset) { |
3367 | return false; |
3368 | } |
3369 | |
3370 | Klass* k = obj->klass(); |
3371 | if (!k->is_instance_klass()) { |
3372 | return false; |
3373 | } |
3374 | |
3375 | InstanceKlass* ik = InstanceKlass::cast(obj->klass()); |
3376 | bool is_reference = ik->reference_type() != REF_NONE; |
3377 | assert(!is_reference || ik->is_subclass_of(SystemDictionary::Reference_klass()), "sanity" ); |
3378 | return is_reference; |
3379 | } |
3380 | |
3381 | // Support for java_lang_ref_SoftReference |
3382 | // |
3383 | |
3384 | #define SOFTREFERENCE_FIELDS_DO(macro) \ |
3385 | macro(timestamp_offset, k, "timestamp", long_signature, false); \ |
3386 | macro(static_clock_offset, k, "clock", long_signature, true) |
3387 | |
3388 | void java_lang_ref_SoftReference::compute_offsets() { |
3389 | InstanceKlass* k = SystemDictionary::SoftReference_klass(); |
3390 | SOFTREFERENCE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3391 | } |
3392 | |
3393 | #if INCLUDE_CDS |
3394 | void java_lang_ref_SoftReference::serialize_offsets(SerializeClosure* f) { |
3395 | SOFTREFERENCE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3396 | } |
3397 | #endif |
3398 | |
3399 | jlong java_lang_ref_SoftReference::timestamp(oop ref) { |
3400 | return ref->long_field(timestamp_offset); |
3401 | } |
3402 | |
3403 | jlong java_lang_ref_SoftReference::clock() { |
3404 | InstanceKlass* ik = SystemDictionary::SoftReference_klass(); |
3405 | oop base = ik->static_field_base_raw(); |
3406 | return base->long_field(static_clock_offset); |
3407 | } |
3408 | |
3409 | void java_lang_ref_SoftReference::set_clock(jlong value) { |
3410 | InstanceKlass* ik = SystemDictionary::SoftReference_klass(); |
3411 | oop base = ik->static_field_base_raw(); |
3412 | base->long_field_put(static_clock_offset, value); |
3413 | } |
3414 | |
3415 | // Support for java_lang_invoke_DirectMethodHandle |
3416 | |
3417 | int java_lang_invoke_DirectMethodHandle::_member_offset; |
3418 | |
3419 | oop java_lang_invoke_DirectMethodHandle::member(oop dmh) { |
3420 | oop member_name = NULL; |
3421 | assert(oopDesc::is_oop(dmh) && java_lang_invoke_DirectMethodHandle::is_instance(dmh), |
3422 | "a DirectMethodHandle oop is expected" ); |
3423 | return dmh->obj_field(member_offset_in_bytes()); |
3424 | } |
3425 | |
3426 | #define DIRECTMETHODHANDLE_FIELDS_DO(macro) \ |
3427 | macro(_member_offset, k, "member", java_lang_invoke_MemberName_signature, false) |
3428 | |
3429 | void java_lang_invoke_DirectMethodHandle::compute_offsets() { |
3430 | InstanceKlass* k = SystemDictionary::DirectMethodHandle_klass(); |
3431 | DIRECTMETHODHANDLE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3432 | } |
3433 | |
3434 | #if INCLUDE_CDS |
3435 | void java_lang_invoke_DirectMethodHandle::serialize_offsets(SerializeClosure* f) { |
3436 | DIRECTMETHODHANDLE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3437 | } |
3438 | #endif |
3439 | |
3440 | // Support for java_lang_invoke_MethodHandle |
3441 | |
3442 | int java_lang_invoke_MethodHandle::_type_offset; |
3443 | int java_lang_invoke_MethodHandle::_form_offset; |
3444 | |
3445 | int java_lang_invoke_MemberName::_clazz_offset; |
3446 | int java_lang_invoke_MemberName::_name_offset; |
3447 | int java_lang_invoke_MemberName::_type_offset; |
3448 | int java_lang_invoke_MemberName::_flags_offset; |
3449 | int java_lang_invoke_MemberName::_method_offset; |
3450 | int java_lang_invoke_MemberName::_vmindex_offset; |
3451 | |
3452 | int java_lang_invoke_ResolvedMethodName::_vmtarget_offset; |
3453 | int java_lang_invoke_ResolvedMethodName::_vmholder_offset; |
3454 | |
3455 | int java_lang_invoke_LambdaForm::_vmentry_offset; |
3456 | |
3457 | #define METHODHANDLE_FIELDS_DO(macro) \ |
3458 | macro(_type_offset, k, vmSymbols::type_name(), java_lang_invoke_MethodType_signature, false); \ |
3459 | macro(_form_offset, k, "form", java_lang_invoke_LambdaForm_signature, false) |
3460 | |
3461 | void java_lang_invoke_MethodHandle::compute_offsets() { |
3462 | InstanceKlass* k = SystemDictionary::MethodHandle_klass(); |
3463 | METHODHANDLE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3464 | } |
3465 | |
3466 | #if INCLUDE_CDS |
3467 | void java_lang_invoke_MethodHandle::serialize_offsets(SerializeClosure* f) { |
3468 | METHODHANDLE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3469 | } |
3470 | #endif |
3471 | |
3472 | #define MEMBERNAME_FIELDS_DO(macro) \ |
3473 | macro(_clazz_offset, k, vmSymbols::clazz_name(), class_signature, false); \ |
3474 | macro(_name_offset, k, vmSymbols::name_name(), string_signature, false); \ |
3475 | macro(_type_offset, k, vmSymbols::type_name(), object_signature, false); \ |
3476 | macro(_flags_offset, k, vmSymbols::flags_name(), int_signature, false); \ |
3477 | macro(_method_offset, k, vmSymbols::method_name(), java_lang_invoke_ResolvedMethodName_signature, false) |
3478 | |
3479 | void java_lang_invoke_MemberName::compute_offsets() { |
3480 | InstanceKlass* k = SystemDictionary::MemberName_klass(); |
3481 | MEMBERNAME_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3482 | MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
3483 | } |
3484 | |
3485 | #if INCLUDE_CDS |
3486 | void java_lang_invoke_MemberName::serialize_offsets(SerializeClosure* f) { |
3487 | MEMBERNAME_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3488 | MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
3489 | } |
3490 | #endif |
3491 | |
3492 | void java_lang_invoke_ResolvedMethodName::compute_offsets() { |
3493 | InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass(); |
3494 | assert(k != NULL, "jdk mismatch" ); |
3495 | RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
3496 | } |
3497 | |
3498 | #if INCLUDE_CDS |
3499 | void java_lang_invoke_ResolvedMethodName::serialize_offsets(SerializeClosure* f) { |
3500 | RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
3501 | } |
3502 | #endif |
3503 | |
3504 | #define LAMBDAFORM_FIELDS_DO(macro) \ |
3505 | macro(_vmentry_offset, k, "vmentry", java_lang_invoke_MemberName_signature, false) |
3506 | |
3507 | void java_lang_invoke_LambdaForm::compute_offsets() { |
3508 | InstanceKlass* k = SystemDictionary::LambdaForm_klass(); |
3509 | assert (k != NULL, "jdk mismatch" ); |
3510 | LAMBDAFORM_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3511 | } |
3512 | |
3513 | #if INCLUDE_CDS |
3514 | void java_lang_invoke_LambdaForm::serialize_offsets(SerializeClosure* f) { |
3515 | LAMBDAFORM_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3516 | } |
3517 | #endif |
3518 | |
3519 | bool java_lang_invoke_LambdaForm::is_instance(oop obj) { |
3520 | return obj != NULL && is_subclass(obj->klass()); |
3521 | } |
3522 | |
3523 | |
3524 | oop java_lang_invoke_MethodHandle::type(oop mh) { |
3525 | return mh->obj_field(_type_offset); |
3526 | } |
3527 | |
3528 | void java_lang_invoke_MethodHandle::set_type(oop mh, oop mtype) { |
3529 | mh->obj_field_put(_type_offset, mtype); |
3530 | } |
3531 | |
3532 | oop java_lang_invoke_MethodHandle::form(oop mh) { |
3533 | assert(_form_offset != 0, "" ); |
3534 | return mh->obj_field(_form_offset); |
3535 | } |
3536 | |
3537 | void java_lang_invoke_MethodHandle::set_form(oop mh, oop lform) { |
3538 | assert(_form_offset != 0, "" ); |
3539 | mh->obj_field_put(_form_offset, lform); |
3540 | } |
3541 | |
3542 | /// MemberName accessors |
3543 | |
3544 | oop java_lang_invoke_MemberName::clazz(oop mname) { |
3545 | assert(is_instance(mname), "wrong type" ); |
3546 | return mname->obj_field(_clazz_offset); |
3547 | } |
3548 | |
3549 | void java_lang_invoke_MemberName::set_clazz(oop mname, oop clazz) { |
3550 | assert(is_instance(mname), "wrong type" ); |
3551 | mname->obj_field_put(_clazz_offset, clazz); |
3552 | } |
3553 | |
3554 | oop java_lang_invoke_MemberName::name(oop mname) { |
3555 | assert(is_instance(mname), "wrong type" ); |
3556 | return mname->obj_field(_name_offset); |
3557 | } |
3558 | |
3559 | void java_lang_invoke_MemberName::set_name(oop mname, oop name) { |
3560 | assert(is_instance(mname), "wrong type" ); |
3561 | mname->obj_field_put(_name_offset, name); |
3562 | } |
3563 | |
3564 | oop java_lang_invoke_MemberName::type(oop mname) { |
3565 | assert(is_instance(mname), "wrong type" ); |
3566 | return mname->obj_field(_type_offset); |
3567 | } |
3568 | |
3569 | void java_lang_invoke_MemberName::set_type(oop mname, oop type) { |
3570 | assert(is_instance(mname), "wrong type" ); |
3571 | mname->obj_field_put(_type_offset, type); |
3572 | } |
3573 | |
3574 | int java_lang_invoke_MemberName::flags(oop mname) { |
3575 | assert(is_instance(mname), "wrong type" ); |
3576 | return mname->int_field(_flags_offset); |
3577 | } |
3578 | |
3579 | void java_lang_invoke_MemberName::set_flags(oop mname, int flags) { |
3580 | assert(is_instance(mname), "wrong type" ); |
3581 | mname->int_field_put(_flags_offset, flags); |
3582 | } |
3583 | |
3584 | |
3585 | // Return vmtarget from ResolvedMethodName method field through indirection |
3586 | Method* java_lang_invoke_MemberName::vmtarget(oop mname) { |
3587 | assert(is_instance(mname), "wrong type" ); |
3588 | oop method = mname->obj_field(_method_offset); |
3589 | return method == NULL ? NULL : java_lang_invoke_ResolvedMethodName::vmtarget(method); |
3590 | } |
3591 | |
3592 | bool java_lang_invoke_MemberName::is_method(oop mname) { |
3593 | assert(is_instance(mname), "must be MemberName" ); |
3594 | return (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0; |
3595 | } |
3596 | |
3597 | void java_lang_invoke_MemberName::set_method(oop mname, oop resolved_method) { |
3598 | assert(is_instance(mname), "wrong type" ); |
3599 | mname->obj_field_put(_method_offset, resolved_method); |
3600 | } |
3601 | |
3602 | intptr_t java_lang_invoke_MemberName::vmindex(oop mname) { |
3603 | assert(is_instance(mname), "wrong type" ); |
3604 | return (intptr_t) mname->address_field(_vmindex_offset); |
3605 | } |
3606 | |
3607 | void java_lang_invoke_MemberName::set_vmindex(oop mname, intptr_t index) { |
3608 | assert(is_instance(mname), "wrong type" ); |
3609 | mname->address_field_put(_vmindex_offset, (address) index); |
3610 | } |
3611 | |
3612 | |
3613 | Method* java_lang_invoke_ResolvedMethodName::vmtarget(oop resolved_method) { |
3614 | assert(is_instance(resolved_method), "wrong type" ); |
3615 | Method* m = (Method*)resolved_method->address_field(_vmtarget_offset); |
3616 | assert(m->is_method(), "must be" ); |
3617 | return m; |
3618 | } |
3619 | |
3620 | // Used by redefinition to change Method* to new Method* with same hash (name, signature) |
3621 | void java_lang_invoke_ResolvedMethodName::set_vmtarget(oop resolved_method, Method* m) { |
3622 | assert(is_instance(resolved_method), "wrong type" ); |
3623 | resolved_method->address_field_put(_vmtarget_offset, (address)m); |
3624 | } |
3625 | |
3626 | void java_lang_invoke_ResolvedMethodName::set_vmholder(oop resolved_method, oop holder) { |
3627 | assert(is_instance(resolved_method), "wrong type" ); |
3628 | resolved_method->obj_field_put(_vmholder_offset, holder); |
3629 | } |
3630 | |
3631 | oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) { |
3632 | const Method* method = m(); |
3633 | |
3634 | // lookup ResolvedMethod oop in the table, or create a new one and intern it |
3635 | oop resolved_method = ResolvedMethodTable::find_method(method); |
3636 | if (resolved_method != NULL) { |
3637 | return resolved_method; |
3638 | } |
3639 | |
3640 | InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass(); |
3641 | if (!k->is_initialized()) { |
3642 | k->initialize(CHECK_NULL); |
3643 | } |
3644 | |
3645 | oop new_resolved_method = k->allocate_instance(CHECK_NULL); |
3646 | |
3647 | NoSafepointVerifier nsv; |
3648 | |
3649 | if (method->is_old()) { |
3650 | method = (method->is_deleted()) ? Universe::throw_no_such_method_error() : |
3651 | method->get_new_method(); |
3652 | } |
3653 | |
3654 | InstanceKlass* holder = method->method_holder(); |
3655 | |
3656 | set_vmtarget(new_resolved_method, const_cast<Method*>(method)); |
3657 | // Add a reference to the loader (actually mirror because unsafe anonymous classes will not have |
3658 | // distinct loaders) to ensure the metadata is kept alive. |
3659 | // This mirror may be different than the one in clazz field. |
3660 | set_vmholder(new_resolved_method, holder->java_mirror()); |
3661 | |
3662 | // Set flag in class to indicate this InstanceKlass has entries in the table |
3663 | // to avoid walking table during redefinition if none of the redefined classes |
3664 | // have any membernames in the table. |
3665 | holder->set_has_resolved_methods(); |
3666 | |
3667 | return ResolvedMethodTable::add_method(method, Handle(THREAD, new_resolved_method)); |
3668 | } |
3669 | |
3670 | oop java_lang_invoke_LambdaForm::vmentry(oop lform) { |
3671 | assert(is_instance(lform), "wrong type" ); |
3672 | return lform->obj_field(_vmentry_offset); |
3673 | } |
3674 | |
3675 | |
3676 | // Support for java_lang_invoke_MethodType |
3677 | |
3678 | int java_lang_invoke_MethodType::_rtype_offset; |
3679 | int java_lang_invoke_MethodType::_ptypes_offset; |
3680 | |
3681 | #define METHODTYPE_FIELDS_DO(macro) \ |
3682 | macro(_rtype_offset, k, "rtype", class_signature, false); \ |
3683 | macro(_ptypes_offset, k, "ptypes", class_array_signature, false) |
3684 | |
3685 | void java_lang_invoke_MethodType::compute_offsets() { |
3686 | InstanceKlass* k = SystemDictionary::MethodType_klass(); |
3687 | METHODTYPE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3688 | } |
3689 | |
3690 | #if INCLUDE_CDS |
3691 | void java_lang_invoke_MethodType::serialize_offsets(SerializeClosure* f) { |
3692 | METHODTYPE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3693 | } |
3694 | #endif |
3695 | |
3696 | void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) { |
3697 | st->print("(" ); |
3698 | objArrayOop pts = ptypes(mt); |
3699 | for (int i = 0, limit = pts->length(); i < limit; i++) { |
3700 | java_lang_Class::print_signature(pts->obj_at(i), st); |
3701 | } |
3702 | st->print(")" ); |
3703 | java_lang_Class::print_signature(rtype(mt), st); |
3704 | } |
3705 | |
3706 | Symbol* java_lang_invoke_MethodType::as_signature(oop mt, bool intern_if_not_found) { |
3707 | ResourceMark rm; |
3708 | stringStream buffer(128); |
3709 | print_signature(mt, &buffer); |
3710 | const char* sigstr = buffer.base(); |
3711 | int siglen = (int) buffer.size(); |
3712 | Symbol *name; |
3713 | if (!intern_if_not_found) { |
3714 | name = SymbolTable::probe(sigstr, siglen); |
3715 | } else { |
3716 | name = SymbolTable::new_symbol(sigstr, siglen); |
3717 | } |
3718 | return name; |
3719 | } |
3720 | |
3721 | bool java_lang_invoke_MethodType::equals(oop mt1, oop mt2) { |
3722 | if (oopDesc::equals(mt1, mt2)) |
3723 | return true; |
3724 | if (!oopDesc::equals(rtype(mt1), rtype(mt2))) |
3725 | return false; |
3726 | if (ptype_count(mt1) != ptype_count(mt2)) |
3727 | return false; |
3728 | for (int i = ptype_count(mt1) - 1; i >= 0; i--) { |
3729 | if (!oopDesc::equals(ptype(mt1, i), ptype(mt2, i))) |
3730 | return false; |
3731 | } |
3732 | return true; |
3733 | } |
3734 | |
3735 | oop java_lang_invoke_MethodType::rtype(oop mt) { |
3736 | assert(is_instance(mt), "must be a MethodType" ); |
3737 | return mt->obj_field(_rtype_offset); |
3738 | } |
3739 | |
3740 | objArrayOop java_lang_invoke_MethodType::ptypes(oop mt) { |
3741 | assert(is_instance(mt), "must be a MethodType" ); |
3742 | return (objArrayOop) mt->obj_field(_ptypes_offset); |
3743 | } |
3744 | |
3745 | oop java_lang_invoke_MethodType::ptype(oop mt, int idx) { |
3746 | return ptypes(mt)->obj_at(idx); |
3747 | } |
3748 | |
3749 | int java_lang_invoke_MethodType::ptype_count(oop mt) { |
3750 | return ptypes(mt)->length(); |
3751 | } |
3752 | |
3753 | int java_lang_invoke_MethodType::ptype_slot_count(oop mt) { |
3754 | objArrayOop pts = ptypes(mt); |
3755 | int count = pts->length(); |
3756 | int slots = 0; |
3757 | for (int i = 0; i < count; i++) { |
3758 | BasicType bt = java_lang_Class::as_BasicType(pts->obj_at(i)); |
3759 | slots += type2size[bt]; |
3760 | } |
3761 | return slots; |
3762 | } |
3763 | |
3764 | int java_lang_invoke_MethodType::rtype_slot_count(oop mt) { |
3765 | BasicType bt = java_lang_Class::as_BasicType(rtype(mt)); |
3766 | return type2size[bt]; |
3767 | } |
3768 | |
3769 | |
3770 | // Support for java_lang_invoke_CallSite |
3771 | |
3772 | int java_lang_invoke_CallSite::_target_offset; |
3773 | int java_lang_invoke_CallSite::_context_offset; |
3774 | |
3775 | #define CALLSITE_FIELDS_DO(macro) \ |
3776 | macro(_target_offset, k, "target", java_lang_invoke_MethodHandle_signature, false); \ |
3777 | macro(_context_offset, k, "context", java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, false) |
3778 | |
3779 | void java_lang_invoke_CallSite::compute_offsets() { |
3780 | InstanceKlass* k = SystemDictionary::CallSite_klass(); |
3781 | CALLSITE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3782 | } |
3783 | |
3784 | #if INCLUDE_CDS |
3785 | void java_lang_invoke_CallSite::serialize_offsets(SerializeClosure* f) { |
3786 | CALLSITE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3787 | } |
3788 | #endif |
3789 | |
3790 | oop java_lang_invoke_CallSite::context_no_keepalive(oop call_site) { |
3791 | assert(java_lang_invoke_CallSite::is_instance(call_site), "" ); |
3792 | |
3793 | oop dep_oop = call_site->obj_field_access<AS_NO_KEEPALIVE>(_context_offset); |
3794 | return dep_oop; |
3795 | } |
3796 | |
3797 | // Support for java_lang_invoke_MethodHandleNatives_CallSiteContext |
3798 | |
3799 | int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset; |
3800 | int java_lang_invoke_MethodHandleNatives_CallSiteContext::_last_cleanup_offset; |
3801 | |
3802 | void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() { |
3803 | InstanceKlass* k = SystemDictionary::Context_klass(); |
3804 | CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
3805 | } |
3806 | |
3807 | #if INCLUDE_CDS |
3808 | void java_lang_invoke_MethodHandleNatives_CallSiteContext::serialize_offsets(SerializeClosure* f) { |
3809 | CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
3810 | } |
3811 | #endif |
3812 | |
3813 | DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) { |
3814 | assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "" ); |
3815 | nmethodBucket* volatile* vmdeps_addr = (nmethodBucket* volatile*)call_site->field_addr(_vmdependencies_offset); |
3816 | volatile uint64_t* last_cleanup_addr = (volatile uint64_t*)call_site->field_addr(_last_cleanup_offset); |
3817 | DependencyContext dep_ctx(vmdeps_addr, last_cleanup_addr); |
3818 | return dep_ctx; |
3819 | } |
3820 | |
3821 | // Support for java_security_AccessControlContext |
3822 | |
3823 | int java_security_AccessControlContext::_context_offset = 0; |
3824 | int java_security_AccessControlContext::_privilegedContext_offset = 0; |
3825 | int java_security_AccessControlContext::_isPrivileged_offset = 0; |
3826 | int java_security_AccessControlContext::_isAuthorized_offset = -1; |
3827 | |
3828 | #define ACCESSCONTROLCONTEXT_FIELDS_DO(macro) \ |
3829 | macro(_context_offset, k, "context", protectiondomain_signature, false); \ |
3830 | macro(_privilegedContext_offset, k, "privilegedContext", accesscontrolcontext_signature, false); \ |
3831 | macro(_isPrivileged_offset, k, "isPrivileged", bool_signature, false); \ |
3832 | macro(_isAuthorized_offset, k, "isAuthorized", bool_signature, false) |
3833 | |
3834 | void java_security_AccessControlContext::compute_offsets() { |
3835 | assert(_isPrivileged_offset == 0, "offsets should be initialized only once" ); |
3836 | InstanceKlass* k = SystemDictionary::AccessControlContext_klass(); |
3837 | ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3838 | } |
3839 | |
3840 | #if INCLUDE_CDS |
3841 | void java_security_AccessControlContext::serialize_offsets(SerializeClosure* f) { |
3842 | ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3843 | } |
3844 | #endif |
3845 | |
3846 | oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) { |
3847 | assert(_isPrivileged_offset != 0, "offsets should have been initialized" ); |
3848 | // Ensure klass is initialized |
3849 | SystemDictionary::AccessControlContext_klass()->initialize(CHECK_0); |
3850 | // Allocate result |
3851 | oop result = SystemDictionary::AccessControlContext_klass()->allocate_instance(CHECK_0); |
3852 | // Fill in values |
3853 | result->obj_field_put(_context_offset, context()); |
3854 | result->obj_field_put(_privilegedContext_offset, privileged_context()); |
3855 | result->bool_field_put(_isPrivileged_offset, isPrivileged); |
3856 | // whitelist AccessControlContexts created by the JVM if present |
3857 | if (_isAuthorized_offset != -1) { |
3858 | result->bool_field_put(_isAuthorized_offset, true); |
3859 | } |
3860 | return result; |
3861 | } |
3862 | |
3863 | |
3864 | // Support for java_lang_ClassLoader |
3865 | |
3866 | bool java_lang_ClassLoader::offsets_computed = false; |
3867 | int java_lang_ClassLoader::_loader_data_offset = -1; |
3868 | int java_lang_ClassLoader::parallelCapable_offset = -1; |
3869 | int java_lang_ClassLoader::name_offset = -1; |
3870 | int java_lang_ClassLoader::nameAndId_offset = -1; |
3871 | int java_lang_ClassLoader::unnamedModule_offset = -1; |
3872 | |
3873 | ClassLoaderData* java_lang_ClassLoader::loader_data_acquire(oop loader) { |
3874 | assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop" ); |
3875 | return HeapAccess<MO_ACQUIRE>::load_at(loader, _loader_data_offset); |
3876 | } |
3877 | |
3878 | ClassLoaderData* java_lang_ClassLoader::loader_data_raw(oop loader) { |
3879 | assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop" ); |
3880 | return RawAccess<>::load_at(loader, _loader_data_offset); |
3881 | } |
3882 | |
3883 | void java_lang_ClassLoader::release_set_loader_data(oop loader, ClassLoaderData* new_data) { |
3884 | assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop" ); |
3885 | HeapAccess<MO_RELEASE>::store_at(loader, _loader_data_offset, new_data); |
3886 | } |
3887 | |
3888 | #define CLASSLOADER_FIELDS_DO(macro) \ |
3889 | macro(parallelCapable_offset, k1, "parallelLockMap", concurrenthashmap_signature, false); \ |
3890 | macro(name_offset, k1, vmSymbols::name_name(), string_signature, false); \ |
3891 | macro(nameAndId_offset, k1, "nameAndId", string_signature, false); \ |
3892 | macro(unnamedModule_offset, k1, "unnamedModule", module_signature, false); \ |
3893 | macro(parent_offset, k1, "parent", classloader_signature, false) |
3894 | |
3895 | void java_lang_ClassLoader::compute_offsets() { |
3896 | assert(!offsets_computed, "offsets should be initialized only once" ); |
3897 | offsets_computed = true; |
3898 | |
3899 | InstanceKlass* k1 = SystemDictionary::ClassLoader_klass(); |
3900 | CLASSLOADER_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
3901 | |
3902 | CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); |
3903 | } |
3904 | |
3905 | #if INCLUDE_CDS |
3906 | void java_lang_ClassLoader::serialize_offsets(SerializeClosure* f) { |
3907 | CLASSLOADER_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
3908 | CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); |
3909 | } |
3910 | #endif |
3911 | |
3912 | oop java_lang_ClassLoader::parent(oop loader) { |
3913 | assert(is_instance(loader), "loader must be oop" ); |
3914 | return loader->obj_field(parent_offset); |
3915 | } |
3916 | |
3917 | // Returns the name field of this class loader. If the name field has not |
3918 | // been set, null will be returned. |
3919 | oop java_lang_ClassLoader::name(oop loader) { |
3920 | assert(is_instance(loader), "loader must be oop" ); |
3921 | return loader->obj_field(name_offset); |
3922 | } |
3923 | |
3924 | // Returns the nameAndId field of this class loader. The format is |
3925 | // as follows: |
3926 | // If the defining loader has a name explicitly set then '<loader-name>' @<id> |
3927 | // If the defining loader has no name then <qualified-class-name> @<id> |
3928 | // If built-in loader, then omit '@<id>' as there is only one instance. |
3929 | // Use ClassLoader::loader_name_id() to obtain this String as a char*. |
3930 | oop java_lang_ClassLoader::nameAndId(oop loader) { |
3931 | assert(is_instance(loader), "loader must be oop" ); |
3932 | return loader->obj_field(nameAndId_offset); |
3933 | } |
3934 | |
3935 | bool java_lang_ClassLoader::isAncestor(oop loader, oop cl) { |
3936 | assert(is_instance(loader), "loader must be oop" ); |
3937 | assert(cl == NULL || is_instance(cl), "cl argument must be oop" ); |
3938 | oop acl = loader; |
3939 | debug_only(jint loop_count = 0); |
3940 | // This loop taken verbatim from ClassLoader.java: |
3941 | do { |
3942 | acl = parent(acl); |
3943 | if (oopDesc::equals(cl, acl)) { |
3944 | return true; |
3945 | } |
3946 | assert(++loop_count > 0, "loop_count overflow" ); |
3947 | } while (acl != NULL); |
3948 | return false; |
3949 | } |
3950 | |
3951 | bool java_lang_ClassLoader::is_instance(oop obj) { |
3952 | return obj != NULL && is_subclass(obj->klass()); |
3953 | } |
3954 | |
3955 | |
3956 | // For class loader classes, parallelCapable defined |
3957 | // based on non-null field |
3958 | // Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it |
3959 | bool java_lang_ClassLoader::parallelCapable(oop class_loader) { |
3960 | if (parallelCapable_offset == -1) { |
3961 | // Default for backward compatibility is false |
3962 | return false; |
3963 | } |
3964 | return (class_loader->obj_field(parallelCapable_offset) != NULL); |
3965 | } |
3966 | |
3967 | bool java_lang_ClassLoader::is_trusted_loader(oop loader) { |
3968 | // Fix for 4474172; see evaluation for more details |
3969 | loader = non_reflection_class_loader(loader); |
3970 | |
3971 | oop cl = SystemDictionary::java_system_loader(); |
3972 | while(cl != NULL) { |
3973 | if (oopDesc::equals(cl, loader)) return true; |
3974 | cl = parent(cl); |
3975 | } |
3976 | return false; |
3977 | } |
3978 | |
3979 | // Return true if this is one of the class loaders associated with |
3980 | // the generated bytecodes for reflection. |
3981 | bool java_lang_ClassLoader::is_reflection_class_loader(oop loader) { |
3982 | if (loader != NULL) { |
3983 | Klass* delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass(); |
3984 | // This might be null in non-1.4 JDKs |
3985 | return (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)); |
3986 | } |
3987 | return false; |
3988 | } |
3989 | |
3990 | oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) { |
3991 | // See whether this is one of the class loaders associated with |
3992 | // the generated bytecodes for reflection, and if so, "magically" |
3993 | // delegate to its parent to prevent class loading from occurring |
3994 | // in places where applications using reflection didn't expect it. |
3995 | if (is_reflection_class_loader(loader)) { |
3996 | return parent(loader); |
3997 | } |
3998 | return loader; |
3999 | } |
4000 | |
4001 | oop java_lang_ClassLoader::unnamedModule(oop loader) { |
4002 | assert(is_instance(loader), "loader must be oop" ); |
4003 | return loader->obj_field(unnamedModule_offset); |
4004 | } |
4005 | |
4006 | // Support for java_lang_System |
4007 | // |
4008 | #define SYSTEM_FIELDS_DO(macro) \ |
4009 | macro(static_in_offset, k, "in", input_stream_signature, true); \ |
4010 | macro(static_out_offset, k, "out", print_stream_signature, true); \ |
4011 | macro(static_err_offset, k, "err", print_stream_signature, true); \ |
4012 | macro(static_security_offset, k, "security", security_manager_signature, true) |
4013 | |
4014 | void java_lang_System::compute_offsets() { |
4015 | InstanceKlass* k = SystemDictionary::System_klass(); |
4016 | SYSTEM_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4017 | } |
4018 | |
4019 | #if INCLUDE_CDS |
4020 | void java_lang_System::serialize_offsets(SerializeClosure* f) { |
4021 | SYSTEM_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4022 | } |
4023 | #endif |
4024 | |
4025 | int java_lang_System::in_offset_in_bytes() { return static_in_offset; } |
4026 | int java_lang_System::out_offset_in_bytes() { return static_out_offset; } |
4027 | int java_lang_System::err_offset_in_bytes() { return static_err_offset; } |
4028 | |
4029 | // Support for jdk_internal_misc_UnsafeConstants |
4030 | // |
4031 | class UnsafeConstantsFixup : public FieldClosure { |
4032 | private: |
4033 | int _address_size; |
4034 | int _page_size; |
4035 | bool _big_endian; |
4036 | bool _use_unaligned_access; |
4037 | public: |
4038 | UnsafeConstantsFixup() { |
4039 | // round up values for all static final fields |
4040 | _address_size = sizeof(void*); |
4041 | _page_size = os::vm_page_size(); |
4042 | _big_endian = LITTLE_ENDIAN_ONLY(false) BIG_ENDIAN_ONLY(true); |
4043 | _use_unaligned_access = UseUnalignedAccesses; |
4044 | } |
4045 | |
4046 | void do_field(fieldDescriptor* fd) { |
4047 | oop mirror = fd->field_holder()->java_mirror(); |
4048 | assert(mirror != NULL, "UnsafeConstants must have mirror already" ); |
4049 | assert(fd->field_holder() == SystemDictionary::UnsafeConstants_klass(), "Should be UnsafeConstants" ); |
4050 | assert(fd->is_final(), "fields of UnsafeConstants must be final" ); |
4051 | assert(fd->is_static(), "fields of UnsafeConstants must be static" ); |
4052 | if (fd->name() == vmSymbols::address_size_name()) { |
4053 | mirror->int_field_put(fd->offset(), _address_size); |
4054 | } else if (fd->name() == vmSymbols::page_size_name()) { |
4055 | mirror->int_field_put(fd->offset(), _page_size); |
4056 | } else if (fd->name() == vmSymbols::big_endian_name()) { |
4057 | mirror->bool_field_put(fd->offset(), _big_endian); |
4058 | } else if (fd->name() == vmSymbols::use_unaligned_access_name()) { |
4059 | mirror->bool_field_put(fd->offset(), _use_unaligned_access); |
4060 | } else { |
4061 | assert(false, "unexpected UnsafeConstants field" ); |
4062 | } |
4063 | } |
4064 | }; |
4065 | |
4066 | void jdk_internal_misc_UnsafeConstants::set_unsafe_constants() { |
4067 | UnsafeConstantsFixup fixup; |
4068 | SystemDictionary::UnsafeConstants_klass()->do_local_static_fields(&fixup); |
4069 | } |
4070 | |
4071 | int java_lang_Class::_klass_offset; |
4072 | int java_lang_Class::_array_klass_offset; |
4073 | int java_lang_Class::_oop_size_offset; |
4074 | int java_lang_Class::_static_oop_field_count_offset; |
4075 | int java_lang_Class::_class_loader_offset; |
4076 | int java_lang_Class::_module_offset; |
4077 | int java_lang_Class::_protection_domain_offset; |
4078 | int java_lang_Class::_component_mirror_offset; |
4079 | int java_lang_Class::_init_lock_offset; |
4080 | int java_lang_Class::_signers_offset; |
4081 | int java_lang_Class::_name_offset; |
4082 | int java_lang_Class::_source_file_offset; |
4083 | GrowableArray<Klass*>* java_lang_Class::_fixup_mirror_list = NULL; |
4084 | GrowableArray<Klass*>* java_lang_Class::_fixup_module_field_list = NULL; |
4085 | int java_lang_Throwable::backtrace_offset; |
4086 | int java_lang_Throwable::detailMessage_offset; |
4087 | int java_lang_Throwable::stackTrace_offset; |
4088 | int java_lang_Throwable::depth_offset; |
4089 | int java_lang_Throwable::static_unassigned_stacktrace_offset; |
4090 | int java_lang_reflect_AccessibleObject::override_offset; |
4091 | int java_lang_reflect_Method::clazz_offset; |
4092 | int java_lang_reflect_Method::name_offset; |
4093 | int java_lang_reflect_Method::returnType_offset; |
4094 | int java_lang_reflect_Method::parameterTypes_offset; |
4095 | int java_lang_reflect_Method::exceptionTypes_offset; |
4096 | int java_lang_reflect_Method::slot_offset; |
4097 | int java_lang_reflect_Method::modifiers_offset; |
4098 | int java_lang_reflect_Method::signature_offset; |
4099 | int java_lang_reflect_Method::annotations_offset; |
4100 | int java_lang_reflect_Method::parameter_annotations_offset; |
4101 | int java_lang_reflect_Method::annotation_default_offset; |
4102 | int java_lang_reflect_Constructor::clazz_offset; |
4103 | int java_lang_reflect_Constructor::parameterTypes_offset; |
4104 | int java_lang_reflect_Constructor::exceptionTypes_offset; |
4105 | int java_lang_reflect_Constructor::slot_offset; |
4106 | int java_lang_reflect_Constructor::modifiers_offset; |
4107 | int java_lang_reflect_Constructor::signature_offset; |
4108 | int java_lang_reflect_Constructor::annotations_offset; |
4109 | int java_lang_reflect_Constructor::parameter_annotations_offset; |
4110 | int java_lang_reflect_Field::clazz_offset; |
4111 | int java_lang_reflect_Field::name_offset; |
4112 | int java_lang_reflect_Field::type_offset; |
4113 | int java_lang_reflect_Field::slot_offset; |
4114 | int java_lang_reflect_Field::modifiers_offset; |
4115 | int java_lang_reflect_Field::signature_offset; |
4116 | int java_lang_reflect_Field::annotations_offset; |
4117 | int java_lang_reflect_Parameter::name_offset; |
4118 | int java_lang_reflect_Parameter::modifiers_offset; |
4119 | int java_lang_reflect_Parameter::index_offset; |
4120 | int java_lang_reflect_Parameter::executable_offset; |
4121 | int java_lang_boxing_object::value_offset; |
4122 | int java_lang_boxing_object::long_value_offset; |
4123 | int java_lang_ref_Reference::referent_offset; |
4124 | int java_lang_ref_Reference::queue_offset; |
4125 | int java_lang_ref_Reference::next_offset; |
4126 | int java_lang_ref_Reference::discovered_offset; |
4127 | int java_lang_ref_SoftReference::timestamp_offset; |
4128 | int java_lang_ref_SoftReference::static_clock_offset; |
4129 | int java_lang_ClassLoader::parent_offset; |
4130 | int java_lang_System::static_in_offset; |
4131 | int java_lang_System::static_out_offset; |
4132 | int java_lang_System::static_err_offset; |
4133 | int java_lang_System::static_security_offset; |
4134 | int java_lang_StackTraceElement::methodName_offset; |
4135 | int java_lang_StackTraceElement::fileName_offset; |
4136 | int java_lang_StackTraceElement::lineNumber_offset; |
4137 | int java_lang_StackTraceElement::moduleName_offset; |
4138 | int java_lang_StackTraceElement::moduleVersion_offset; |
4139 | int java_lang_StackTraceElement::classLoaderName_offset; |
4140 | int java_lang_StackTraceElement::declaringClass_offset; |
4141 | int java_lang_StackTraceElement::declaringClassObject_offset; |
4142 | int java_lang_StackFrameInfo::_memberName_offset; |
4143 | int java_lang_StackFrameInfo::_bci_offset; |
4144 | int java_lang_StackFrameInfo::_version_offset; |
4145 | int java_lang_LiveStackFrameInfo::_monitors_offset; |
4146 | int java_lang_LiveStackFrameInfo::_locals_offset; |
4147 | int java_lang_LiveStackFrameInfo::_operands_offset; |
4148 | int java_lang_LiveStackFrameInfo::_mode_offset; |
4149 | int java_lang_AssertionStatusDirectives::classes_offset; |
4150 | int java_lang_AssertionStatusDirectives::classEnabled_offset; |
4151 | int java_lang_AssertionStatusDirectives::packages_offset; |
4152 | int java_lang_AssertionStatusDirectives::packageEnabled_offset; |
4153 | int java_lang_AssertionStatusDirectives::deflt_offset; |
4154 | int java_nio_Buffer::_limit_offset; |
4155 | int java_util_concurrent_locks_AbstractOwnableSynchronizer::_owner_offset; |
4156 | int reflect_ConstantPool::_oop_offset; |
4157 | int reflect_UnsafeStaticFieldAccessorImpl::_base_offset; |
4158 | int java_lang_Integer_IntegerCache::_static_cache_offset; |
4159 | int java_lang_Long_LongCache::_static_cache_offset; |
4160 | int java_lang_Character_CharacterCache::_static_cache_offset; |
4161 | int java_lang_Short_ShortCache::_static_cache_offset; |
4162 | int java_lang_Byte_ByteCache::_static_cache_offset; |
4163 | int java_lang_Boolean::_static_TRUE_offset; |
4164 | int java_lang_Boolean::_static_FALSE_offset; |
4165 | |
4166 | |
4167 | |
4168 | #define STACKTRACEELEMENT_FIELDS_DO(macro) \ |
4169 | macro(declaringClassObject_offset, k, "declaringClassObject", class_signature, false); \ |
4170 | macro(classLoaderName_offset, k, "classLoaderName", string_signature, false); \ |
4171 | macro(moduleName_offset, k, "moduleName", string_signature, false); \ |
4172 | macro(moduleVersion_offset, k, "moduleVersion", string_signature, false); \ |
4173 | macro(declaringClass_offset, k, "declaringClass", string_signature, false); \ |
4174 | macro(methodName_offset, k, "methodName", string_signature, false); \ |
4175 | macro(fileName_offset, k, "fileName", string_signature, false); \ |
4176 | macro(lineNumber_offset, k, "lineNumber", int_signature, false) |
4177 | |
4178 | // Support for java_lang_StackTraceElement |
4179 | void java_lang_StackTraceElement::compute_offsets() { |
4180 | InstanceKlass* k = SystemDictionary::StackTraceElement_klass(); |
4181 | STACKTRACEELEMENT_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4182 | } |
4183 | |
4184 | #if INCLUDE_CDS |
4185 | void java_lang_StackTraceElement::serialize_offsets(SerializeClosure* f) { |
4186 | STACKTRACEELEMENT_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4187 | } |
4188 | #endif |
4189 | |
4190 | void java_lang_StackTraceElement::set_fileName(oop element, oop value) { |
4191 | element->obj_field_put(fileName_offset, value); |
4192 | } |
4193 | |
4194 | void java_lang_StackTraceElement::set_declaringClass(oop element, oop value) { |
4195 | element->obj_field_put(declaringClass_offset, value); |
4196 | } |
4197 | |
4198 | void java_lang_StackTraceElement::set_methodName(oop element, oop value) { |
4199 | element->obj_field_put(methodName_offset, value); |
4200 | } |
4201 | |
4202 | void java_lang_StackTraceElement::set_lineNumber(oop element, int value) { |
4203 | element->int_field_put(lineNumber_offset, value); |
4204 | } |
4205 | |
4206 | void java_lang_StackTraceElement::set_moduleName(oop element, oop value) { |
4207 | element->obj_field_put(moduleName_offset, value); |
4208 | } |
4209 | |
4210 | void java_lang_StackTraceElement::set_moduleVersion(oop element, oop value) { |
4211 | element->obj_field_put(moduleVersion_offset, value); |
4212 | } |
4213 | |
4214 | void java_lang_StackTraceElement::set_classLoaderName(oop element, oop value) { |
4215 | element->obj_field_put(classLoaderName_offset, value); |
4216 | } |
4217 | |
4218 | void java_lang_StackTraceElement::set_declaringClassObject(oop element, oop value) { |
4219 | element->obj_field_put(declaringClassObject_offset, value); |
4220 | } |
4221 | |
4222 | void java_lang_StackFrameInfo::set_version(oop element, short value) { |
4223 | element->short_field_put(_version_offset, value); |
4224 | } |
4225 | |
4226 | void java_lang_StackFrameInfo::set_bci(oop element, int value) { |
4227 | element->int_field_put(_bci_offset, value); |
4228 | } |
4229 | |
4230 | void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) { |
4231 | element->obj_field_put(_monitors_offset, value); |
4232 | } |
4233 | |
4234 | void java_lang_LiveStackFrameInfo::set_locals(oop element, oop value) { |
4235 | element->obj_field_put(_locals_offset, value); |
4236 | } |
4237 | |
4238 | void java_lang_LiveStackFrameInfo::set_operands(oop element, oop value) { |
4239 | element->obj_field_put(_operands_offset, value); |
4240 | } |
4241 | |
4242 | void java_lang_LiveStackFrameInfo::set_mode(oop element, int value) { |
4243 | element->int_field_put(_mode_offset, value); |
4244 | } |
4245 | |
4246 | // Support for java Assertions - java_lang_AssertionStatusDirectives. |
4247 | #define ASSERTIONSTATUSDIRECTIVES_FIELDS_DO(macro) \ |
4248 | macro(classes_offset, k, "classes", string_array_signature, false); \ |
4249 | macro(classEnabled_offset, k, "classEnabled", bool_array_signature, false); \ |
4250 | macro(packages_offset, k, "packages", string_array_signature, false); \ |
4251 | macro(packageEnabled_offset, k, "packageEnabled", bool_array_signature, false); \ |
4252 | macro(deflt_offset, k, "deflt", bool_signature, false) |
4253 | |
4254 | void java_lang_AssertionStatusDirectives::compute_offsets() { |
4255 | InstanceKlass* k = SystemDictionary::AssertionStatusDirectives_klass(); |
4256 | ASSERTIONSTATUSDIRECTIVES_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4257 | } |
4258 | |
4259 | #if INCLUDE_CDS |
4260 | void java_lang_AssertionStatusDirectives::serialize_offsets(SerializeClosure* f) { |
4261 | ASSERTIONSTATUSDIRECTIVES_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4262 | } |
4263 | #endif |
4264 | |
4265 | void java_lang_AssertionStatusDirectives::set_classes(oop o, oop val) { |
4266 | o->obj_field_put(classes_offset, val); |
4267 | } |
4268 | |
4269 | void java_lang_AssertionStatusDirectives::set_classEnabled(oop o, oop val) { |
4270 | o->obj_field_put(classEnabled_offset, val); |
4271 | } |
4272 | |
4273 | void java_lang_AssertionStatusDirectives::set_packages(oop o, oop val) { |
4274 | o->obj_field_put(packages_offset, val); |
4275 | } |
4276 | |
4277 | void java_lang_AssertionStatusDirectives::set_packageEnabled(oop o, oop val) { |
4278 | o->obj_field_put(packageEnabled_offset, val); |
4279 | } |
4280 | |
4281 | void java_lang_AssertionStatusDirectives::set_deflt(oop o, bool val) { |
4282 | o->bool_field_put(deflt_offset, val); |
4283 | } |
4284 | |
4285 | |
4286 | // Support for intrinsification of java.nio.Buffer.checkIndex |
4287 | int java_nio_Buffer::limit_offset() { |
4288 | return _limit_offset; |
4289 | } |
4290 | |
4291 | #define BUFFER_FIELDS_DO(macro) \ |
4292 | macro(_limit_offset, k, "limit", int_signature, false) |
4293 | |
4294 | void java_nio_Buffer::compute_offsets() { |
4295 | InstanceKlass* k = SystemDictionary::nio_Buffer_klass(); |
4296 | assert(k != NULL, "must be loaded in 1.4+" ); |
4297 | BUFFER_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4298 | } |
4299 | |
4300 | #if INCLUDE_CDS |
4301 | void java_nio_Buffer::serialize_offsets(SerializeClosure* f) { |
4302 | BUFFER_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4303 | } |
4304 | #endif |
4305 | |
4306 | #define AOS_FIELDS_DO(macro) \ |
4307 | macro(_owner_offset, k, "exclusiveOwnerThread", thread_signature, false) |
4308 | |
4309 | void java_util_concurrent_locks_AbstractOwnableSynchronizer::compute_offsets() { |
4310 | InstanceKlass* k = SystemDictionary::java_util_concurrent_locks_AbstractOwnableSynchronizer_klass(); |
4311 | AOS_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4312 | } |
4313 | |
4314 | oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(oop obj) { |
4315 | assert(_owner_offset != 0, "Must be initialized" ); |
4316 | return obj->obj_field(_owner_offset); |
4317 | } |
4318 | |
4319 | #if INCLUDE_CDS |
4320 | void java_util_concurrent_locks_AbstractOwnableSynchronizer::serialize_offsets(SerializeClosure* f) { |
4321 | AOS_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4322 | } |
4323 | #endif |
4324 | |
4325 | #define INTEGER_CACHE_FIELDS_DO(macro) \ |
4326 | macro(_static_cache_offset, k, "cache", java_lang_Integer_array_signature, true) |
4327 | |
4328 | void java_lang_Integer_IntegerCache::compute_offsets(InstanceKlass *k) { |
4329 | guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized" ); |
4330 | INTEGER_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4331 | } |
4332 | |
4333 | objArrayOop java_lang_Integer_IntegerCache::cache(InstanceKlass *ik) { |
4334 | oop base = ik->static_field_base_raw(); |
4335 | return objArrayOop(base->obj_field(_static_cache_offset)); |
4336 | } |
4337 | |
4338 | Symbol* java_lang_Integer_IntegerCache::symbol() { |
4339 | return vmSymbols::java_lang_Integer_IntegerCache(); |
4340 | } |
4341 | |
4342 | #if INCLUDE_CDS |
4343 | void java_lang_Integer_IntegerCache::serialize_offsets(SerializeClosure* f) { |
4344 | INTEGER_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4345 | } |
4346 | #endif |
4347 | #undef INTEGER_CACHE_FIELDS_DO |
4348 | |
4349 | jint java_lang_Integer::value(oop obj) { |
4350 | jvalue v; |
4351 | java_lang_boxing_object::get_value(obj, &v); |
4352 | return v.i; |
4353 | } |
4354 | |
4355 | #define LONG_CACHE_FIELDS_DO(macro) \ |
4356 | macro(_static_cache_offset, k, "cache", java_lang_Long_array_signature, true) |
4357 | |
4358 | void java_lang_Long_LongCache::compute_offsets(InstanceKlass *k) { |
4359 | guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized" ); |
4360 | LONG_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4361 | } |
4362 | |
4363 | objArrayOop java_lang_Long_LongCache::cache(InstanceKlass *ik) { |
4364 | oop base = ik->static_field_base_raw(); |
4365 | return objArrayOop(base->obj_field(_static_cache_offset)); |
4366 | } |
4367 | |
4368 | Symbol* java_lang_Long_LongCache::symbol() { |
4369 | return vmSymbols::java_lang_Long_LongCache(); |
4370 | } |
4371 | |
4372 | #if INCLUDE_CDS |
4373 | void java_lang_Long_LongCache::serialize_offsets(SerializeClosure* f) { |
4374 | LONG_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4375 | } |
4376 | #endif |
4377 | #undef LONG_CACHE_FIELDS_DO |
4378 | |
4379 | jlong java_lang_Long::value(oop obj) { |
4380 | jvalue v; |
4381 | java_lang_boxing_object::get_value(obj, &v); |
4382 | return v.j; |
4383 | } |
4384 | |
4385 | #define CHARACTER_CACHE_FIELDS_DO(macro) \ |
4386 | macro(_static_cache_offset, k, "cache", java_lang_Character_array_signature, true) |
4387 | |
4388 | void java_lang_Character_CharacterCache::compute_offsets(InstanceKlass *k) { |
4389 | guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized" ); |
4390 | CHARACTER_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4391 | } |
4392 | |
4393 | objArrayOop java_lang_Character_CharacterCache::cache(InstanceKlass *ik) { |
4394 | oop base = ik->static_field_base_raw(); |
4395 | return objArrayOop(base->obj_field(_static_cache_offset)); |
4396 | } |
4397 | |
4398 | Symbol* java_lang_Character_CharacterCache::symbol() { |
4399 | return vmSymbols::java_lang_Character_CharacterCache(); |
4400 | } |
4401 | |
4402 | #if INCLUDE_CDS |
4403 | void java_lang_Character_CharacterCache::serialize_offsets(SerializeClosure* f) { |
4404 | CHARACTER_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4405 | } |
4406 | #endif |
4407 | #undef CHARACTER_CACHE_FIELDS_DO |
4408 | |
4409 | jchar java_lang_Character::value(oop obj) { |
4410 | jvalue v; |
4411 | java_lang_boxing_object::get_value(obj, &v); |
4412 | return v.c; |
4413 | } |
4414 | |
4415 | #define SHORT_CACHE_FIELDS_DO(macro) \ |
4416 | macro(_static_cache_offset, k, "cache", java_lang_Short_array_signature, true) |
4417 | |
4418 | void java_lang_Short_ShortCache::compute_offsets(InstanceKlass *k) { |
4419 | guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized" ); |
4420 | SHORT_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4421 | } |
4422 | |
4423 | objArrayOop java_lang_Short_ShortCache::cache(InstanceKlass *ik) { |
4424 | oop base = ik->static_field_base_raw(); |
4425 | return objArrayOop(base->obj_field(_static_cache_offset)); |
4426 | } |
4427 | |
4428 | Symbol* java_lang_Short_ShortCache::symbol() { |
4429 | return vmSymbols::java_lang_Short_ShortCache(); |
4430 | } |
4431 | |
4432 | #if INCLUDE_CDS |
4433 | void java_lang_Short_ShortCache::serialize_offsets(SerializeClosure* f) { |
4434 | SHORT_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4435 | } |
4436 | #endif |
4437 | #undef SHORT_CACHE_FIELDS_DO |
4438 | |
4439 | jshort java_lang_Short::value(oop obj) { |
4440 | jvalue v; |
4441 | java_lang_boxing_object::get_value(obj, &v); |
4442 | return v.s; |
4443 | } |
4444 | |
4445 | #define BYTE_CACHE_FIELDS_DO(macro) \ |
4446 | macro(_static_cache_offset, k, "cache", java_lang_Byte_array_signature, true) |
4447 | |
4448 | void java_lang_Byte_ByteCache::compute_offsets(InstanceKlass *k) { |
4449 | guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized" ); |
4450 | BYTE_CACHE_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4451 | } |
4452 | |
4453 | objArrayOop java_lang_Byte_ByteCache::cache(InstanceKlass *ik) { |
4454 | oop base = ik->static_field_base_raw(); |
4455 | return objArrayOop(base->obj_field(_static_cache_offset)); |
4456 | } |
4457 | |
4458 | Symbol* java_lang_Byte_ByteCache::symbol() { |
4459 | return vmSymbols::java_lang_Byte_ByteCache(); |
4460 | } |
4461 | |
4462 | #if INCLUDE_CDS |
4463 | void java_lang_Byte_ByteCache::serialize_offsets(SerializeClosure* f) { |
4464 | BYTE_CACHE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4465 | } |
4466 | #endif |
4467 | #undef BYTE_CACHE_FIELDS_DO |
4468 | |
4469 | jbyte java_lang_Byte::value(oop obj) { |
4470 | jvalue v; |
4471 | java_lang_boxing_object::get_value(obj, &v); |
4472 | return v.b; |
4473 | } |
4474 | #define BOOLEAN_FIELDS_DO(macro) \ |
4475 | macro(_static_TRUE_offset, k, "TRUE", java_lang_Boolean_signature, true); \ |
4476 | macro(_static_FALSE_offset, k, "FALSE", java_lang_Boolean_signature, true) |
4477 | |
4478 | |
4479 | void java_lang_Boolean::compute_offsets(InstanceKlass *k) { |
4480 | guarantee(k != NULL && k->is_initialized(), "must be loaded and initialized" ); |
4481 | BOOLEAN_FIELDS_DO(FIELD_COMPUTE_OFFSET); |
4482 | } |
4483 | |
4484 | oop java_lang_Boolean::get_TRUE(InstanceKlass *ik) { |
4485 | oop base = ik->static_field_base_raw(); |
4486 | return base->obj_field(_static_TRUE_offset); |
4487 | } |
4488 | |
4489 | oop java_lang_Boolean::get_FALSE(InstanceKlass *ik) { |
4490 | oop base = ik->static_field_base_raw(); |
4491 | return base->obj_field(_static_FALSE_offset); |
4492 | } |
4493 | |
4494 | Symbol* java_lang_Boolean::symbol() { |
4495 | return vmSymbols::java_lang_Boolean(); |
4496 | } |
4497 | |
4498 | #if INCLUDE_CDS |
4499 | void java_lang_Boolean::serialize_offsets(SerializeClosure* f) { |
4500 | BOOLEAN_FIELDS_DO(FIELD_SERIALIZE_OFFSET); |
4501 | } |
4502 | #endif |
4503 | #undef BOOLEAN_CACHE_FIELDS_DO |
4504 | |
4505 | jboolean java_lang_Boolean::value(oop obj) { |
4506 | jvalue v; |
4507 | java_lang_boxing_object::get_value(obj, &v); |
4508 | return v.z; |
4509 | } |
4510 | |
4511 | static int member_offset(int hardcoded_offset) { |
4512 | return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes(); |
4513 | } |
4514 | |
4515 | // Compute hard-coded offsets |
4516 | // Invoked before SystemDictionary::initialize, so pre-loaded classes |
4517 | // are not available to determine the offset_of_static_fields. |
4518 | void JavaClasses::compute_hard_coded_offsets() { |
4519 | |
4520 | // java_lang_boxing_object |
4521 | java_lang_boxing_object::value_offset = member_offset(java_lang_boxing_object::hc_value_offset); |
4522 | java_lang_boxing_object::long_value_offset = align_up(member_offset(java_lang_boxing_object::hc_value_offset), BytesPerLong); |
4523 | |
4524 | // java_lang_ref_Reference |
4525 | java_lang_ref_Reference::referent_offset = member_offset(java_lang_ref_Reference::hc_referent_offset); |
4526 | java_lang_ref_Reference::queue_offset = member_offset(java_lang_ref_Reference::hc_queue_offset); |
4527 | java_lang_ref_Reference::next_offset = member_offset(java_lang_ref_Reference::hc_next_offset); |
4528 | java_lang_ref_Reference::discovered_offset = member_offset(java_lang_ref_Reference::hc_discovered_offset); |
4529 | } |
4530 | |
4531 | #define DO_COMPUTE_OFFSETS(k) k::compute_offsets(); |
4532 | |
4533 | // Compute non-hard-coded field offsets of all the classes in this file |
4534 | void JavaClasses::compute_offsets() { |
4535 | if (UseSharedSpaces) { |
4536 | assert(JvmtiExport::is_early_phase() && !(JvmtiExport::should_post_class_file_load_hook() && |
4537 | JvmtiExport::has_early_class_hook_env()), |
4538 | "JavaClasses::compute_offsets() must be called in early JVMTI phase." ); |
4539 | // None of the classes used by the rest of this function can be replaced by |
4540 | // JMVTI ClassFileLoadHook. |
4541 | // We are safe to use the archived offsets, which have already been restored |
4542 | // by JavaClasses::serialize_offsets, without computing the offsets again. |
4543 | return; |
4544 | } |
4545 | |
4546 | // We have already called the compute_offsets() of the |
4547 | // BASIC_JAVA_CLASSES_DO_PART1 classes (java_lang_String and java_lang_Class) |
4548 | // earlier inside SystemDictionary::resolve_well_known_classes() |
4549 | BASIC_JAVA_CLASSES_DO_PART2(DO_COMPUTE_OFFSETS); |
4550 | |
4551 | // generated interpreter code wants to know about the offsets we just computed: |
4552 | AbstractAssembler::update_delayed_values(); |
4553 | } |
4554 | |
4555 | #if INCLUDE_CDS |
4556 | #define DO_SERIALIZE_OFFSETS(k) k::serialize_offsets(soc); |
4557 | |
4558 | void JavaClasses::serialize_offsets(SerializeClosure* soc) { |
4559 | BASIC_JAVA_CLASSES_DO(DO_SERIALIZE_OFFSETS); |
4560 | } |
4561 | #endif |
4562 | |
4563 | |
4564 | #ifndef PRODUCT |
4565 | |
4566 | // These functions exist to assert the validity of hard-coded field offsets to guard |
4567 | // against changes in the class files |
4568 | |
4569 | bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) { |
4570 | EXCEPTION_MARK; |
4571 | fieldDescriptor fd; |
4572 | TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name); |
4573 | Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); |
4574 | InstanceKlass* ik = InstanceKlass::cast(k); |
4575 | TempNewSymbol f_name = SymbolTable::new_symbol(field_name); |
4576 | TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig); |
4577 | if (!ik->find_local_field(f_name, f_sig, &fd)) { |
4578 | tty->print_cr("Nonstatic field %s.%s not found" , klass_name, field_name); |
4579 | return false; |
4580 | } |
4581 | if (fd.is_static()) { |
4582 | tty->print_cr("Nonstatic field %s.%s appears to be static" , klass_name, field_name); |
4583 | return false; |
4584 | } |
4585 | if (fd.offset() == hardcoded_offset ) { |
4586 | return true; |
4587 | } else { |
4588 | tty->print_cr("Offset of nonstatic field %s.%s is hardcoded as %d but should really be %d." , |
4589 | klass_name, field_name, hardcoded_offset, fd.offset()); |
4590 | return false; |
4591 | } |
4592 | } |
4593 | |
4594 | // Check the hard-coded field offsets of all the classes in this file |
4595 | |
4596 | void JavaClasses::check_offsets() { |
4597 | bool valid = true; |
4598 | |
4599 | #define CHECK_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ |
4600 | valid &= check_offset(klass_name, cpp_klass_name :: field_name ## _offset, #field_name, field_sig) |
4601 | |
4602 | #define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ |
4603 | valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig) |
4604 | |
4605 | // Boxed primitive objects (java_lang_boxing_object) |
4606 | |
4607 | CHECK_OFFSET("java/lang/Boolean" , java_lang_boxing_object, value, "Z" ); |
4608 | CHECK_OFFSET("java/lang/Character" , java_lang_boxing_object, value, "C" ); |
4609 | CHECK_OFFSET("java/lang/Float" , java_lang_boxing_object, value, "F" ); |
4610 | CHECK_LONG_OFFSET("java/lang/Double" , java_lang_boxing_object, value, "D" ); |
4611 | CHECK_OFFSET("java/lang/Byte" , java_lang_boxing_object, value, "B" ); |
4612 | CHECK_OFFSET("java/lang/Short" , java_lang_boxing_object, value, "S" ); |
4613 | CHECK_OFFSET("java/lang/Integer" , java_lang_boxing_object, value, "I" ); |
4614 | CHECK_LONG_OFFSET("java/lang/Long" , java_lang_boxing_object, value, "J" ); |
4615 | |
4616 | // java.lang.ref.Reference |
4617 | |
4618 | CHECK_OFFSET("java/lang/ref/Reference" , java_lang_ref_Reference, referent, "Ljava/lang/Object;" ); |
4619 | CHECK_OFFSET("java/lang/ref/Reference" , java_lang_ref_Reference, queue, "Ljava/lang/ref/ReferenceQueue;" ); |
4620 | CHECK_OFFSET("java/lang/ref/Reference" , java_lang_ref_Reference, next, "Ljava/lang/ref/Reference;" ); |
4621 | // Fake field |
4622 | //CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, discovered, "Ljava/lang/ref/Reference;"); |
4623 | |
4624 | if (!valid) vm_exit_during_initialization("Hard-coded field offset verification failed" ); |
4625 | } |
4626 | |
4627 | #endif // PRODUCT |
4628 | |
4629 | int InjectedField::compute_offset() { |
4630 | InstanceKlass* ik = InstanceKlass::cast(klass()); |
4631 | for (AllFieldStream fs(ik); !fs.done(); fs.next()) { |
4632 | if (!may_be_java && !fs.access_flags().is_internal()) { |
4633 | // Only look at injected fields |
4634 | continue; |
4635 | } |
4636 | if (fs.name() == name() && fs.signature() == signature()) { |
4637 | return fs.offset(); |
4638 | } |
4639 | } |
4640 | ResourceMark rm; |
4641 | tty->print_cr("Invalid layout of %s at %s/%s%s" , ik->external_name(), name()->as_C_string(), signature()->as_C_string(), may_be_java ? " (may_be_java)" : "" ); |
4642 | #ifndef PRODUCT |
4643 | ik->print(); |
4644 | tty->print_cr("all fields:" ); |
4645 | for (AllFieldStream fs(ik); !fs.done(); fs.next()) { |
4646 | tty->print_cr(" name: %s, sig: %s, flags: %08x" , fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); |
4647 | } |
4648 | #endif //PRODUCT |
4649 | vm_exit_during_initialization("Invalid layout of well-known class: use -Xlog:class+load=info to see the origin of the problem class" ); |
4650 | return -1; |
4651 | } |
4652 | |
4653 | void javaClasses_init() { |
4654 | JavaClasses::compute_offsets(); |
4655 | JavaClasses::check_offsets(); |
4656 | FilteredFieldsMap::initialize(); // must be done after computing offsets. |
4657 | } |
4658 | |