common.opt (Warray-bounds): Add Warning attribute.
[gcc.git] / libjava / jvmti.cc
1 // jvmti.cc - JVMTI implementation
2
3 /* Copyright (C) 2006, 2007 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 #include <config.h>
12 #include <platform.h>
13
14 #include <jvm.h>
15 #include <java-threads.h>
16 #include <java-gc.h>
17 #include <java-interp.h>
18 #include <jvmti.h>
19 #include "jvmti-int.h"
20
21 #include <gcj/method.h>
22
23 #include <gnu/classpath/SystemProperties.h>
24 #include <gnu/gcj/runtime/BootClassLoader.h>
25 #include <gnu/gcj/jvmti/Breakpoint.h>
26 #include <gnu/gcj/jvmti/BreakpointManager.h>
27
28 #include <java/lang/Class.h>
29 #include <java/lang/ClassLoader.h>
30 #include <java/lang/OutOfMemoryError.h>
31 #include <java/lang/Thread.h>
32 #include <java/lang/ThreadGroup.h>
33 #include <java/lang/Throwable.h>
34 #include <java/lang/VMClassLoader.h>
35 #include <java/lang/reflect/Field.h>
36 #include <java/lang/reflect/Modifier.h>
37 #include <java/util/Collection.h>
38 #include <java/util/HashMap.h>
39 #include <java/util/concurrent/locks/Lock.h>
40 #include <java/util/concurrent/locks/ReentrantReadWriteLock.h>
41 #include <java/net/URL.h>
42
43 static void check_enabled_events (void);
44 static void check_enabled_event (jvmtiEvent);
45
46 namespace JVMTI
47 {
48 // Is JVMTI enabled? (i.e., any jvmtiEnv created?)
49 bool enabled;
50
51 // Event notifications
52 bool VMInit = false;
53 bool VMDeath = false;
54 bool ThreadStart = false;
55 bool ThreadEnd = false;
56 bool ClassFileLoadHook = false;
57 bool ClassLoad = false;
58 bool ClassPrepare = false;
59 bool VMStart = false;
60 bool Exception = false;
61 bool ExceptionCatch = false;
62 bool SingleStep = false;
63 bool FramePop = false;
64 bool Breakpoint = false;
65 bool FieldAccess = false;
66 bool FieldModification = false;
67 bool MethodEntry = false;
68 bool MethodExit = false;
69 bool NativeMethodBind = false;
70 bool CompiledMethodLoad = false;
71 bool CompiledMethodUnload = false;
72 bool DynamicCodeGenerated = false;
73 bool DataDumpRequest = false;
74 bool reserved72 = false;
75 bool MonitorWait = false;
76 bool MonitorWaited = false;
77 bool MonitorContendedEnter = false;
78 bool MonitorContendedEntered = false;
79 bool reserved77 = false;
80 bool reserved78 = false;
81 bool reserved79 = false;
82 bool reserved80 = false;
83 bool GarbageCollectionStart = false;
84 bool GarbageCollectionFinish = false;
85 bool ObjectFree = false;
86 bool VMObjectAlloc = false;
87 };
88
89 extern struct JNINativeInterface _Jv_JNIFunctions;
90
91 struct _Jv_rawMonitorID
92 {
93 _Jv_Mutex_t mutex;
94 _Jv_ConditionVariable_t condition;
95 };
96
97 /* A simple linked list of all JVMTI environments. Since
98 events must be delivered to environments in the order
99 in which the environments were created, new environments
100 are added to the end of the list. */
101 struct jvmti_env_list
102 {
103 jvmtiEnv *env;
104 struct jvmti_env_list *next;
105 };
106 static struct jvmti_env_list *_jvmtiEnvironments = NULL;
107 static java::util::concurrent::locks::
108 ReentrantReadWriteLock *_envListLock = NULL;
109 #define FOREACH_ENVIRONMENT(Ele) \
110 for (Ele = _jvmtiEnvironments; Ele != NULL; Ele = Ele->next)
111
112 // Some commonly-used checks
113
114 #define THREAD_DEFAULT_TO_CURRENT(Ajthread) \
115 do \
116 { \
117 if (Ajthread == NULL) \
118 Ajthread = java::lang::Thread::currentThread (); \
119 } \
120 while (0)
121
122 #define THREAD_CHECK_VALID(Athread) \
123 do \
124 { \
125 if (!java::lang::Thread::class$.isAssignableFrom (&(Athread->class$))) \
126 return JVMTI_ERROR_INVALID_THREAD; \
127 } \
128 while (0)
129
130 #define THREAD_CHECK_IS_ALIVE(Athread) \
131 do \
132 { \
133 if (!Athread->isAlive ()) \
134 return JVMTI_ERROR_THREAD_NOT_ALIVE; \
135 } \
136 while (0)
137
138 // FIXME: if current phase is not set in Phases,
139 // return JVMTI_ERROR_WRONG_PHASE
140 #define REQUIRE_PHASE(Env, Phases)
141
142 #define NULL_CHECK(Ptr) \
143 do \
144 { \
145 if (Ptr == NULL) \
146 return JVMTI_ERROR_NULL_POINTER; \
147 } \
148 while (0)
149
150 #define ILLEGAL_ARGUMENT(Cond) \
151 do \
152 { \
153 if ((Cond)) \
154 return JVMTI_ERROR_ILLEGAL_ARGUMENT; \
155 } \
156 while (0)
157
158 #define CHECK_FOR_NATIVE_METHOD(AjmethodID) \
159 do \
160 { \
161 jboolean is_native; \
162 jvmtiError jerr = env->IsMethodNative (AjmethodID, &is_native); \
163 if (jerr != JVMTI_ERROR_NONE) \
164 return jerr; \
165 if (is_native) \
166 return JVMTI_ERROR_NATIVE_METHOD; \
167 } \
168 while (0)
169
170 static jvmtiError JNICALL
171 _Jv_JVMTI_SuspendThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
172 {
173 using namespace java::lang;
174
175 THREAD_DEFAULT_TO_CURRENT (thread);
176 THREAD_CHECK_VALID (thread);
177 THREAD_CHECK_IS_ALIVE (thread);
178
179 _Jv_Thread_t *data = _Jv_ThreadGetData (thread);
180 _Jv_SuspendThread (data);
181 return JVMTI_ERROR_NONE;
182 }
183
184 static jvmtiError JNICALL
185 _Jv_JVMTI_ResumeThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
186 {
187 using namespace java::lang;
188
189 THREAD_DEFAULT_TO_CURRENT (thread);
190 THREAD_CHECK_VALID (thread);
191 THREAD_CHECK_IS_ALIVE (thread);
192
193 _Jv_Thread_t *data = _Jv_ThreadGetData (thread);
194 _Jv_ResumeThread (data);
195 return JVMTI_ERROR_NONE;
196 }
197
198 static jvmtiError JNICALL
199 _Jv_JVMTI_InterruptThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
200 {
201 using namespace java::lang;
202
203 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
204 // FIXME: capability handling? 'can_signal_thread'
205 if (thread == NULL)
206 return JVMTI_ERROR_INVALID_THREAD;
207
208 THREAD_CHECK_VALID (thread);
209 THREAD_CHECK_IS_ALIVE (thread);
210 thread->interrupt();
211 return JVMTI_ERROR_NONE;
212 }
213
214 // This method performs the common tasks to get and set variables of all types.
215 // It is called by the _Jv_JVMTI_Get/SetLocalInt/Object/.... methods.
216 static jvmtiError
217 getLocalFrame (jvmtiEnv *env, jthread thread, jint depth, jint slot, char type,
218 _Jv_InterpFrame **iframe)
219 {
220 using namespace java::lang;
221
222 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
223
224 ILLEGAL_ARGUMENT (depth < 0);
225
226 THREAD_DEFAULT_TO_CURRENT (thread);
227 THREAD_CHECK_VALID (thread);
228 THREAD_CHECK_IS_ALIVE (thread);
229
230 _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
231
232 for (int i = 0; i < depth; i++)
233 {
234 frame = frame->next;
235
236 if (frame == NULL)
237 return JVMTI_ERROR_NO_MORE_FRAMES;
238 }
239
240 if (frame->frame_type == frame_native)
241 return JVMTI_ERROR_OPAQUE_FRAME;
242
243 jint max_locals;
244 jvmtiError jerr = env->GetMaxLocals (reinterpret_cast<jmethodID>
245 (frame->self->get_method ()),
246 &max_locals);
247 if (jerr != JVMTI_ERROR_NONE)
248 return jerr;
249
250 _Jv_InterpFrame *tmp_iframe = reinterpret_cast<_Jv_InterpFrame *> (frame);
251
252 // The second slot taken up by a long type is marked as type 'x' meaning it
253 // is not valid for access since it holds only the 4 low bytes of the value.
254 if (tmp_iframe->locals_type[slot] == 'x')
255 return JVMTI_ERROR_INVALID_SLOT;
256
257 if (tmp_iframe->locals_type[slot] != type)
258 return JVMTI_ERROR_TYPE_MISMATCH;
259
260 // Check for invalid slots, if the type is a long type, we must check that
261 // the next slot is valid as well.
262 if (slot < 0 || slot >= max_locals
263 || ((type == 'l' || type == 'd') && slot + 1 >= max_locals))
264 return JVMTI_ERROR_INVALID_SLOT;
265
266 *iframe = tmp_iframe;
267
268 return JVMTI_ERROR_NONE;
269 }
270
271 static jvmtiError JNICALL
272 _Jv_JVMTI_GetLocalObject (jvmtiEnv *env, jthread thread, jint depth, jint slot,
273 jobject *value)
274 {
275 NULL_CHECK (value);
276
277 _Jv_InterpFrame *frame;
278 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'o', &frame);
279
280 if (jerr != JVMTI_ERROR_NONE)
281 return jerr;
282
283 *value = frame->locals[slot].o;
284
285 return JVMTI_ERROR_NONE;
286 }
287
288 static jvmtiError JNICALL
289 _Jv_JVMTI_SetLocalObject (jvmtiEnv *env, jthread thread, jint depth, jint slot,
290 jobject value)
291 {
292 _Jv_InterpFrame *frame;
293 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'o', &frame);
294
295 if (jerr != JVMTI_ERROR_NONE)
296 return jerr;
297
298 frame->locals[slot].o = value;
299
300 return JVMTI_ERROR_NONE;
301 }
302
303 static jvmtiError JNICALL
304 _Jv_JVMTI_GetLocalInt (jvmtiEnv *env, jthread thread, jint depth, jint slot,
305 jint *value)
306 {
307 NULL_CHECK (value);
308
309 _Jv_InterpFrame *frame;
310 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'i', &frame);
311
312 if (jerr != JVMTI_ERROR_NONE)
313 return jerr;
314
315 *value = frame->locals[slot].i;
316
317 return JVMTI_ERROR_NONE;
318 }
319
320 static jvmtiError JNICALL
321 _Jv_JVMTI_SetLocalInt (jvmtiEnv *env, jthread thread, jint depth, jint slot,
322 jint value)
323 {
324 _Jv_InterpFrame *frame;
325 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'i', &frame);
326
327 if (jerr != JVMTI_ERROR_NONE)
328 return jerr;
329
330 frame->locals[slot].i = value;
331
332 return JVMTI_ERROR_NONE;
333 }
334
335 static jvmtiError JNICALL
336 _Jv_JVMTI_GetLocalLong (jvmtiEnv *env, jthread thread, jint depth, jint slot,
337 jlong *value)
338 {
339 NULL_CHECK (value);
340
341 _Jv_InterpFrame *frame;
342 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'l', &frame);
343
344 if (jerr != JVMTI_ERROR_NONE)
345 return jerr;
346
347 #if SIZEOF_VOID_P==8
348 *value = frame->locals[slot].l;
349 #else
350 _Jv_word2 val;
351 val.ia[0] = frame->locals[slot].ia[0];
352 val.ia[1] = frame->locals[slot + 1].ia[0];
353 *value = val.l;
354 #endif
355
356 return JVMTI_ERROR_NONE;
357 }
358
359 static jvmtiError JNICALL
360 _Jv_JVMTI_SetLocalLong (jvmtiEnv *env, jthread thread, jint depth, jint slot,
361 jlong value)
362 {
363 _Jv_InterpFrame *frame;
364 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'l', &frame);
365
366 if (jerr != JVMTI_ERROR_NONE)
367 return jerr;
368
369 #if SIZEOF_VOID_P==8
370 frame->locals[slot].l = value;
371 #else
372 _Jv_word2 val;
373 val.l = value;
374 frame->locals[slot].ia[0] = val.ia[0];
375 frame->locals[slot + 1].ia[0] = val.ia[1];
376 #endif
377
378 return JVMTI_ERROR_NONE;
379 }
380
381
382 static jvmtiError JNICALL
383 _Jv_JVMTI_GetLocalFloat (jvmtiEnv *env, jthread thread, jint depth, jint slot,
384 jfloat *value)
385 {
386 NULL_CHECK (value);
387
388 _Jv_InterpFrame *frame;
389 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'f', &frame);
390
391 if (jerr != JVMTI_ERROR_NONE)
392 return jerr;
393
394 *value = frame->locals[slot].f;
395
396 return JVMTI_ERROR_NONE;
397 }
398
399 static jvmtiError JNICALL
400 _Jv_JVMTI_SetLocalFloat (jvmtiEnv *env, jthread thread, jint depth, jint slot,
401 jfloat value)
402 {
403 _Jv_InterpFrame *frame;
404 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'f', &frame);
405
406 if (jerr != JVMTI_ERROR_NONE)
407 return jerr;
408
409 frame->locals[slot].f = value;
410
411 return JVMTI_ERROR_NONE;
412 }
413
414
415 static jvmtiError JNICALL
416 _Jv_JVMTI_GetLocalDouble (jvmtiEnv *env, jthread thread, jint depth, jint slot,
417 jdouble *value)
418 {
419 NULL_CHECK (value);
420
421 _Jv_InterpFrame *frame;
422 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'd', &frame);
423
424 if (jerr != JVMTI_ERROR_NONE)
425 return jerr;
426
427 #if SIZEOF_VOID_P==8
428 *value = frame->locals[slot].d;
429 #else
430 _Jv_word2 val;
431 val.ia[0] = frame->locals[slot].ia[0];
432 val.ia[1] = frame->locals[slot + 1].ia[0];
433 *value = val.d;
434 #endif
435
436 return JVMTI_ERROR_NONE;
437 }
438
439 static jvmtiError JNICALL
440 _Jv_JVMTI_SetLocalDouble (jvmtiEnv *env, jthread thread, jint depth, jint slot,
441 jdouble value)
442 {
443 _Jv_InterpFrame *frame;
444 jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'd', &frame);
445
446 if (jerr != JVMTI_ERROR_NONE)
447 return jerr;
448
449 #if SIZEOF_VOID_P==8
450 frame->locals[slot].d = value;
451 #else
452 _Jv_word2 val;
453 val.d = value;
454 frame->locals[slot].ia[0] = val.ia[0];
455 frame->locals[slot + 1].ia[0] = val.ia[1];
456 #endif
457
458 return JVMTI_ERROR_NONE;
459 }
460
461 static jvmtiError JNICALL
462 _Jv_JVMTI_GetAllThreads(MAYBE_UNUSED jvmtiEnv *env, jint *thread_cnt,
463 jthread **threads)
464 {
465 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
466 NULL_CHECK (thread_cnt);
467 NULL_CHECK (threads);
468
469 using namespace java::lang;
470
471 ThreadGroup *root_grp = ThreadGroup::root;
472 jint estimate = root_grp->activeCount ();
473
474 JArray<Thread *> *thr_arr;
475
476 // Allocate some extra space since threads can be created between calls
477 try
478 {
479 thr_arr = reinterpret_cast<JArray<Thread *> *> (JvNewObjectArray
480 ((estimate * 2),
481 &Thread::class$, NULL));
482 }
483 catch (java::lang::OutOfMemoryError *err)
484 {
485 return JVMTI_ERROR_OUT_OF_MEMORY;
486 }
487
488 *thread_cnt = root_grp->enumerate (thr_arr);
489
490 jvmtiError jerr = env->Allocate ((jlong) ((*thread_cnt) * sizeof (jthread)),
491 (unsigned char **) threads);
492
493 if (jerr != JVMTI_ERROR_NONE)
494 return jerr;
495
496 // Transfer the threads to the result array
497 jthread *tmp_arr = reinterpret_cast<jthread *> (elements (thr_arr));
498
499 memcpy ((*threads), tmp_arr, (*thread_cnt));
500
501 return JVMTI_ERROR_NONE;
502 }
503
504 static jvmtiError JNICALL
505 _Jv_JVMTI_GetFrameCount (MAYBE_UNUSED jvmtiEnv *env, jthread thread,
506 jint *frame_count)
507 {
508 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
509
510 NULL_CHECK (frame_count);
511
512 using namespace java::lang;
513
514 THREAD_DEFAULT_TO_CURRENT (thread);
515 THREAD_CHECK_VALID (thread);
516 THREAD_CHECK_IS_ALIVE (thread);
517
518 _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
519 (*frame_count) = frame->depth ();
520 return JVMTI_ERROR_NONE;
521 }
522
523 static jvmtiError JNICALL
524 _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name,
525 jrawMonitorID *result)
526 {
527 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
528 NULL_CHECK (name);
529 NULL_CHECK (result);
530 *result = (jrawMonitorID) _Jv_MallocUnchecked (sizeof (_Jv_rawMonitorID));
531 if (*result == NULL)
532 return JVMTI_ERROR_OUT_OF_MEMORY;
533 _Jv_MutexInit (&(*result)->mutex);
534 _Jv_CondInit (&(*result)->condition);
535 return JVMTI_ERROR_NONE;
536 }
537
538 static jvmtiError JNICALL
539 _Jv_JVMTI_DestroyRawMonitor (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
540 {
541 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
542 // Note we have no better way of knowing whether this object is
543 // really a raw monitor.
544 if (monitor == NULL)
545 return JVMTI_ERROR_INVALID_MONITOR;
546 // FIXME: perform checks on monitor, release it if this thread owns
547 // it.
548 #ifdef _Jv_HaveMutexDestroy
549 _Jv_MutexDestroy (&monitor->mutex);
550 #endif
551 _Jv_Free (monitor);
552 return JVMTI_ERROR_NONE;
553 }
554
555 static jvmtiError JNICALL
556 _Jv_JVMTI_RawMonitorEnter (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
557 {
558 if (monitor == NULL)
559 return JVMTI_ERROR_INVALID_MONITOR;
560 _Jv_MutexLock (&monitor->mutex);
561 return JVMTI_ERROR_NONE;
562 }
563
564 static jvmtiError JNICALL
565 _Jv_JVMTI_RawMonitorExit (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
566 {
567 if (monitor == NULL)
568 return JVMTI_ERROR_INVALID_MONITOR;
569 if (_Jv_MutexUnlock (&monitor->mutex))
570 return JVMTI_ERROR_NOT_MONITOR_OWNER;
571 return JVMTI_ERROR_NONE;
572 }
573
574 static jvmtiError JNICALL
575 _Jv_JVMTI_RawMonitorWait (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor,
576 jlong millis)
577 {
578 if (monitor == NULL)
579 return JVMTI_ERROR_INVALID_MONITOR;
580 int r = _Jv_CondWait (&monitor->condition, &monitor->mutex, millis, 0);
581 if (r == _JV_NOT_OWNER)
582 return JVMTI_ERROR_NOT_MONITOR_OWNER;
583 if (r == _JV_INTERRUPTED)
584 return JVMTI_ERROR_INTERRUPT;
585 return JVMTI_ERROR_NONE;
586 }
587
588 static jvmtiError JNICALL
589 _Jv_JVMTI_RawMonitorNotify (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
590 {
591 if (monitor == NULL)
592 return JVMTI_ERROR_INVALID_MONITOR;
593 if (_Jv_CondNotify (&monitor->condition, &monitor->mutex) == _JV_NOT_OWNER)
594 return JVMTI_ERROR_NOT_MONITOR_OWNER;
595 return JVMTI_ERROR_NONE;
596 }
597
598 static jvmtiError JNICALL
599 _Jv_JVMTI_RawMonitorNotifyAll (MAYBE_UNUSED jvmtiEnv *env,
600 jrawMonitorID monitor)
601 {
602 if (monitor == NULL)
603 return JVMTI_ERROR_INVALID_MONITOR;
604 if (_Jv_CondNotifyAll (&monitor->condition, &monitor->mutex)
605 == _JV_NOT_OWNER)
606 return JVMTI_ERROR_NOT_MONITOR_OWNER;
607 return JVMTI_ERROR_NONE;
608 }
609
610 static jvmtiError JNICALL
611 _Jv_JVMTI_SetBreakpoint (jvmtiEnv *env, jmethodID method, jlocation location)
612 {
613 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
614
615 using namespace gnu::gcj::jvmti;
616 Breakpoint *bp
617 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
618 location);
619 if (bp == NULL)
620 {
621 jclass klass;
622 jvmtiError err = env->GetMethodDeclaringClass (method, &klass);
623 if (err != JVMTI_ERROR_NONE)
624 return err;
625
626 if (!_Jv_IsInterpretedClass (klass))
627 return JVMTI_ERROR_INVALID_CLASS;
628
629 _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method);
630 if (base == NULL)
631 return JVMTI_ERROR_INVALID_METHODID;
632
633 jint flags;
634 err = env->GetMethodModifiers (method, &flags);
635 if (err != JVMTI_ERROR_NONE)
636 return err;
637
638 if (flags & java::lang::reflect::Modifier::NATIVE)
639 return JVMTI_ERROR_NATIVE_METHOD;
640
641 _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base);
642 if (imeth->get_insn (location) == NULL)
643 return JVMTI_ERROR_INVALID_LOCATION;
644
645 // Now the breakpoint can be safely installed
646 bp = BreakpointManager::newBreakpoint (reinterpret_cast<jlong> (method),
647 location);
648 }
649 else
650 {
651 // Duplicate breakpoints are not permitted by JVMTI
652 return JVMTI_ERROR_DUPLICATE;
653 }
654
655 return JVMTI_ERROR_NONE;
656 }
657
658 static jvmtiError JNICALL
659 _Jv_JVMTI_ClearBreakpoint (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
660 jlocation location)
661 {
662 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
663
664 using namespace gnu::gcj::jvmti;
665
666 Breakpoint *bp
667 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
668 location);
669 if (bp == NULL)
670 return JVMTI_ERROR_NOT_FOUND;
671
672 BreakpointManager::deleteBreakpoint (reinterpret_cast<jlong> (method), location);
673 return JVMTI_ERROR_NONE;
674 }
675
676 static jvmtiError JNICALL
677 _Jv_JVMTI_Allocate (MAYBE_UNUSED jvmtiEnv *env, jlong size,
678 unsigned char **result)
679 {
680 ILLEGAL_ARGUMENT (size < 0);
681 NULL_CHECK (result);
682 if (size == 0)
683 *result = NULL;
684 else
685 {
686 *result = (unsigned char *) _Jv_MallocUnchecked (size);
687 if (*result == NULL)
688 return JVMTI_ERROR_OUT_OF_MEMORY;
689 }
690 return JVMTI_ERROR_NONE;
691 }
692
693 static jvmtiError JNICALL
694 _Jv_JVMTI_Deallocate (MAYBE_UNUSED jvmtiEnv *env, unsigned char *mem)
695 {
696 if (mem != NULL)
697 _Jv_Free (mem);
698 return JVMTI_ERROR_NONE;
699 }
700
701 static jvmtiError JNICALL
702 _Jv_JVMTI_GetClassStatus (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
703 jint *status_ptr)
704 {
705 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
706 NULL_CHECK (status_ptr);
707 if (klass == NULL)
708 return JVMTI_ERROR_INVALID_CLASS;
709
710 if (klass->isArray ())
711 *status_ptr = JVMTI_CLASS_STATUS_ARRAY;
712 else if (klass->isPrimitive ())
713 *status_ptr = JVMTI_CLASS_STATUS_PRIMITIVE;
714 else
715 {
716 jbyte state = _Jv_GetClassState (klass);
717 *status_ptr = 0;
718 if (state >= JV_STATE_LINKED)
719 (*status_ptr) |= JVMTI_CLASS_STATUS_VERIFIED;
720 if (state >= JV_STATE_PREPARED)
721 (*status_ptr) |= JVMTI_CLASS_STATUS_PREPARED;
722 if (state == JV_STATE_ERROR || state == JV_STATE_PHANTOM)
723 (*status_ptr) |= JVMTI_CLASS_STATUS_ERROR;
724 else if (state == JV_STATE_DONE)
725 (*status_ptr) |= JVMTI_CLASS_STATUS_INITIALIZED;
726 }
727
728 return JVMTI_ERROR_NONE;
729 }
730
731 static jvmtiError JNICALL
732 _Jv_JVMTI_GetClassModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
733 jint *mods)
734 {
735 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
736 // Don't bother checking KLASS' type.
737 if (klass == NULL)
738 return JVMTI_ERROR_INVALID_CLASS;
739 NULL_CHECK (mods);
740 *mods = klass->getModifiers();
741 return JVMTI_ERROR_NONE;
742 }
743
744 static jvmtiError JNICALL
745 _Jv_JVMTI_GetClassMethods (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
746 jint *count_ptr, jmethodID **methods_ptr)
747 {
748 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
749 // FIXME: capability can_maintain_original_method_order
750 // Don't bother checking KLASS' type.
751 if (klass == NULL)
752 return JVMTI_ERROR_INVALID_CLASS;
753 NULL_CHECK (count_ptr);
754 NULL_CHECK (methods_ptr);
755 *count_ptr = JvNumMethods(klass);
756
757 *methods_ptr
758 = (jmethodID *) _Jv_MallocUnchecked (*count_ptr * sizeof (jmethodID));
759 if (*methods_ptr == NULL)
760 return JVMTI_ERROR_OUT_OF_MEMORY;
761
762 jmethodID start = JvGetFirstMethod (klass);
763 for (jint i = 0; i < *count_ptr; ++i)
764 // FIXME: correct?
765 (*methods_ptr)[i] = start + i;
766
767 return JVMTI_ERROR_NONE;
768 }
769
770 static jvmtiError JNICALL
771 _Jv_JVMTI_IsInterface (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
772 jboolean *result)
773 {
774 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
775 if (klass == NULL)
776 return JVMTI_ERROR_INVALID_CLASS;
777 NULL_CHECK (result);
778 *result = klass->isInterface();
779 return JVMTI_ERROR_NONE;
780 }
781
782 static jvmtiError JNICALL
783 _Jv_JVMTI_IsArrayClass (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
784 jboolean *result)
785 {
786 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
787 if (klass == NULL)
788 return JVMTI_ERROR_INVALID_CLASS;
789 NULL_CHECK (result);
790 *result = klass->isArray();
791 return JVMTI_ERROR_NONE;
792 }
793
794 static jvmtiError JNICALL
795 _Jv_JVMTI_GetClassLoader (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
796 jobject *result)
797 {
798 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
799 if (klass == NULL)
800 return JVMTI_ERROR_INVALID_CLASS;
801 NULL_CHECK (result);
802 *result = klass->getClassLoaderInternal();
803 return JVMTI_ERROR_NONE;
804 }
805
806 static jvmtiError JNICALL
807 _Jv_JVMTI_GetObjectHashCode (MAYBE_UNUSED jvmtiEnv *env, jobject obj,
808 jint *result)
809 {
810 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
811 if (obj == NULL)
812 return JVMTI_ERROR_INVALID_OBJECT;
813 NULL_CHECK (result);
814 *result = _Jv_HashCode (obj);
815 return JVMTI_ERROR_NONE;
816 }
817
818 static jvmtiError JNICALL
819 _Jv_JVMTI_GetFieldModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
820 jfieldID field, jint *result)
821 {
822 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
823 if (klass == NULL)
824 return JVMTI_ERROR_INVALID_CLASS;
825 if (field == NULL)
826 return JVMTI_ERROR_INVALID_FIELDID;
827 NULL_CHECK (result);
828 *result = field->getModifiers();
829 return JVMTI_ERROR_NONE;
830 }
831
832 static jvmtiError JNICALL
833 _Jv_JVMTI_IsFieldSynthetic (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
834 jfieldID field, jboolean *result)
835 {
836 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
837 if (klass == NULL)
838 return JVMTI_ERROR_INVALID_CLASS;
839 if (field == NULL)
840 return JVMTI_ERROR_INVALID_FIELDID;
841 NULL_CHECK (result);
842
843 // FIXME: capability can_get_synthetic_attribute
844 *result = ((field->getModifiers() & java::lang::reflect::Modifier::SYNTHETIC)
845 != 0);
846 return JVMTI_ERROR_NONE;
847 }
848
849 static jvmtiError JNICALL
850 _Jv_JVMTI_GetMethodName (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
851 char **name_ptr, char **signature_ptr,
852 char **generic_ptr)
853 {
854 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
855
856 if (method == NULL)
857 return JVMTI_ERROR_INVALID_METHODID;
858
859 if (name_ptr != NULL)
860 {
861 int len = static_cast<int> (method->name->len ());
862 *name_ptr = (char *) _Jv_MallocUnchecked (len + 1);
863 if (*name_ptr == NULL)
864 return JVMTI_ERROR_OUT_OF_MEMORY;
865 strncpy (*name_ptr, method->name->chars (), len);
866 (*name_ptr)[len] = '\0';
867 }
868
869 if (signature_ptr != NULL)
870 {
871 int len = static_cast<int> (method->signature->len ());
872 *signature_ptr = (char *) _Jv_MallocUnchecked (len + 1);
873 if (*signature_ptr == NULL)
874 {
875 if (name_ptr != NULL)
876 _Jv_Free (*name_ptr);
877 return JVMTI_ERROR_OUT_OF_MEMORY;
878 }
879 strncpy (*signature_ptr, method->signature->chars (), len);
880 (*signature_ptr)[len] = '\0';
881 }
882
883 if (generic_ptr != NULL)
884 {
885 *generic_ptr = NULL;
886 }
887
888 return JVMTI_ERROR_NONE;
889 }
890
891 static jvmtiError JNICALL
892 _Jv_JVMTI_GetMethodModifiers (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
893 jint *result)
894 {
895 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
896 if (method == NULL)
897 return JVMTI_ERROR_INVALID_METHODID;
898 NULL_CHECK (result);
899
900 // FIXME: mask off some internal bits...
901 *result = method->accflags;
902 return JVMTI_ERROR_NONE;
903 }
904
905 static jvmtiError JNICALL
906 _Jv_JVMTI_GetLineNumberTable (jvmtiEnv *env, jmethodID method,
907 jint *entry_count_ptr,
908 jvmtiLineNumberEntry **table_ptr)
909 {
910 NULL_CHECK (entry_count_ptr);
911 NULL_CHECK (table_ptr);
912
913 jclass klass;
914 jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass);
915 if (jerr != JVMTI_ERROR_NONE)
916 return jerr;
917
918 _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method);
919 if (base == NULL)
920 return JVMTI_ERROR_INVALID_METHODID;
921
922 if (java::lang::reflect::Modifier::isNative (method->accflags)
923 || !_Jv_IsInterpretedClass (klass))
924 return JVMTI_ERROR_NATIVE_METHOD;
925
926 _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base);
927 jlong start, end;
928 jintArray lines = NULL;
929 jlongArray indices = NULL;
930 imeth->get_line_table (start, end, lines, indices);
931 if (lines == NULL)
932 return JVMTI_ERROR_ABSENT_INFORMATION;
933
934 jvmtiLineNumberEntry *table;
935 jsize len = lines->length * sizeof (jvmtiLineNumberEntry);
936 table = (jvmtiLineNumberEntry *) _Jv_MallocUnchecked (len);
937 if (table == NULL)
938 return JVMTI_ERROR_OUT_OF_MEMORY;
939
940 jint *line = elements (lines);
941 jlong *index = elements (indices);
942 for (int i = 0; i < lines->length; ++i)
943 {
944 table[i].start_location = index[i];
945 table[i].line_number = line[i];
946 }
947
948 *table_ptr = table;
949 *entry_count_ptr = lines->length;
950 return JVMTI_ERROR_NONE;
951 }
952
953 static jvmtiError JNICALL
954 _Jv_JVMTI_GetLocalVariableTable (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
955 jint *num_locals,
956 jvmtiLocalVariableEntry **locals)
957 {
958 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
959 NULL_CHECK (num_locals);
960 NULL_CHECK (locals);
961
962 CHECK_FOR_NATIVE_METHOD(method);
963
964 jclass klass;
965 jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass);
966 if (jerr != JVMTI_ERROR_NONE)
967 return jerr;
968
969 _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *>
970 (_Jv_FindInterpreterMethod (klass, method));
971
972 if (imeth == NULL)
973 return JVMTI_ERROR_INVALID_METHODID;
974
975 jerr = env->GetMaxLocals (method, num_locals);
976 if (jerr != JVMTI_ERROR_NONE)
977 return jerr;
978
979 jerr = env->Allocate (static_cast<jlong>
980 ((*num_locals) * sizeof (jvmtiLocalVariableEntry)),
981 reinterpret_cast<unsigned char **> (locals));
982
983 if (jerr != JVMTI_ERROR_NONE)
984 return jerr;
985
986 //the slot in the methods local_var_table to get
987 int table_slot = 0;
988 char *name;
989 char *sig;
990 char *generic_sig;
991
992 while (table_slot < *num_locals
993 && imeth->get_local_var_table (&name, &sig, &generic_sig,
994 &((((*locals)[table_slot].start_location))),
995 &((*locals)[table_slot].length),
996 &((*locals)[table_slot].slot),
997 table_slot)
998 >= 0)
999 {
1000 jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
1001 reinterpret_cast<unsigned char **>
1002 (&(*locals)[table_slot].name));
1003 if (jerr != JVMTI_ERROR_NONE)
1004 return jerr;
1005 strcpy ((*locals)[table_slot].name, name);
1006
1007 jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
1008 reinterpret_cast<unsigned char **>
1009 (&(*locals)[table_slot].signature));
1010 if (jerr != JVMTI_ERROR_NONE)
1011 return jerr;
1012 strcpy ((*locals)[table_slot].signature, sig);
1013
1014 jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
1015 reinterpret_cast<unsigned char **>
1016 (&(*locals)[table_slot].generic_signature));
1017 if (jerr != JVMTI_ERROR_NONE)
1018 return jerr;
1019 strcpy ((*locals)[table_slot].generic_signature, generic_sig);
1020
1021 table_slot++;
1022 }
1023
1024 if (table_slot == 0)
1025 return JVMTI_ERROR_ABSENT_INFORMATION;
1026
1027 // If there are double or long variables in the table, the the table will be
1028 // smaller than the max number of slots, so correct for this here.
1029 if ((table_slot) < *num_locals)
1030 *num_locals = table_slot;
1031
1032 return JVMTI_ERROR_NONE;
1033 }
1034
1035 static jvmtiError JNICALL
1036 _Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
1037 jboolean *result)
1038 {
1039 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1040 if (method == NULL)
1041 return JVMTI_ERROR_INVALID_METHODID;
1042 NULL_CHECK (result);
1043
1044 *result = ((method->accflags & java::lang::reflect::Modifier::NATIVE) != 0);
1045 return JVMTI_ERROR_NONE;
1046 }
1047
1048 static jvmtiError JNICALL
1049 _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
1050 jboolean *result)
1051 {
1052 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1053 if (method == NULL)
1054 return JVMTI_ERROR_INVALID_METHODID;
1055 NULL_CHECK (result);
1056
1057 // FIXME capability can_get_synthetic_attribute
1058
1059 *result = ((method->accflags & java::lang::reflect::Modifier::SYNTHETIC)
1060 != 0);
1061 return JVMTI_ERROR_NONE;
1062 }
1063
1064 static jvmtiError JNICALL
1065 _Jv_JVMTI_GetMaxLocals (jvmtiEnv *env, jmethodID method, jint *max_locals)
1066 {
1067 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1068 NULL_CHECK (max_locals);
1069
1070 CHECK_FOR_NATIVE_METHOD (method);
1071
1072 jclass klass;
1073 jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass);
1074 if (jerr != JVMTI_ERROR_NONE)
1075 return jerr;
1076
1077 _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *>
1078 (_Jv_FindInterpreterMethod (klass, method));
1079
1080 if (imeth == NULL)
1081 return JVMTI_ERROR_INVALID_METHODID;
1082
1083 *max_locals = imeth->get_max_locals ();
1084
1085 return JVMTI_ERROR_NONE;
1086 }
1087
1088 static jvmtiError JNICALL
1089 _Jv_JVMTI_GetMethodDeclaringClass (MAYBE_UNUSED jvmtiEnv *env,
1090 jmethodID method,
1091 jclass *declaring_class_ptr)
1092 {
1093 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1094 NULL_CHECK (declaring_class_ptr);
1095
1096 jclass klass = _Jv_GetMethodDeclaringClass (method);
1097 if (klass != NULL)
1098 {
1099 *declaring_class_ptr = klass;
1100 return JVMTI_ERROR_NONE;
1101 }
1102
1103 return JVMTI_ERROR_INVALID_METHODID;
1104 }
1105
1106 static jvmtiError JNICALL
1107 _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env,
1108 jobject init_loader,
1109 jint *count_ptr,
1110 jclass **result_ptr)
1111 {
1112 using namespace java::lang;
1113 using namespace java::util;
1114
1115 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1116 NULL_CHECK (count_ptr);
1117 NULL_CHECK (result_ptr);
1118
1119 ClassLoader *loader = (ClassLoader *) init_loader;
1120 if (loader == NULL)
1121 loader = VMClassLoader::bootLoader;
1122
1123 Collection *values = loader->loadedClasses->values();
1124 jobjectArray array = values->toArray();
1125 *count_ptr = array->length;
1126 jobject *elts = elements (array);
1127 jclass *result
1128 = (jclass *) _Jv_MallocUnchecked (*count_ptr * sizeof (jclass));
1129 if (result == NULL)
1130 return JVMTI_ERROR_OUT_OF_MEMORY;
1131
1132 // FIXME: JNI references...
1133 memcpy (result, elts, *count_ptr * sizeof (jclass));
1134
1135 *result_ptr = result;
1136
1137 return JVMTI_ERROR_NONE;
1138 }
1139
1140 static jvmtiError JNICALL
1141 _Jv_JVMTI_GetStackTrace (MAYBE_UNUSED jvmtiEnv *env, jthread thread,
1142 jint start_depth, jint max_frames,
1143 jvmtiFrameInfo *frames, jint *frame_count)
1144 {
1145 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1146
1147 ILLEGAL_ARGUMENT (max_frames < 0);
1148
1149 NULL_CHECK (frames);
1150 NULL_CHECK (frame_count);
1151
1152 using namespace java::lang;
1153
1154 THREAD_DEFAULT_TO_CURRENT (thread);
1155 THREAD_CHECK_VALID (thread);
1156 THREAD_CHECK_IS_ALIVE (thread);
1157
1158 jvmtiError jerr = env->GetFrameCount (thread, frame_count);
1159 if (jerr != JVMTI_ERROR_NONE)
1160 return jerr;
1161
1162 // start_depth can be either a positive number, indicating the depth of the
1163 // stack at which to begin the trace, or a negative number indicating the
1164 // number of frames at the bottom of the stack to exclude. These checks
1165 // ensure that it is a valid value in either case
1166
1167 ILLEGAL_ARGUMENT (start_depth >= (*frame_count));
1168 ILLEGAL_ARGUMENT (start_depth < (-(*frame_count)));
1169
1170 _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
1171
1172 // If start_depth is negative use this to determine at what depth to start
1173 // the trace by adding it to the length of the call stack. This allows the
1174 // use of the same frame "discarding" mechanism as for a positive start_depth
1175 if (start_depth < 0)
1176 start_depth = *frame_count + start_depth;
1177
1178 // If start_depth > 0 "remove" start_depth frames from the beginning
1179 // of the stack before beginning the trace by moving along the frame list.
1180 while (start_depth > 0)
1181 {
1182 frame = frame->next;
1183 start_depth--;
1184 (*frame_count)--;
1185 }
1186
1187 // Now check to see if the array supplied by the agent is large enough to
1188 // hold frame_count frames, after adjustment for start_depth.
1189 if ((*frame_count) > max_frames)
1190 (*frame_count) = max_frames;
1191
1192 for (int i = 0; i < (*frame_count); i++)
1193 {
1194 frames[i].method = frame->self->get_method ();
1195
1196 // Set the location in the frame, native frames have location = -1
1197 if (frame->frame_type == frame_interpreter)
1198 {
1199 _Jv_InterpMethod *imeth
1200 = static_cast<_Jv_InterpMethod *> (frame->self);
1201 _Jv_InterpFrame *interp_frame
1202 = static_cast<_Jv_InterpFrame *> (frame);
1203 frames[i].location = imeth->insn_index (interp_frame->pc);
1204 }
1205 else
1206 frames[i].location = -1;
1207
1208 frame = frame->next;
1209 }
1210
1211 return JVMTI_ERROR_NONE;
1212 }
1213
1214 static jvmtiError JNICALL
1215 _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env)
1216 {
1217 REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1218 _Jv_RunGC();
1219 return JVMTI_ERROR_NONE;
1220 }
1221
1222 static jvmtiError JNICALL
1223 _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
1224 const jniNativeInterface *function_table)
1225 {
1226 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1227 NULL_CHECK (function_table);
1228 memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface));
1229 return JVMTI_ERROR_NONE;
1230 }
1231
1232 static jvmtiError JNICALL
1233 _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
1234 jniNativeInterface **function_table)
1235 {
1236 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1237 NULL_CHECK (function_table);
1238 *function_table
1239 = (jniNativeInterface *) _Jv_MallocUnchecked (sizeof (jniNativeInterface));
1240 if (*function_table == NULL)
1241 return JVMTI_ERROR_OUT_OF_MEMORY;
1242 memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface));
1243 return JVMTI_ERROR_NONE;
1244 }
1245
1246 static jvmtiError JNICALL
1247 _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env)
1248 {
1249 NULL_CHECK (env);
1250
1251 if (_jvmtiEnvironments == NULL)
1252 return JVMTI_ERROR_INVALID_ENVIRONMENT;
1253 else
1254 {
1255 _envListLock->writeLock ()->lock ();
1256 if (_jvmtiEnvironments->env == env)
1257 {
1258 struct jvmti_env_list *next = _jvmtiEnvironments->next;
1259 _Jv_Free (_jvmtiEnvironments);
1260 _jvmtiEnvironments = next;
1261 }
1262 else
1263 {
1264 struct jvmti_env_list *e = _jvmtiEnvironments;
1265 while (e->next != NULL && e->next->env != env)
1266 e = e->next;
1267 if (e->next == NULL)
1268 {
1269 _envListLock->writeLock ()->unlock ();
1270 return JVMTI_ERROR_INVALID_ENVIRONMENT;
1271 }
1272
1273 struct jvmti_env_list *next = e->next->next;
1274 _Jv_Free (e->next);
1275 e->next = next;
1276 }
1277 _envListLock->writeLock ()->unlock ();
1278 }
1279
1280 _Jv_Free (env);
1281
1282 check_enabled_events ();
1283
1284 return JVMTI_ERROR_NONE;
1285 }
1286
1287 static jvmtiError JNICALL
1288 _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
1289 char **result)
1290 {
1291 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1292 NULL_CHECK (property);
1293 NULL_CHECK (result);
1294
1295 jstring name = JvNewStringUTF(property);
1296 jstring result_str = gnu::classpath::SystemProperties::getProperty(name);
1297
1298 if (result_str == NULL)
1299 return JVMTI_ERROR_NOT_AVAILABLE;
1300
1301 int len = JvGetStringUTFLength (result_str);
1302 *result = (char *) _Jv_MallocUnchecked (len + 1);
1303 if (*result == NULL)
1304 return JVMTI_ERROR_OUT_OF_MEMORY;
1305 JvGetStringUTFRegion (result_str, 0, result_str->length(), *result);
1306 (*result)[len] = '\0';
1307
1308 return JVMTI_ERROR_NONE;
1309 }
1310
1311 static jvmtiError JNICALL
1312 _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
1313 const char *value)
1314 {
1315 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
1316
1317 NULL_CHECK (property);
1318 if (value == NULL)
1319 {
1320 // FIXME: When would a property not be writeable?
1321 return JVMTI_ERROR_NONE;
1322 }
1323
1324 jstring prop_str = JvNewStringUTF(property);
1325 jstring value_str = JvNewStringUTF(value);
1326 gnu::classpath::SystemProperties::setProperty(prop_str, value_str);
1327 return JVMTI_ERROR_NONE;
1328 }
1329
1330 static jvmtiError JNICALL
1331 _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr)
1332 {
1333 NULL_CHECK (nanos_ptr);
1334 *nanos_ptr = _Jv_platform_nanotime();
1335 return JVMTI_ERROR_NONE;
1336 }
1337
1338 static jvmtiError JNICALL
1339 _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env,
1340 jint *nprocessors_ptr)
1341 {
1342 NULL_CHECK (nprocessors_ptr);
1343 #ifdef _SC_NPROCESSORS_ONLN
1344 *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN);
1345 #else
1346 *nprocessors_ptr = 1;
1347 #endif
1348 return JVMTI_ERROR_NONE;
1349 }
1350
1351 static jvmtiError JNICALL
1352 _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env,
1353 const char *segment)
1354 {
1355 using namespace java::lang;
1356 using namespace java::net;
1357 using namespace gnu::gcj::runtime;
1358
1359 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
1360 NULL_CHECK (segment);
1361
1362 jstring str_segment = JvNewStringUTF(segment);
1363 URL *url;
1364 try
1365 {
1366 url = new URL(JvNewStringUTF("file"), NULL, str_segment);
1367 }
1368 catch (jthrowable ignore)
1369 {
1370 return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1371 }
1372
1373 BootClassLoader *loader = VMClassLoader::bootLoader;
1374 // Don't call this too early.
1375 // assert (loader != NULL);
1376 loader->addURL(url);
1377 return JVMTI_ERROR_NONE;
1378 }
1379
1380 static jvmtiError JNICALL
1381 _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag,
1382 jboolean value)
1383 {
1384 switch (flag)
1385 {
1386 case JVMTI_VERBOSE_OTHER:
1387 case JVMTI_VERBOSE_GC:
1388 case JVMTI_VERBOSE_JNI:
1389 // Ignore.
1390 break;
1391 case JVMTI_VERBOSE_CLASS:
1392 gcj::verbose_class_flag = value;
1393 break;
1394 default:
1395 return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1396 }
1397 return JVMTI_ERROR_NONE;
1398 }
1399
1400 static jvmtiError JNICALL
1401 _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object,
1402 jlong *result)
1403 {
1404 REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1405 if (object == NULL)
1406 return JVMTI_ERROR_INVALID_OBJECT;
1407 NULL_CHECK (result);
1408
1409 jclass klass = object->getClass();
1410 if (klass->isArray())
1411 {
1412 jclass comp = klass->getComponentType();
1413 jint base
1414 = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL,
1415 klass->getComponentType());
1416 // FIXME: correct for primitive types?
1417 jint compSize = comp->size();
1418 __JArray *array = (__JArray *) object;
1419 *result = base + array->length * compSize;
1420 }
1421 else
1422 {
1423 // Note that if OBJECT is a String then it may (if
1424 // str->data==str) take more space. Do we care?
1425 *result = klass->size();
1426 }
1427 return JVMTI_ERROR_NONE;
1428 }
1429
1430 /* An event is enabled only if it has both an event handler
1431 and it is enabled in the environment. */
1432 static void
1433 check_enabled_event (jvmtiEvent type)
1434 {
1435 bool *enabled;
1436 int offset;
1437
1438 #define GET_OFFSET(Event) \
1439 do \
1440 { \
1441 enabled = &JVMTI::Event; \
1442 offset = offsetof (jvmtiEventCallbacks, Event); \
1443 } \
1444 while (0)
1445
1446 switch (type)
1447 {
1448 case JVMTI_EVENT_VM_INIT:
1449 GET_OFFSET (VMInit);
1450 break;
1451
1452 case JVMTI_EVENT_VM_DEATH:
1453 GET_OFFSET (VMDeath);
1454 break;
1455
1456 case JVMTI_EVENT_THREAD_START:
1457 GET_OFFSET (ThreadStart);
1458 break;
1459
1460 case JVMTI_EVENT_THREAD_END:
1461 GET_OFFSET (ThreadEnd);
1462 break;
1463
1464 case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1465 GET_OFFSET (ClassFileLoadHook);
1466 break;
1467
1468 case JVMTI_EVENT_CLASS_LOAD:
1469 GET_OFFSET (ClassLoad);
1470 break;
1471
1472 case JVMTI_EVENT_CLASS_PREPARE:
1473 GET_OFFSET (ClassPrepare);
1474 break;
1475
1476 case JVMTI_EVENT_VM_START:
1477 GET_OFFSET (VMStart);
1478 break;
1479
1480 case JVMTI_EVENT_EXCEPTION:
1481 GET_OFFSET (Exception);
1482 break;
1483
1484 case JVMTI_EVENT_EXCEPTION_CATCH:
1485 GET_OFFSET (ExceptionCatch);
1486 break;
1487
1488 case JVMTI_EVENT_SINGLE_STEP:
1489 GET_OFFSET (SingleStep);
1490 break;
1491
1492 case JVMTI_EVENT_FRAME_POP:
1493 GET_OFFSET (FramePop);
1494 break;
1495
1496 case JVMTI_EVENT_BREAKPOINT:
1497 GET_OFFSET (Breakpoint);
1498 break;
1499
1500 case JVMTI_EVENT_FIELD_ACCESS:
1501 GET_OFFSET (FieldAccess);
1502 break;
1503
1504 case JVMTI_EVENT_FIELD_MODIFICATION:
1505 GET_OFFSET (FieldModification);
1506 break;
1507
1508 case JVMTI_EVENT_METHOD_ENTRY:
1509 GET_OFFSET (MethodEntry);
1510 break;
1511
1512 case JVMTI_EVENT_METHOD_EXIT:
1513 GET_OFFSET (MethodExit);
1514 break;
1515
1516 case JVMTI_EVENT_NATIVE_METHOD_BIND:
1517 GET_OFFSET (NativeMethodBind);
1518 break;
1519
1520 case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1521 GET_OFFSET (CompiledMethodLoad);
1522 break;
1523
1524 case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1525 GET_OFFSET (CompiledMethodUnload);
1526 break;
1527
1528 case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1529 GET_OFFSET (DynamicCodeGenerated);
1530 break;
1531
1532 case JVMTI_EVENT_DATA_DUMP_REQUEST:
1533 GET_OFFSET (DataDumpRequest);
1534 break;
1535
1536 case JVMTI_EVENT_MONITOR_WAIT:
1537 GET_OFFSET (MonitorWait);
1538 break;
1539
1540 case JVMTI_EVENT_MONITOR_WAITED:
1541 GET_OFFSET (MonitorWaited);
1542 break;
1543
1544 case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1545 GET_OFFSET (MonitorContendedEnter);
1546 break;
1547
1548 case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1549 GET_OFFSET (MonitorContendedEntered);
1550 break;
1551
1552 case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1553 GET_OFFSET (GarbageCollectionStart);
1554 break;
1555
1556 case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1557 GET_OFFSET (GarbageCollectionFinish);
1558 break;
1559
1560 case JVMTI_EVENT_OBJECT_FREE:
1561 GET_OFFSET (ObjectFree);
1562 break;
1563
1564 case JVMTI_EVENT_VM_OBJECT_ALLOC:
1565 GET_OFFSET (VMObjectAlloc);
1566 break;
1567
1568 default:
1569 fprintf (stderr,
1570 "libgcj: check_enabled_event for unknown JVMTI event (%d)\n",
1571 (int) type);
1572 return;
1573 }
1574 #undef GET_OFFSET
1575
1576 int index = EVENT_INDEX (type); // safe since caller checks this
1577
1578 if (_jvmtiEnvironments != NULL)
1579 {
1580 _envListLock->readLock ()->lock ();
1581 struct jvmti_env_list *e;
1582 FOREACH_ENVIRONMENT (e)
1583 {
1584 char *addr
1585 = reinterpret_cast<char *> (&e->env->callbacks) + offset;
1586 void **callback = reinterpret_cast<void **> (addr);
1587 if (e->env->enabled[index] && *callback != NULL)
1588 {
1589 *enabled = true;
1590 _envListLock->readLock ()->unlock ();
1591 return;
1592 }
1593 }
1594
1595 _envListLock->readLock ()->unlock ();
1596 }
1597
1598 *enabled = false;
1599 }
1600
1601 static void
1602 check_enabled_events ()
1603 {
1604 check_enabled_event (JVMTI_EVENT_VM_INIT);
1605 check_enabled_event (JVMTI_EVENT_VM_DEATH);
1606 check_enabled_event (JVMTI_EVENT_THREAD_START);
1607 check_enabled_event (JVMTI_EVENT_THREAD_END);
1608 check_enabled_event (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK);
1609 check_enabled_event (JVMTI_EVENT_CLASS_LOAD);
1610 check_enabled_event (JVMTI_EVENT_CLASS_PREPARE);
1611 check_enabled_event (JVMTI_EVENT_VM_START);
1612 check_enabled_event (JVMTI_EVENT_EXCEPTION);
1613 check_enabled_event (JVMTI_EVENT_EXCEPTION_CATCH);
1614 check_enabled_event (JVMTI_EVENT_SINGLE_STEP);
1615 check_enabled_event (JVMTI_EVENT_FRAME_POP);
1616 check_enabled_event (JVMTI_EVENT_BREAKPOINT);
1617 check_enabled_event (JVMTI_EVENT_FIELD_ACCESS);
1618 check_enabled_event (JVMTI_EVENT_FIELD_MODIFICATION);
1619 check_enabled_event (JVMTI_EVENT_METHOD_ENTRY);
1620 check_enabled_event (JVMTI_EVENT_METHOD_EXIT);
1621 check_enabled_event (JVMTI_EVENT_NATIVE_METHOD_BIND);
1622 check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_LOAD);
1623 check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_UNLOAD);
1624 check_enabled_event (JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
1625 check_enabled_event (JVMTI_EVENT_DATA_DUMP_REQUEST);
1626 check_enabled_event (JVMTI_EVENT_MONITOR_WAIT);
1627 check_enabled_event (JVMTI_EVENT_MONITOR_WAITED);
1628 check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTER);
1629 check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED);
1630 check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_START);
1631 check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH);
1632 check_enabled_event (JVMTI_EVENT_OBJECT_FREE);
1633 check_enabled_event (JVMTI_EVENT_VM_OBJECT_ALLOC);
1634 }
1635
1636 static jvmtiError JNICALL
1637 _Jv_JVMTI_SetEventNotificationMode (jvmtiEnv *env, jvmtiEventMode mode,
1638 jvmtiEvent type, jthread event_thread, ...)
1639 {
1640 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1641
1642 if (event_thread != NULL)
1643 {
1644 THREAD_CHECK_VALID (event_thread);
1645 THREAD_CHECK_IS_ALIVE (event_thread);
1646 }
1647
1648 bool enabled;
1649 switch (mode)
1650 {
1651 case JVMTI_DISABLE:
1652 enabled = false;
1653 break;
1654 case JVMTI_ENABLE:
1655 enabled = true;
1656 break;
1657
1658 default:
1659 return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1660 }
1661
1662 switch (type)
1663 {
1664 case JVMTI_EVENT_VM_INIT:
1665 case JVMTI_EVENT_VM_DEATH:
1666 case JVMTI_EVENT_THREAD_START:
1667 case JVMTI_EVENT_VM_START:
1668 case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1669 case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1670 case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1671 case JVMTI_EVENT_DATA_DUMP_REQUEST:
1672 ILLEGAL_ARGUMENT (event_thread != NULL);
1673 break;
1674
1675 case JVMTI_EVENT_THREAD_END:
1676 case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1677 case JVMTI_EVENT_CLASS_LOAD:
1678 case JVMTI_EVENT_CLASS_PREPARE:
1679 case JVMTI_EVENT_EXCEPTION:
1680 case JVMTI_EVENT_EXCEPTION_CATCH:
1681 case JVMTI_EVENT_SINGLE_STEP:
1682 case JVMTI_EVENT_FRAME_POP:
1683 case JVMTI_EVENT_BREAKPOINT:
1684 case JVMTI_EVENT_FIELD_ACCESS:
1685 case JVMTI_EVENT_FIELD_MODIFICATION:
1686 case JVMTI_EVENT_METHOD_ENTRY:
1687 case JVMTI_EVENT_METHOD_EXIT:
1688 case JVMTI_EVENT_NATIVE_METHOD_BIND:
1689 case JVMTI_EVENT_MONITOR_WAIT:
1690 case JVMTI_EVENT_MONITOR_WAITED:
1691 case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1692 case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1693 case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1694 case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1695 case JVMTI_EVENT_OBJECT_FREE:
1696 case JVMTI_EVENT_VM_OBJECT_ALLOC:
1697 break;
1698
1699 default:
1700 return JVMTI_ERROR_INVALID_EVENT_TYPE;
1701 }
1702
1703 env->thread[EVENT_INDEX(type)] = event_thread;
1704 env->enabled[EVENT_INDEX(type)] = enabled;
1705 check_enabled_event (type);
1706 return JVMTI_ERROR_NONE;
1707 }
1708
1709 static jvmtiError JNICALL
1710 _Jv_JVMTI_SetEventCallbacks (jvmtiEnv *env,
1711 const jvmtiEventCallbacks *callbacks,
1712 jint size_of_callbacks)
1713 {
1714 REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1715 ILLEGAL_ARGUMENT (size_of_callbacks < 0);
1716
1717 // Copy the list of callbacks into the environment
1718 memcpy (&env->callbacks, callbacks, sizeof (jvmtiEventCallbacks));
1719
1720 /* Check which events are now enabeld (JVMTI makes no requirements
1721 about the order in which SetEventCallbacks and SetEventNotifications
1722 are called. So we must check all events here. */
1723 check_enabled_events ();
1724
1725 return JVMTI_ERROR_NONE;
1726 }
1727
1728 static jvmtiError JNICALL
1729 _Jv_JVMTI_GetErrorName (MAYBE_UNUSED jvmtiEnv *env, jvmtiError error,
1730 char **name_ptr)
1731 {
1732 NULL_CHECK (name_ptr);
1733
1734 const char *name;
1735 switch (error)
1736 {
1737 case JVMTI_ERROR_NONE:
1738 name = "none";
1739 break;
1740
1741 case JVMTI_ERROR_NULL_POINTER:
1742 name = "null pointer";
1743 break;
1744
1745 case JVMTI_ERROR_OUT_OF_MEMORY:
1746 name = "out of memory";
1747 break;
1748
1749 case JVMTI_ERROR_ACCESS_DENIED:
1750 name = "access denied";
1751 break;
1752
1753 case JVMTI_ERROR_WRONG_PHASE:
1754 name = "wrong phase";
1755 break;
1756
1757 case JVMTI_ERROR_INTERNAL:
1758 name = "internal error";
1759 break;
1760
1761 case JVMTI_ERROR_UNATTACHED_THREAD:
1762 name = "unattached thread";
1763 break;
1764
1765 case JVMTI_ERROR_INVALID_ENVIRONMENT:
1766 name = "invalid environment";
1767 break;
1768
1769 case JVMTI_ERROR_INVALID_PRIORITY:
1770 name = "invalid priority";
1771 break;
1772
1773 case JVMTI_ERROR_THREAD_NOT_SUSPENDED:
1774 name = "thread not suspended";
1775 break;
1776
1777 case JVMTI_ERROR_THREAD_SUSPENDED:
1778 name = "thread suspended";
1779 break;
1780
1781 case JVMTI_ERROR_THREAD_NOT_ALIVE:
1782 name = "thread not alive";
1783 break;
1784
1785 case JVMTI_ERROR_CLASS_NOT_PREPARED:
1786 name = "class not prepared";
1787 break;
1788
1789 case JVMTI_ERROR_NO_MORE_FRAMES:
1790 name = "no more frames";
1791 break;
1792
1793 case JVMTI_ERROR_OPAQUE_FRAME:
1794 name = "opaque frame";
1795 break;
1796
1797 case JVMTI_ERROR_DUPLICATE:
1798 name = "duplicate";
1799 break;
1800
1801 case JVMTI_ERROR_NOT_FOUND:
1802 name = "not found";
1803 break;
1804
1805 case JVMTI_ERROR_NOT_MONITOR_OWNER:
1806 name = "not monitor owner";
1807 break;
1808
1809 case JVMTI_ERROR_INTERRUPT:
1810 name = "interrupted";
1811 break;
1812
1813 case JVMTI_ERROR_UNMODIFIABLE_CLASS:
1814 name = "unmodifiable class";
1815 break;
1816
1817 case JVMTI_ERROR_NOT_AVAILABLE:
1818 name = "not available";
1819 break;
1820
1821 case JVMTI_ERROR_ABSENT_INFORMATION:
1822 name = "absent information";
1823 break;
1824
1825 case JVMTI_ERROR_INVALID_EVENT_TYPE:
1826 name = "invalid event type";
1827 break;
1828
1829 case JVMTI_ERROR_NATIVE_METHOD:
1830 name = "native method";
1831 break;
1832
1833 case JVMTI_ERROR_INVALID_THREAD:
1834 name = "invalid thread";
1835 break;
1836
1837 case JVMTI_ERROR_INVALID_THREAD_GROUP:
1838 name = "invalid thread group";
1839 break;
1840
1841 case JVMTI_ERROR_INVALID_OBJECT:
1842 name = "invalid object";
1843 break;
1844
1845 case JVMTI_ERROR_INVALID_CLASS:
1846 name = "invalid class";
1847 break;
1848
1849 case JVMTI_ERROR_INVALID_METHODID:
1850 name = "invalid method ID";
1851 break;
1852
1853 case JVMTI_ERROR_INVALID_LOCATION:
1854 name = "invalid location";
1855 break;
1856
1857 case JVMTI_ERROR_INVALID_FIELDID:
1858 name = "invalid field ID";
1859 break;
1860
1861 case JVMTI_ERROR_TYPE_MISMATCH:
1862 name = "type mismatch";
1863 break;
1864
1865 case JVMTI_ERROR_INVALID_SLOT:
1866 name = "invalid slot";
1867 break;
1868
1869 case JVMTI_ERROR_INVALID_MONITOR:
1870 name = "invalid monitor";
1871 break;
1872
1873 case JVMTI_ERROR_INVALID_CLASS_FORMAT:
1874 name = "invalid class format";
1875 break;
1876
1877 case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION:
1878 name = "circular class definition";
1879 break;
1880
1881 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED:
1882 name = "unsupported redefinition: method added";
1883 break;
1884
1885 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED:
1886 name = "unsupported redefinition: schema changed";
1887 break;
1888
1889 case JVMTI_ERROR_INVALID_TYPESTATE:
1890 name = "invalid type state";
1891 break;
1892
1893 case JVMTI_ERROR_FAILS_VERIFICATION:
1894 name = "fails verification";
1895 break;
1896
1897 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED:
1898 name = "unsupported redefinition: hierarchy changed";
1899 break;
1900
1901 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED:
1902 name = "unsupported redefinition: method deleted";
1903 break;
1904
1905 case JVMTI_ERROR_UNSUPPORTED_VERSION:
1906 name = "unsupported version";
1907 break;
1908
1909 case JVMTI_ERROR_NAMES_DONT_MATCH:
1910 name = "names do not match";
1911 break;
1912
1913 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED:
1914 name = "unsupported redefinition: class modifiers changed";
1915 break;
1916
1917 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
1918 name = "unsupported redefinition: method modifiers changed";
1919 break;
1920
1921 case JVMTI_ERROR_MUST_POSSESS_CAPABILITY:
1922 name = "must possess capability";
1923 break;
1924
1925 case JVMTI_ERROR_ILLEGAL_ARGUMENT:
1926 name = "illegal argument";
1927 break;
1928
1929 default:
1930 return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1931 }
1932
1933 *name_ptr = (char *) _Jv_MallocUnchecked (strlen (name) + 1);
1934 if (*name_ptr == NULL)
1935 return JVMTI_ERROR_OUT_OF_MEMORY;
1936
1937 strcpy (*name_ptr, name);
1938 return JVMTI_ERROR_NONE;
1939 }
1940
1941 #define RESERVED NULL
1942 #define UNIMPLEMENTED NULL
1943
1944 struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
1945 {
1946 RESERVED, // reserved1
1947 _Jv_JVMTI_SetEventNotificationMode, // SetEventNotificationMode
1948 RESERVED, // reserved3
1949 _Jv_JVMTI_GetAllThreads, // GetAllThreads
1950 _Jv_JVMTI_SuspendThread, // SuspendThread
1951 _Jv_JVMTI_ResumeThread, // ResumeThread
1952 UNIMPLEMENTED, // StopThread
1953 _Jv_JVMTI_InterruptThread, // InterruptThread
1954 UNIMPLEMENTED, // GetThreadInfo
1955 UNIMPLEMENTED, // GetOwnedMonitorInfo
1956 UNIMPLEMENTED, // GetCurrentContendedMonitor
1957 UNIMPLEMENTED, // RunAgentThread
1958 UNIMPLEMENTED, // GetTopThreadGroups
1959 UNIMPLEMENTED, // GetThreadGroupInfo
1960 UNIMPLEMENTED, // GetThreadGroupChildren
1961 _Jv_JVMTI_GetFrameCount, // GetFrameCount
1962 UNIMPLEMENTED, // GetThreadState
1963 RESERVED, // reserved18
1964 UNIMPLEMENTED, // GetFrameLocation
1965 UNIMPLEMENTED, // NotifyPopFrame
1966 _Jv_JVMTI_GetLocalObject, // GetLocalObject
1967 _Jv_JVMTI_GetLocalInt, // GetLocalInt
1968 _Jv_JVMTI_GetLocalLong, // GetLocalLong
1969 _Jv_JVMTI_GetLocalFloat, // GetLocalFloat
1970 _Jv_JVMTI_GetLocalDouble, // GetLocalDouble
1971 _Jv_JVMTI_SetLocalObject, // SetLocalObject
1972 _Jv_JVMTI_SetLocalInt, // SetLocalInt
1973 _Jv_JVMTI_SetLocalLong, // SetLocalLong
1974 _Jv_JVMTI_SetLocalFloat, // SetLocalFloat
1975 _Jv_JVMTI_SetLocalDouble, // SetLocalDouble
1976 _Jv_JVMTI_CreateRawMonitor, // CreateRawMonitor
1977 _Jv_JVMTI_DestroyRawMonitor, // DestroyRawMonitor
1978 _Jv_JVMTI_RawMonitorEnter, // RawMonitorEnter
1979 _Jv_JVMTI_RawMonitorExit, // RawMonitorExit
1980 _Jv_JVMTI_RawMonitorWait, // RawMonitorWait
1981 _Jv_JVMTI_RawMonitorNotify, // RawMonitorNotify
1982 _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll
1983 _Jv_JVMTI_SetBreakpoint, // SetBreakpoint
1984 _Jv_JVMTI_ClearBreakpoint, // ClearBreakpoint
1985 RESERVED, // reserved40
1986 UNIMPLEMENTED, // SetFieldAccessWatch
1987 UNIMPLEMENTED, // ClearFieldAccessWatch
1988 UNIMPLEMENTED, // SetFieldModificationWatch
1989 UNIMPLEMENTED, // ClearFieldModificationWatch
1990 RESERVED, // reserved45
1991 _Jv_JVMTI_Allocate, // Allocate
1992 _Jv_JVMTI_Deallocate, // Deallocate
1993 UNIMPLEMENTED, // GetClassSignature
1994 _Jv_JVMTI_GetClassStatus, // GetClassStatus
1995 UNIMPLEMENTED, // GetSourceFileName
1996 _Jv_JVMTI_GetClassModifiers, // GetClassModifiers
1997 _Jv_JVMTI_GetClassMethods, // GetClassMethods
1998 UNIMPLEMENTED, // GetClassFields
1999 UNIMPLEMENTED, // GetImplementedInterfaces
2000 _Jv_JVMTI_IsInterface, // IsInterface
2001 _Jv_JVMTI_IsArrayClass, // IsArrayClass
2002 _Jv_JVMTI_GetClassLoader, // GetClassLoader
2003 _Jv_JVMTI_GetObjectHashCode, // GetObjectHashCode
2004 UNIMPLEMENTED, // GetObjectMonitorUsage
2005 UNIMPLEMENTED, // GetFieldName
2006 UNIMPLEMENTED, // GetFieldDeclaringClass
2007 _Jv_JVMTI_GetFieldModifiers, // GetFieldModifiers
2008 _Jv_JVMTI_IsFieldSynthetic, // IsFieldSynthetic
2009 _Jv_JVMTI_GetMethodName, // GetMethodName
2010 _Jv_JVMTI_GetMethodDeclaringClass, // GetMethodDeclaringClass
2011 _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers
2012 RESERVED, // reserved67
2013 _Jv_JVMTI_GetMaxLocals, // GetMaxLocals
2014 UNIMPLEMENTED, // GetArgumentsSize
2015 _Jv_JVMTI_GetLineNumberTable, // GetLineNumberTable
2016 UNIMPLEMENTED, // GetMethodLocation
2017 _Jv_JVMTI_GetLocalVariableTable, // GetLocalVariableTable
2018 RESERVED, // reserved73
2019 RESERVED, // reserved74
2020 UNIMPLEMENTED, // GetBytecodes
2021 _Jv_JVMTI_IsMethodNative, // IsMethodNative
2022 _Jv_JVMTI_IsMethodSynthetic, // IsMethodSynthetic
2023 UNIMPLEMENTED, // GetLoadedClasses
2024 _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses
2025 UNIMPLEMENTED, // PopFrame
2026 RESERVED, // reserved81
2027 RESERVED, // reserved82
2028 RESERVED, // reserved83
2029 RESERVED, // reserved84
2030 RESERVED, // reserved85
2031 RESERVED, // reserved86
2032 UNIMPLEMENTED, // RedefineClasses
2033 UNIMPLEMENTED, // GetVersionNumber
2034 UNIMPLEMENTED, // GetCapabilities
2035 UNIMPLEMENTED, // GetSourceDebugExtension
2036 UNIMPLEMENTED, // IsMethodObsolete
2037 UNIMPLEMENTED, // SuspendThreadList
2038 UNIMPLEMENTED, // ResumeThreadList
2039 RESERVED, // reserved94
2040 RESERVED, // reserved95
2041 RESERVED, // reserved96
2042 RESERVED, // reserved97
2043 RESERVED, // reserved98
2044 RESERVED, // reserved99
2045 UNIMPLEMENTED, // GetAllStackTraces
2046 UNIMPLEMENTED, // GetThreadListStackTraces
2047 UNIMPLEMENTED, // GetThreadLocalStorage
2048 UNIMPLEMENTED, // SetThreadLocalStorage
2049 _Jv_JVMTI_GetStackTrace, // GetStackTrace
2050 RESERVED, // reserved105
2051 UNIMPLEMENTED, // GetTag
2052 UNIMPLEMENTED, // SetTag
2053 _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection
2054 UNIMPLEMENTED, // IterateOverObjectsReachable
2055 UNIMPLEMENTED, // IterateOverReachableObjects
2056 UNIMPLEMENTED, // IterateOverHeap
2057 UNIMPLEMENTED, // IterateOverInstanceOfClass
2058 RESERVED, // reserved113
2059 UNIMPLEMENTED, // GetObjectsWithTags
2060 RESERVED, // reserved115
2061 RESERVED, // reserved116
2062 RESERVED, // reserved117
2063 RESERVED, // reserved118
2064 RESERVED, // reserved119
2065 _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable
2066 _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable
2067 _Jv_JVMTI_SetEventCallbacks, // SetEventCallbacks
2068 UNIMPLEMENTED, // GenerateEvents
2069 UNIMPLEMENTED, // GetExtensionFunctions
2070 UNIMPLEMENTED, // GetExtensionEvents
2071 UNIMPLEMENTED, // SetExtensionEventCallback
2072 _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment
2073 _Jv_JVMTI_GetErrorName, // GetErrorName
2074 UNIMPLEMENTED, // GetJLocationFormat
2075 UNIMPLEMENTED, // GetSystemProperties
2076 _Jv_JVMTI_GetSystemProperty, // GetSystemProperty
2077 _Jv_JVMTI_SetSystemProperty, // SetSystemProperty
2078 UNIMPLEMENTED, // GetPhase
2079 UNIMPLEMENTED, // GetCurrentThreadCpuTimerInfo
2080 UNIMPLEMENTED, // GetCurrentThreadCpuTime
2081 UNIMPLEMENTED, // GetThreadCpuTimerInfo
2082 UNIMPLEMENTED, // GetThreadCpuTime
2083 UNIMPLEMENTED, // GetTimerInfo
2084 _Jv_JVMTI_GetTime, // GetTime
2085 UNIMPLEMENTED, // GetPotentialCapabilities
2086 RESERVED, // reserved141
2087 UNIMPLEMENTED, // AddCapabilities
2088 UNIMPLEMENTED, // RelinquishCapabilities
2089 _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors
2090 RESERVED, // reserved145
2091 RESERVED, // reserved146
2092 UNIMPLEMENTED, // GetEnvironmentLocalStorage
2093 UNIMPLEMENTED, // SetEnvironmentLocalStorage
2094 _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch
2095 _Jv_JVMTI_SetVerboseFlag, // SetVerboseFlag
2096 RESERVED, // reserved151
2097 RESERVED, // reserved152
2098 RESERVED, // reserved153
2099 _Jv_JVMTI_GetObjectSize // GetObjectSize
2100 };
2101
2102 _Jv_JVMTIEnv *
2103 _Jv_GetJVMTIEnv (void)
2104 {
2105 _Jv_JVMTIEnv *env
2106 = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv));
2107 env->p = &_Jv_JVMTI_Interface;
2108 struct jvmti_env_list *element
2109 = (struct jvmti_env_list *) _Jv_MallocUnchecked (sizeof (struct jvmti_env_list));
2110 element->env = env;
2111 element->next = NULL;
2112
2113 _envListLock->writeLock ()->lock ();
2114 if (_jvmtiEnvironments == NULL)
2115 _jvmtiEnvironments = element;
2116 else
2117 {
2118 struct jvmti_env_list *e;
2119 for (e = _jvmtiEnvironments; e->next != NULL; e = e->next)
2120 ;
2121 e->next = element;
2122 }
2123 _envListLock->writeLock ()->unlock ();
2124
2125 /* Mark JVMTI active. This is used to force the interpreter
2126 to use either debugging or non-debugging code. Once JVMTI
2127 has been enabled, the non-debug interpreter cannot be used. */
2128 JVMTI::enabled = true;
2129 return env;
2130 }
2131
2132 void
2133 _Jv_JVMTI_Init ()
2134 {
2135 _jvmtiEnvironments = NULL;
2136 _envListLock
2137 = new java::util::concurrent::locks::ReentrantReadWriteLock ();
2138
2139 // No environments, so this should set all JVMTI:: members to false
2140 check_enabled_events ();
2141 }
2142
2143 static void
2144 post_event (jvmtiEnv *env, jvmtiEvent type, jthread event_thread, va_list args)
2145 {
2146 #define ARG(Type,Name) Type Name = (Type) va_arg (args, Type)
2147
2148 #define GET_BOOLEAN_ARG(Name) \
2149 ARG (int, b); \
2150 jboolean Name = (b == 0) ? false : true
2151
2152 #define GET_CHAR_ARG(Name) \
2153 ARG (int, c); \
2154 char Name = static_cast<char> (c)
2155
2156 switch (type)
2157 {
2158 case JVMTI_EVENT_VM_INIT:
2159 if (env->callbacks.VMInit != NULL)
2160 {
2161 ARG (JNIEnv *, jni_env);
2162 env->callbacks.VMInit (env, jni_env, event_thread);
2163 }
2164 break;
2165
2166 case JVMTI_EVENT_VM_DEATH:
2167 if (env->callbacks.VMDeath != NULL)
2168 {
2169 ARG (JNIEnv *, jni_env);
2170 env->callbacks.VMDeath (env, jni_env);
2171 }
2172 break;
2173
2174 case JVMTI_EVENT_THREAD_START:
2175 if (env->callbacks.ThreadStart != NULL)
2176 {
2177 ARG (JNIEnv *, jni_env);
2178 env->callbacks.ThreadStart (env, jni_env, event_thread);
2179 }
2180 break;
2181
2182 case JVMTI_EVENT_THREAD_END:
2183 if (env->callbacks.ThreadEnd != NULL)
2184 {
2185 ARG (JNIEnv *, jni_env);
2186 env->callbacks.ThreadEnd (env, jni_env, event_thread);
2187 }
2188 break;
2189
2190 case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
2191 if (env->callbacks.ClassFileLoadHook != NULL)
2192 {
2193 ARG (JNIEnv *, jni_env);
2194 ARG (jclass, class_being_redefined);
2195 ARG (jobject, loader);
2196 ARG (const char *, name);
2197 ARG (jobject, protection_domain);
2198 ARG (jint, class_data_len);
2199 ARG (const unsigned char *, class_data);
2200 ARG (jint *, new_class_data_len);
2201 ARG (unsigned char **, new_class_data);
2202 env->callbacks.ClassFileLoadHook (env, jni_env,
2203 class_being_redefined, loader,
2204 name, protection_domain,
2205 class_data_len, class_data,
2206 new_class_data_len,
2207 new_class_data);
2208 }
2209 break;
2210
2211 case JVMTI_EVENT_CLASS_LOAD:
2212 if (env->callbacks.ClassLoad != NULL)
2213 {
2214 ARG (JNIEnv *, jni_env);
2215 ARG (jclass, klass);
2216 env->callbacks.ClassLoad (env, jni_env, event_thread, klass);
2217 }
2218 break;
2219
2220 case JVMTI_EVENT_CLASS_PREPARE:
2221 if (env->callbacks.ClassPrepare != NULL)
2222 {
2223 ARG (JNIEnv *, jni_env);
2224 ARG (jclass, klass);
2225 env->callbacks.ClassPrepare (env, jni_env, event_thread, klass);
2226 }
2227 break;
2228
2229 case JVMTI_EVENT_VM_START:
2230 if (env->callbacks.VMStart != NULL)
2231 {
2232 ARG (JNIEnv *, jni_env);
2233 env->callbacks.VMStart (env, jni_env);
2234 }
2235 break;
2236
2237 case JVMTI_EVENT_EXCEPTION:
2238 if (env->callbacks.Exception != NULL)
2239 {
2240 ARG (JNIEnv *, jni_env);
2241 ARG (jmethodID, method);
2242 ARG (jlocation, location);
2243 ARG (jobject, exception);
2244 ARG (jmethodID, catch_method);
2245 ARG (jlocation, catch_location);
2246 env->callbacks.Exception (env, jni_env, event_thread, method,
2247 location, exception, catch_method,
2248 catch_location);
2249 }
2250 break;
2251
2252 case JVMTI_EVENT_EXCEPTION_CATCH:
2253 if (env->callbacks.ExceptionCatch != NULL)
2254 {
2255 ARG (JNIEnv *, jni_env);
2256 ARG (jmethodID, method);
2257 ARG (jlocation, location);
2258 ARG (jobject, exception);
2259 env->callbacks.ExceptionCatch (env, jni_env, event_thread, method,
2260 location, exception);
2261 }
2262 break;
2263
2264 case JVMTI_EVENT_SINGLE_STEP:
2265 if (env->callbacks.SingleStep != NULL)
2266 {
2267 ARG (JNIEnv *, jni_env);
2268 ARG (jmethodID, method);
2269 ARG (jlocation, location);
2270 env->callbacks.SingleStep (env, jni_env, event_thread, method,
2271 location);
2272 }
2273 break;
2274
2275 case JVMTI_EVENT_FRAME_POP:
2276 if (env->callbacks.FramePop != NULL)
2277 {
2278 ARG (JNIEnv *, jni_env);
2279 ARG (jmethodID, method);
2280 GET_BOOLEAN_ARG (was_popped_by_exception);
2281 env->callbacks.FramePop (env, jni_env, event_thread, method,
2282 was_popped_by_exception);
2283 }
2284 break;
2285
2286 case JVMTI_EVENT_BREAKPOINT:
2287 if (env->callbacks.Breakpoint != NULL)
2288 {
2289 ARG (JNIEnv *, jni_env);
2290 ARG (jmethodID, method);
2291 ARG (jlocation, location);
2292 env->callbacks.Breakpoint (env, jni_env, event_thread, method,
2293 location);
2294 }
2295 break;
2296
2297 case JVMTI_EVENT_FIELD_ACCESS:
2298 if (env->callbacks.FieldAccess != NULL)
2299 {
2300 ARG (JNIEnv *, jni_env);
2301 ARG (jmethodID, method);
2302 ARG (jlocation, location);
2303 ARG (jclass, field_class);
2304 ARG (jobject, object);
2305 ARG (jfieldID, field);
2306 env->callbacks.FieldAccess (env, jni_env, event_thread, method,
2307 location, field_class, object, field);
2308 }
2309 break;
2310
2311 case JVMTI_EVENT_FIELD_MODIFICATION:
2312 if (env->callbacks.FieldModification != NULL)
2313 {
2314 ARG (JNIEnv *, jni_env);
2315 ARG (jmethodID, method);
2316 ARG (jlocation, location);
2317 ARG (jclass, field_class);
2318 ARG (jobject, object);
2319 ARG (jfieldID, field);
2320 GET_CHAR_ARG (signature_type);
2321 ARG (jvalue, new_value);
2322 env->callbacks.FieldModification (env, jni_env, event_thread, method,
2323 location, field_class, object,
2324 field, signature_type, new_value);
2325 }
2326 break;
2327
2328 case JVMTI_EVENT_METHOD_ENTRY:
2329 if (env->callbacks.MethodEntry != NULL)
2330 {
2331 ARG (JNIEnv *, jni_env);
2332 ARG (jmethodID, method);
2333 env->callbacks.MethodEntry (env, jni_env, event_thread, method);
2334 }
2335 break;
2336
2337 case JVMTI_EVENT_METHOD_EXIT:
2338 if (env->callbacks.MethodExit != NULL)
2339 {
2340 ARG (JNIEnv *, jni_env);
2341 ARG (jmethodID, method);
2342 GET_BOOLEAN_ARG (was_popped_by_exception);
2343 ARG (jvalue, return_value);
2344 env->callbacks.MethodExit (env, jni_env, event_thread, method,
2345 was_popped_by_exception, return_value);
2346 }
2347 break;
2348
2349 case JVMTI_EVENT_NATIVE_METHOD_BIND:
2350 if (env->callbacks.NativeMethodBind != NULL)
2351 {
2352 ARG (JNIEnv *, jni_env);
2353 ARG (jmethodID, method);
2354 ARG (void *, address);
2355 ARG (void **, new_address_ptr);
2356 env->callbacks.NativeMethodBind (env, jni_env, event_thread, method,
2357 address, new_address_ptr);
2358 }
2359 break;
2360
2361 case JVMTI_EVENT_COMPILED_METHOD_LOAD:
2362 if (env->callbacks.CompiledMethodLoad != NULL)
2363 {
2364 ARG (jmethodID, method);
2365 ARG (jint, code_size);
2366 ARG (const void *, code_addr);
2367 ARG (jint, map_length);
2368 ARG (const jvmtiAddrLocationMap *, map);
2369 ARG (const void *, compile_info);
2370 env->callbacks.CompiledMethodLoad (env, method, code_size, code_addr,
2371 map_length, map, compile_info);
2372 }
2373 break;
2374
2375 case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
2376 if (env->callbacks.CompiledMethodUnload != NULL)
2377 {
2378 ARG (jmethodID, method);
2379 ARG (const void *, code_addr);
2380 env->callbacks.CompiledMethodUnload (env, method, code_addr);
2381 }
2382 break;
2383
2384 case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
2385 if (env->callbacks.DynamicCodeGenerated != NULL)
2386 {
2387 ARG (const char *, name);
2388 ARG (const void *, address);
2389 ARG (jint, length);
2390 env->callbacks.DynamicCodeGenerated (env, name, address, length);
2391 }
2392 break;
2393
2394 case JVMTI_EVENT_DATA_DUMP_REQUEST:
2395 if (env->callbacks.DataDumpRequest != NULL)
2396 {
2397 env->callbacks.DataDumpRequest (env);
2398 }
2399 break;
2400
2401 case JVMTI_EVENT_MONITOR_WAIT:
2402 if (env->callbacks.MonitorWait != NULL)
2403 {
2404 ARG (JNIEnv *, jni_env);
2405 ARG (jobject, object);
2406 ARG (jlong, timeout);
2407 env->callbacks.MonitorWait (env, jni_env, event_thread, object,
2408 timeout);
2409 }
2410 break;
2411
2412 case JVMTI_EVENT_MONITOR_WAITED:
2413 if (env->callbacks.MonitorWaited != NULL)
2414 {
2415 ARG (JNIEnv *, jni_env);
2416 ARG (jobject, object);
2417 GET_BOOLEAN_ARG (timed_out);
2418 env->callbacks.MonitorWaited (env, jni_env, event_thread, object,
2419 timed_out);
2420 }
2421 break;
2422
2423 case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
2424 if (env->callbacks.MonitorContendedEnter != NULL)
2425 {
2426 ARG (JNIEnv *, jni_env);
2427 ARG (jobject, object);
2428 env->callbacks.MonitorContendedEnter (env, jni_env, event_thread,
2429 object);
2430 }
2431 break;
2432
2433 case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
2434 if (env->callbacks.MonitorContendedEntered != NULL)
2435 {
2436 ARG (JNIEnv *, jni_env);
2437 ARG (jobject, object);
2438 env->callbacks.MonitorContendedEntered (env, jni_env, event_thread,
2439 object);
2440 }
2441 break;
2442
2443 case JVMTI_EVENT_GARBAGE_COLLECTION_START:
2444 if (env->callbacks.GarbageCollectionStart != NULL)
2445 {
2446 env->callbacks.GarbageCollectionStart (env);
2447 }
2448 break;
2449
2450 case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
2451 if (env->callbacks.GarbageCollectionFinish != NULL)
2452 {
2453 env->callbacks.GarbageCollectionFinish (env);
2454 }
2455 break;
2456
2457 case JVMTI_EVENT_OBJECT_FREE:
2458 if (env->callbacks.ObjectFree != NULL)
2459 {
2460 ARG (jlong, tag);
2461 env->callbacks.ObjectFree (env, tag);
2462 }
2463 break;
2464
2465 case JVMTI_EVENT_VM_OBJECT_ALLOC:
2466 if (env->callbacks.VMObjectAlloc != NULL)
2467 {
2468 ARG (JNIEnv *, jni_env);
2469 ARG (jobject, object);
2470 ARG (jclass, object_class);
2471 ARG (jlong, size);
2472 env->callbacks.VMObjectAlloc (env, jni_env, event_thread,
2473 object, object_class, size);
2474 }
2475 break;
2476
2477 default:
2478 fprintf (stderr, "libgcj: post of unknown JVMTI event (%d)\n",
2479 (int) type);
2480 break;
2481 }
2482 va_end (args);
2483 #undef ARG
2484 #undef GET_BOOLEAN_ARG
2485 #undef GET_CHAR_ARG
2486 }
2487
2488 /* Post an event to requesting JVMTI environments
2489 *
2490 * This function should not be called without consulting the
2491 * JVMTI_REQUESTED_EVENT macro first (for speed). It does no real
2492 * harm (other than kill speed), since this function will still
2493 * only send the event if it was properly requested by an environment.
2494 */
2495 void
2496 _Jv_JVMTI_PostEvent (jvmtiEvent type, jthread event_thread, ...)
2497 {
2498 va_list args;
2499 va_start (args, event_thread);
2500
2501 _envListLock->readLock ()->lock ();
2502 struct jvmti_env_list *e;
2503 FOREACH_ENVIRONMENT (e)
2504 {
2505 /* Events are only posted if the event was explicitly enabled,
2506 it has a registered event handler, and the event thread
2507 matches (either globally or restricted to a specific thread).
2508 Here we check all but the event handler, which will be handled
2509 by post_event. */
2510 if (e->env->enabled[EVENT_INDEX(type)]
2511 && (e->env->thread[EVENT_INDEX(type)] == NULL
2512 || e->env->thread[EVENT_INDEX(type)] == event_thread))
2513 {
2514 post_event (e->env, type, event_thread, args);
2515 }
2516 }
2517 _envListLock->readLock ()->unlock ();
2518 va_end (args);
2519 }