Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiEventController.cpp @ 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 | 78bbf4d43a14 |
children | 52b4284cb496 |
rev | line source |
---|---|
0 | 1 /* |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
2 * Copyright (c) 2003, 2014, 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:
1213
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1213
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:
1213
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "interpreter/interpreter.hpp" | |
27 #include "jvmtifiles/jvmtiEnv.hpp" | |
28 #include "memory/resourceArea.hpp" | |
29 #include "prims/jvmtiEventController.hpp" | |
30 #include "prims/jvmtiEventController.inline.hpp" | |
31 #include "prims/jvmtiExport.hpp" | |
32 #include "prims/jvmtiImpl.hpp" | |
33 #include "prims/jvmtiThreadState.inline.hpp" | |
34 #include "runtime/frame.hpp" | |
35 #include "runtime/thread.hpp" | |
36 #include "runtime/vframe.hpp" | |
37 #include "runtime/vframe_hp.hpp" | |
38 #include "runtime/vmThread.hpp" | |
39 #include "runtime/vm_operations.hpp" | |
0 | 40 |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
41 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC |
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
42 |
0 | 43 #ifdef JVMTI_TRACE |
8871
6b19fe41b577
8011009: Use do-while(0) instead of while(0) in EC_TRACE and RC_TRACE* macros
kmo
parents:
2426
diff
changeset
|
44 #define EC_TRACE(out) do { \ |
6b19fe41b577
8011009: Use do-while(0) instead of while(0) in EC_TRACE and RC_TRACE* macros
kmo
parents:
2426
diff
changeset
|
45 if (JvmtiTrace::trace_event_controller()) { \ |
6b19fe41b577
8011009: Use do-while(0) instead of while(0) in EC_TRACE and RC_TRACE* macros
kmo
parents:
2426
diff
changeset
|
46 SafeResourceMark rm; \ |
6b19fe41b577
8011009: Use do-while(0) instead of while(0) in EC_TRACE and RC_TRACE* macros
kmo
parents:
2426
diff
changeset
|
47 tty->print_cr out; \ |
6b19fe41b577
8011009: Use do-while(0) instead of while(0) in EC_TRACE and RC_TRACE* macros
kmo
parents:
2426
diff
changeset
|
48 } \ |
6b19fe41b577
8011009: Use do-while(0) instead of while(0) in EC_TRACE and RC_TRACE* macros
kmo
parents:
2426
diff
changeset
|
49 } while (0) |
0 | 50 #else |
51 #define EC_TRACE(out) | |
52 #endif /*JVMTI_TRACE */ | |
53 | |
54 // bits for standard events | |
55 | |
56 static const jlong SINGLE_STEP_BIT = (((jlong)1) << (JVMTI_EVENT_SINGLE_STEP - TOTAL_MIN_EVENT_TYPE_VAL)); | |
57 static const jlong FRAME_POP_BIT = (((jlong)1) << (JVMTI_EVENT_FRAME_POP - TOTAL_MIN_EVENT_TYPE_VAL)); | |
58 static const jlong BREAKPOINT_BIT = (((jlong)1) << (JVMTI_EVENT_BREAKPOINT - TOTAL_MIN_EVENT_TYPE_VAL)); | |
59 static const jlong FIELD_ACCESS_BIT = (((jlong)1) << (JVMTI_EVENT_FIELD_ACCESS - TOTAL_MIN_EVENT_TYPE_VAL)); | |
60 static const jlong FIELD_MODIFICATION_BIT = (((jlong)1) << (JVMTI_EVENT_FIELD_MODIFICATION - TOTAL_MIN_EVENT_TYPE_VAL)); | |
61 static const jlong METHOD_ENTRY_BIT = (((jlong)1) << (JVMTI_EVENT_METHOD_ENTRY - TOTAL_MIN_EVENT_TYPE_VAL)); | |
62 static const jlong METHOD_EXIT_BIT = (((jlong)1) << (JVMTI_EVENT_METHOD_EXIT - TOTAL_MIN_EVENT_TYPE_VAL)); | |
63 static const jlong CLASS_FILE_LOAD_HOOK_BIT = (((jlong)1) << (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK - TOTAL_MIN_EVENT_TYPE_VAL)); | |
64 static const jlong NATIVE_METHOD_BIND_BIT = (((jlong)1) << (JVMTI_EVENT_NATIVE_METHOD_BIND - TOTAL_MIN_EVENT_TYPE_VAL)); | |
65 static const jlong VM_START_BIT = (((jlong)1) << (JVMTI_EVENT_VM_START - TOTAL_MIN_EVENT_TYPE_VAL)); | |
66 static const jlong VM_INIT_BIT = (((jlong)1) << (JVMTI_EVENT_VM_INIT - TOTAL_MIN_EVENT_TYPE_VAL)); | |
67 static const jlong VM_DEATH_BIT = (((jlong)1) << (JVMTI_EVENT_VM_DEATH - TOTAL_MIN_EVENT_TYPE_VAL)); | |
68 static const jlong CLASS_LOAD_BIT = (((jlong)1) << (JVMTI_EVENT_CLASS_LOAD - TOTAL_MIN_EVENT_TYPE_VAL)); | |
69 static const jlong CLASS_PREPARE_BIT = (((jlong)1) << (JVMTI_EVENT_CLASS_PREPARE - TOTAL_MIN_EVENT_TYPE_VAL)); | |
70 static const jlong THREAD_START_BIT = (((jlong)1) << (JVMTI_EVENT_THREAD_START - TOTAL_MIN_EVENT_TYPE_VAL)); | |
71 static const jlong THREAD_END_BIT = (((jlong)1) << (JVMTI_EVENT_THREAD_END - TOTAL_MIN_EVENT_TYPE_VAL)); | |
72 static const jlong EXCEPTION_THROW_BIT = (((jlong)1) << (JVMTI_EVENT_EXCEPTION - TOTAL_MIN_EVENT_TYPE_VAL)); | |
73 static const jlong EXCEPTION_CATCH_BIT = (((jlong)1) << (JVMTI_EVENT_EXCEPTION_CATCH - TOTAL_MIN_EVENT_TYPE_VAL)); | |
74 static const jlong MONITOR_CONTENDED_ENTER_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_CONTENDED_ENTER - TOTAL_MIN_EVENT_TYPE_VAL)); | |
75 static const jlong MONITOR_CONTENDED_ENTERED_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED - TOTAL_MIN_EVENT_TYPE_VAL)); | |
76 static const jlong MONITOR_WAIT_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_WAIT - TOTAL_MIN_EVENT_TYPE_VAL)); | |
77 static const jlong MONITOR_WAITED_BIT = (((jlong)1) << (JVMTI_EVENT_MONITOR_WAITED - TOTAL_MIN_EVENT_TYPE_VAL)); | |
78 static const jlong DYNAMIC_CODE_GENERATED_BIT = (((jlong)1) << (JVMTI_EVENT_DYNAMIC_CODE_GENERATED - TOTAL_MIN_EVENT_TYPE_VAL)); | |
79 static const jlong DATA_DUMP_BIT = (((jlong)1) << (JVMTI_EVENT_DATA_DUMP_REQUEST - TOTAL_MIN_EVENT_TYPE_VAL)); | |
80 static const jlong COMPILED_METHOD_LOAD_BIT = (((jlong)1) << (JVMTI_EVENT_COMPILED_METHOD_LOAD - TOTAL_MIN_EVENT_TYPE_VAL)); | |
81 static const jlong COMPILED_METHOD_UNLOAD_BIT = (((jlong)1) << (JVMTI_EVENT_COMPILED_METHOD_UNLOAD - TOTAL_MIN_EVENT_TYPE_VAL)); | |
82 static const jlong GARBAGE_COLLECTION_START_BIT = (((jlong)1) << (JVMTI_EVENT_GARBAGE_COLLECTION_START - TOTAL_MIN_EVENT_TYPE_VAL)); | |
83 static const jlong GARBAGE_COLLECTION_FINISH_BIT = (((jlong)1) << (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH - TOTAL_MIN_EVENT_TYPE_VAL)); | |
84 static const jlong OBJECT_FREE_BIT = (((jlong)1) << (JVMTI_EVENT_OBJECT_FREE - TOTAL_MIN_EVENT_TYPE_VAL)); | |
85 static const jlong RESOURCE_EXHAUSTED_BIT = (((jlong)1) << (JVMTI_EVENT_RESOURCE_EXHAUSTED - TOTAL_MIN_EVENT_TYPE_VAL)); | |
86 static const jlong VM_OBJECT_ALLOC_BIT = (((jlong)1) << (JVMTI_EVENT_VM_OBJECT_ALLOC - TOTAL_MIN_EVENT_TYPE_VAL)); | |
87 | |
88 // bits for extension events | |
89 static const jlong CLASS_UNLOAD_BIT = (((jlong)1) << (EXT_EVENT_CLASS_UNLOAD - TOTAL_MIN_EVENT_TYPE_VAL)); | |
90 | |
91 | |
92 static const jlong MONITOR_BITS = MONITOR_CONTENDED_ENTER_BIT | MONITOR_CONTENDED_ENTERED_BIT | | |
93 MONITOR_WAIT_BIT | MONITOR_WAITED_BIT; | |
94 static const jlong EXCEPTION_BITS = EXCEPTION_THROW_BIT | EXCEPTION_CATCH_BIT; | |
95 static const jlong INTERP_EVENT_BITS = SINGLE_STEP_BIT | METHOD_ENTRY_BIT | METHOD_EXIT_BIT | | |
96 FRAME_POP_BIT | FIELD_ACCESS_BIT | FIELD_MODIFICATION_BIT; | |
97 static const jlong THREAD_FILTERED_EVENT_BITS = INTERP_EVENT_BITS | EXCEPTION_BITS | MONITOR_BITS | | |
98 BREAKPOINT_BIT | CLASS_LOAD_BIT | CLASS_PREPARE_BIT | THREAD_END_BIT; | |
99 static const jlong NEED_THREAD_LIFE_EVENTS = THREAD_FILTERED_EVENT_BITS | THREAD_START_BIT; | |
100 static const jlong EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT | | |
101 VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT | | |
102 THREAD_START_BIT | THREAD_END_BIT | | |
103 DYNAMIC_CODE_GENERATED_BIT; | |
104 static const jlong GLOBAL_EVENT_BITS = ~THREAD_FILTERED_EVENT_BITS; | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
105 static const jlong SHOULD_POST_ON_EXCEPTIONS_BITS = EXCEPTION_BITS | METHOD_EXIT_BIT | FRAME_POP_BIT; |
0 | 106 |
107 /////////////////////////////////////////////////////////////// | |
108 // | |
109 // JvmtiEventEnabled | |
110 // | |
111 | |
112 JvmtiEventEnabled::JvmtiEventEnabled() { | |
113 clear(); | |
114 } | |
115 | |
116 | |
117 void JvmtiEventEnabled::clear() { | |
118 _enabled_bits = 0; | |
119 #ifndef PRODUCT | |
120 _init_guard = JEE_INIT_GUARD; | |
121 #endif | |
122 } | |
123 | |
124 void JvmtiEventEnabled::set_enabled(jvmtiEvent event_type, bool enabled) { | |
125 jlong bits = get_bits(); | |
126 jlong mask = bit_for(event_type); | |
127 if (enabled) { | |
128 bits |= mask; | |
129 } else { | |
130 bits &= ~mask; | |
131 } | |
132 set_bits(bits); | |
133 } | |
134 | |
135 | |
136 /////////////////////////////////////////////////////////////// | |
137 // | |
138 // JvmtiEnvThreadEventEnable | |
139 // | |
140 | |
141 JvmtiEnvThreadEventEnable::JvmtiEnvThreadEventEnable() { | |
142 _event_user_enabled.clear(); | |
143 _event_enabled.clear(); | |
144 } | |
145 | |
146 | |
147 JvmtiEnvThreadEventEnable::~JvmtiEnvThreadEventEnable() { | |
148 _event_user_enabled.clear(); | |
149 _event_enabled.clear(); | |
150 } | |
151 | |
152 | |
153 /////////////////////////////////////////////////////////////// | |
154 // | |
155 // JvmtiThreadEventEnable | |
156 // | |
157 | |
158 JvmtiThreadEventEnable::JvmtiThreadEventEnable() { | |
159 _event_enabled.clear(); | |
160 } | |
161 | |
162 | |
163 JvmtiThreadEventEnable::~JvmtiThreadEventEnable() { | |
164 _event_enabled.clear(); | |
165 } | |
166 | |
167 | |
168 /////////////////////////////////////////////////////////////// | |
169 // | |
170 // JvmtiEnvEventEnable | |
171 // | |
172 | |
173 JvmtiEnvEventEnable::JvmtiEnvEventEnable() { | |
174 _event_user_enabled.clear(); | |
175 _event_callback_enabled.clear(); | |
176 _event_enabled.clear(); | |
177 } | |
178 | |
179 | |
180 JvmtiEnvEventEnable::~JvmtiEnvEventEnable() { | |
181 _event_user_enabled.clear(); | |
182 _event_callback_enabled.clear(); | |
183 _event_enabled.clear(); | |
184 } | |
185 | |
186 | |
187 /////////////////////////////////////////////////////////////// | |
188 // | |
189 // VM_EnterInterpOnlyMode | |
190 // | |
191 | |
192 class VM_EnterInterpOnlyMode : public VM_Operation { | |
193 private: | |
194 JvmtiThreadState *_state; | |
195 | |
196 public: | |
197 VM_EnterInterpOnlyMode(JvmtiThreadState *state); | |
198 | |
199 bool allow_nested_vm_operations() const { return true; } | |
200 VMOp_Type type() const { return VMOp_EnterInterpOnlyMode; } | |
201 void doit(); | |
202 | |
203 // to do: this same function is in jvmtiImpl - should be in one place | |
204 bool can_be_deoptimized(vframe* vf) { | |
205 return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized()); | |
206 } | |
207 }; | |
208 | |
209 VM_EnterInterpOnlyMode::VM_EnterInterpOnlyMode(JvmtiThreadState *state) | |
210 : _state(state) | |
211 { | |
212 } | |
213 | |
214 | |
215 void VM_EnterInterpOnlyMode::doit() { | |
216 // Set up the current stack depth for later tracking | |
217 _state->invalidate_cur_stack_depth(); | |
218 | |
219 _state->enter_interp_only_mode(); | |
220 | |
221 JavaThread *thread = _state->get_thread(); | |
222 if (thread->has_last_Java_frame()) { | |
223 // If running in fullspeed mode, single stepping is implemented | |
224 // as follows: first, the interpreter does not dispatch to | |
225 // compiled code for threads that have single stepping enabled; | |
226 // second, we deoptimize all methods on the thread's stack when | |
227 // interpreted-only mode is enabled the first time for a given | |
228 // thread (nothing to do if no Java frames yet). | |
229 int num_marked = 0; | |
230 ResourceMark resMark; | |
231 RegisterMap rm(thread, false); | |
232 for (vframe* vf = thread->last_java_vframe(&rm); vf; vf = vf->sender()) { | |
233 if (can_be_deoptimized(vf)) { | |
234 ((compiledVFrame*) vf)->code()->mark_for_deoptimization(); | |
235 ++num_marked; | |
236 } | |
237 } | |
238 if (num_marked > 0) { | |
239 VM_Deoptimize op; | |
240 VMThread::execute(&op); | |
241 } | |
242 } | |
243 } | |
244 | |
245 | |
246 /////////////////////////////////////////////////////////////// | |
247 // | |
248 // VM_ChangeSingleStep | |
249 // | |
250 | |
251 class VM_ChangeSingleStep : public VM_Operation { | |
252 private: | |
253 bool _on; | |
254 | |
255 public: | |
256 VM_ChangeSingleStep(bool on); | |
257 VMOp_Type type() const { return VMOp_ChangeSingleStep; } | |
258 bool allow_nested_vm_operations() const { return true; } | |
259 void doit(); // method definition is after definition of JvmtiEventControllerPrivate because of scoping | |
260 }; | |
261 | |
262 | |
263 VM_ChangeSingleStep::VM_ChangeSingleStep(bool on) | |
264 : _on(on != 0) | |
265 { | |
266 } | |
267 | |
268 | |
269 | |
270 | |
271 /////////////////////////////////////////////////////////////// | |
272 // | |
273 // JvmtiEventControllerPrivate | |
274 // | |
275 // Private internal implementation methods for JvmtiEventController. | |
276 // | |
277 // These methods are thread safe either because they are called | |
278 // in early VM initialization which is single threaded, or they | |
279 // hold the JvmtiThreadState_lock. | |
280 // | |
281 | |
282 class JvmtiEventControllerPrivate : public AllStatic { | |
283 static bool _initialized; | |
284 public: | |
285 static void set_should_post_single_step(bool on); | |
286 static void enter_interp_only_mode(JvmtiThreadState *state); | |
287 static void leave_interp_only_mode(JvmtiThreadState *state); | |
288 static void recompute_enabled(); | |
289 static jlong recompute_env_enabled(JvmtiEnvBase* env); | |
290 static jlong recompute_env_thread_enabled(JvmtiEnvThreadState* ets, JvmtiThreadState* state); | |
291 static jlong recompute_thread_enabled(JvmtiThreadState *state); | |
292 static void event_init(); | |
293 | |
294 static void set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, | |
295 jvmtiEvent event_type, bool enabled); | |
296 static void set_event_callbacks(JvmtiEnvBase *env, | |
297 const jvmtiEventCallbacks* callbacks, | |
298 jint size_of_callbacks); | |
299 | |
300 static void set_extension_event_callback(JvmtiEnvBase *env, | |
301 jint extension_event_index, | |
302 jvmtiExtensionEvent callback); | |
303 | |
304 static void set_frame_pop(JvmtiEnvThreadState *env_thread, JvmtiFramePop fpop); | |
305 static void clear_frame_pop(JvmtiEnvThreadState *env_thread, JvmtiFramePop fpop); | |
306 static void clear_to_frame_pop(JvmtiEnvThreadState *env_thread, JvmtiFramePop fpop); | |
307 static void change_field_watch(jvmtiEvent event_type, bool added); | |
308 | |
309 static void thread_started(JavaThread *thread); | |
310 static void thread_ended(JavaThread *thread); | |
311 | |
312 static void env_initialize(JvmtiEnvBase *env); | |
313 static void env_dispose(JvmtiEnvBase *env); | |
314 | |
315 static void vm_start(); | |
316 static void vm_init(); | |
317 static void vm_death(); | |
318 | |
319 static void trace_changed(JvmtiThreadState *state, jlong now_enabled, jlong changed); | |
320 static void trace_changed(jlong now_enabled, jlong changed); | |
321 }; | |
322 | |
323 bool JvmtiEventControllerPrivate::_initialized = false; | |
324 | |
325 void JvmtiEventControllerPrivate::set_should_post_single_step(bool on) { | |
326 // we have permission to do this, VM op doesn't | |
327 JvmtiExport::set_should_post_single_step(on); | |
328 } | |
329 | |
330 | |
331 // This change must always be occur when at a safepoint. | |
332 // Being at a safepoint causes the interpreter to use the | |
333 // safepoint dispatch table which we overload to find single | |
334 // step points. Just to be sure that it has been set, we | |
335 // call notice_safepoints when turning on single stepping. | |
336 // When we leave our current safepoint, should_post_single_step | |
337 // will be checked by the interpreter, and the table kept | |
338 // or changed accordingly. | |
339 void VM_ChangeSingleStep::doit() { | |
340 JvmtiEventControllerPrivate::set_should_post_single_step(_on); | |
341 if (_on) { | |
342 Interpreter::notice_safepoints(); | |
343 } | |
344 } | |
345 | |
346 | |
347 void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state) { | |
348 EC_TRACE(("JVMTI [%s] # Entering interpreter only mode", | |
349 JvmtiTrace::safe_get_thread_name(state->get_thread()))); | |
350 | |
351 VM_EnterInterpOnlyMode op(state); | |
352 VMThread::execute(&op); | |
353 } | |
354 | |
355 | |
356 void | |
357 JvmtiEventControllerPrivate::leave_interp_only_mode(JvmtiThreadState *state) { | |
358 EC_TRACE(("JVMTI [%s] # Leaving interpreter only mode", | |
359 JvmtiTrace::safe_get_thread_name(state->get_thread()))); | |
360 state->leave_interp_only_mode(); | |
361 } | |
362 | |
363 | |
364 void | |
365 JvmtiEventControllerPrivate::trace_changed(JvmtiThreadState *state, jlong now_enabled, jlong changed) { | |
366 #ifdef JVMTI_TRACE | |
367 if (JvmtiTrace::trace_event_controller()) { | |
368 SafeResourceMark rm; | |
369 // traces standard events only | |
370 for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) { | |
371 jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei); | |
372 if (changed & bit) { | |
373 // it changed, print it | |
374 tty->print_cr("JVMTI [%s] # %s event %s", | |
375 JvmtiTrace::safe_get_thread_name(state->get_thread()), | |
376 (now_enabled & bit)? "Enabling" : "Disabling", JvmtiTrace::event_name((jvmtiEvent)ei)); | |
377 } | |
378 } | |
379 } | |
380 #endif /*JVMTI_TRACE */ | |
381 } | |
382 | |
383 | |
384 void | |
385 JvmtiEventControllerPrivate::trace_changed(jlong now_enabled, jlong changed) { | |
386 #ifdef JVMTI_TRACE | |
387 if (JvmtiTrace::trace_event_controller()) { | |
388 SafeResourceMark rm; | |
389 // traces standard events only | |
390 for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) { | |
391 jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei); | |
392 if (changed & bit) { | |
393 // it changed, print it | |
394 tty->print_cr("JVMTI [-] # %s event %s", | |
395 (now_enabled & bit)? "Enabling" : "Disabling", JvmtiTrace::event_name((jvmtiEvent)ei)); | |
396 } | |
397 } | |
398 } | |
399 #endif /*JVMTI_TRACE */ | |
400 } | |
401 | |
402 | |
403 // For the specified env: compute the currently truly enabled events | |
404 // set external state accordingly. | |
405 // Return value and set value must include all events. | |
406 // But outside this class, only non-thread-filtered events can be queried.. | |
407 jlong | |
408 JvmtiEventControllerPrivate::recompute_env_enabled(JvmtiEnvBase* env) { | |
409 jlong was_enabled = env->env_event_enable()->_event_enabled.get_bits(); | |
410 jlong now_enabled = | |
411 env->env_event_enable()->_event_callback_enabled.get_bits() & | |
412 env->env_event_enable()->_event_user_enabled.get_bits(); | |
413 | |
414 switch (JvmtiEnv::get_phase()) { | |
415 case JVMTI_PHASE_PRIMORDIAL: | |
416 case JVMTI_PHASE_ONLOAD: | |
417 // only these events allowed in primordial or onload phase | |
418 now_enabled &= (EARLY_EVENT_BITS & ~THREAD_FILTERED_EVENT_BITS); | |
419 break; | |
420 case JVMTI_PHASE_START: | |
421 // only these events allowed in start phase | |
422 now_enabled &= EARLY_EVENT_BITS; | |
423 break; | |
424 case JVMTI_PHASE_LIVE: | |
425 // all events allowed during live phase | |
426 break; | |
427 case JVMTI_PHASE_DEAD: | |
428 // no events allowed when dead | |
429 now_enabled = 0; | |
430 break; | |
431 default: | |
432 assert(false, "no other phases - sanity check"); | |
433 break; | |
434 } | |
435 | |
436 // will we really send these events to this env | |
437 env->env_event_enable()->_event_enabled.set_bits(now_enabled); | |
438 | |
439 trace_changed(now_enabled, (now_enabled ^ was_enabled) & ~THREAD_FILTERED_EVENT_BITS); | |
440 | |
441 return now_enabled; | |
442 } | |
443 | |
444 | |
445 // For the specified env and thread: compute the currently truly enabled events | |
446 // set external state accordingly. Only thread-filtered events are included. | |
447 jlong | |
448 JvmtiEventControllerPrivate::recompute_env_thread_enabled(JvmtiEnvThreadState* ets, JvmtiThreadState* state) { | |
449 JvmtiEnv *env = ets->get_env(); | |
450 | |
451 jlong was_enabled = ets->event_enable()->_event_enabled.get_bits(); | |
452 jlong now_enabled = THREAD_FILTERED_EVENT_BITS & | |
453 env->env_event_enable()->_event_callback_enabled.get_bits() & | |
454 (env->env_event_enable()->_event_user_enabled.get_bits() | | |
455 ets->event_enable()->_event_user_enabled.get_bits()); | |
456 | |
457 // for frame pops and field watchs, computed enabled state | |
458 // is only true if an event has been requested | |
459 if (!ets->has_frame_pops()) { | |
460 now_enabled &= ~FRAME_POP_BIT; | |
461 } | |
462 if (*((int *)JvmtiExport::get_field_access_count_addr()) == 0) { | |
463 now_enabled &= ~FIELD_ACCESS_BIT; | |
464 } | |
465 if (*((int *)JvmtiExport::get_field_modification_count_addr()) == 0) { | |
466 now_enabled &= ~FIELD_MODIFICATION_BIT; | |
467 } | |
468 | |
469 switch (JvmtiEnv::get_phase()) { | |
470 case JVMTI_PHASE_DEAD: | |
471 // no events allowed when dead | |
472 now_enabled = 0; | |
473 break; | |
474 } | |
475 | |
476 // if anything changed do update | |
477 if (now_enabled != was_enabled) { | |
478 | |
479 // will we really send these events to this thread x env | |
480 ets->event_enable()->_event_enabled.set_bits(now_enabled); | |
481 | |
482 // If the enabled status of the single step or breakpoint events changed, | |
483 // the location status may need to change as well. | |
484 jlong changed = now_enabled ^ was_enabled; | |
485 if (changed & SINGLE_STEP_BIT) { | |
486 ets->reset_current_location(JVMTI_EVENT_SINGLE_STEP, (now_enabled & SINGLE_STEP_BIT) != 0); | |
487 } | |
488 if (changed & BREAKPOINT_BIT) { | |
489 ets->reset_current_location(JVMTI_EVENT_BREAKPOINT, (now_enabled & BREAKPOINT_BIT) != 0); | |
490 } | |
491 trace_changed(state, now_enabled, changed); | |
492 } | |
493 return now_enabled; | |
494 } | |
495 | |
496 | |
497 // For the specified thread: compute the currently truly enabled events | |
498 // set external state accordingly. Only thread-filtered events are included. | |
499 jlong | |
500 JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) { | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
501 if (state == NULL) { |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
502 // associated JavaThread is exiting |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
503 return (jlong)0; |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
504 } |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
505 |
0 | 506 jlong was_any_env_enabled = state->thread_event_enable()->_event_enabled.get_bits(); |
507 jlong any_env_enabled = 0; | |
508 | |
509 { | |
510 // This iteration will include JvmtiEnvThreadStates whoses environments | |
511 // have been disposed. These JvmtiEnvThreadStates must not be filtered | |
512 // as recompute must be called on them to disable their events, | |
513 JvmtiEnvThreadStateIterator it(state); | |
514 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { | |
515 any_env_enabled |= recompute_env_thread_enabled(ets, state); | |
516 } | |
517 } | |
518 | |
519 if (any_env_enabled != was_any_env_enabled) { | |
520 // mark if event is truly enabled on this thread in any environment | |
521 state->thread_event_enable()->_event_enabled.set_bits(any_env_enabled); | |
522 | |
523 // compute interp_only mode | |
524 bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0; | |
525 bool is_now_interp = state->is_interp_only_mode(); | |
526 | |
527 if (should_be_interp != is_now_interp) { | |
528 if (should_be_interp) { | |
529 enter_interp_only_mode(state); | |
530 } else { | |
531 leave_interp_only_mode(state); | |
532 } | |
533 } | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
534 |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
535 // update the JavaThread cached value for thread-specific should_post_on_exceptions value |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
536 bool should_post_on_exceptions = (any_env_enabled & SHOULD_POST_ON_EXCEPTIONS_BITS) != 0; |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
537 state->set_should_post_on_exceptions(should_post_on_exceptions); |
0 | 538 } |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
539 |
0 | 540 return any_env_enabled; |
541 } | |
542 | |
543 | |
544 // Compute truly enabled events - meaning if the event can and could be | |
545 // sent. An event is truly enabled if it is user enabled on the thread | |
546 // or globally user enabled, but only if there is a callback or event hook | |
547 // for it and, for field watch and frame pop, one has been set. | |
548 // Compute if truly enabled, per thread, per environment, per combination | |
549 // (thread x environment), and overall. These merges are true if any is true. | |
550 // True per thread if some environment has callback set and the event is globally | |
551 // enabled or enabled for this thread. | |
552 // True per environment if the callback is set and the event is globally | |
553 // enabled in this environment or enabled for any thread in this environment. | |
554 // True per combination if the environment has the callback set and the | |
555 // event is globally enabled in this environment or the event is enabled | |
556 // for this thread and environment. | |
557 // | |
558 // All states transitions dependent on these transitions are also handled here. | |
559 void | |
560 JvmtiEventControllerPrivate::recompute_enabled() { | |
561 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
562 | |
563 // event enabled for any thread in any environment | |
564 jlong was_any_env_thread_enabled = JvmtiEventController::_universal_global_event_enabled.get_bits(); | |
565 jlong any_env_thread_enabled = 0; | |
566 | |
567 EC_TRACE(("JVMTI [-] # recompute enabled - before %llx", was_any_env_thread_enabled)); | |
568 | |
569 // compute non-thread-filters events. | |
570 // This must be done separately from thread-filtered events, since some | |
571 // events can occur before any threads exist. | |
572 JvmtiEnvIterator it; | |
573 for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { | |
574 any_env_thread_enabled |= recompute_env_enabled(env); | |
575 } | |
576 | |
577 // We need to create any missing jvmti_thread_state if there are globally set thread | |
578 // filtered events and there weren't last time | |
579 if ( (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 && | |
580 (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) { | |
581 assert(JvmtiEnv::is_vm_live() || (JvmtiEnv::get_phase()==JVMTI_PHASE_START), | |
582 "thread filtered events should not be enabled when VM not in start or live phase"); | |
583 { | |
584 MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration | |
585 for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) { | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
586 // state_for_while_locked() makes tp->is_exiting() check |
0 | 587 JvmtiThreadState::state_for_while_locked(tp); // create the thread state if missing |
588 } | |
589 }// release Threads_lock | |
590 } | |
591 | |
592 // compute and set thread-filtered events | |
593 for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) { | |
594 any_env_thread_enabled |= recompute_thread_enabled(state); | |
595 } | |
596 | |
597 // set universal state (across all envs and threads) | |
598 jlong delta = any_env_thread_enabled ^ was_any_env_thread_enabled; | |
599 if (delta != 0) { | |
600 JvmtiExport::set_should_post_field_access((any_env_thread_enabled & FIELD_ACCESS_BIT) != 0); | |
601 JvmtiExport::set_should_post_field_modification((any_env_thread_enabled & FIELD_MODIFICATION_BIT) != 0); | |
602 JvmtiExport::set_should_post_class_load((any_env_thread_enabled & CLASS_LOAD_BIT) != 0); | |
603 JvmtiExport::set_should_post_class_file_load_hook((any_env_thread_enabled & CLASS_FILE_LOAD_HOOK_BIT) != 0); | |
604 JvmtiExport::set_should_post_native_method_bind((any_env_thread_enabled & NATIVE_METHOD_BIND_BIT) != 0); | |
605 JvmtiExport::set_should_post_dynamic_code_generated((any_env_thread_enabled & DYNAMIC_CODE_GENERATED_BIT) != 0); | |
606 JvmtiExport::set_should_post_data_dump((any_env_thread_enabled & DATA_DUMP_BIT) != 0); | |
607 JvmtiExport::set_should_post_class_prepare((any_env_thread_enabled & CLASS_PREPARE_BIT) != 0); | |
608 JvmtiExport::set_should_post_class_unload((any_env_thread_enabled & CLASS_UNLOAD_BIT) != 0); | |
609 JvmtiExport::set_should_post_monitor_contended_enter((any_env_thread_enabled & MONITOR_CONTENDED_ENTER_BIT) != 0); | |
610 JvmtiExport::set_should_post_monitor_contended_entered((any_env_thread_enabled & MONITOR_CONTENDED_ENTERED_BIT) != 0); | |
611 JvmtiExport::set_should_post_monitor_wait((any_env_thread_enabled & MONITOR_WAIT_BIT) != 0); | |
612 JvmtiExport::set_should_post_monitor_waited((any_env_thread_enabled & MONITOR_WAITED_BIT) != 0); | |
613 JvmtiExport::set_should_post_garbage_collection_start((any_env_thread_enabled & GARBAGE_COLLECTION_START_BIT) != 0); | |
614 JvmtiExport::set_should_post_garbage_collection_finish((any_env_thread_enabled & GARBAGE_COLLECTION_FINISH_BIT) != 0); | |
615 JvmtiExport::set_should_post_object_free((any_env_thread_enabled & OBJECT_FREE_BIT) != 0); | |
616 JvmtiExport::set_should_post_resource_exhausted((any_env_thread_enabled & RESOURCE_EXHAUSTED_BIT) != 0); | |
617 JvmtiExport::set_should_post_compiled_method_load((any_env_thread_enabled & COMPILED_METHOD_LOAD_BIT) != 0); | |
618 JvmtiExport::set_should_post_compiled_method_unload((any_env_thread_enabled & COMPILED_METHOD_UNLOAD_BIT) != 0); | |
619 JvmtiExport::set_should_post_vm_object_alloc((any_env_thread_enabled & VM_OBJECT_ALLOC_BIT) != 0); | |
620 | |
621 // need this if we want thread events or we need them to init data | |
622 JvmtiExport::set_should_post_thread_life((any_env_thread_enabled & NEED_THREAD_LIFE_EVENTS) != 0); | |
623 | |
624 // If single stepping is turned on or off, execute the VM op to change it. | |
625 if (delta & SINGLE_STEP_BIT) { | |
626 switch (JvmtiEnv::get_phase()) { | |
627 case JVMTI_PHASE_DEAD: | |
628 // If the VM is dying we can't execute VM ops | |
629 break; | |
630 case JVMTI_PHASE_LIVE: { | |
631 VM_ChangeSingleStep op((any_env_thread_enabled & SINGLE_STEP_BIT) != 0); | |
632 VMThread::execute(&op); | |
633 break; | |
634 } | |
635 default: | |
636 assert(false, "should never come here before live phase"); | |
637 break; | |
638 } | |
639 } | |
640 | |
641 // set global truly enabled, that is, any thread in any environment | |
642 JvmtiEventController::_universal_global_event_enabled.set_bits(any_env_thread_enabled); | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
643 |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
644 // set global should_post_on_exceptions |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
645 JvmtiExport::set_should_post_on_exceptions((any_env_thread_enabled & SHOULD_POST_ON_EXCEPTIONS_BITS) != 0); |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
609
diff
changeset
|
646 |
0 | 647 } |
648 | |
649 EC_TRACE(("JVMTI [-] # recompute enabled - after %llx", any_env_thread_enabled)); | |
650 } | |
651 | |
652 | |
653 void | |
654 JvmtiEventControllerPrivate::thread_started(JavaThread *thread) { | |
655 assert(thread->is_Java_thread(), "Must be JavaThread"); | |
656 assert(thread == Thread::current(), "must be current thread"); | |
657 assert(JvmtiEnvBase::environments_might_exist(), "to enter event controller, JVM TI environments must exist"); | |
658 | |
659 EC_TRACE(("JVMTI [%s] # thread started", JvmtiTrace::safe_get_thread_name(thread))); | |
660 | |
661 // if we have any thread filtered events globally enabled, create/update the thread state | |
662 if ((JvmtiEventController::_universal_global_event_enabled.get_bits() & THREAD_FILTERED_EVENT_BITS) != 0) { | |
663 MutexLocker mu(JvmtiThreadState_lock); | |
664 // create the thread state if missing | |
665 JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread); | |
666 if (state != NULL) { // skip threads with no JVMTI thread state | |
667 recompute_thread_enabled(state); | |
668 } | |
669 } | |
670 } | |
671 | |
672 | |
673 void | |
674 JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) { | |
675 // Removes the JvmtiThreadState associated with the specified thread. | |
676 // May be called after all environments have been disposed. | |
2126
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
1972
diff
changeset
|
677 assert(JvmtiThreadState_lock->is_locked(), "sanity check"); |
0 | 678 |
679 EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread))); | |
680 | |
681 JvmtiThreadState *state = thread->jvmti_thread_state(); | |
2126
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
1972
diff
changeset
|
682 assert(state != NULL, "else why are we here?"); |
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
1972
diff
changeset
|
683 delete state; |
0 | 684 } |
685 | |
686 void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env, | |
687 const jvmtiEventCallbacks* callbacks, | |
688 jint size_of_callbacks) { | |
689 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
690 EC_TRACE(("JVMTI [*] # set event callbacks")); | |
691 | |
692 env->set_event_callbacks(callbacks, size_of_callbacks); | |
693 jlong enabled_bits = 0; | |
694 for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) { | |
695 jvmtiEvent evt_t = (jvmtiEvent)ei; | |
696 if (env->has_callback(evt_t)) { | |
697 enabled_bits |= JvmtiEventEnabled::bit_for(evt_t); | |
698 } | |
699 } | |
700 env->env_event_enable()->_event_callback_enabled.set_bits(enabled_bits); | |
701 recompute_enabled(); | |
702 } | |
703 | |
704 void | |
705 JvmtiEventControllerPrivate::set_extension_event_callback(JvmtiEnvBase *env, | |
706 jint extension_event_index, | |
707 jvmtiExtensionEvent callback) | |
708 { | |
709 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
710 EC_TRACE(("JVMTI [*] # set extension event callback")); | |
711 | |
712 // extension events are allocated below JVMTI_MIN_EVENT_TYPE_VAL | |
713 assert(extension_event_index >= (jint)EXT_MIN_EVENT_TYPE_VAL && | |
714 extension_event_index <= (jint)EXT_MAX_EVENT_TYPE_VAL, "sanity check"); | |
715 | |
716 | |
717 // As the bits for both standard (jvmtiEvent) and extension | |
718 // (jvmtiExtEvents) are stored in the same word we cast here to | |
719 // jvmtiEvent to set/clear the bit for this extension event. | |
720 jvmtiEvent event_type = (jvmtiEvent)extension_event_index; | |
721 | |
722 // Prevent a possible race condition where events are re-enabled by a call to | |
723 // set event callbacks, where the DisposeEnvironment occurs after the boiler-plate | |
724 // environment check and before the lock is acquired. | |
725 // We can safely do the is_valid check now, as JvmtiThreadState_lock is held. | |
726 bool enabling = (callback != NULL) && (env->is_valid()); | |
727 env->env_event_enable()->set_user_enabled(event_type, enabling); | |
728 | |
729 // update the callback | |
730 jvmtiExtEventCallbacks* ext_callbacks = env->ext_callbacks(); | |
731 switch (extension_event_index) { | |
732 case EXT_EVENT_CLASS_UNLOAD : | |
733 ext_callbacks->ClassUnload = callback; | |
734 break; | |
735 default: | |
736 ShouldNotReachHere(); | |
737 } | |
738 | |
739 // update the callback enable/disable bit | |
740 jlong enabled_bits = env->env_event_enable()->_event_callback_enabled.get_bits(); | |
741 jlong bit_for = JvmtiEventEnabled::bit_for(event_type); | |
742 if (enabling) { | |
743 enabled_bits |= bit_for; | |
744 } else { | |
745 enabled_bits &= ~bit_for; | |
746 } | |
747 env->env_event_enable()->_event_callback_enabled.set_bits(enabled_bits); | |
748 | |
749 recompute_enabled(); | |
750 } | |
751 | |
752 | |
753 void | |
754 JvmtiEventControllerPrivate::env_initialize(JvmtiEnvBase *env) { | |
755 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
756 EC_TRACE(("JVMTI [*] # env initialize")); | |
757 | |
758 if (JvmtiEnvBase::is_vm_live()) { | |
759 // if we didn't initialize event info already (this is a late | |
760 // launched environment), do it now. | |
761 event_init(); | |
762 } | |
763 | |
764 env->initialize(); | |
765 | |
766 // add the JvmtiEnvThreadState to each JvmtiThreadState | |
767 for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) { | |
768 state->add_env(env); | |
769 assert((JvmtiEnv*)(state->env_thread_state(env)->get_env()) == env, "sanity check"); | |
770 } | |
771 JvmtiEventControllerPrivate::recompute_enabled(); | |
772 } | |
773 | |
774 | |
775 void | |
776 JvmtiEventControllerPrivate::env_dispose(JvmtiEnvBase *env) { | |
777 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
778 EC_TRACE(("JVMTI [*] # env dispose")); | |
779 | |
780 // Before the environment is marked disposed, disable all events on this | |
781 // environment (by zapping the callbacks). As a result, the disposed | |
782 // environment will not call event handlers. | |
783 set_event_callbacks(env, NULL, 0); | |
784 for (jint extension_event_index = EXT_MIN_EVENT_TYPE_VAL; | |
785 extension_event_index <= EXT_MAX_EVENT_TYPE_VAL; | |
786 ++extension_event_index) { | |
787 set_extension_event_callback(env, extension_event_index, NULL); | |
788 } | |
789 | |
790 // Let the environment finish disposing itself. | |
791 env->env_dispose(); | |
792 } | |
793 | |
794 | |
795 void | |
796 JvmtiEventControllerPrivate::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, | |
797 jvmtiEvent event_type, bool enabled) { | |
798 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
799 | |
800 EC_TRACE(("JVMTI [%s] # user %s event %s", | |
801 thread==NULL? "ALL": JvmtiTrace::safe_get_thread_name(thread), | |
802 enabled? "enabled" : "disabled", JvmtiTrace::event_name(event_type))); | |
803 | |
804 if (thread == NULL) { | |
805 env->env_event_enable()->set_user_enabled(event_type, enabled); | |
806 } else { | |
807 // create the thread state (if it didn't exist before) | |
808 JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread); | |
809 if (state != NULL) { | |
810 state->env_thread_state(env)->event_enable()->set_user_enabled(event_type, enabled); | |
811 } | |
812 } | |
813 recompute_enabled(); | |
814 } | |
815 | |
816 | |
817 void | |
818 JvmtiEventControllerPrivate::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { | |
819 EC_TRACE(("JVMTI [%s] # set frame pop - frame=%d", | |
820 JvmtiTrace::safe_get_thread_name(ets->get_thread()), | |
821 fpop.frame_number() )); | |
822 | |
823 ets->get_frame_pops()->set(fpop); | |
824 recompute_thread_enabled(ets->get_thread()->jvmti_thread_state()); | |
825 } | |
826 | |
827 | |
828 void | |
829 JvmtiEventControllerPrivate::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { | |
830 EC_TRACE(("JVMTI [%s] # clear frame pop - frame=%d", | |
831 JvmtiTrace::safe_get_thread_name(ets->get_thread()), | |
832 fpop.frame_number() )); | |
833 | |
834 ets->get_frame_pops()->clear(fpop); | |
835 recompute_thread_enabled(ets->get_thread()->jvmti_thread_state()); | |
836 } | |
837 | |
838 | |
839 void | |
840 JvmtiEventControllerPrivate::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { | |
841 int cleared_cnt = ets->get_frame_pops()->clear_to(fpop); | |
842 | |
843 EC_TRACE(("JVMTI [%s] # clear to frame pop - frame=%d, count=%d", | |
844 JvmtiTrace::safe_get_thread_name(ets->get_thread()), | |
845 fpop.frame_number(), | |
846 cleared_cnt )); | |
847 | |
848 if (cleared_cnt > 0) { | |
849 recompute_thread_enabled(ets->get_thread()->jvmti_thread_state()); | |
850 } | |
851 } | |
852 | |
853 void | |
854 JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool added) { | |
855 int *count_addr; | |
856 | |
857 switch (event_type) { | |
858 case JVMTI_EVENT_FIELD_MODIFICATION: | |
859 count_addr = (int *)JvmtiExport::get_field_modification_count_addr(); | |
860 break; | |
861 case JVMTI_EVENT_FIELD_ACCESS: | |
862 count_addr = (int *)JvmtiExport::get_field_access_count_addr(); | |
863 break; | |
864 default: | |
865 assert(false, "incorrect event"); | |
866 return; | |
867 } | |
868 | |
869 EC_TRACE(("JVMTI [-] # change field watch - %s %s count=%d", | |
870 event_type==JVMTI_EVENT_FIELD_MODIFICATION? "modification" : "access", | |
871 added? "add" : "remove", | |
872 *count_addr)); | |
873 | |
874 if (added) { | |
875 (*count_addr)++; | |
876 if (*count_addr == 1) { | |
877 recompute_enabled(); | |
878 } | |
879 } else { | |
880 if (*count_addr > 0) { | |
881 (*count_addr)--; | |
882 if (*count_addr == 0) { | |
883 recompute_enabled(); | |
884 } | |
885 } else { | |
886 assert(false, "field watch out of phase"); | |
887 } | |
888 } | |
889 } | |
890 | |
891 void | |
892 JvmtiEventControllerPrivate::event_init() { | |
893 assert(JvmtiThreadState_lock->is_locked(), "sanity check"); | |
894 | |
895 if (_initialized) { | |
896 return; | |
897 } | |
898 | |
899 EC_TRACE(("JVMTI [-] # VM live")); | |
900 | |
901 #ifdef ASSERT | |
902 // check that our idea and the spec's idea of threaded events match | |
903 for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) { | |
904 jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei); | |
905 assert(((THREAD_FILTERED_EVENT_BITS & bit) != 0) == JvmtiUtil::event_threaded(ei), | |
906 "thread filtered event list does not match"); | |
907 } | |
908 #endif | |
909 | |
910 _initialized = true; | |
911 } | |
912 | |
913 void | |
914 JvmtiEventControllerPrivate::vm_start() { | |
915 // some events are now able to be enabled (phase has changed) | |
916 JvmtiEventControllerPrivate::recompute_enabled(); | |
917 } | |
918 | |
919 | |
920 void | |
921 JvmtiEventControllerPrivate::vm_init() { | |
922 event_init(); | |
923 | |
924 // all the events are now able to be enabled (phase has changed) | |
925 JvmtiEventControllerPrivate::recompute_enabled(); | |
926 } | |
927 | |
928 | |
929 void | |
930 JvmtiEventControllerPrivate::vm_death() { | |
931 // events are disabled (phase has changed) | |
932 JvmtiEventControllerPrivate::recompute_enabled(); | |
933 } | |
934 | |
935 | |
936 /////////////////////////////////////////////////////////////// | |
937 // | |
938 // JvmtiEventController | |
939 // | |
940 | |
941 JvmtiEventEnabled JvmtiEventController::_universal_global_event_enabled; | |
942 | |
943 bool | |
944 JvmtiEventController::is_global_event(jvmtiEvent event_type) { | |
945 assert(is_valid_event_type(event_type), "invalid event type"); | |
946 jlong bit_for = ((jlong)1) << (event_type - TOTAL_MIN_EVENT_TYPE_VAL); | |
947 return((bit_for & GLOBAL_EVENT_BITS)!=0); | |
948 } | |
949 | |
950 void | |
951 JvmtiEventController::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, jvmtiEvent event_type, bool enabled) { | |
952 if (Threads::number_of_threads() == 0) { | |
953 // during early VM start-up locks don't exist, but we are safely single threaded, | |
954 // call the functionality without holding the JvmtiThreadState_lock. | |
955 JvmtiEventControllerPrivate::set_user_enabled(env, thread, event_type, enabled); | |
956 } else { | |
957 MutexLocker mu(JvmtiThreadState_lock); | |
958 JvmtiEventControllerPrivate::set_user_enabled(env, thread, event_type, enabled); | |
959 } | |
960 } | |
961 | |
962 | |
963 void | |
964 JvmtiEventController::set_event_callbacks(JvmtiEnvBase *env, | |
965 const jvmtiEventCallbacks* callbacks, | |
966 jint size_of_callbacks) { | |
967 if (Threads::number_of_threads() == 0) { | |
968 // during early VM start-up locks don't exist, but we are safely single threaded, | |
969 // call the functionality without holding the JvmtiThreadState_lock. | |
970 JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks); | |
971 } else { | |
972 MutexLocker mu(JvmtiThreadState_lock); | |
973 JvmtiEventControllerPrivate::set_event_callbacks(env, callbacks, size_of_callbacks); | |
974 } | |
975 } | |
976 | |
977 void | |
978 JvmtiEventController::set_extension_event_callback(JvmtiEnvBase *env, | |
979 jint extension_event_index, | |
980 jvmtiExtensionEvent callback) { | |
981 if (Threads::number_of_threads() == 0) { | |
982 JvmtiEventControllerPrivate::set_extension_event_callback(env, extension_event_index, callback); | |
983 } else { | |
984 MutexLocker mu(JvmtiThreadState_lock); | |
985 JvmtiEventControllerPrivate::set_extension_event_callback(env, extension_event_index, callback); | |
986 } | |
987 } | |
988 | |
989 | |
990 | |
991 | |
992 void | |
993 JvmtiEventController::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { | |
994 MutexLocker mu(JvmtiThreadState_lock); | |
995 JvmtiEventControllerPrivate::set_frame_pop(ets, fpop); | |
996 } | |
997 | |
998 | |
999 void | |
1000 JvmtiEventController::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { | |
1001 MutexLocker mu(JvmtiThreadState_lock); | |
1002 JvmtiEventControllerPrivate::clear_frame_pop(ets, fpop); | |
1003 } | |
1004 | |
1005 | |
1006 void | |
1007 JvmtiEventController::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { | |
1008 MutexLocker mu(JvmtiThreadState_lock); | |
1009 JvmtiEventControllerPrivate::clear_to_frame_pop(ets, fpop); | |
1010 } | |
1011 | |
1012 void | |
1013 JvmtiEventController::change_field_watch(jvmtiEvent event_type, bool added) { | |
1014 MutexLocker mu(JvmtiThreadState_lock); | |
1015 JvmtiEventControllerPrivate::change_field_watch(event_type, added); | |
1016 } | |
1017 | |
1018 void | |
1019 JvmtiEventController::thread_started(JavaThread *thread) { | |
1020 // operates only on the current thread | |
1021 // JvmtiThreadState_lock grabbed only if needed. | |
1022 JvmtiEventControllerPrivate::thread_started(thread); | |
1023 } | |
1024 | |
1025 void | |
1026 JvmtiEventController::thread_ended(JavaThread *thread) { | |
1027 // operates only on the current thread | |
1028 // JvmtiThreadState_lock grabbed only if needed. | |
1029 JvmtiEventControllerPrivate::thread_ended(thread); | |
1030 } | |
1031 | |
1032 void | |
1033 JvmtiEventController::env_initialize(JvmtiEnvBase *env) { | |
1034 if (Threads::number_of_threads() == 0) { | |
1035 // during early VM start-up locks don't exist, but we are safely single threaded, | |
1036 // call the functionality without holding the JvmtiThreadState_lock. | |
1037 JvmtiEventControllerPrivate::env_initialize(env); | |
1038 } else { | |
1039 MutexLocker mu(JvmtiThreadState_lock); | |
1040 JvmtiEventControllerPrivate::env_initialize(env); | |
1041 } | |
1042 } | |
1043 | |
1044 void | |
1045 JvmtiEventController::env_dispose(JvmtiEnvBase *env) { | |
1046 if (Threads::number_of_threads() == 0) { | |
1047 // during early VM start-up locks don't exist, but we are safely single threaded, | |
1048 // call the functionality without holding the JvmtiThreadState_lock. | |
1049 JvmtiEventControllerPrivate::env_dispose(env); | |
1050 } else { | |
1051 MutexLocker mu(JvmtiThreadState_lock); | |
1052 JvmtiEventControllerPrivate::env_dispose(env); | |
1053 } | |
1054 } | |
1055 | |
1056 | |
1057 void | |
1058 JvmtiEventController::vm_start() { | |
1059 if (JvmtiEnvBase::environments_might_exist()) { | |
1060 MutexLocker mu(JvmtiThreadState_lock); | |
1061 JvmtiEventControllerPrivate::vm_start(); | |
1062 } | |
1063 } | |
1064 | |
1065 void | |
1066 JvmtiEventController::vm_init() { | |
1067 if (JvmtiEnvBase::environments_might_exist()) { | |
1068 MutexLocker mu(JvmtiThreadState_lock); | |
1069 JvmtiEventControllerPrivate::vm_init(); | |
1070 } | |
1071 } | |
1072 | |
1073 void | |
1074 JvmtiEventController::vm_death() { | |
1075 if (JvmtiEnvBase::environments_might_exist()) { | |
1076 MutexLocker mu(JvmtiThreadState_lock); | |
1077 JvmtiEventControllerPrivate::vm_death(); | |
1078 } | |
1079 } |