File: | jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp |
Warning: | line 1225, column 5 Null pointer passed to 1st parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 2003, 2021, 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/classLoaderDataGraph.hpp" | |||
27 | #include "classfile/javaClasses.hpp" | |||
28 | #include "classfile/moduleEntry.hpp" | |||
29 | #include "jvmtifiles/jvmtiEnv.hpp" | |||
30 | #include "memory/iterator.hpp" | |||
31 | #include "memory/resourceArea.hpp" | |||
32 | #include "oops/klass.inline.hpp" | |||
33 | #include "oops/objArrayKlass.hpp" | |||
34 | #include "oops/objArrayOop.hpp" | |||
35 | #include "oops/oop.inline.hpp" | |||
36 | #include "oops/oopHandle.inline.hpp" | |||
37 | #include "prims/jvmtiEnvBase.hpp" | |||
38 | #include "prims/jvmtiEventController.inline.hpp" | |||
39 | #include "prims/jvmtiExtensions.hpp" | |||
40 | #include "prims/jvmtiImpl.hpp" | |||
41 | #include "prims/jvmtiManageCapabilities.hpp" | |||
42 | #include "prims/jvmtiTagMap.hpp" | |||
43 | #include "prims/jvmtiThreadState.inline.hpp" | |||
44 | #include "runtime/deoptimization.hpp" | |||
45 | #include "runtime/frame.inline.hpp" | |||
46 | #include "runtime/handles.inline.hpp" | |||
47 | #include "runtime/interfaceSupport.inline.hpp" | |||
48 | #include "runtime/jfieldIDWorkaround.hpp" | |||
49 | #include "runtime/jniHandles.inline.hpp" | |||
50 | #include "runtime/objectMonitor.inline.hpp" | |||
51 | #include "runtime/osThread.hpp" | |||
52 | #include "runtime/signature.hpp" | |||
53 | #include "runtime/thread.inline.hpp" | |||
54 | #include "runtime/threadSMR.hpp" | |||
55 | #include "runtime/vframe.inline.hpp" | |||
56 | #include "runtime/vframe_hp.hpp" | |||
57 | #include "runtime/vmThread.hpp" | |||
58 | #include "runtime/vmOperations.hpp" | |||
59 | ||||
60 | ||||
61 | /////////////////////////////////////////////////////////////// | |||
62 | // | |||
63 | // JvmtiEnvBase | |||
64 | // | |||
65 | ||||
66 | JvmtiEnvBase* JvmtiEnvBase::_head_environment = NULL__null; | |||
67 | ||||
68 | bool JvmtiEnvBase::_globally_initialized = false; | |||
69 | volatile bool JvmtiEnvBase::_needs_clean_up = false; | |||
70 | ||||
71 | jvmtiPhase JvmtiEnvBase::_phase = JVMTI_PHASE_PRIMORDIAL; | |||
72 | ||||
73 | volatile int JvmtiEnvBase::_dying_thread_env_iteration_count = 0; | |||
74 | ||||
75 | extern jvmtiInterface_1_ jvmti_Interface; | |||
76 | extern jvmtiInterface_1_ jvmtiTrace_Interface; | |||
77 | ||||
78 | ||||
79 | // perform initializations that must occur before any JVMTI environments | |||
80 | // are released but which should only be initialized once (no matter | |||
81 | // how many environments are created). | |||
82 | void | |||
83 | JvmtiEnvBase::globally_initialize() { | |||
84 | assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check")do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 84, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
85 | assert(_globally_initialized == false, "bad call")do { if (!(_globally_initialized == false)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 85, "assert(" "_globally_initialized == false" ") failed", "bad call" ); ::breakpoint(); } } while (0); | |||
86 | ||||
87 | JvmtiManageCapabilities::initialize(); | |||
88 | ||||
89 | // register extension functions and events | |||
90 | JvmtiExtensions::register_extensions(); | |||
91 | ||||
92 | #ifdef JVMTI_TRACE | |||
93 | JvmtiTrace::initialize(); | |||
94 | #endif | |||
95 | ||||
96 | _globally_initialized = true; | |||
97 | } | |||
98 | ||||
99 | ||||
100 | void | |||
101 | JvmtiEnvBase::initialize() { | |||
102 | assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check")do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 102, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
103 | ||||
104 | // Add this environment to the end of the environment list (order is important) | |||
105 | { | |||
106 | // This block of code must not contain any safepoints, as list deallocation | |||
107 | // (which occurs at a safepoint) cannot occur simultaneously with this list | |||
108 | // addition. Note: NoSafepointVerifier cannot, currently, be used before | |||
109 | // threads exist. | |||
110 | JvmtiEnvIterator it; | |||
111 | JvmtiEnvBase *previous_env = NULL__null; | |||
112 | for (JvmtiEnvBase* env = it.first(); env != NULL__null; env = it.next(env)) { | |||
113 | previous_env = env; | |||
114 | } | |||
115 | if (previous_env == NULL__null) { | |||
116 | _head_environment = this; | |||
117 | } else { | |||
118 | previous_env->set_next_environment(this); | |||
119 | } | |||
120 | } | |||
121 | ||||
122 | if (_globally_initialized == false) { | |||
123 | globally_initialize(); | |||
124 | } | |||
125 | } | |||
126 | ||||
127 | jvmtiPhase | |||
128 | JvmtiEnvBase::phase() { | |||
129 | // For the JVMTI environments possessed the can_generate_early_vmstart: | |||
130 | // replace JVMTI_PHASE_PRIMORDIAL with JVMTI_PHASE_START | |||
131 | if (_phase == JVMTI_PHASE_PRIMORDIAL && | |||
132 | JvmtiExport::early_vmstart_recorded() && | |||
133 | early_vmstart_env()) { | |||
134 | return JVMTI_PHASE_START; | |||
135 | } | |||
136 | return _phase; // Normal case | |||
137 | } | |||
138 | ||||
139 | bool | |||
140 | JvmtiEnvBase::is_valid() { | |||
141 | jint value = 0; | |||
142 | ||||
143 | // This object might not be a JvmtiEnvBase so we can't assume | |||
144 | // the _magic field is properly aligned. Get the value in a safe | |||
145 | // way and then check against JVMTI_MAGIC. | |||
146 | ||||
147 | switch (sizeof(_magic)) { | |||
148 | case 2: | |||
149 | value = Bytes::get_native_u2((address)&_magic); | |||
150 | break; | |||
151 | ||||
152 | case 4: | |||
153 | value = Bytes::get_native_u4((address)&_magic); | |||
154 | break; | |||
155 | ||||
156 | case 8: | |||
157 | value = Bytes::get_native_u8((address)&_magic); | |||
158 | break; | |||
159 | ||||
160 | default: | |||
161 | guarantee(false, "_magic field is an unexpected size")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 161, "guarantee(" "false" ") failed", "_magic field is an unexpected size" ); ::breakpoint(); } } while (0); | |||
162 | } | |||
163 | ||||
164 | return value == JVMTI_MAGIC; | |||
165 | } | |||
166 | ||||
167 | ||||
168 | bool | |||
169 | JvmtiEnvBase::use_version_1_0_semantics() { | |||
170 | int major, minor, micro; | |||
171 | ||||
172 | JvmtiExport::decode_version_values(_version, &major, &minor, µ); | |||
173 | return major == 1 && minor == 0; // micro version doesn't matter here | |||
174 | } | |||
175 | ||||
176 | ||||
177 | bool | |||
178 | JvmtiEnvBase::use_version_1_1_semantics() { | |||
179 | int major, minor, micro; | |||
180 | ||||
181 | JvmtiExport::decode_version_values(_version, &major, &minor, µ); | |||
182 | return major == 1 && minor == 1; // micro version doesn't matter here | |||
183 | } | |||
184 | ||||
185 | bool | |||
186 | JvmtiEnvBase::use_version_1_2_semantics() { | |||
187 | int major, minor, micro; | |||
188 | ||||
189 | JvmtiExport::decode_version_values(_version, &major, &minor, µ); | |||
190 | return major == 1 && minor == 2; // micro version doesn't matter here | |||
191 | } | |||
192 | ||||
193 | ||||
194 | JvmtiEnvBase::JvmtiEnvBase(jint version) : _env_event_enable() { | |||
195 | _version = version; | |||
196 | _env_local_storage = NULL__null; | |||
197 | _tag_map = NULL__null; | |||
198 | _native_method_prefix_count = 0; | |||
199 | _native_method_prefixes = NULL__null; | |||
200 | _next = NULL__null; | |||
201 | _class_file_load_hook_ever_enabled = false; | |||
202 | ||||
203 | // Moot since ClassFileLoadHook not yet enabled. | |||
204 | // But "true" will give a more predictable ClassFileLoadHook behavior | |||
205 | // for environment creation during ClassFileLoadHook. | |||
206 | _is_retransformable = true; | |||
207 | ||||
208 | // all callbacks initially NULL | |||
209 | memset(&_event_callbacks,0,sizeof(jvmtiEventCallbacks)); | |||
210 | ||||
211 | // all capabilities initially off | |||
212 | memset(&_current_capabilities, 0, sizeof(_current_capabilities)); | |||
213 | ||||
214 | // all prohibited capabilities initially off | |||
215 | memset(&_prohibited_capabilities, 0, sizeof(_prohibited_capabilities)); | |||
216 | ||||
217 | _magic = JVMTI_MAGIC; | |||
218 | ||||
219 | JvmtiEventController::env_initialize((JvmtiEnv*)this); | |||
220 | ||||
221 | #ifdef JVMTI_TRACE | |||
222 | _jvmti_external.functions = TraceJVMTI != NULL__null ? &jvmtiTrace_Interface : &jvmti_Interface; | |||
223 | #else | |||
224 | _jvmti_external.functions = &jvmti_Interface; | |||
225 | #endif | |||
226 | } | |||
227 | ||||
228 | ||||
229 | void | |||
230 | JvmtiEnvBase::dispose() { | |||
231 | ||||
232 | #ifdef JVMTI_TRACE | |||
233 | JvmtiTrace::shutdown(); | |||
234 | #endif | |||
235 | ||||
236 | // Dispose of event info and let the event controller call us back | |||
237 | // in a locked state (env_dispose, below) | |||
238 | JvmtiEventController::env_dispose(this); | |||
239 | } | |||
240 | ||||
241 | void | |||
242 | JvmtiEnvBase::env_dispose() { | |||
243 | assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check")do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 243, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
244 | ||||
245 | // We have been entered with all events disabled on this environment. | |||
246 | // A race to re-enable events (by setting callbacks) is prevented by | |||
247 | // checking for a valid environment when setting callbacks (while | |||
248 | // holding the JvmtiThreadState_lock). | |||
249 | ||||
250 | // Mark as invalid. | |||
251 | _magic = DISPOSED_MAGIC; | |||
252 | ||||
253 | // Relinquish all capabilities. | |||
254 | jvmtiCapabilities *caps = get_capabilities(); | |||
255 | JvmtiManageCapabilities::relinquish_capabilities(caps, caps, caps); | |||
256 | ||||
257 | // Same situation as with events (see above) | |||
258 | set_native_method_prefixes(0, NULL__null); | |||
259 | ||||
260 | JvmtiTagMap* tag_map_to_clear = tag_map_acquire(); | |||
261 | // A tag map can be big, clear it now to save memory until | |||
262 | // the destructor runs. | |||
263 | if (tag_map_to_clear != NULL__null) { | |||
264 | tag_map_to_clear->clear(); | |||
265 | } | |||
266 | ||||
267 | _needs_clean_up = true; | |||
268 | } | |||
269 | ||||
270 | ||||
271 | JvmtiEnvBase::~JvmtiEnvBase() { | |||
272 | assert(SafepointSynchronize::is_at_safepoint(), "sanity check")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 272, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "sanity check"); ::breakpoint(); } } while (0); | |||
273 | ||||
274 | // There is a small window of time during which the tag map of a | |||
275 | // disposed environment could have been reallocated. | |||
276 | // Make sure it is gone. | |||
277 | JvmtiTagMap* tag_map_to_deallocate = _tag_map; | |||
278 | set_tag_map(NULL__null); | |||
279 | // A tag map can be big, deallocate it now | |||
280 | if (tag_map_to_deallocate != NULL__null) { | |||
281 | delete tag_map_to_deallocate; | |||
282 | } | |||
283 | ||||
284 | _magic = BAD_MAGIC; | |||
285 | } | |||
286 | ||||
287 | ||||
288 | void | |||
289 | JvmtiEnvBase::periodic_clean_up() { | |||
290 | assert(SafepointSynchronize::is_at_safepoint(), "sanity check")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 290, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "sanity check"); ::breakpoint(); } } while (0); | |||
291 | ||||
292 | // JvmtiEnvBase reference is saved in JvmtiEnvThreadState. So | |||
293 | // clean up JvmtiThreadState before deleting JvmtiEnv pointer. | |||
294 | JvmtiThreadState::periodic_clean_up(); | |||
295 | ||||
296 | // Unlink all invalid environments from the list of environments | |||
297 | // and deallocate them | |||
298 | JvmtiEnvIterator it; | |||
299 | JvmtiEnvBase* previous_env = NULL__null; | |||
300 | JvmtiEnvBase* env = it.first(); | |||
301 | while (env != NULL__null) { | |||
302 | if (env->is_valid()) { | |||
303 | previous_env = env; | |||
304 | env = it.next(env); | |||
305 | } else { | |||
306 | // This one isn't valid, remove it from the list and deallocate it | |||
307 | JvmtiEnvBase* defunct_env = env; | |||
308 | env = it.next(env); | |||
309 | if (previous_env == NULL__null) { | |||
310 | _head_environment = env; | |||
311 | } else { | |||
312 | previous_env->set_next_environment(env); | |||
313 | } | |||
314 | delete defunct_env; | |||
315 | } | |||
316 | } | |||
317 | ||||
318 | } | |||
319 | ||||
320 | ||||
321 | void | |||
322 | JvmtiEnvBase::check_for_periodic_clean_up() { | |||
323 | assert(SafepointSynchronize::is_at_safepoint(), "sanity check")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 323, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "sanity check"); ::breakpoint(); } } while (0); | |||
324 | ||||
325 | class ThreadInsideIterationClosure: public ThreadClosure { | |||
326 | private: | |||
327 | bool _inside; | |||
328 | public: | |||
329 | ThreadInsideIterationClosure() : _inside(false) {}; | |||
330 | ||||
331 | void do_thread(Thread* thread) { | |||
332 | _inside |= thread->is_inside_jvmti_env_iteration(); | |||
333 | } | |||
334 | ||||
335 | bool is_inside_jvmti_env_iteration() { | |||
336 | return _inside; | |||
337 | } | |||
338 | }; | |||
339 | ||||
340 | if (_needs_clean_up) { | |||
341 | // Check if we are currently iterating environment, | |||
342 | // deallocation should not occur if we are | |||
343 | ThreadInsideIterationClosure tiic; | |||
344 | Threads::threads_do(&tiic); | |||
345 | if (!tiic.is_inside_jvmti_env_iteration() && | |||
346 | !is_inside_dying_thread_env_iteration()) { | |||
347 | _needs_clean_up = false; | |||
348 | JvmtiEnvBase::periodic_clean_up(); | |||
349 | } | |||
350 | } | |||
351 | } | |||
352 | ||||
353 | ||||
354 | void | |||
355 | JvmtiEnvBase::record_first_time_class_file_load_hook_enabled() { | |||
356 | assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(),do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 357, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0) | |||
357 | "sanity check")do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 357, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
358 | ||||
359 | if (!_class_file_load_hook_ever_enabled) { | |||
360 | _class_file_load_hook_ever_enabled = true; | |||
361 | ||||
362 | if (get_capabilities()->can_retransform_classes) { | |||
363 | _is_retransformable = true; | |||
364 | } else { | |||
365 | _is_retransformable = false; | |||
366 | ||||
367 | // cannot add retransform capability after ClassFileLoadHook has been enabled | |||
368 | get_prohibited_capabilities()->can_retransform_classes = 1; | |||
369 | } | |||
370 | } | |||
371 | } | |||
372 | ||||
373 | ||||
374 | void | |||
375 | JvmtiEnvBase::record_class_file_load_hook_enabled() { | |||
376 | if (!_class_file_load_hook_ever_enabled) { | |||
377 | if (Threads::number_of_threads() == 0) { | |||
378 | record_first_time_class_file_load_hook_enabled(); | |||
379 | } else { | |||
380 | MutexLocker mu(JvmtiThreadState_lock); | |||
381 | record_first_time_class_file_load_hook_enabled(); | |||
382 | } | |||
383 | } | |||
384 | } | |||
385 | ||||
386 | ||||
387 | jvmtiError | |||
388 | JvmtiEnvBase::set_native_method_prefixes(jint prefix_count, char** prefixes) { | |||
389 | assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(),do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 390, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0) | |||
390 | "sanity check")do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 390, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
391 | ||||
392 | int old_prefix_count = get_native_method_prefix_count(); | |||
393 | char **old_prefixes = get_native_method_prefixes(); | |||
394 | ||||
395 | // allocate and install the new prefixex | |||
396 | if (prefix_count == 0 || !is_valid()) { | |||
397 | _native_method_prefix_count = 0; | |||
398 | _native_method_prefixes = NULL__null; | |||
399 | } else { | |||
400 | // there are prefixes, allocate an array to hold them, and fill it | |||
401 | char** new_prefixes = (char**)os::malloc((prefix_count) * sizeof(char*), mtInternal); | |||
402 | if (new_prefixes == NULL__null) { | |||
403 | return JVMTI_ERROR_OUT_OF_MEMORY; | |||
404 | } | |||
405 | for (int i = 0; i < prefix_count; i++) { | |||
406 | char* prefix = prefixes[i]; | |||
407 | if (prefix == NULL__null) { | |||
408 | for (int j = 0; j < (i-1); j++) { | |||
409 | os::free(new_prefixes[j]); | |||
410 | } | |||
411 | os::free(new_prefixes); | |||
412 | return JVMTI_ERROR_NULL_POINTER; | |||
413 | } | |||
414 | prefix = os::strdup(prefixes[i]); | |||
415 | if (prefix == NULL__null) { | |||
416 | for (int j = 0; j < (i-1); j++) { | |||
417 | os::free(new_prefixes[j]); | |||
418 | } | |||
419 | os::free(new_prefixes); | |||
420 | return JVMTI_ERROR_OUT_OF_MEMORY; | |||
421 | } | |||
422 | new_prefixes[i] = prefix; | |||
423 | } | |||
424 | _native_method_prefix_count = prefix_count; | |||
425 | _native_method_prefixes = new_prefixes; | |||
426 | } | |||
427 | ||||
428 | // now that we know the new prefixes have been successfully installed we can | |||
429 | // safely remove the old ones | |||
430 | if (old_prefix_count != 0) { | |||
431 | for (int i = 0; i < old_prefix_count; i++) { | |||
432 | os::free(old_prefixes[i]); | |||
433 | } | |||
434 | os::free(old_prefixes); | |||
435 | } | |||
436 | ||||
437 | return JVMTI_ERROR_NONE; | |||
438 | } | |||
439 | ||||
440 | ||||
441 | // Collect all the prefixes which have been set in any JVM TI environments | |||
442 | // by the SetNativeMethodPrefix(es) functions. Be sure to maintain the | |||
443 | // order of environments and the order of prefixes within each environment. | |||
444 | // Return in a resource allocated array. | |||
445 | char** | |||
446 | JvmtiEnvBase::get_all_native_method_prefixes(int* count_ptr) { | |||
447 | assert(Threads::number_of_threads() == 0 ||do { if (!(Threads::number_of_threads() == 0 || SafepointSynchronize ::is_at_safepoint() || JvmtiThreadState_lock->is_locked()) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 450, "assert(" "Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint() || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0) | |||
448 | SafepointSynchronize::is_at_safepoint() ||do { if (!(Threads::number_of_threads() == 0 || SafepointSynchronize ::is_at_safepoint() || JvmtiThreadState_lock->is_locked()) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 450, "assert(" "Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint() || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0) | |||
449 | JvmtiThreadState_lock->is_locked(),do { if (!(Threads::number_of_threads() == 0 || SafepointSynchronize ::is_at_safepoint() || JvmtiThreadState_lock->is_locked()) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 450, "assert(" "Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint() || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0) | |||
450 | "sanity check")do { if (!(Threads::number_of_threads() == 0 || SafepointSynchronize ::is_at_safepoint() || JvmtiThreadState_lock->is_locked()) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 450, "assert(" "Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint() || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
451 | ||||
452 | int total_count = 0; | |||
453 | GrowableArray<char*>* prefix_array =new GrowableArray<char*>(5); | |||
454 | ||||
455 | JvmtiEnvIterator it; | |||
456 | for (JvmtiEnvBase* env = it.first(); env != NULL__null; env = it.next(env)) { | |||
457 | int prefix_count = env->get_native_method_prefix_count(); | |||
458 | char** prefixes = env->get_native_method_prefixes(); | |||
459 | for (int j = 0; j < prefix_count; j++) { | |||
460 | // retrieve a prefix and so that it is safe against asynchronous changes | |||
461 | // copy it into the resource area | |||
462 | char* prefix = prefixes[j]; | |||
463 | char* prefix_copy = NEW_RESOURCE_ARRAY(char, strlen(prefix)+1)(char*) resource_allocate_bytes((strlen(prefix)+1) * sizeof(char )); | |||
464 | strcpy(prefix_copy, prefix); | |||
465 | prefix_array->at_put_grow(total_count++, prefix_copy); | |||
466 | } | |||
467 | } | |||
468 | ||||
469 | char** all_prefixes = NEW_RESOURCE_ARRAY(char*, total_count)(char**) resource_allocate_bytes((total_count) * sizeof(char* )); | |||
470 | char** p = all_prefixes; | |||
471 | for (int i = 0; i < total_count; ++i) { | |||
472 | *p++ = prefix_array->at(i); | |||
473 | } | |||
474 | *count_ptr = total_count; | |||
475 | return all_prefixes; | |||
476 | } | |||
477 | ||||
478 | void | |||
479 | JvmtiEnvBase::set_event_callbacks(const jvmtiEventCallbacks* callbacks, | |||
480 | jint size_of_callbacks) { | |||
481 | assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check")do { if (!(Threads::number_of_threads() == 0 || JvmtiThreadState_lock ->is_locked())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 481, "assert(" "Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked()" ") failed", "sanity check"); ::breakpoint(); } } while (0); | |||
482 | ||||
483 | size_t byte_cnt = sizeof(jvmtiEventCallbacks); | |||
484 | ||||
485 | // clear in either case to be sure we got any gap between sizes | |||
486 | memset(&_event_callbacks, 0, byte_cnt); | |||
487 | ||||
488 | // Now that JvmtiThreadState_lock is held, prevent a possible race condition where events | |||
489 | // are re-enabled by a call to set event callbacks where the DisposeEnvironment | |||
490 | // occurs after the boiler-plate environment check and before the lock is acquired. | |||
491 | if (callbacks != NULL__null && is_valid()) { | |||
492 | if (size_of_callbacks < (jint)byte_cnt) { | |||
493 | byte_cnt = size_of_callbacks; | |||
494 | } | |||
495 | memcpy(&_event_callbacks, callbacks, byte_cnt); | |||
496 | } | |||
497 | } | |||
498 | ||||
499 | ||||
500 | // In the fullness of time, all users of the method should instead | |||
501 | // directly use allocate, besides being cleaner and faster, this will | |||
502 | // mean much better out of memory handling | |||
503 | unsigned char * | |||
504 | JvmtiEnvBase::jvmtiMalloc(jlong size) { | |||
505 | unsigned char* mem = NULL__null; | |||
506 | jvmtiError result = allocate(size, &mem); | |||
507 | assert(result == JVMTI_ERROR_NONE, "Allocate failed")do { if (!(result == JVMTI_ERROR_NONE)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 507, "assert(" "result == JVMTI_ERROR_NONE" ") failed", "Allocate failed" ); ::breakpoint(); } } while (0); | |||
508 | return mem; | |||
509 | } | |||
510 | ||||
511 | ||||
512 | // Handle management | |||
513 | ||||
514 | jobject JvmtiEnvBase::jni_reference(Handle hndl) { | |||
515 | return JNIHandles::make_local(hndl()); | |||
516 | } | |||
517 | ||||
518 | jobject JvmtiEnvBase::jni_reference(JavaThread *thread, Handle hndl) { | |||
519 | return JNIHandles::make_local(thread, hndl()); | |||
520 | } | |||
521 | ||||
522 | void JvmtiEnvBase::destroy_jni_reference(jobject jobj) { | |||
523 | JNIHandles::destroy_local(jobj); | |||
524 | } | |||
525 | ||||
526 | void JvmtiEnvBase::destroy_jni_reference(JavaThread *thread, jobject jobj) { | |||
527 | JNIHandles::destroy_local(jobj); // thread is unused. | |||
528 | } | |||
529 | ||||
530 | // | |||
531 | // Threads | |||
532 | // | |||
533 | ||||
534 | jobject * | |||
535 | JvmtiEnvBase::new_jobjectArray(int length, Handle *handles) { | |||
536 | if (length == 0) { | |||
537 | return NULL__null; | |||
538 | } | |||
539 | ||||
540 | jobject *objArray = (jobject *) jvmtiMalloc(sizeof(jobject) * length); | |||
541 | NULL_CHECK(objArray, NULL)if ((objArray) == __null) { return (__null); }; | |||
542 | ||||
543 | for (int i=0; i<length; i++) { | |||
544 | objArray[i] = jni_reference(handles[i]); | |||
545 | } | |||
546 | return objArray; | |||
547 | } | |||
548 | ||||
549 | jthread * | |||
550 | JvmtiEnvBase::new_jthreadArray(int length, Handle *handles) { | |||
551 | return (jthread *) new_jobjectArray(length,handles); | |||
552 | } | |||
553 | ||||
554 | jthreadGroup * | |||
555 | JvmtiEnvBase::new_jthreadGroupArray(int length, Handle *handles) { | |||
556 | return (jthreadGroup *) new_jobjectArray(length,handles); | |||
557 | } | |||
558 | ||||
559 | // return the vframe on the specified thread and depth, NULL if no such frame | |||
560 | // The thread and the oops in the returned vframe might not have been process. | |||
561 | vframe* | |||
562 | JvmtiEnvBase::vframeForNoProcess(JavaThread* java_thread, jint depth) { | |||
563 | if (!java_thread->has_last_Java_frame()) { | |||
564 | return NULL__null; | |||
565 | } | |||
566 | RegisterMap reg_map(java_thread, true /* update_map */, false /* process_frames */); | |||
567 | vframe *vf = java_thread->last_java_vframe(®_map); | |||
568 | int d = 0; | |||
569 | while ((vf != NULL__null) && (d < depth)) { | |||
570 | vf = vf->java_sender(); | |||
571 | d++; | |||
572 | } | |||
573 | return vf; | |||
574 | } | |||
575 | ||||
576 | ||||
577 | // | |||
578 | // utilities: JNI objects | |||
579 | // | |||
580 | ||||
581 | ||||
582 | jclass | |||
583 | JvmtiEnvBase::get_jni_class_non_null(Klass* k) { | |||
584 | assert(k != NULL, "k != NULL")do { if (!(k != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 584, "assert(" "k != __null" ") failed", "k != NULL"); ::breakpoint (); } } while (0); | |||
585 | Thread *thread = Thread::current(); | |||
586 | return (jclass)jni_reference(Handle(thread, k->java_mirror())); | |||
587 | } | |||
588 | ||||
589 | // | |||
590 | // Field Information | |||
591 | // | |||
592 | ||||
593 | bool | |||
594 | JvmtiEnvBase::get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd) { | |||
595 | if (!jfieldIDWorkaround::is_valid_jfieldID(k, field)) { | |||
596 | return false; | |||
597 | } | |||
598 | bool found = false; | |||
599 | if (jfieldIDWorkaround::is_static_jfieldID(field)) { | |||
600 | JNIid* id = jfieldIDWorkaround::from_static_jfieldID(field); | |||
601 | found = id->find_local_field(fd); | |||
602 | } else { | |||
603 | // Non-static field. The fieldID is really the offset of the field within the object. | |||
604 | int offset = jfieldIDWorkaround::from_instance_jfieldID(k, field); | |||
605 | found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, fd); | |||
606 | } | |||
607 | return found; | |||
608 | } | |||
609 | ||||
610 | // | |||
611 | // Object Monitor Information | |||
612 | // | |||
613 | ||||
614 | // | |||
615 | // Count the number of objects for a lightweight monitor. The hobj | |||
616 | // parameter is object that owns the monitor so this routine will | |||
617 | // count the number of times the same object was locked by frames | |||
618 | // in java_thread. | |||
619 | // | |||
620 | jint | |||
621 | JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) { | |||
622 | jint ret = 0; | |||
623 | if (!java_thread->has_last_Java_frame()) { | |||
624 | return ret; // no Java frames so no monitors | |||
625 | } | |||
626 | ||||
627 | Thread* current_thread = Thread::current(); | |||
628 | ResourceMark rm(current_thread); | |||
629 | HandleMark hm(current_thread); | |||
630 | RegisterMap reg_map(java_thread); | |||
631 | ||||
632 | for(javaVFrame *jvf=java_thread->last_java_vframe(®_map); jvf != NULL__null; | |||
633 | jvf = jvf->java_sender()) { | |||
634 | GrowableArray<MonitorInfo*>* mons = jvf->monitors(); | |||
635 | if (!mons->is_empty()) { | |||
636 | for (int i = 0; i < mons->length(); i++) { | |||
637 | MonitorInfo *mi = mons->at(i); | |||
638 | if (mi->owner_is_scalar_replaced()) continue; | |||
639 | ||||
640 | // see if owner of the monitor is our object | |||
641 | if (mi->owner() != NULL__null && mi->owner() == hobj()) { | |||
642 | ret++; | |||
643 | } | |||
644 | } | |||
645 | } | |||
646 | } | |||
647 | return ret; | |||
648 | } | |||
649 | ||||
650 | ||||
651 | ||||
652 | jvmtiError | |||
653 | JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread, jobject *monitor_ptr) { | |||
654 | Thread *current_thread = Thread::current(); | |||
655 | assert(java_thread->is_handshake_safe_for(current_thread),do { if (!(java_thread->is_handshake_safe_for(current_thread ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 656, "assert(" "java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself or at handshake"); ::breakpoint( ); } } while (0) | |||
656 | "call by myself or at handshake")do { if (!(java_thread->is_handshake_safe_for(current_thread ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 656, "assert(" "java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself or at handshake"); ::breakpoint( ); } } while (0); | |||
657 | oop obj = NULL__null; | |||
658 | // The ObjectMonitor* can't be async deflated since we are either | |||
659 | // at a safepoint or the calling thread is operating on itself so | |||
660 | // it cannot leave the underlying wait()/enter() call. | |||
661 | ObjectMonitor *mon = java_thread->current_waiting_monitor(); | |||
662 | if (mon == NULL__null) { | |||
663 | // thread is not doing an Object.wait() call | |||
664 | mon = java_thread->current_pending_monitor(); | |||
665 | if (mon != NULL__null) { | |||
666 | // The thread is trying to enter() an ObjectMonitor. | |||
667 | obj = mon->object(); | |||
668 | assert(obj != NULL, "ObjectMonitor should have a valid object!")do { if (!(obj != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 668, "assert(" "obj != __null" ") failed", "ObjectMonitor should have a valid object!" ); ::breakpoint(); } } while (0); | |||
669 | } | |||
670 | // implied else: no contended ObjectMonitor | |||
671 | } else { | |||
672 | // thread is doing an Object.wait() call | |||
673 | obj = mon->object(); | |||
674 | assert(obj != NULL, "Object.wait() should have an object")do { if (!(obj != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 674, "assert(" "obj != __null" ") failed", "Object.wait() should have an object" ); ::breakpoint(); } } while (0); | |||
675 | } | |||
676 | ||||
677 | if (obj == NULL__null) { | |||
678 | *monitor_ptr = NULL__null; | |||
679 | } else { | |||
680 | HandleMark hm(current_thread); | |||
681 | Handle hobj(current_thread, obj); | |||
682 | *monitor_ptr = jni_reference(calling_thread, hobj); | |||
683 | } | |||
684 | return JVMTI_ERROR_NONE; | |||
685 | } | |||
686 | ||||
687 | ||||
688 | jvmtiError | |||
689 | JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread, | |||
690 | GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) { | |||
691 | // Note: | |||
692 | // calling_thread is the thread that requested the list of monitors for java_thread. | |||
693 | // java_thread is the thread owning the monitors. | |||
694 | // current_thread is the thread executing this code, can be a non-JavaThread (e.g. VM Thread). | |||
695 | // And they all may be different threads. | |||
696 | jvmtiError err = JVMTI_ERROR_NONE; | |||
697 | Thread *current_thread = Thread::current(); | |||
698 | assert(java_thread->is_handshake_safe_for(current_thread),do { if (!(java_thread->is_handshake_safe_for(current_thread ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 699, "assert(" "java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself or at handshake"); ::breakpoint( ); } } while (0) | |||
699 | "call by myself or at handshake")do { if (!(java_thread->is_handshake_safe_for(current_thread ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 699, "assert(" "java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself or at handshake"); ::breakpoint( ); } } while (0); | |||
700 | ||||
701 | if (java_thread->has_last_Java_frame()) { | |||
702 | ResourceMark rm(current_thread); | |||
703 | HandleMark hm(current_thread); | |||
704 | RegisterMap reg_map(java_thread); | |||
705 | ||||
706 | int depth = 0; | |||
707 | for (javaVFrame *jvf = java_thread->last_java_vframe(®_map); jvf != NULL__null; | |||
708 | jvf = jvf->java_sender()) { | |||
709 | if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep | |||
710 | // add locked objects for this frame into list | |||
711 | err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth-1); | |||
712 | if (err != JVMTI_ERROR_NONE) { | |||
713 | return err; | |||
714 | } | |||
715 | } | |||
716 | } | |||
717 | } | |||
718 | ||||
719 | // Get off stack monitors. (e.g. acquired via jni MonitorEnter). | |||
720 | JvmtiMonitorClosure jmc(calling_thread, owned_monitors_list, this); | |||
721 | ObjectSynchronizer::monitors_iterate(&jmc, java_thread); | |||
722 | err = jmc.error(); | |||
723 | ||||
724 | return err; | |||
725 | } | |||
726 | ||||
727 | // Save JNI local handles for any objects that this frame owns. | |||
728 | jvmtiError | |||
729 | JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* java_thread, | |||
730 | javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, jint stack_depth) { | |||
731 | jvmtiError err = JVMTI_ERROR_NONE; | |||
732 | Thread* current_thread = Thread::current(); | |||
733 | ResourceMark rm(current_thread); | |||
734 | HandleMark hm(current_thread); | |||
735 | ||||
736 | GrowableArray<MonitorInfo*>* mons = jvf->monitors(); | |||
737 | if (mons->is_empty()) { | |||
738 | return err; // this javaVFrame holds no monitors | |||
739 | } | |||
740 | ||||
741 | oop wait_obj = NULL__null; | |||
742 | { | |||
743 | // The ObjectMonitor* can't be async deflated since we are either | |||
744 | // at a safepoint or the calling thread is operating on itself so | |||
745 | // it cannot leave the underlying wait() call. | |||
746 | // Save object of current wait() call (if any) for later comparison. | |||
747 | ObjectMonitor *mon = java_thread->current_waiting_monitor(); | |||
748 | if (mon != NULL__null) { | |||
749 | wait_obj = mon->object(); | |||
750 | } | |||
751 | } | |||
752 | oop pending_obj = NULL__null; | |||
753 | { | |||
754 | // The ObjectMonitor* can't be async deflated since we are either | |||
755 | // at a safepoint or the calling thread is operating on itself so | |||
756 | // it cannot leave the underlying enter() call. | |||
757 | // Save object of current enter() call (if any) for later comparison. | |||
758 | ObjectMonitor *mon = java_thread->current_pending_monitor(); | |||
759 | if (mon != NULL__null) { | |||
760 | pending_obj = mon->object(); | |||
761 | } | |||
762 | } | |||
763 | ||||
764 | for (int i = 0; i < mons->length(); i++) { | |||
765 | MonitorInfo *mi = mons->at(i); | |||
766 | ||||
767 | if (mi->owner_is_scalar_replaced()) continue; | |||
768 | ||||
769 | oop obj = mi->owner(); | |||
770 | if (obj == NULL__null) { | |||
771 | // this monitor doesn't have an owning object so skip it | |||
772 | continue; | |||
773 | } | |||
774 | ||||
775 | if (wait_obj == obj) { | |||
776 | // the thread is waiting on this monitor so it isn't really owned | |||
777 | continue; | |||
778 | } | |||
779 | ||||
780 | if (pending_obj == obj) { | |||
781 | // the thread is pending on this monitor so it isn't really owned | |||
782 | continue; | |||
783 | } | |||
784 | ||||
785 | if (owned_monitors_list->length() > 0) { | |||
786 | // Our list has at least one object on it so we have to check | |||
787 | // for recursive object locking | |||
788 | bool found = false; | |||
789 | for (int j = 0; j < owned_monitors_list->length(); j++) { | |||
790 | jobject jobj = ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(j))->monitor; | |||
791 | oop check = JNIHandles::resolve(jobj); | |||
792 | if (check == obj) { | |||
793 | found = true; // we found the object | |||
794 | break; | |||
795 | } | |||
796 | } | |||
797 | ||||
798 | if (found) { | |||
799 | // already have this object so don't include it | |||
800 | continue; | |||
801 | } | |||
802 | } | |||
803 | ||||
804 | // add the owning object to our list | |||
805 | jvmtiMonitorStackDepthInfo *jmsdi; | |||
806 | err = allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi); | |||
807 | if (err != JVMTI_ERROR_NONE) { | |||
808 | return err; | |||
809 | } | |||
810 | Handle hobj(Thread::current(), obj); | |||
811 | jmsdi->monitor = jni_reference(calling_thread, hobj); | |||
812 | jmsdi->stack_depth = stack_depth; | |||
813 | owned_monitors_list->append(jmsdi); | |||
814 | } | |||
815 | ||||
816 | return err; | |||
817 | } | |||
818 | ||||
819 | jvmtiError | |||
820 | JvmtiEnvBase::get_stack_trace(JavaThread *java_thread, | |||
821 | jint start_depth, jint max_count, | |||
822 | jvmtiFrameInfo* frame_buffer, jint* count_ptr) { | |||
823 | #ifdef ASSERT1 | |||
824 | uint32_t debug_bits = 0; | |||
825 | #endif | |||
826 | Thread *current_thread = Thread::current(); | |||
827 | assert(SafepointSynchronize::is_at_safepoint() ||do { if (!(SafepointSynchronize::is_at_safepoint() || java_thread ->is_handshake_safe_for(current_thread))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 829, "assert(" "SafepointSynchronize::is_at_safepoint() || java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself / at safepoint / at handshake"); ::breakpoint(); } } while (0) | |||
828 | java_thread->is_handshake_safe_for(current_thread),do { if (!(SafepointSynchronize::is_at_safepoint() || java_thread ->is_handshake_safe_for(current_thread))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 829, "assert(" "SafepointSynchronize::is_at_safepoint() || java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself / at safepoint / at handshake"); ::breakpoint(); } } while (0) | |||
829 | "call by myself / at safepoint / at handshake")do { if (!(SafepointSynchronize::is_at_safepoint() || java_thread ->is_handshake_safe_for(current_thread))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 829, "assert(" "SafepointSynchronize::is_at_safepoint() || java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself / at safepoint / at handshake"); ::breakpoint(); } } while (0); | |||
830 | int count = 0; | |||
831 | if (java_thread->has_last_Java_frame()) { | |||
832 | RegisterMap reg_map(java_thread, false /* update_map */, false /* process_frames */); | |||
833 | ResourceMark rm(current_thread); | |||
834 | javaVFrame *jvf = java_thread->last_java_vframe(®_map); | |||
835 | HandleMark hm(current_thread); | |||
836 | if (start_depth != 0) { | |||
837 | if (start_depth > 0) { | |||
838 | for (int j = 0; j < start_depth && jvf != NULL__null; j++) { | |||
839 | jvf = jvf->java_sender(); | |||
840 | } | |||
841 | if (jvf == NULL__null) { | |||
842 | // start_depth is deeper than the stack depth | |||
843 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |||
844 | } | |||
845 | } else { // start_depth < 0 | |||
846 | // we are referencing the starting depth based on the oldest | |||
847 | // part of the stack. | |||
848 | // optimize to limit the number of times that java_sender() is called | |||
849 | javaVFrame *jvf_cursor = jvf; | |||
850 | javaVFrame *jvf_prev = NULL__null; | |||
851 | javaVFrame *jvf_prev_prev = NULL__null; | |||
852 | int j = 0; | |||
853 | while (jvf_cursor != NULL__null) { | |||
854 | jvf_prev_prev = jvf_prev; | |||
855 | jvf_prev = jvf_cursor; | |||
856 | for (j = 0; j > start_depth && jvf_cursor != NULL__null; j--) { | |||
857 | jvf_cursor = jvf_cursor->java_sender(); | |||
858 | } | |||
859 | } | |||
860 | if (j == start_depth) { | |||
861 | // previous pointer is exactly where we want to start | |||
862 | jvf = jvf_prev; | |||
863 | } else { | |||
864 | // we need to back up further to get to the right place | |||
865 | if (jvf_prev_prev == NULL__null) { | |||
866 | // the -start_depth is greater than the stack depth | |||
867 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |||
868 | } | |||
869 | // j now is the number of frames on the stack starting with | |||
870 | // jvf_prev, we start from jvf_prev_prev and move older on | |||
871 | // the stack that many, the result is -start_depth frames | |||
872 | // remaining. | |||
873 | jvf = jvf_prev_prev; | |||
874 | for (; j < 0; j++) { | |||
875 | jvf = jvf->java_sender(); | |||
876 | } | |||
877 | } | |||
878 | } | |||
879 | } | |||
880 | for (; count < max_count && jvf != NULL__null; count++) { | |||
881 | frame_buffer[count].method = jvf->method()->jmethod_id(); | |||
882 | frame_buffer[count].location = (jvf->method()->is_native() ? -1 : jvf->bci()); | |||
883 | jvf = jvf->java_sender(); | |||
884 | } | |||
885 | } else { | |||
886 | if (start_depth != 0) { | |||
887 | // no frames and there is a starting depth | |||
888 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |||
889 | } | |||
890 | } | |||
891 | *count_ptr = count; | |||
892 | return JVMTI_ERROR_NONE; | |||
893 | } | |||
894 | ||||
895 | jvmtiError | |||
896 | JvmtiEnvBase::get_frame_count(JvmtiThreadState *state, jint *count_ptr) { | |||
897 | assert((state != NULL),do { if (!((state != __null))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 898, "assert(" "(state != __null)" ") failed", "JavaThread should create JvmtiThreadState before calling this method" ); ::breakpoint(); } } while (0) | |||
898 | "JavaThread should create JvmtiThreadState before calling this method")do { if (!((state != __null))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 898, "assert(" "(state != __null)" ") failed", "JavaThread should create JvmtiThreadState before calling this method" ); ::breakpoint(); } } while (0); | |||
899 | *count_ptr = state->count_frames(); | |||
900 | return JVMTI_ERROR_NONE; | |||
901 | } | |||
902 | ||||
903 | jvmtiError | |||
904 | JvmtiEnvBase::get_frame_location(JavaThread *java_thread, jint depth, | |||
905 | jmethodID* method_ptr, jlocation* location_ptr) { | |||
906 | #ifdef ASSERT1 | |||
907 | uint32_t debug_bits = 0; | |||
908 | #endif | |||
909 | Thread* current_thread = Thread::current(); | |||
910 | assert(java_thread->is_handshake_safe_for(current_thread),do { if (!(java_thread->is_handshake_safe_for(current_thread ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 911, "assert(" "java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself or at handshake"); ::breakpoint( ); } } while (0) | |||
911 | "call by myself or at handshake")do { if (!(java_thread->is_handshake_safe_for(current_thread ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 911, "assert(" "java_thread->is_handshake_safe_for(current_thread)" ") failed", "call by myself or at handshake"); ::breakpoint( ); } } while (0); | |||
912 | ResourceMark rm(current_thread); | |||
913 | ||||
914 | vframe *vf = vframeForNoProcess(java_thread, depth); | |||
915 | if (vf == NULL__null) { | |||
916 | return JVMTI_ERROR_NO_MORE_FRAMES; | |||
917 | } | |||
918 | ||||
919 | // vframeFor should return a java frame. If it doesn't | |||
920 | // it means we've got an internal error and we return the | |||
921 | // error in product mode. In debug mode we will instead | |||
922 | // attempt to cast the vframe to a javaVFrame and will | |||
923 | // cause an assertion/crash to allow further diagnosis. | |||
924 | #ifdef PRODUCT | |||
925 | if (!vf->is_java_frame()) { | |||
926 | return JVMTI_ERROR_INTERNAL; | |||
927 | } | |||
928 | #endif | |||
929 | ||||
930 | HandleMark hm(current_thread); | |||
931 | javaVFrame *jvf = javaVFrame::cast(vf); | |||
932 | Method* method = jvf->method(); | |||
933 | if (method->is_native()) { | |||
934 | *location_ptr = -1; | |||
935 | } else { | |||
936 | *location_ptr = jvf->bci(); | |||
937 | } | |||
938 | *method_ptr = method->jmethod_id(); | |||
939 | ||||
940 | return JVMTI_ERROR_NONE; | |||
941 | } | |||
942 | ||||
943 | ||||
944 | jvmtiError | |||
945 | JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { | |||
946 | assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 946, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "must be at safepoint"); ::breakpoint(); } } while (0); | |||
947 | Thread* current_thread = VMThread::vm_thread(); | |||
948 | assert(current_thread == Thread::current(), "must be")do { if (!(current_thread == Thread::current())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 948, "assert(" "current_thread == Thread::current()" ") failed" , "must be"); ::breakpoint(); } } while (0); | |||
949 | ||||
950 | HandleMark hm(current_thread); | |||
951 | Handle hobj; | |||
952 | ||||
953 | // Check arguments | |||
954 | { | |||
955 | oop mirror = JNIHandles::resolve_external_guard(object); | |||
956 | NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT)if ((mirror) == __null) { return (JVMTI_ERROR_INVALID_OBJECT) ; }; | |||
957 | NULL_CHECK(info_ptr, JVMTI_ERROR_NULL_POINTER)if ((info_ptr) == __null) { return (JVMTI_ERROR_NULL_POINTER) ; }; | |||
958 | ||||
959 | hobj = Handle(current_thread, mirror); | |||
960 | } | |||
961 | ||||
962 | ThreadsListHandle tlh(current_thread); | |||
963 | JavaThread *owning_thread = NULL__null; | |||
964 | ObjectMonitor *mon = NULL__null; | |||
965 | jvmtiMonitorUsage ret = { | |||
966 | NULL__null, 0, 0, NULL__null, 0, NULL__null | |||
967 | }; | |||
968 | ||||
969 | uint32_t debug_bits = 0; | |||
970 | // first derive the object's owner and entry_count (if any) | |||
971 | { | |||
972 | address owner = NULL__null; | |||
973 | { | |||
974 | markWord mark = hobj()->mark(); | |||
975 | ||||
976 | if (!mark.has_monitor()) { | |||
977 | // this object has a lightweight monitor | |||
978 | ||||
979 | if (mark.has_locker()) { | |||
980 | owner = (address)mark.locker(); // save the address of the Lock word | |||
981 | } | |||
982 | // implied else: no owner | |||
983 | } else { | |||
984 | // this object has a heavyweight monitor | |||
985 | mon = mark.monitor(); | |||
986 | ||||
987 | // The owner field of a heavyweight monitor may be NULL for no | |||
988 | // owner, a JavaThread * or it may still be the address of the | |||
989 | // Lock word in a JavaThread's stack. A monitor can be inflated | |||
990 | // by a non-owning JavaThread, but only the owning JavaThread | |||
991 | // can change the owner field from the Lock word to the | |||
992 | // JavaThread * and it may not have done that yet. | |||
993 | owner = (address)mon->owner(); | |||
994 | } | |||
995 | } | |||
996 | ||||
997 | if (owner != NULL__null) { | |||
998 | // This monitor is owned so we have to find the owning JavaThread. | |||
999 | owning_thread = Threads::owning_thread_from_monitor_owner(tlh.list(), owner); | |||
1000 | assert(owning_thread != NULL, "owning JavaThread must not be NULL")do { if (!(owning_thread != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1000, "assert(" "owning_thread != __null" ") failed", "owning JavaThread must not be NULL" ); ::breakpoint(); } } while (0); | |||
1001 | Handle th(current_thread, owning_thread->threadObj()); | |||
1002 | ret.owner = (jthread)jni_reference(calling_thread, th); | |||
1003 | } | |||
1004 | ||||
1005 | if (owning_thread != NULL__null) { // monitor is owned | |||
1006 | // The recursions field of a monitor does not reflect recursions | |||
1007 | // as lightweight locks before inflating the monitor are not included. | |||
1008 | // We have to count the number of recursive monitor entries the hard way. | |||
1009 | // We pass a handle to survive any GCs along the way. | |||
1010 | ret.entry_count = count_locked_objects(owning_thread, hobj); | |||
1011 | } | |||
1012 | // implied else: entry_count == 0 | |||
1013 | } | |||
1014 | ||||
1015 | jint nWant = 0, nWait = 0; | |||
1016 | if (mon != NULL__null) { | |||
1017 | // this object has a heavyweight monitor | |||
1018 | nWant = mon->contentions(); // # of threads contending for monitor | |||
1019 | nWait = mon->waiters(); // # of threads in Object.wait() | |||
1020 | ret.waiter_count = nWant + nWait; | |||
1021 | ret.notify_waiter_count = nWait; | |||
1022 | } else { | |||
1023 | // this object has a lightweight monitor | |||
1024 | ret.waiter_count = 0; | |||
1025 | ret.notify_waiter_count = 0; | |||
1026 | } | |||
1027 | ||||
1028 | // Allocate memory for heavyweight and lightweight monitor. | |||
1029 | jvmtiError err; | |||
1030 | err = allocate(ret.waiter_count * sizeof(jthread *), (unsigned char**)&ret.waiters); | |||
1031 | if (err != JVMTI_ERROR_NONE) { | |||
1032 | return err; | |||
1033 | } | |||
1034 | err = allocate(ret.notify_waiter_count * sizeof(jthread *), | |||
1035 | (unsigned char**)&ret.notify_waiters); | |||
1036 | if (err != JVMTI_ERROR_NONE) { | |||
1037 | deallocate((unsigned char*)ret.waiters); | |||
1038 | return err; | |||
1039 | } | |||
1040 | ||||
1041 | // now derive the rest of the fields | |||
1042 | if (mon != NULL__null) { | |||
1043 | // this object has a heavyweight monitor | |||
1044 | ||||
1045 | // Number of waiters may actually be less than the waiter count. | |||
1046 | // So NULL out memory so that unused memory will be NULL. | |||
1047 | memset(ret.waiters, 0, ret.waiter_count * sizeof(jthread *)); | |||
1048 | memset(ret.notify_waiters, 0, ret.notify_waiter_count * sizeof(jthread *)); | |||
1049 | ||||
1050 | if (ret.waiter_count > 0) { | |||
1051 | // we have contending and/or waiting threads | |||
1052 | if (nWant > 0) { | |||
1053 | // we have contending threads | |||
1054 | ResourceMark rm(current_thread); | |||
1055 | // get_pending_threads returns only java thread so we do not need to | |||
1056 | // check for non java threads. | |||
1057 | GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads(tlh.list(), nWant, (address)mon); | |||
1058 | if (wantList->length() < nWant) { | |||
1059 | // robustness: the pending list has gotten smaller | |||
1060 | nWant = wantList->length(); | |||
1061 | } | |||
1062 | for (int i = 0; i < nWant; i++) { | |||
1063 | JavaThread *pending_thread = wantList->at(i); | |||
1064 | Handle th(current_thread, pending_thread->threadObj()); | |||
1065 | ret.waiters[i] = (jthread)jni_reference(calling_thread, th); | |||
1066 | } | |||
1067 | } | |||
1068 | if (nWait > 0) { | |||
1069 | // we have threads in Object.wait() | |||
1070 | int offset = nWant; // add after any contending threads | |||
1071 | ObjectWaiter *waiter = mon->first_waiter(); | |||
1072 | for (int i = 0, j = 0; i < nWait; i++) { | |||
1073 | if (waiter == NULL__null) { | |||
1074 | // robustness: the waiting list has gotten smaller | |||
1075 | nWait = j; | |||
1076 | break; | |||
1077 | } | |||
1078 | JavaThread *w = mon->thread_of_waiter(waiter); | |||
1079 | if (w != NULL__null) { | |||
1080 | // If the thread was found on the ObjectWaiter list, then | |||
1081 | // it has not been notified. This thread can't change the | |||
1082 | // state of the monitor so it doesn't need to be suspended. | |||
1083 | Handle th(current_thread, w->threadObj()); | |||
1084 | ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th); | |||
1085 | ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th); | |||
1086 | } | |||
1087 | waiter = mon->next_waiter(waiter); | |||
1088 | } | |||
1089 | } | |||
1090 | } // ThreadsListHandle is destroyed here. | |||
1091 | ||||
1092 | // Adjust count. nWant and nWait count values may be less than original. | |||
1093 | ret.waiter_count = nWant + nWait; | |||
1094 | ret.notify_waiter_count = nWait; | |||
1095 | } else { | |||
1096 | // this object has a lightweight monitor and we have nothing more | |||
1097 | // to do here because the defaults are just fine. | |||
1098 | } | |||
1099 | ||||
1100 | // we don't update return parameter unless everything worked | |||
1101 | *info_ptr = ret; | |||
1102 | ||||
1103 | return JVMTI_ERROR_NONE; | |||
1104 | } | |||
1105 | ||||
1106 | ResourceTracker::ResourceTracker(JvmtiEnv* env) { | |||
1107 | _env = env; | |||
1108 | _allocations = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<unsigned char*>(20, mtServiceability); | |||
1109 | _failed = false; | |||
1110 | } | |||
1111 | ResourceTracker::~ResourceTracker() { | |||
1112 | if (_failed) { | |||
1113 | for (int i=0; i<_allocations->length(); i++) { | |||
1114 | _env->deallocate(_allocations->at(i)); | |||
1115 | } | |||
1116 | } | |||
1117 | delete _allocations; | |||
1118 | } | |||
1119 | ||||
1120 | jvmtiError ResourceTracker::allocate(jlong size, unsigned char** mem_ptr) { | |||
1121 | unsigned char *ptr; | |||
1122 | jvmtiError err = _env->allocate(size, &ptr); | |||
1123 | if (err == JVMTI_ERROR_NONE) { | |||
1124 | _allocations->append(ptr); | |||
1125 | *mem_ptr = ptr; | |||
1126 | } else { | |||
1127 | *mem_ptr = NULL__null; | |||
1128 | _failed = true; | |||
1129 | } | |||
1130 | return err; | |||
1131 | } | |||
1132 | ||||
1133 | unsigned char* ResourceTracker::allocate(jlong size) { | |||
1134 | unsigned char* ptr; | |||
1135 | allocate(size, &ptr); | |||
1136 | return ptr; | |||
1137 | } | |||
1138 | ||||
1139 | char* ResourceTracker::strdup(const char* str) { | |||
1140 | char *dup_str = (char*)allocate(strlen(str)+1); | |||
1141 | if (dup_str != NULL__null) { | |||
1142 | strcpy(dup_str, str); | |||
1143 | } | |||
1144 | return dup_str; | |||
1145 | } | |||
1146 | ||||
1147 | struct StackInfoNode { | |||
1148 | struct StackInfoNode *next; | |||
1149 | jvmtiStackInfo info; | |||
1150 | }; | |||
1151 | ||||
1152 | // Create a jvmtiStackInfo inside a linked list node and create a | |||
1153 | // buffer for the frame information, both allocated as resource objects. | |||
1154 | // Fill in both the jvmtiStackInfo and the jvmtiFrameInfo. | |||
1155 | // Note that either or both of thr and thread_oop | |||
1156 | // may be null if the thread is new or has exited. | |||
1157 | void | |||
1158 | MultipleStackTracesCollector::fill_frames(jthread jt, JavaThread *thr, oop thread_oop) { | |||
1159 | #ifdef ASSERT1 | |||
1160 | Thread *current_thread = Thread::current(); | |||
1161 | assert(SafepointSynchronize::is_at_safepoint() ||do { if (!(SafepointSynchronize::is_at_safepoint() || thr-> is_handshake_safe_for(current_thread))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1163, "assert(" "SafepointSynchronize::is_at_safepoint() || thr->is_handshake_safe_for(current_thread)" ") failed", "call by myself / at safepoint / at handshake"); ::breakpoint(); } } while (0) | |||
1162 | thr->is_handshake_safe_for(current_thread),do { if (!(SafepointSynchronize::is_at_safepoint() || thr-> is_handshake_safe_for(current_thread))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1163, "assert(" "SafepointSynchronize::is_at_safepoint() || thr->is_handshake_safe_for(current_thread)" ") failed", "call by myself / at safepoint / at handshake"); ::breakpoint(); } } while (0) | |||
1163 | "call by myself / at safepoint / at handshake")do { if (!(SafepointSynchronize::is_at_safepoint() || thr-> is_handshake_safe_for(current_thread))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1163, "assert(" "SafepointSynchronize::is_at_safepoint() || thr->is_handshake_safe_for(current_thread)" ") failed", "call by myself / at safepoint / at handshake"); ::breakpoint(); } } while (0); | |||
1164 | #endif | |||
1165 | ||||
1166 | jint state = 0; | |||
1167 | struct StackInfoNode *node = NEW_RESOURCE_OBJ(struct StackInfoNode)(struct StackInfoNode*) resource_allocate_bytes((1) * sizeof( struct StackInfoNode)); | |||
1168 | jvmtiStackInfo *infop = &(node->info); | |||
1169 | node->next = head(); | |||
1170 | set_head(node); | |||
1171 | infop->frame_count = 0; | |||
1172 | infop->thread = jt; | |||
1173 | ||||
1174 | if (thread_oop != NULL__null) { | |||
1175 | // get most state bits | |||
1176 | state = (jint)java_lang_Thread::get_thread_status(thread_oop); | |||
1177 | } | |||
1178 | ||||
1179 | if (thr != NULL__null) { // add more state bits if there is a JavaThead to query | |||
1180 | if (thr->is_suspended()) { | |||
1181 | state |= JVMTI_THREAD_STATE_SUSPENDED; | |||
1182 | } | |||
1183 | JavaThreadState jts = thr->thread_state(); | |||
1184 | if (jts == _thread_in_native) { | |||
1185 | state |= JVMTI_THREAD_STATE_IN_NATIVE; | |||
1186 | } | |||
1187 | if (thr->is_interrupted(false)) { | |||
1188 | state |= JVMTI_THREAD_STATE_INTERRUPTED; | |||
1189 | } | |||
1190 | } | |||
1191 | infop->state = state; | |||
1192 | ||||
1193 | if (thr != NULL__null && (state & JVMTI_THREAD_STATE_ALIVE) != 0) { | |||
1194 | infop->frame_buffer = NEW_RESOURCE_ARRAY(jvmtiFrameInfo, max_frame_count())(jvmtiFrameInfo*) resource_allocate_bytes((max_frame_count()) * sizeof(jvmtiFrameInfo)); | |||
1195 | env()->get_stack_trace(thr, 0, max_frame_count(), | |||
1196 | infop->frame_buffer, &(infop->frame_count)); | |||
1197 | } else { | |||
1198 | infop->frame_buffer = NULL__null; | |||
1199 | infop->frame_count = 0; | |||
1200 | } | |||
1201 | _frame_count_total += infop->frame_count; | |||
1202 | } | |||
1203 | ||||
1204 | // Based on the stack information in the linked list, allocate memory | |||
1205 | // block to return and fill it from the info in the linked list. | |||
1206 | void | |||
1207 | MultipleStackTracesCollector::allocate_and_fill_stacks(jint thread_count) { | |||
1208 | // do I need to worry about alignment issues? | |||
1209 | jlong alloc_size = thread_count * sizeof(jvmtiStackInfo) | |||
1210 | + _frame_count_total * sizeof(jvmtiFrameInfo); | |||
1211 | env()->allocate(alloc_size, (unsigned char **)&_stack_info); | |||
1212 | ||||
1213 | // pointers to move through the newly allocated space as it is filled in | |||
1214 | jvmtiStackInfo *si = _stack_info + thread_count; // bottom of stack info | |||
1215 | jvmtiFrameInfo *fi = (jvmtiFrameInfo *)si; // is the top of frame info | |||
1216 | ||||
1217 | // copy information in resource area into allocated buffer | |||
1218 | // insert stack info backwards since linked list is backwards | |||
1219 | // insert frame info forwards | |||
1220 | // walk the StackInfoNodes | |||
1221 | for (struct StackInfoNode *sin = head(); sin != NULL__null; sin = sin->next) { | |||
1222 | jint frame_count = sin->info.frame_count; | |||
1223 | size_t frames_size = frame_count * sizeof(jvmtiFrameInfo); | |||
1224 | --si; | |||
1225 | memcpy(si, &(sin->info), sizeof(jvmtiStackInfo)); | |||
| ||||
1226 | if (frames_size == 0) { | |||
1227 | si->frame_buffer = NULL__null; | |||
1228 | } else { | |||
1229 | memcpy(fi, sin->info.frame_buffer, frames_size); | |||
1230 | si->frame_buffer = fi; // point to the new allocated copy of the frames | |||
1231 | fi += frame_count; | |||
1232 | } | |||
1233 | } | |||
1234 | assert(si == _stack_info, "the last copied stack info must be the first record")do { if (!(si == _stack_info)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1234, "assert(" "si == _stack_info" ") failed", "the last copied stack info must be the first record" ); ::breakpoint(); } } while (0); | |||
1235 | assert((unsigned char *)fi == ((unsigned char *)_stack_info) + alloc_size,do { if (!((unsigned char *)fi == ((unsigned char *)_stack_info ) + alloc_size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1236, "assert(" "(unsigned char *)fi == ((unsigned char *)_stack_info) + alloc_size" ") failed", "the last copied frame info must be the last record" ); ::breakpoint(); } } while (0) | |||
1236 | "the last copied frame info must be the last record")do { if (!((unsigned char *)fi == ((unsigned char *)_stack_info ) + alloc_size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1236, "assert(" "(unsigned char *)fi == ((unsigned char *)_stack_info) + alloc_size" ") failed", "the last copied frame info must be the last record" ); ::breakpoint(); } } while (0); | |||
1237 | } | |||
1238 | ||||
1239 | ||||
1240 | void | |||
1241 | VM_GetThreadListStackTraces::doit() { | |||
1242 | assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1242, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "must be at safepoint"); ::breakpoint(); } } while (0); | |||
1243 | ||||
1244 | ResourceMark rm; | |||
1245 | ThreadsListHandle tlh; | |||
1246 | for (int i = 0; i < _thread_count; ++i) { | |||
1247 | jthread jt = _thread_list[i]; | |||
1248 | JavaThread* java_thread = NULL__null; | |||
1249 | oop thread_oop = NULL__null; | |||
1250 | jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), jt, &java_thread, &thread_oop); | |||
1251 | if (err != JVMTI_ERROR_NONE) { | |||
1252 | // We got an error code so we don't have a JavaThread *, but | |||
1253 | // only return an error from here if we didn't get a valid | |||
1254 | // thread_oop. | |||
1255 | if (thread_oop == NULL__null) { | |||
1256 | _collector.set_result(err); | |||
1257 | return; | |||
1258 | } | |||
1259 | // We have a valid thread_oop. | |||
1260 | } | |||
1261 | _collector.fill_frames(jt, java_thread, thread_oop); | |||
1262 | } | |||
1263 | _collector.allocate_and_fill_stacks(_thread_count); | |||
1264 | } | |||
1265 | ||||
1266 | void | |||
1267 | GetSingleStackTraceClosure::do_thread(Thread *target) { | |||
1268 | JavaThread *jt = JavaThread::cast(target); | |||
1269 | oop thread_oop = jt->threadObj(); | |||
1270 | ||||
1271 | if (!jt->is_exiting() && thread_oop != NULL__null) { | |||
1272 | ResourceMark rm; | |||
1273 | _collector.fill_frames(_jthread, jt, thread_oop); | |||
1274 | _collector.allocate_and_fill_stacks(1); | |||
1275 | } | |||
1276 | } | |||
1277 | ||||
1278 | void | |||
1279 | VM_GetAllStackTraces::doit() { | |||
1280 | assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1280, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed" , "must be at safepoint"); ::breakpoint(); } } while (0); | |||
| ||||
1281 | ||||
1282 | ResourceMark rm; | |||
1283 | _final_thread_count = 0; | |||
1284 | for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { | |||
1285 | oop thread_oop = jt->threadObj(); | |||
1286 | if (thread_oop != NULL__null && | |||
1287 | !jt->is_exiting() && | |||
1288 | java_lang_Thread::is_alive(thread_oop) && | |||
1289 | !jt->is_hidden_from_external_view()) { | |||
1290 | ++_final_thread_count; | |||
1291 | // Handle block of the calling thread is used to create local refs. | |||
1292 | _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), | |||
1293 | jt, thread_oop); | |||
1294 | } | |||
1295 | } | |||
1296 | _collector.allocate_and_fill_stacks(_final_thread_count); | |||
1297 | } | |||
1298 | ||||
1299 | // Verifies that the top frame is a java frame in an expected state. | |||
1300 | // Deoptimizes frame if needed. | |||
1301 | // Checks that the frame method signature matches the return type (tos). | |||
1302 | // HandleMark must be defined in the caller only. | |||
1303 | // It is to keep a ret_ob_h handle alive after return to the caller. | |||
1304 | jvmtiError | |||
1305 | JvmtiEnvBase::check_top_frame(Thread* current_thread, JavaThread* java_thread, | |||
1306 | jvalue value, TosState tos, Handle* ret_ob_h) { | |||
1307 | ResourceMark rm(current_thread); | |||
1308 | ||||
1309 | vframe *vf = vframeForNoProcess(java_thread, 0); | |||
1310 | NULL_CHECK(vf, JVMTI_ERROR_NO_MORE_FRAMES)if ((vf) == __null) { return (JVMTI_ERROR_NO_MORE_FRAMES); }; | |||
1311 | ||||
1312 | javaVFrame *jvf = (javaVFrame*) vf; | |||
1313 | if (!vf->is_java_frame() || jvf->method()->is_native()) { | |||
1314 | return JVMTI_ERROR_OPAQUE_FRAME; | |||
1315 | } | |||
1316 | ||||
1317 | // If the frame is a compiled one, need to deoptimize it. | |||
1318 | if (vf->is_compiled_frame()) { | |||
1319 | if (!vf->fr().can_be_deoptimized()) { | |||
1320 | return JVMTI_ERROR_OPAQUE_FRAME; | |||
1321 | } | |||
1322 | Deoptimization::deoptimize_frame(java_thread, jvf->fr().id()); | |||
1323 | } | |||
1324 | ||||
1325 | // Get information about method return type | |||
1326 | Symbol* signature = jvf->method()->signature(); | |||
1327 | ||||
1328 | ResultTypeFinder rtf(signature); | |||
1329 | TosState fr_tos = as_TosState(rtf.type()); | |||
1330 | if (fr_tos != tos) { | |||
1331 | if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) { | |||
1332 | return JVMTI_ERROR_TYPE_MISMATCH; | |||
1333 | } | |||
1334 | } | |||
1335 | ||||
1336 | // Check that the jobject class matches the return type signature. | |||
1337 | jobject jobj = value.l; | |||
1338 | if (tos == atos && jobj != NULL__null) { // NULL reference is allowed | |||
1339 | Handle ob_h(current_thread, JNIHandles::resolve_external_guard(jobj)); | |||
1340 | NULL_CHECK(ob_h, JVMTI_ERROR_INVALID_OBJECT)if ((ob_h) == __null) { return (JVMTI_ERROR_INVALID_OBJECT); }; | |||
1341 | Klass* ob_k = ob_h()->klass(); | |||
1342 | NULL_CHECK(ob_k, JVMTI_ERROR_INVALID_OBJECT)if ((ob_k) == __null) { return (JVMTI_ERROR_INVALID_OBJECT); }; | |||
1343 | ||||
1344 | // Method return type signature. | |||
1345 | char* ty_sign = 1 + strchr(signature->as_C_string(), JVM_SIGNATURE_ENDFUNC); | |||
1346 | ||||
1347 | if (!VM_GetOrSetLocal::is_assignable(ty_sign, ob_k, current_thread)) { | |||
1348 | return JVMTI_ERROR_TYPE_MISMATCH; | |||
1349 | } | |||
1350 | *ret_ob_h = ob_h; | |||
1351 | } | |||
1352 | return JVMTI_ERROR_NONE; | |||
1353 | } /* end check_top_frame */ | |||
1354 | ||||
1355 | ||||
1356 | // ForceEarlyReturn<type> follows the PopFrame approach in many aspects. | |||
1357 | // Main difference is on the last stage in the interpreter. | |||
1358 | // The PopFrame stops method execution to continue execution | |||
1359 | // from the same method call instruction. | |||
1360 | // The ForceEarlyReturn forces return from method so the execution | |||
1361 | // continues at the bytecode following the method call. | |||
1362 | ||||
1363 | // java_thread - protected by ThreadsListHandle and pre-checked | |||
1364 | ||||
1365 | jvmtiError | |||
1366 | JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState tos) { | |||
1367 | // retrieve or create the state | |||
1368 | JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); | |||
1369 | if (state == NULL__null) { | |||
1370 | return JVMTI_ERROR_THREAD_NOT_ALIVE; | |||
1371 | } | |||
1372 | ||||
1373 | // Eagerly reallocate scalar replaced objects. | |||
1374 | JavaThread* current_thread = JavaThread::current(); | |||
1375 | EscapeBarrier eb(true, current_thread, java_thread); | |||
1376 | if (!eb.deoptimize_objects(0)) { | |||
1377 | // Reallocation of scalar replaced objects failed -> return with error | |||
1378 | return JVMTI_ERROR_OUT_OF_MEMORY; | |||
1379 | } | |||
1380 | ||||
1381 | SetForceEarlyReturn op(state, value, tos); | |||
1382 | if (java_thread == current_thread) { | |||
1383 | op.doit(java_thread, true /* self */); | |||
1384 | } else { | |||
1385 | Handshake::execute(&op, java_thread); | |||
1386 | } | |||
1387 | return op.result(); | |||
1388 | } | |||
1389 | ||||
1390 | void | |||
1391 | SetForceEarlyReturn::doit(Thread *target, bool self) { | |||
1392 | JavaThread* java_thread = JavaThread::cast(target); | |||
1393 | Thread* current_thread = Thread::current(); | |||
1394 | HandleMark hm(current_thread); | |||
1395 | ||||
1396 | if (java_thread->is_exiting()) { | |||
1397 | return; /* JVMTI_ERROR_THREAD_NOT_ALIVE (default) */ | |||
1398 | } | |||
1399 | if (!self) { | |||
1400 | if (!java_thread->is_suspended()) { | |||
1401 | _result = JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |||
1402 | return; | |||
1403 | } | |||
1404 | } | |||
1405 | ||||
1406 | // Check to see if a ForceEarlyReturn was already in progress | |||
1407 | if (_state->is_earlyret_pending()) { | |||
1408 | // Probably possible for JVMTI clients to trigger this, but the | |||
1409 | // JPDA backend shouldn't allow this to happen | |||
1410 | _result = JVMTI_ERROR_INTERNAL; | |||
1411 | return; | |||
1412 | } | |||
1413 | { | |||
1414 | // The same as for PopFrame. Workaround bug: | |||
1415 | // 4812902: popFrame hangs if the method is waiting at a synchronize | |||
1416 | // Catch this condition and return an error to avoid hanging. | |||
1417 | // Now JVMTI spec allows an implementation to bail out with an opaque | |||
1418 | // frame error. | |||
1419 | OSThread* osThread = java_thread->osthread(); | |||
1420 | if (osThread->get_state() == MONITOR_WAIT) { | |||
1421 | _result = JVMTI_ERROR_OPAQUE_FRAME; | |||
1422 | return; | |||
1423 | } | |||
1424 | } | |||
1425 | ||||
1426 | Handle ret_ob_h; | |||
1427 | _result = JvmtiEnvBase::check_top_frame(current_thread, java_thread, _value, _tos, &ret_ob_h); | |||
1428 | if (_result != JVMTI_ERROR_NONE) { | |||
1429 | return; | |||
1430 | } | |||
1431 | assert(_tos != atos || _value.l == NULL || ret_ob_h() != NULL,do { if (!(_tos != atos || _value.l == __null || ret_ob_h() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1432, "assert(" "_tos != atos || _value.l == __null || ret_ob_h() != __null" ") failed", "return object oop must not be NULL if jobject is not NULL" ); ::breakpoint(); } } while (0) | |||
1432 | "return object oop must not be NULL if jobject is not NULL")do { if (!(_tos != atos || _value.l == __null || ret_ob_h() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1432, "assert(" "_tos != atos || _value.l == __null || ret_ob_h() != __null" ") failed", "return object oop must not be NULL if jobject is not NULL" ); ::breakpoint(); } } while (0); | |||
1433 | ||||
1434 | // Update the thread state to reflect that the top frame must be | |||
1435 | // forced to return. | |||
1436 | // The current frame will be returned later when the suspended | |||
1437 | // thread is resumed and right before returning from VM to Java. | |||
1438 | // (see call_VM_base() in assembler_<cpu>.cpp). | |||
1439 | ||||
1440 | _state->set_earlyret_pending(); | |||
1441 | _state->set_earlyret_oop(ret_ob_h()); | |||
1442 | _state->set_earlyret_value(_value, _tos); | |||
1443 | ||||
1444 | // Set pending step flag for this early return. | |||
1445 | // It is cleared when next step event is posted. | |||
1446 | _state->set_pending_step_for_earlyret(); | |||
1447 | } | |||
1448 | ||||
1449 | void | |||
1450 | JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { | |||
1451 | if ( _error != JVMTI_ERROR_NONE) { | |||
1452 | // Error occurred in previous iteration so no need to add | |||
1453 | // to the list. | |||
1454 | return; | |||
1455 | } | |||
1456 | // Filter out on stack monitors collected during stack walk. | |||
1457 | oop obj = mon->object(); | |||
1458 | bool found = false; | |||
1459 | for (int j = 0; j < _owned_monitors_list->length(); j++) { | |||
1460 | jobject jobj = ((jvmtiMonitorStackDepthInfo*)_owned_monitors_list->at(j))->monitor; | |||
1461 | oop check = JNIHandles::resolve(jobj); | |||
1462 | if (check == obj) { | |||
1463 | // On stack monitor already collected during the stack walk. | |||
1464 | found = true; | |||
1465 | break; | |||
1466 | } | |||
1467 | } | |||
1468 | if (found == false) { | |||
1469 | // This is off stack monitor (e.g. acquired via jni MonitorEnter). | |||
1470 | jvmtiError err; | |||
1471 | jvmtiMonitorStackDepthInfo *jmsdi; | |||
1472 | err = _env->allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi); | |||
1473 | if (err != JVMTI_ERROR_NONE) { | |||
1474 | _error = err; | |||
1475 | return; | |||
1476 | } | |||
1477 | Handle hobj(Thread::current(), obj); | |||
1478 | jmsdi->monitor = _env->jni_reference(_calling_thread, hobj); | |||
1479 | // stack depth is unknown for this monitor. | |||
1480 | jmsdi->stack_depth = -1; | |||
1481 | _owned_monitors_list->append(jmsdi); | |||
1482 | } | |||
1483 | } | |||
1484 | ||||
1485 | GrowableArray<OopHandle>* JvmtiModuleClosure::_tbl = NULL__null; | |||
1486 | ||||
1487 | void JvmtiModuleClosure::do_module(ModuleEntry* entry) { | |||
1488 | assert_locked_or_safepoint(Module_lock); | |||
1489 | OopHandle module = entry->module_handle(); | |||
1490 | guarantee(module.resolve() != NULL, "module object is NULL")do { if (!(module.resolve() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1490, "guarantee(" "module.resolve() != NULL" ") failed", "module object is NULL" ); ::breakpoint(); } } while (0); | |||
1491 | _tbl->push(module); | |||
1492 | } | |||
1493 | ||||
1494 | jvmtiError | |||
1495 | JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) { | |||
1496 | ResourceMark rm; | |||
1497 | MutexLocker mcld(ClassLoaderDataGraph_lock); | |||
1498 | MutexLocker ml(Module_lock); | |||
1499 | ||||
1500 | _tbl = new GrowableArray<OopHandle>(77); | |||
1501 | if (_tbl == NULL__null) { | |||
1502 | return JVMTI_ERROR_OUT_OF_MEMORY; | |||
1503 | } | |||
1504 | ||||
1505 | // Iterate over all the modules loaded to the system. | |||
1506 | ClassLoaderDataGraph::modules_do(&do_module); | |||
1507 | ||||
1508 | jint len = _tbl->length(); | |||
1509 | guarantee(len > 0, "at least one module must be present")do { if (!(len > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1509, "guarantee(" "len > 0" ") failed", "at least one module must be present" ); ::breakpoint(); } } while (0); | |||
1510 | ||||
1511 | jobject* array = (jobject*)env->jvmtiMalloc((jlong)(len * sizeof(jobject))); | |||
1512 | if (array == NULL__null) { | |||
1513 | return JVMTI_ERROR_OUT_OF_MEMORY; | |||
1514 | } | |||
1515 | for (jint idx = 0; idx < len; idx++) { | |||
1516 | array[idx] = JNIHandles::make_local(_tbl->at(idx).resolve()); | |||
1517 | } | |||
1518 | _tbl = NULL__null; | |||
1519 | *modules_ptr = array; | |||
1520 | *module_count_ptr = len; | |||
1521 | return JVMTI_ERROR_NONE; | |||
1522 | } | |||
1523 | ||||
1524 | void | |||
1525 | UpdateForPopTopFrameClosure::doit(Thread *target, bool self) { | |||
1526 | Thread* current_thread = Thread::current(); | |||
1527 | HandleMark hm(current_thread); | |||
1528 | JavaThread* java_thread = JavaThread::cast(target); | |||
1529 | ||||
1530 | if (java_thread->is_exiting()) { | |||
1531 | return; /* JVMTI_ERROR_THREAD_NOT_ALIVE (default) */ | |||
1532 | } | |||
1533 | assert(java_thread == _state->get_thread(), "Must be")do { if (!(java_thread == _state->get_thread())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1533, "assert(" "java_thread == _state->get_thread()" ") failed" , "Must be"); ::breakpoint(); } } while (0); | |||
1534 | ||||
1535 | if (!self && !java_thread->is_suspended()) { | |||
1536 | _result = JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |||
1537 | return; | |||
1538 | } | |||
1539 | ||||
1540 | // Check to see if a PopFrame was already in progress | |||
1541 | if (java_thread->popframe_condition() != JavaThread::popframe_inactive) { | |||
1542 | // Probably possible for JVMTI clients to trigger this, but the | |||
1543 | // JPDA backend shouldn't allow this to happen | |||
1544 | _result = JVMTI_ERROR_INTERNAL; | |||
1545 | return; | |||
1546 | } | |||
1547 | ||||
1548 | // Was workaround bug | |||
1549 | // 4812902: popFrame hangs if the method is waiting at a synchronize | |||
1550 | // Catch this condition and return an error to avoid hanging. | |||
1551 | // Now JVMTI spec allows an implementation to bail out with an opaque frame error. | |||
1552 | OSThread* osThread = java_thread->osthread(); | |||
1553 | if (osThread->get_state() == MONITOR_WAIT) { | |||
1554 | _result = JVMTI_ERROR_OPAQUE_FRAME; | |||
1555 | return; | |||
1556 | } | |||
1557 | ||||
1558 | ResourceMark rm(current_thread); | |||
1559 | // Check if there is more than one Java frame in this thread, that the top two frames | |||
1560 | // are Java (not native) frames, and that there is no intervening VM frame | |||
1561 | int frame_count = 0; | |||
1562 | bool is_interpreted[2]; | |||
1563 | intptr_t *frame_sp[2]; | |||
1564 | // The 2-nd arg of constructor is needed to stop iterating at java entry frame. | |||
1565 | for (vframeStream vfs(java_thread, true, false /* process_frames */); !vfs.at_end(); vfs.next()) { | |||
1566 | methodHandle mh(current_thread, vfs.method()); | |||
1567 | if (mh->is_native()) { | |||
1568 | _result = JVMTI_ERROR_OPAQUE_FRAME; | |||
1569 | return; | |||
1570 | } | |||
1571 | is_interpreted[frame_count] = vfs.is_interpreted_frame(); | |||
1572 | frame_sp[frame_count] = vfs.frame_id(); | |||
1573 | if (++frame_count > 1) break; | |||
1574 | } | |||
1575 | if (frame_count < 2) { | |||
1576 | // We haven't found two adjacent non-native Java frames on the top. | |||
1577 | // There can be two situations here: | |||
1578 | // 1. There are no more java frames | |||
1579 | // 2. Two top java frames are separated by non-java native frames | |||
1580 | if(JvmtiEnvBase::vframeForNoProcess(java_thread, 1) == NULL__null) { | |||
1581 | _result = JVMTI_ERROR_NO_MORE_FRAMES; | |||
1582 | return; | |||
1583 | } else { | |||
1584 | // Intervening non-java native or VM frames separate java frames. | |||
1585 | // Current implementation does not support this. See bug #5031735. | |||
1586 | // In theory it is possible to pop frames in such cases. | |||
1587 | _result = JVMTI_ERROR_OPAQUE_FRAME; | |||
1588 | return; | |||
1589 | } | |||
1590 | } | |||
1591 | ||||
1592 | // If any of the top 2 frames is a compiled one, need to deoptimize it | |||
1593 | for (int i = 0; i < 2; i++) { | |||
1594 | if (!is_interpreted[i]) { | |||
1595 | Deoptimization::deoptimize_frame(java_thread, frame_sp[i]); | |||
1596 | } | |||
1597 | } | |||
1598 | ||||
1599 | // Update the thread state to reflect that the top frame is popped | |||
1600 | // so that cur_stack_depth is maintained properly and all frameIDs | |||
1601 | // are invalidated. | |||
1602 | // The current frame will be popped later when the suspended thread | |||
1603 | // is resumed and right before returning from VM to Java. | |||
1604 | // (see call_VM_base() in assembler_<cpu>.cpp). | |||
1605 | ||||
1606 | // It's fine to update the thread state here because no JVMTI events | |||
1607 | // shall be posted for this PopFrame. | |||
1608 | ||||
1609 | _state->update_for_pop_top_frame(); | |||
1610 | java_thread->set_popframe_condition(JavaThread::popframe_pending_bit); | |||
1611 | // Set pending step flag for this popframe and it is cleared when next | |||
1612 | // step event is posted. | |||
1613 | _state->set_pending_step_for_popframe(); | |||
1614 | _result = JVMTI_ERROR_NONE; | |||
1615 | } | |||
1616 | ||||
1617 | void | |||
1618 | SetFramePopClosure::doit(Thread *target, bool self) { | |||
1619 | ResourceMark rm; | |||
1620 | JavaThread* java_thread = JavaThread::cast(target); | |||
1621 | ||||
1622 | if (java_thread->is_exiting()) { | |||
1623 | return; /* JVMTI_ERROR_THREAD_NOT_ALIVE (default) */ | |||
1624 | } | |||
1625 | assert(_state->get_thread() == java_thread, "Must be")do { if (!(_state->get_thread() == java_thread)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1625, "assert(" "_state->get_thread() == java_thread" ") failed" , "Must be"); ::breakpoint(); } } while (0); | |||
1626 | ||||
1627 | if (!self && !java_thread->is_suspended()) { | |||
1628 | _result = JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |||
1629 | return; | |||
1630 | } | |||
1631 | ||||
1632 | vframe *vf = JvmtiEnvBase::vframeForNoProcess(java_thread, _depth); | |||
1633 | if (vf == NULL__null) { | |||
1634 | _result = JVMTI_ERROR_NO_MORE_FRAMES; | |||
1635 | return; | |||
1636 | } | |||
1637 | ||||
1638 | if (!vf->is_java_frame() || ((javaVFrame*) vf)->method()->is_native()) { | |||
1639 | _result = JVMTI_ERROR_OPAQUE_FRAME; | |||
1640 | return; | |||
1641 | } | |||
1642 | ||||
1643 | assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL")do { if (!(vf->frame_pointer() != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1643, "assert(" "vf->frame_pointer() != __null" ") failed" , "frame pointer mustn't be NULL"); ::breakpoint(); } } while (0); | |||
1644 | int frame_number = _state->count_frames() - _depth; | |||
1645 | _state->env_thread_state((JvmtiEnvBase*)_env)->set_frame_pop(frame_number); | |||
1646 | _result = JVMTI_ERROR_NONE; | |||
1647 | } | |||
1648 | ||||
1649 | void | |||
1650 | GetOwnedMonitorInfoClosure::do_thread(Thread *target) { | |||
1651 | JavaThread *jt = JavaThread::cast(target); | |||
1652 | if (!jt->is_exiting() && (jt->threadObj() != NULL__null)) { | |||
1653 | _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, | |||
1654 | jt, | |||
1655 | _owned_monitors_list); | |||
1656 | } | |||
1657 | } | |||
1658 | ||||
1659 | void | |||
1660 | GetCurrentContendedMonitorClosure::do_thread(Thread *target) { | |||
1661 | JavaThread *jt = JavaThread::cast(target); | |||
1662 | if (!jt->is_exiting() && (jt->threadObj() != NULL__null)) { | |||
1663 | _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread, | |||
1664 | jt, | |||
1665 | _owned_monitor_ptr); | |||
1666 | } | |||
1667 | } | |||
1668 | ||||
1669 | void | |||
1670 | GetStackTraceClosure::do_thread(Thread *target) { | |||
1671 | JavaThread *jt = JavaThread::cast(target); | |||
1672 | if (!jt->is_exiting() && jt->threadObj() != NULL__null) { | |||
1673 | _result = ((JvmtiEnvBase *)_env)->get_stack_trace(jt, | |||
1674 | _start_depth, _max_count, | |||
1675 | _frame_buffer, _count_ptr); | |||
1676 | } | |||
1677 | } | |||
1678 | ||||
1679 | void | |||
1680 | GetFrameCountClosure::do_thread(Thread *target) { | |||
1681 | JavaThread* jt = _state->get_thread(); | |||
1682 | assert(target == jt, "just checking")do { if (!(target == jt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/prims/jvmtiEnvBase.cpp" , 1682, "assert(" "target == jt" ") failed", "just checking") ; ::breakpoint(); } } while (0); | |||
1683 | if (!jt->is_exiting() && jt->threadObj() != NULL__null) { | |||
1684 | _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); | |||
1685 | } | |||
1686 | } | |||
1687 | ||||
1688 | void | |||
1689 | GetFrameLocationClosure::do_thread(Thread *target) { | |||
1690 | JavaThread *jt = JavaThread::cast(target); | |||
1691 | if (!jt->is_exiting() && jt->threadObj() != NULL__null) { | |||
1692 | _result = ((JvmtiEnvBase*)_env)->get_frame_location(jt, _depth, | |||
1693 | _method_ptr, _location_ptr); | |||
1694 | } | |||
1695 | } |