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