Mercurial > hg > graal-compiler
annotate src/share/vm/prims/jvmtiEnvBase.hpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | e6b1331a51d2 |
children | d2a62e0f25eb |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1122
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1122
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1122
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_PRIMS_JVMTIENVBASE_HPP |
26 #define SHARE_VM_PRIMS_JVMTIENVBASE_HPP | |
27 | |
28 #include "classfile/classLoader.hpp" | |
29 #include "prims/jvmtiEnvThreadState.hpp" | |
30 #include "prims/jvmtiEventController.hpp" | |
31 #include "prims/jvmtiThreadState.hpp" | |
32 #include "runtime/fieldDescriptor.hpp" | |
33 #include "runtime/frame.hpp" | |
34 #include "runtime/handles.inline.hpp" | |
35 #include "runtime/thread.hpp" | |
36 #include "runtime/vm_operations.hpp" | |
37 #include "utilities/growableArray.hpp" | |
0 | 38 |
39 // | |
40 // Forward Declarations | |
41 // | |
42 | |
43 class JvmtiEnv; | |
44 class JvmtiThreadState; | |
45 class JvmtiRawMonitor; // for jvmtiEnv.hpp | |
46 class JvmtiEventControllerPrivate; | |
47 class JvmtiTagMap; | |
48 | |
49 | |
50 | |
51 // One JvmtiEnv object is created per jvmti attachment; | |
52 // done via JNI GetEnv() call. Multiple attachments are | |
53 // allowed in jvmti. | |
54 | |
55 class JvmtiEnvBase : public CHeapObj { | |
56 | |
57 private: | |
58 | |
59 static JvmtiEnvBase* _head_environment; // head of environment list | |
60 | |
61 static bool _globally_initialized; | |
62 static jvmtiPhase _phase; | |
63 static volatile int _dying_thread_env_iteration_count; | |
64 | |
65 public: | |
66 | |
67 enum { | |
68 JDK15_JVMTI_VERSION = JVMTI_VERSION_1_0 + 33, /* version: 1.0.33 */ | |
1988 | 69 JDK16_JVMTI_VERSION = JVMTI_VERSION_1_1 + 102, /* version: 1.1.102 */ |
70 JDK17_JVMTI_VERSION = JVMTI_VERSION_1_2 + 1 /* version: 1.2.1 */ | |
0 | 71 }; |
72 | |
73 static jvmtiPhase get_phase() { return _phase; } | |
74 static void set_phase(jvmtiPhase phase) { _phase = phase; } | |
75 static bool is_vm_live() { return _phase == JVMTI_PHASE_LIVE; } | |
76 | |
77 static void entering_dying_thread_env_iteration() { ++_dying_thread_env_iteration_count; } | |
78 static void leaving_dying_thread_env_iteration() { --_dying_thread_env_iteration_count; } | |
79 static bool is_inside_dying_thread_env_iteration(){ return _dying_thread_env_iteration_count > 0; } | |
80 | |
81 private: | |
82 | |
83 enum { | |
84 JVMTI_MAGIC = 0x71EE, | |
85 DISPOSED_MAGIC = 0xDEFC, | |
86 BAD_MAGIC = 0xDEAD | |
87 }; | |
88 | |
89 jvmtiEnv _jvmti_external; | |
90 jint _magic; | |
1121 | 91 jint _version; // version value passed to JNI GetEnv() |
0 | 92 JvmtiEnvBase* _next; |
93 bool _is_retransformable; | |
94 const void *_env_local_storage; // per env agent allocated data. | |
95 jvmtiEventCallbacks _event_callbacks; | |
96 jvmtiExtEventCallbacks _ext_event_callbacks; | |
97 JvmtiTagMap* _tag_map; | |
98 JvmtiEnvEventEnable _env_event_enable; | |
99 jvmtiCapabilities _current_capabilities; | |
100 jvmtiCapabilities _prohibited_capabilities; | |
101 volatile bool _class_file_load_hook_ever_enabled; | |
102 static volatile bool _needs_clean_up; | |
103 char** _native_method_prefixes; | |
104 int _native_method_prefix_count; | |
105 | |
106 protected: | |
1121 | 107 JvmtiEnvBase(jint version); |
0 | 108 ~JvmtiEnvBase(); |
109 void dispose(); | |
110 void env_dispose(); | |
111 | |
112 void set_env_local_storage(const void* data) { _env_local_storage = data; } | |
113 const void* get_env_local_storage() { return _env_local_storage; } | |
114 | |
115 void record_class_file_load_hook_enabled(); | |
116 void record_first_time_class_file_load_hook_enabled(); | |
117 | |
118 char** get_native_method_prefixes() { return _native_method_prefixes; } | |
119 int get_native_method_prefix_count() { return _native_method_prefix_count; } | |
120 jvmtiError set_native_method_prefixes(jint prefix_count, char** prefixes); | |
121 | |
122 private: | |
123 friend class JvmtiEventControllerPrivate; | |
124 void initialize(); | |
125 void set_event_callbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks); | |
126 static void globally_initialize(); | |
127 static void periodic_clean_up(); | |
128 | |
129 friend class JvmtiEnvIterator; | |
130 JvmtiEnv* next_environment() { return (JvmtiEnv*)_next; } | |
131 void set_next_environment(JvmtiEnvBase* env) { _next = env; } | |
132 static JvmtiEnv* head_environment() { return (JvmtiEnv*)_head_environment; } | |
133 | |
134 public: | |
135 | |
611
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
0
diff
changeset
|
136 bool is_valid(); |
0 | 137 |
1121 | 138 bool use_version_1_0_semantics(); // agent asked for version 1.0 |
139 bool use_version_1_1_semantics(); // agent asked for version 1.1 | |
1988 | 140 bool use_version_1_2_semantics(); // agent asked for version 1.2 |
1121 | 141 |
0 | 142 bool is_retransformable() { return _is_retransformable; } |
143 | |
144 static ByteSize jvmti_external_offset() { | |
145 return byte_offset_of(JvmtiEnvBase, _jvmti_external); | |
146 }; | |
147 | |
148 static JvmtiEnv* JvmtiEnv_from_jvmti_env(jvmtiEnv *env) { | |
149 return (JvmtiEnv*)((intptr_t)env - in_bytes(jvmti_external_offset())); | |
150 }; | |
151 | |
152 jvmtiCapabilities *get_capabilities() { return &_current_capabilities; } | |
153 | |
154 jvmtiCapabilities *get_prohibited_capabilities() { return &_prohibited_capabilities; } | |
155 | |
156 static char** get_all_native_method_prefixes(int* count_ptr); | |
157 | |
158 // This test will answer true when all environments have been disposed and some have | |
159 // not yet been deallocated. As a result, this test should only be used as an | |
160 // optimization for the no environment case. | |
161 static bool environments_might_exist() { | |
162 return head_environment() != NULL; | |
163 } | |
164 | |
165 static void check_for_periodic_clean_up(); | |
166 | |
167 JvmtiEnvEventEnable *env_event_enable() { | |
168 return &_env_event_enable; | |
169 } | |
170 | |
171 jvmtiError allocate(jlong size, unsigned char** mem_ptr) { | |
172 if (size < 0) { | |
173 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
174 } | |
175 if (size == 0) { | |
176 *mem_ptr = NULL; | |
177 } else { | |
178 *mem_ptr = (unsigned char *)os::malloc((size_t)size); | |
179 if (*mem_ptr == NULL) { | |
180 return JVMTI_ERROR_OUT_OF_MEMORY; | |
181 } | |
182 } | |
183 return JVMTI_ERROR_NONE; | |
184 } | |
185 | |
186 jvmtiError deallocate(unsigned char* mem) { | |
187 if (mem != NULL) { | |
188 os::free(mem); | |
189 } | |
190 return JVMTI_ERROR_NONE; | |
191 } | |
192 | |
193 | |
194 // Memory functions | |
195 unsigned char* jvmtiMalloc(jlong size); // don't use this - call allocate | |
196 | |
197 // method to create a local handle | |
198 jobject jni_reference(Handle hndl) { | |
199 return JNIHandles::make_local(hndl()); | |
200 } | |
201 | |
202 // method to create a local handle. | |
203 // This function allows caller to specify which | |
204 // threads local handle table to use. | |
205 jobject jni_reference(JavaThread *thread, Handle hndl) { | |
206 return JNIHandles::make_local(thread, hndl()); | |
207 } | |
208 | |
209 // method to destroy a local handle | |
210 void destroy_jni_reference(jobject jobj) { | |
211 JNIHandles::destroy_local(jobj); | |
212 } | |
213 | |
214 // method to destroy a local handle. | |
215 // This function allows caller to specify which | |
216 // threads local handle table to use although currently it is | |
217 // not used. | |
218 void destroy_jni_reference(JavaThread *thread, jobject jobj) { | |
219 destroy_jni_reference(jobj); | |
220 } | |
221 | |
222 jvmtiEnv* jvmti_external() { return &_jvmti_external; }; | |
223 | |
224 // Event Dispatch | |
225 | |
226 bool has_callback(jvmtiEvent event_type) { | |
227 assert(event_type >= JVMTI_MIN_EVENT_TYPE_VAL && | |
228 event_type <= JVMTI_MAX_EVENT_TYPE_VAL, "checking"); | |
229 return ((void**)&_event_callbacks)[event_type-JVMTI_MIN_EVENT_TYPE_VAL] != NULL; | |
230 } | |
231 | |
232 jvmtiEventCallbacks* callbacks() { | |
233 return &_event_callbacks; | |
234 } | |
235 | |
236 jvmtiExtEventCallbacks* ext_callbacks() { | |
237 return &_ext_event_callbacks; | |
238 } | |
239 | |
240 void set_tag_map(JvmtiTagMap* tag_map) { | |
241 _tag_map = tag_map; | |
242 } | |
243 | |
244 JvmtiTagMap* tag_map() { | |
245 return _tag_map; | |
246 } | |
247 | |
248 | |
249 // return true if event is enabled globally or for any thread | |
250 // True only if there is a callback for it. | |
251 bool is_enabled(jvmtiEvent event_type) { | |
252 return _env_event_enable.is_enabled(event_type); | |
253 } | |
254 | |
255 // Random Utilities | |
256 | |
257 protected: | |
258 // helper methods for creating arrays of global JNI Handles from local Handles | |
259 // allocated into environment specific storage | |
260 jobject * new_jobjectArray(int length, Handle *handles); | |
261 jthread * new_jthreadArray(int length, Handle *handles); | |
262 jthreadGroup * new_jthreadGroupArray(int length, Handle *handles); | |
263 | |
264 // convert from JNIHandle to JavaThread * | |
265 JavaThread * get_JavaThread(jthread jni_thread); | |
266 | |
267 // convert to a jni jclass from a non-null klassOop | |
268 jclass get_jni_class_non_null(klassOop k); | |
269 | |
270 jint count_locked_objects(JavaThread *java_thread, Handle hobj); | |
271 jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread, | |
272 JavaThread* java_thread, | |
273 javaVFrame *jvf, | |
274 GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, | |
275 jint depth); | |
276 vframe* vframeFor(JavaThread* java_thread, jint depth); | |
277 | |
278 public: | |
279 // get a field descriptor for the specified class and field | |
280 static bool get_field_descriptor(klassOop k, jfieldID field, fieldDescriptor* fd); | |
281 // test for suspend - most (all?) of these should go away | |
282 static bool is_thread_fully_suspended(JavaThread *thread, | |
283 bool wait_for_suspend, | |
284 uint32_t *bits); | |
285 | |
286 | |
287 // JVMTI API helper functions which are called at safepoint or thread is suspended. | |
288 jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr); | |
289 jvmtiError get_frame_location(JavaThread* java_thread, jint depth, | |
290 jmethodID* method_ptr, jlocation* location_ptr); | |
291 jvmtiError get_object_monitor_usage(JavaThread *calling_thread, | |
292 jobject object, jvmtiMonitorUsage* info_ptr); | |
293 jvmtiError get_stack_trace(JavaThread *java_thread, | |
294 jint stack_depth, jint max_count, | |
295 jvmtiFrameInfo* frame_buffer, jint* count_ptr); | |
296 jvmtiError get_current_contended_monitor(JavaThread *calling_thread, | |
297 JavaThread *java_thread, | |
298 jobject *monitor_ptr); | |
299 jvmtiError get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread, | |
300 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list); | |
301 jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread, | |
302 jvalue value, TosState tos, Handle* ret_ob_h); | |
303 jvmtiError force_early_return(JavaThread* java_thread, jvalue value, TosState tos); | |
304 }; | |
305 | |
306 // This class is the only safe means of iterating through environments. | |
307 // Note that this iteratation includes invalid environments pending | |
308 // deallocation -- in fact, some uses depend on this behavior. | |
309 | |
310 class JvmtiEnvIterator : public StackObj { | |
311 private: | |
312 bool _entry_was_marked; | |
313 public: | |
314 JvmtiEnvIterator() { | |
315 if (Threads::number_of_threads() == 0) { | |
316 _entry_was_marked = false; // we are single-threaded, no need | |
317 } else { | |
318 Thread::current()->entering_jvmti_env_iteration(); | |
319 _entry_was_marked = true; | |
320 } | |
321 } | |
322 ~JvmtiEnvIterator() { | |
323 if (_entry_was_marked) { | |
324 Thread::current()->leaving_jvmti_env_iteration(); | |
325 } | |
326 } | |
327 JvmtiEnv* first() { return JvmtiEnvBase::head_environment(); } | |
328 JvmtiEnv* next(JvmtiEnvBase* env) { return env->next_environment(); } | |
329 }; | |
330 | |
331 | |
332 // VM operation to get monitor information with stack depth. | |
333 class VM_GetOwnedMonitorInfo : public VM_Operation { | |
334 private: | |
335 JvmtiEnv *_env; | |
336 JavaThread* _calling_thread; | |
337 JavaThread *_java_thread; | |
338 jvmtiError _result; | |
339 GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list; | |
340 | |
341 public: | |
342 VM_GetOwnedMonitorInfo(JvmtiEnv* env, JavaThread* calling_thread, | |
343 JavaThread* java_thread, | |
344 GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list) { | |
345 _env = env; | |
346 _calling_thread = calling_thread; | |
347 _java_thread = java_thread; | |
348 _owned_monitors_list = owned_monitor_list; | |
349 _result = JVMTI_ERROR_NONE; | |
350 } | |
351 VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; } | |
352 void doit() { | |
353 ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, | |
354 _owned_monitors_list); | |
355 } | |
356 jvmtiError result() { return _result; } | |
357 }; | |
358 | |
359 | |
360 // VM operation to get object monitor usage. | |
361 class VM_GetObjectMonitorUsage : public VM_Operation { | |
362 private: | |
363 JvmtiEnv *_env; | |
364 jobject _object; | |
365 JavaThread* _calling_thread; | |
366 jvmtiMonitorUsage* _info_ptr; | |
367 jvmtiError _result; | |
368 | |
369 public: | |
370 VM_GetObjectMonitorUsage(JvmtiEnv *env, JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { | |
371 _env = env; | |
372 _object = object; | |
373 _calling_thread = calling_thread; | |
374 _info_ptr = info_ptr; | |
375 } | |
376 VMOp_Type type() const { return VMOp_GetObjectMonitorUsage; } | |
377 jvmtiError result() { return _result; } | |
378 void doit() { | |
379 _result = ((JvmtiEnvBase*) _env)->get_object_monitor_usage(_calling_thread, _object, _info_ptr); | |
380 } | |
381 | |
382 }; | |
383 | |
384 // VM operation to get current contended monitor. | |
385 class VM_GetCurrentContendedMonitor : public VM_Operation { | |
386 private: | |
387 JvmtiEnv *_env; | |
388 JavaThread *_calling_thread; | |
389 JavaThread *_java_thread; | |
390 jobject *_owned_monitor_ptr; | |
391 jvmtiError _result; | |
392 | |
393 public: | |
394 VM_GetCurrentContendedMonitor(JvmtiEnv *env, JavaThread *calling_thread, JavaThread *java_thread, jobject *mon_ptr) { | |
395 _env = env; | |
396 _calling_thread = calling_thread; | |
397 _java_thread = java_thread; | |
398 _owned_monitor_ptr = mon_ptr; | |
399 } | |
400 VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; } | |
401 jvmtiError result() { return _result; } | |
402 void doit() { | |
403 _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); | |
404 } | |
405 }; | |
406 | |
407 // VM operation to get stack trace at safepoint. | |
408 class VM_GetStackTrace : public VM_Operation { | |
409 private: | |
410 JvmtiEnv *_env; | |
411 JavaThread *_java_thread; | |
412 jint _start_depth; | |
413 jint _max_count; | |
414 jvmtiFrameInfo *_frame_buffer; | |
415 jint *_count_ptr; | |
416 jvmtiError _result; | |
417 | |
418 public: | |
419 VM_GetStackTrace(JvmtiEnv *env, JavaThread *java_thread, | |
420 jint start_depth, jint max_count, | |
421 jvmtiFrameInfo* frame_buffer, jint* count_ptr) { | |
422 _env = env; | |
423 _java_thread = java_thread; | |
424 _start_depth = start_depth; | |
425 _max_count = max_count; | |
426 _frame_buffer = frame_buffer; | |
427 _count_ptr = count_ptr; | |
428 } | |
429 jvmtiError result() { return _result; } | |
430 VMOp_Type type() const { return VMOp_GetStackTrace; } | |
431 void doit() { | |
432 _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, | |
433 _start_depth, _max_count, | |
434 _frame_buffer, _count_ptr); | |
435 } | |
436 }; | |
437 | |
438 // forward declaration | |
439 struct StackInfoNode; | |
440 | |
441 // VM operation to get stack trace at safepoint. | |
442 class VM_GetMultipleStackTraces : public VM_Operation { | |
443 private: | |
444 JvmtiEnv *_env; | |
445 jint _max_frame_count; | |
446 jvmtiStackInfo *_stack_info; | |
447 jvmtiError _result; | |
448 int _frame_count_total; | |
449 struct StackInfoNode *_head; | |
450 | |
451 JvmtiEnvBase *env() { return (JvmtiEnvBase *)_env; } | |
452 jint max_frame_count() { return _max_frame_count; } | |
453 struct StackInfoNode *head() { return _head; } | |
454 void set_head(StackInfoNode *head) { _head = head; } | |
455 | |
456 protected: | |
457 void set_result(jvmtiError result) { _result = result; } | |
458 void fill_frames(jthread jt, JavaThread *thr, oop thread_oop); | |
459 void allocate_and_fill_stacks(jint thread_count); | |
460 | |
461 public: | |
462 VM_GetMultipleStackTraces(JvmtiEnv *env, jint max_frame_count) { | |
463 _env = env; | |
464 _max_frame_count = max_frame_count; | |
465 _frame_count_total = 0; | |
466 _head = NULL; | |
467 _result = JVMTI_ERROR_NONE; | |
468 } | |
469 VMOp_Type type() const { return VMOp_GetMultipleStackTraces; } | |
470 jvmtiStackInfo *stack_info() { return _stack_info; } | |
471 jvmtiError result() { return _result; } | |
472 }; | |
473 | |
474 | |
475 // VM operation to get stack trace at safepoint. | |
476 class VM_GetAllStackTraces : public VM_GetMultipleStackTraces { | |
477 private: | |
478 JavaThread *_calling_thread; | |
479 jint _final_thread_count; | |
480 | |
481 public: | |
482 VM_GetAllStackTraces(JvmtiEnv *env, JavaThread *calling_thread, | |
483 jint max_frame_count) | |
484 : VM_GetMultipleStackTraces(env, max_frame_count) { | |
485 _calling_thread = calling_thread; | |
486 } | |
487 VMOp_Type type() const { return VMOp_GetAllStackTraces; } | |
488 void doit(); | |
489 jint final_thread_count() { return _final_thread_count; } | |
490 }; | |
491 | |
492 // VM operation to get stack trace at safepoint. | |
493 class VM_GetThreadListStackTraces : public VM_GetMultipleStackTraces { | |
494 private: | |
495 jint _thread_count; | |
496 const jthread* _thread_list; | |
497 | |
498 public: | |
499 VM_GetThreadListStackTraces(JvmtiEnv *env, jint thread_count, const jthread* thread_list, jint max_frame_count) | |
500 : VM_GetMultipleStackTraces(env, max_frame_count) { | |
501 _thread_count = thread_count; | |
502 _thread_list = thread_list; | |
503 } | |
504 VMOp_Type type() const { return VMOp_GetThreadListStackTraces; } | |
505 void doit(); | |
506 }; | |
507 | |
508 | |
509 // VM operation to count stack frames at safepoint. | |
510 class VM_GetFrameCount : public VM_Operation { | |
511 private: | |
512 JvmtiEnv *_env; | |
513 JvmtiThreadState *_state; | |
514 jint *_count_ptr; | |
515 jvmtiError _result; | |
516 | |
517 public: | |
518 VM_GetFrameCount(JvmtiEnv *env, JvmtiThreadState *state, jint *count_ptr) { | |
519 _env = env; | |
520 _state = state; | |
521 _count_ptr = count_ptr; | |
522 } | |
523 VMOp_Type type() const { return VMOp_GetFrameCount; } | |
524 jvmtiError result() { return _result; } | |
525 void doit() { | |
526 _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); | |
527 } | |
528 }; | |
529 | |
530 // VM operation to frame location at safepoint. | |
531 class VM_GetFrameLocation : public VM_Operation { | |
532 private: | |
533 JvmtiEnv *_env; | |
534 JavaThread* _java_thread; | |
535 jint _depth; | |
536 jmethodID* _method_ptr; | |
537 jlocation* _location_ptr; | |
538 jvmtiError _result; | |
539 | |
540 public: | |
541 VM_GetFrameLocation(JvmtiEnv *env, JavaThread* java_thread, jint depth, | |
542 jmethodID* method_ptr, jlocation* location_ptr) { | |
543 _env = env; | |
544 _java_thread = java_thread; | |
545 _depth = depth; | |
546 _method_ptr = method_ptr; | |
547 _location_ptr = location_ptr; | |
548 } | |
549 VMOp_Type type() const { return VMOp_GetFrameLocation; } | |
550 jvmtiError result() { return _result; } | |
551 void doit() { | |
552 _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, | |
553 _method_ptr, _location_ptr); | |
554 } | |
555 }; | |
556 | |
557 | |
558 // ResourceTracker | |
559 // | |
560 // ResourceTracker works a little like a ResourceMark. All allocates | |
561 // using the resource tracker are recorded. If an allocate using the | |
562 // resource tracker fails the destructor will free any resources | |
563 // that were allocated using the tracker. | |
564 // The motive for this class is to avoid messy error recovery code | |
565 // in situations where multiple allocations are done in sequence. If | |
566 // the second or subsequent allocation fails it avoids any code to | |
567 // release memory allocated in the previous calls. | |
568 // | |
569 // Usage :- | |
570 // ResourceTracker rt(env); | |
571 // : | |
572 // err = rt.allocate(1024, &ptr); | |
573 | |
574 class ResourceTracker : public StackObj { | |
575 private: | |
576 JvmtiEnv* _env; | |
577 GrowableArray<unsigned char*> *_allocations; | |
578 bool _failed; | |
579 public: | |
580 ResourceTracker(JvmtiEnv* env); | |
581 ~ResourceTracker(); | |
582 jvmtiError allocate(jlong size, unsigned char** mem_ptr); | |
583 unsigned char* allocate(jlong size); | |
584 char* strdup(const char* str); | |
585 }; | |
586 | |
587 | |
588 // Jvmti monitor closure to collect off stack monitors. | |
589 class JvmtiMonitorClosure: public MonitorClosure { | |
590 private: | |
591 JavaThread *_java_thread; | |
592 JavaThread *_calling_thread; | |
593 GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list; | |
594 jvmtiError _error; | |
595 JvmtiEnvBase *_env; | |
596 | |
597 public: | |
598 JvmtiMonitorClosure(JavaThread* thread, JavaThread *calling_thread, | |
599 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors, | |
600 JvmtiEnvBase *env) { | |
601 _java_thread = thread; | |
602 _calling_thread = calling_thread; | |
603 _owned_monitors_list = owned_monitors; | |
604 _error = JVMTI_ERROR_NONE; | |
605 _env = env; | |
606 } | |
607 void do_monitor(ObjectMonitor* mon); | |
608 jvmtiError error() { return _error;} | |
609 }; | |
610 | |
1972 | 611 #endif // SHARE_VM_PRIMS_JVMTIENVBASE_HPP |