Mercurial > hg > graal-compiler
annotate src/share/vm/prims/jvmtiEnvBase.hpp @ 3249:e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author | johnc |
---|---|
date | Thu, 07 Apr 2011 09:53:20 -0700 |
parents | 684faacebf20 |
children | e6b1331a51d2 |
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 void update_klass_field_access_flag(fieldDescriptor *fd); | |
271 | |
272 jint count_locked_objects(JavaThread *java_thread, Handle hobj); | |
273 jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread, | |
274 JavaThread* java_thread, | |
275 javaVFrame *jvf, | |
276 GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, | |
277 jint depth); | |
278 vframe* vframeFor(JavaThread* java_thread, jint depth); | |
279 | |
280 public: | |
281 // get a field descriptor for the specified class and field | |
282 static bool get_field_descriptor(klassOop k, jfieldID field, fieldDescriptor* fd); | |
283 // test for suspend - most (all?) of these should go away | |
284 static bool is_thread_fully_suspended(JavaThread *thread, | |
285 bool wait_for_suspend, | |
286 uint32_t *bits); | |
287 | |
288 | |
289 // JVMTI API helper functions which are called at safepoint or thread is suspended. | |
290 jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr); | |
291 jvmtiError get_frame_location(JavaThread* java_thread, jint depth, | |
292 jmethodID* method_ptr, jlocation* location_ptr); | |
293 jvmtiError get_object_monitor_usage(JavaThread *calling_thread, | |
294 jobject object, jvmtiMonitorUsage* info_ptr); | |
295 jvmtiError get_stack_trace(JavaThread *java_thread, | |
296 jint stack_depth, jint max_count, | |
297 jvmtiFrameInfo* frame_buffer, jint* count_ptr); | |
298 jvmtiError get_current_contended_monitor(JavaThread *calling_thread, | |
299 JavaThread *java_thread, | |
300 jobject *monitor_ptr); | |
301 jvmtiError get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread, | |
302 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list); | |
303 jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread, | |
304 jvalue value, TosState tos, Handle* ret_ob_h); | |
305 jvmtiError force_early_return(JavaThread* java_thread, jvalue value, TosState tos); | |
306 }; | |
307 | |
308 // This class is the only safe means of iterating through environments. | |
309 // Note that this iteratation includes invalid environments pending | |
310 // deallocation -- in fact, some uses depend on this behavior. | |
311 | |
312 class JvmtiEnvIterator : public StackObj { | |
313 private: | |
314 bool _entry_was_marked; | |
315 public: | |
316 JvmtiEnvIterator() { | |
317 if (Threads::number_of_threads() == 0) { | |
318 _entry_was_marked = false; // we are single-threaded, no need | |
319 } else { | |
320 Thread::current()->entering_jvmti_env_iteration(); | |
321 _entry_was_marked = true; | |
322 } | |
323 } | |
324 ~JvmtiEnvIterator() { | |
325 if (_entry_was_marked) { | |
326 Thread::current()->leaving_jvmti_env_iteration(); | |
327 } | |
328 } | |
329 JvmtiEnv* first() { return JvmtiEnvBase::head_environment(); } | |
330 JvmtiEnv* next(JvmtiEnvBase* env) { return env->next_environment(); } | |
331 }; | |
332 | |
333 | |
334 // VM operation to get monitor information with stack depth. | |
335 class VM_GetOwnedMonitorInfo : public VM_Operation { | |
336 private: | |
337 JvmtiEnv *_env; | |
338 JavaThread* _calling_thread; | |
339 JavaThread *_java_thread; | |
340 jvmtiError _result; | |
341 GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list; | |
342 | |
343 public: | |
344 VM_GetOwnedMonitorInfo(JvmtiEnv* env, JavaThread* calling_thread, | |
345 JavaThread* java_thread, | |
346 GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list) { | |
347 _env = env; | |
348 _calling_thread = calling_thread; | |
349 _java_thread = java_thread; | |
350 _owned_monitors_list = owned_monitor_list; | |
351 _result = JVMTI_ERROR_NONE; | |
352 } | |
353 VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; } | |
354 void doit() { | |
355 ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, | |
356 _owned_monitors_list); | |
357 } | |
358 jvmtiError result() { return _result; } | |
359 }; | |
360 | |
361 | |
362 // VM operation to get object monitor usage. | |
363 class VM_GetObjectMonitorUsage : public VM_Operation { | |
364 private: | |
365 JvmtiEnv *_env; | |
366 jobject _object; | |
367 JavaThread* _calling_thread; | |
368 jvmtiMonitorUsage* _info_ptr; | |
369 jvmtiError _result; | |
370 | |
371 public: | |
372 VM_GetObjectMonitorUsage(JvmtiEnv *env, JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { | |
373 _env = env; | |
374 _object = object; | |
375 _calling_thread = calling_thread; | |
376 _info_ptr = info_ptr; | |
377 } | |
378 VMOp_Type type() const { return VMOp_GetObjectMonitorUsage; } | |
379 jvmtiError result() { return _result; } | |
380 void doit() { | |
381 _result = ((JvmtiEnvBase*) _env)->get_object_monitor_usage(_calling_thread, _object, _info_ptr); | |
382 } | |
383 | |
384 }; | |
385 | |
386 // VM operation to get current contended monitor. | |
387 class VM_GetCurrentContendedMonitor : public VM_Operation { | |
388 private: | |
389 JvmtiEnv *_env; | |
390 JavaThread *_calling_thread; | |
391 JavaThread *_java_thread; | |
392 jobject *_owned_monitor_ptr; | |
393 jvmtiError _result; | |
394 | |
395 public: | |
396 VM_GetCurrentContendedMonitor(JvmtiEnv *env, JavaThread *calling_thread, JavaThread *java_thread, jobject *mon_ptr) { | |
397 _env = env; | |
398 _calling_thread = calling_thread; | |
399 _java_thread = java_thread; | |
400 _owned_monitor_ptr = mon_ptr; | |
401 } | |
402 VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; } | |
403 jvmtiError result() { return _result; } | |
404 void doit() { | |
405 _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); | |
406 } | |
407 }; | |
408 | |
409 // VM operation to get stack trace at safepoint. | |
410 class VM_GetStackTrace : public VM_Operation { | |
411 private: | |
412 JvmtiEnv *_env; | |
413 JavaThread *_java_thread; | |
414 jint _start_depth; | |
415 jint _max_count; | |
416 jvmtiFrameInfo *_frame_buffer; | |
417 jint *_count_ptr; | |
418 jvmtiError _result; | |
419 | |
420 public: | |
421 VM_GetStackTrace(JvmtiEnv *env, JavaThread *java_thread, | |
422 jint start_depth, jint max_count, | |
423 jvmtiFrameInfo* frame_buffer, jint* count_ptr) { | |
424 _env = env; | |
425 _java_thread = java_thread; | |
426 _start_depth = start_depth; | |
427 _max_count = max_count; | |
428 _frame_buffer = frame_buffer; | |
429 _count_ptr = count_ptr; | |
430 } | |
431 jvmtiError result() { return _result; } | |
432 VMOp_Type type() const { return VMOp_GetStackTrace; } | |
433 void doit() { | |
434 _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, | |
435 _start_depth, _max_count, | |
436 _frame_buffer, _count_ptr); | |
437 } | |
438 }; | |
439 | |
440 // forward declaration | |
441 struct StackInfoNode; | |
442 | |
443 // VM operation to get stack trace at safepoint. | |
444 class VM_GetMultipleStackTraces : public VM_Operation { | |
445 private: | |
446 JvmtiEnv *_env; | |
447 jint _max_frame_count; | |
448 jvmtiStackInfo *_stack_info; | |
449 jvmtiError _result; | |
450 int _frame_count_total; | |
451 struct StackInfoNode *_head; | |
452 | |
453 JvmtiEnvBase *env() { return (JvmtiEnvBase *)_env; } | |
454 jint max_frame_count() { return _max_frame_count; } | |
455 struct StackInfoNode *head() { return _head; } | |
456 void set_head(StackInfoNode *head) { _head = head; } | |
457 | |
458 protected: | |
459 void set_result(jvmtiError result) { _result = result; } | |
460 void fill_frames(jthread jt, JavaThread *thr, oop thread_oop); | |
461 void allocate_and_fill_stacks(jint thread_count); | |
462 | |
463 public: | |
464 VM_GetMultipleStackTraces(JvmtiEnv *env, jint max_frame_count) { | |
465 _env = env; | |
466 _max_frame_count = max_frame_count; | |
467 _frame_count_total = 0; | |
468 _head = NULL; | |
469 _result = JVMTI_ERROR_NONE; | |
470 } | |
471 VMOp_Type type() const { return VMOp_GetMultipleStackTraces; } | |
472 jvmtiStackInfo *stack_info() { return _stack_info; } | |
473 jvmtiError result() { return _result; } | |
474 }; | |
475 | |
476 | |
477 // VM operation to get stack trace at safepoint. | |
478 class VM_GetAllStackTraces : public VM_GetMultipleStackTraces { | |
479 private: | |
480 JavaThread *_calling_thread; | |
481 jint _final_thread_count; | |
482 | |
483 public: | |
484 VM_GetAllStackTraces(JvmtiEnv *env, JavaThread *calling_thread, | |
485 jint max_frame_count) | |
486 : VM_GetMultipleStackTraces(env, max_frame_count) { | |
487 _calling_thread = calling_thread; | |
488 } | |
489 VMOp_Type type() const { return VMOp_GetAllStackTraces; } | |
490 void doit(); | |
491 jint final_thread_count() { return _final_thread_count; } | |
492 }; | |
493 | |
494 // VM operation to get stack trace at safepoint. | |
495 class VM_GetThreadListStackTraces : public VM_GetMultipleStackTraces { | |
496 private: | |
497 jint _thread_count; | |
498 const jthread* _thread_list; | |
499 | |
500 public: | |
501 VM_GetThreadListStackTraces(JvmtiEnv *env, jint thread_count, const jthread* thread_list, jint max_frame_count) | |
502 : VM_GetMultipleStackTraces(env, max_frame_count) { | |
503 _thread_count = thread_count; | |
504 _thread_list = thread_list; | |
505 } | |
506 VMOp_Type type() const { return VMOp_GetThreadListStackTraces; } | |
507 void doit(); | |
508 }; | |
509 | |
510 | |
511 // VM operation to count stack frames at safepoint. | |
512 class VM_GetFrameCount : public VM_Operation { | |
513 private: | |
514 JvmtiEnv *_env; | |
515 JvmtiThreadState *_state; | |
516 jint *_count_ptr; | |
517 jvmtiError _result; | |
518 | |
519 public: | |
520 VM_GetFrameCount(JvmtiEnv *env, JvmtiThreadState *state, jint *count_ptr) { | |
521 _env = env; | |
522 _state = state; | |
523 _count_ptr = count_ptr; | |
524 } | |
525 VMOp_Type type() const { return VMOp_GetFrameCount; } | |
526 jvmtiError result() { return _result; } | |
527 void doit() { | |
528 _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); | |
529 } | |
530 }; | |
531 | |
532 // VM operation to frame location at safepoint. | |
533 class VM_GetFrameLocation : public VM_Operation { | |
534 private: | |
535 JvmtiEnv *_env; | |
536 JavaThread* _java_thread; | |
537 jint _depth; | |
538 jmethodID* _method_ptr; | |
539 jlocation* _location_ptr; | |
540 jvmtiError _result; | |
541 | |
542 public: | |
543 VM_GetFrameLocation(JvmtiEnv *env, JavaThread* java_thread, jint depth, | |
544 jmethodID* method_ptr, jlocation* location_ptr) { | |
545 _env = env; | |
546 _java_thread = java_thread; | |
547 _depth = depth; | |
548 _method_ptr = method_ptr; | |
549 _location_ptr = location_ptr; | |
550 } | |
551 VMOp_Type type() const { return VMOp_GetFrameLocation; } | |
552 jvmtiError result() { return _result; } | |
553 void doit() { | |
554 _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, | |
555 _method_ptr, _location_ptr); | |
556 } | |
557 }; | |
558 | |
559 | |
560 // ResourceTracker | |
561 // | |
562 // ResourceTracker works a little like a ResourceMark. All allocates | |
563 // using the resource tracker are recorded. If an allocate using the | |
564 // resource tracker fails the destructor will free any resources | |
565 // that were allocated using the tracker. | |
566 // The motive for this class is to avoid messy error recovery code | |
567 // in situations where multiple allocations are done in sequence. If | |
568 // the second or subsequent allocation fails it avoids any code to | |
569 // release memory allocated in the previous calls. | |
570 // | |
571 // Usage :- | |
572 // ResourceTracker rt(env); | |
573 // : | |
574 // err = rt.allocate(1024, &ptr); | |
575 | |
576 class ResourceTracker : public StackObj { | |
577 private: | |
578 JvmtiEnv* _env; | |
579 GrowableArray<unsigned char*> *_allocations; | |
580 bool _failed; | |
581 public: | |
582 ResourceTracker(JvmtiEnv* env); | |
583 ~ResourceTracker(); | |
584 jvmtiError allocate(jlong size, unsigned char** mem_ptr); | |
585 unsigned char* allocate(jlong size); | |
586 char* strdup(const char* str); | |
587 }; | |
588 | |
589 | |
590 // Jvmti monitor closure to collect off stack monitors. | |
591 class JvmtiMonitorClosure: public MonitorClosure { | |
592 private: | |
593 JavaThread *_java_thread; | |
594 JavaThread *_calling_thread; | |
595 GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list; | |
596 jvmtiError _error; | |
597 JvmtiEnvBase *_env; | |
598 | |
599 public: | |
600 JvmtiMonitorClosure(JavaThread* thread, JavaThread *calling_thread, | |
601 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors, | |
602 JvmtiEnvBase *env) { | |
603 _java_thread = thread; | |
604 _calling_thread = calling_thread; | |
605 _owned_monitors_list = owned_monitors; | |
606 _error = JVMTI_ERROR_NONE; | |
607 _env = env; | |
608 } | |
609 void do_monitor(ObjectMonitor* mon); | |
610 jvmtiError error() { return _error;} | |
611 }; | |
612 | |
1972 | 613 #endif // SHARE_VM_PRIMS_JVMTIENVBASE_HPP |