OSDN Git Service

2007-02-21 Kyle Galloway <kgallowa@redhat.com>
[pf3gnuchains/gcc-fork.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_GetArgumentsSize (jvmtiEnv *env, jmethodID method, jint *size)
1090 {
1091   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1092   NULL_CHECK (size);
1093   
1094   CHECK_FOR_NATIVE_METHOD (method);
1095   
1096   jvmtiError jerr;
1097   char *sig;
1098   jint num_slots = 0;
1099   
1100   jerr = env->GetMethodName (method, NULL, &sig, NULL);
1101   if (jerr != JVMTI_ERROR_NONE)
1102     return jerr;
1103   
1104   // If the method is non-static add a slot for the "this" pointer.
1105   if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
1106     num_slots++;
1107   
1108   for (int i = 0; sig[i] != ')'; i++)
1109     {
1110       if (sig[i] == 'Z' || sig[i] == 'B' || sig[i] == 'C' || sig[i] == 'S'
1111           || sig[i] == 'I' || sig[i] == 'F')
1112         num_slots++;
1113       else if (sig[i] == 'J' || sig[i] == 'D')
1114         num_slots+=2;
1115       else if (sig[i] == 'L')
1116         {
1117           num_slots++;
1118           while (sig[i] != ';')
1119             i++;
1120         }
1121     }
1122   
1123   *size = num_slots;
1124   return JVMTI_ERROR_NONE;
1125 }
1126
1127 static jvmtiError JNICALL
1128 _Jv_JVMTI_GetMethodDeclaringClass (MAYBE_UNUSED jvmtiEnv *env,
1129                                    jmethodID method,
1130                                    jclass *declaring_class_ptr)
1131 {
1132   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1133   NULL_CHECK (declaring_class_ptr);
1134
1135   jclass klass = _Jv_GetMethodDeclaringClass (method);
1136   if (klass != NULL)
1137     {
1138       *declaring_class_ptr = klass;
1139       return JVMTI_ERROR_NONE;
1140     }
1141
1142   return JVMTI_ERROR_INVALID_METHODID;
1143 }
1144
1145 static jvmtiError JNICALL
1146 _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env,
1147                                  jobject init_loader,
1148                                  jint *count_ptr,
1149                                  jclass **result_ptr)
1150 {
1151   using namespace java::lang;
1152   using namespace java::util;
1153
1154   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1155   NULL_CHECK (count_ptr);
1156   NULL_CHECK (result_ptr);
1157
1158   ClassLoader *loader = (ClassLoader *) init_loader;
1159   if (loader == NULL)
1160     loader = VMClassLoader::bootLoader;
1161
1162   Collection *values = loader->loadedClasses->values();
1163   jobjectArray array = values->toArray();
1164   *count_ptr = array->length;
1165   jobject *elts = elements (array);
1166   jclass *result
1167     = (jclass *) _Jv_MallocUnchecked (*count_ptr * sizeof (jclass));
1168   if (result == NULL)
1169     return JVMTI_ERROR_OUT_OF_MEMORY;
1170
1171   // FIXME: JNI references...
1172   memcpy (result, elts, *count_ptr * sizeof (jclass));
1173
1174   *result_ptr = result;
1175
1176   return JVMTI_ERROR_NONE;
1177 }
1178
1179 static jvmtiError JNICALL
1180 _Jv_JVMTI_GetStackTrace (MAYBE_UNUSED jvmtiEnv *env, jthread thread,
1181                          jint start_depth, jint max_frames,
1182                          jvmtiFrameInfo *frames, jint *frame_count)
1183 {
1184   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1185
1186   ILLEGAL_ARGUMENT (max_frames < 0);
1187   
1188   NULL_CHECK (frames);
1189   NULL_CHECK (frame_count);
1190         
1191   using namespace java::lang;
1192   
1193   THREAD_DEFAULT_TO_CURRENT (thread);
1194   THREAD_CHECK_VALID (thread);
1195   THREAD_CHECK_IS_ALIVE (thread);
1196     
1197   jvmtiError jerr = env->GetFrameCount (thread, frame_count);
1198   if (jerr != JVMTI_ERROR_NONE)
1199     return jerr;
1200   
1201   // start_depth can be either a positive number, indicating the depth of the
1202   // stack at which to begin the trace, or a negative number indicating the
1203   // number of frames at the bottom of the stack to exclude.  These checks
1204   // ensure that it is a valid value in either case
1205   
1206   ILLEGAL_ARGUMENT (start_depth >= (*frame_count));
1207   ILLEGAL_ARGUMENT (start_depth < (-(*frame_count)));
1208   
1209   _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame);
1210
1211   // If start_depth is negative use this to determine at what depth to start
1212   // the trace by adding it to the length of the call stack.  This allows the
1213   // use of the same frame "discarding" mechanism as for a positive start_depth
1214   if (start_depth < 0)
1215     start_depth = *frame_count + start_depth;
1216   
1217   // If start_depth > 0 "remove" start_depth frames from the beginning
1218   // of the stack before beginning the trace by moving along the frame list.
1219   while (start_depth > 0)
1220     {
1221       frame = frame->next;
1222       start_depth--;
1223       (*frame_count)--;
1224     }
1225   
1226   // Now check to see if the array supplied by the agent is large enough to
1227   // hold frame_count frames, after adjustment for start_depth.
1228   if ((*frame_count) > max_frames)
1229     (*frame_count) = max_frames;
1230   
1231   for (int i = 0; i < (*frame_count); i++)
1232     {
1233       frames[i].method = frame->self->get_method ();
1234       
1235       // Set the location in the frame, native frames have location = -1
1236       if (frame->frame_type == frame_interpreter)
1237         {
1238           _Jv_InterpMethod *imeth 
1239             = static_cast<_Jv_InterpMethod *> (frame->self);
1240           _Jv_InterpFrame *interp_frame 
1241             = static_cast<_Jv_InterpFrame *> (frame);
1242           frames[i].location = imeth->insn_index (interp_frame->pc);
1243         }
1244       else
1245         frames[i].location = -1;
1246         
1247       frame = frame->next;
1248     }
1249     
1250   return JVMTI_ERROR_NONE;
1251 }
1252
1253 static jvmtiError JNICALL
1254 _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env)
1255 {
1256   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
1257   _Jv_RunGC();
1258   return JVMTI_ERROR_NONE;
1259 }
1260
1261 static jvmtiError JNICALL
1262 _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
1263                                const jniNativeInterface *function_table)
1264 {
1265   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1266   NULL_CHECK (function_table);
1267   memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface));
1268   return JVMTI_ERROR_NONE;
1269 }
1270
1271 static jvmtiError JNICALL
1272 _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
1273                                jniNativeInterface **function_table)
1274 {
1275   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1276   NULL_CHECK (function_table);
1277   *function_table
1278     = (jniNativeInterface *) _Jv_MallocUnchecked (sizeof (jniNativeInterface));
1279   if (*function_table == NULL)
1280     return JVMTI_ERROR_OUT_OF_MEMORY;
1281   memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface));
1282   return JVMTI_ERROR_NONE;
1283 }
1284
1285 static jvmtiError JNICALL
1286 _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env)
1287 {
1288   NULL_CHECK (env);
1289
1290   if (_jvmtiEnvironments == NULL)
1291     return JVMTI_ERROR_INVALID_ENVIRONMENT;
1292   else
1293     {
1294       _envListLock->writeLock ()->lock ();
1295       if (_jvmtiEnvironments->env == env)
1296         {
1297           struct jvmti_env_list *next = _jvmtiEnvironments->next;
1298           _Jv_Free (_jvmtiEnvironments);
1299           _jvmtiEnvironments = next;
1300         }
1301       else
1302         {
1303           struct jvmti_env_list *e = _jvmtiEnvironments; 
1304           while (e->next != NULL && e->next->env != env)
1305             e = e->next;
1306           if (e->next == NULL)
1307             {
1308               _envListLock->writeLock ()->unlock ();
1309               return JVMTI_ERROR_INVALID_ENVIRONMENT;
1310             }
1311
1312           struct jvmti_env_list *next = e->next->next;
1313           _Jv_Free (e->next);
1314           e->next = next;
1315         }
1316       _envListLock->writeLock ()->unlock ();
1317     }
1318
1319   _Jv_Free (env);
1320
1321   check_enabled_events ();
1322
1323   return JVMTI_ERROR_NONE;
1324 }
1325
1326 static jvmtiError JNICALL
1327 _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
1328                              char **result)
1329 {
1330   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1331   NULL_CHECK (property);
1332   NULL_CHECK (result);
1333
1334   jstring name = JvNewStringUTF(property);
1335   jstring result_str = gnu::classpath::SystemProperties::getProperty(name);
1336
1337   if (result_str == NULL)
1338     return JVMTI_ERROR_NOT_AVAILABLE;
1339
1340   int len = JvGetStringUTFLength (result_str);
1341   *result = (char *) _Jv_MallocUnchecked (len + 1);
1342   if (*result == NULL)
1343     return JVMTI_ERROR_OUT_OF_MEMORY;
1344   JvGetStringUTFRegion (result_str, 0, result_str->length(), *result);
1345   (*result)[len] = '\0';
1346
1347   return JVMTI_ERROR_NONE;
1348 }
1349
1350 static jvmtiError JNICALL
1351 _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
1352                              const char *value)
1353 {
1354   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
1355
1356   NULL_CHECK (property);
1357   if (value == NULL)
1358     {
1359       // FIXME: When would a property not be writeable?
1360       return JVMTI_ERROR_NONE;
1361     }
1362
1363   jstring prop_str = JvNewStringUTF(property);
1364   jstring value_str = JvNewStringUTF(value);
1365   gnu::classpath::SystemProperties::setProperty(prop_str, value_str);
1366   return JVMTI_ERROR_NONE;
1367 }
1368
1369 static jvmtiError JNICALL
1370 _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr)
1371 {
1372   NULL_CHECK (nanos_ptr);
1373   *nanos_ptr = _Jv_platform_nanotime();
1374   return JVMTI_ERROR_NONE;
1375 }
1376
1377 static jvmtiError JNICALL
1378 _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env,
1379                                   jint *nprocessors_ptr)
1380 {
1381   NULL_CHECK (nprocessors_ptr);
1382 #ifdef _SC_NPROCESSORS_ONLN
1383   *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN);
1384 #else
1385   *nprocessors_ptr = 1;
1386 #endif
1387   return JVMTI_ERROR_NONE;
1388 }
1389
1390 static jvmtiError JNICALL
1391 _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env,
1392                                            const char *segment)
1393 {
1394   using namespace java::lang;
1395   using namespace java::net;
1396   using namespace gnu::gcj::runtime;
1397
1398   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
1399   NULL_CHECK (segment);
1400
1401   jstring str_segment = JvNewStringUTF(segment);
1402   URL *url;
1403   try
1404     {
1405       url = new URL(JvNewStringUTF("file"), NULL, str_segment);
1406     }
1407   catch (jthrowable ignore)
1408     {
1409       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1410     }
1411
1412   BootClassLoader *loader = VMClassLoader::bootLoader;
1413   // Don't call this too early.
1414   // assert (loader != NULL);
1415   loader->addURL(url);
1416   return JVMTI_ERROR_NONE;
1417 }
1418
1419 static jvmtiError JNICALL
1420 _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag,
1421                           jboolean value)
1422 {
1423   switch (flag)
1424     {
1425     case JVMTI_VERBOSE_OTHER:
1426     case JVMTI_VERBOSE_GC:
1427     case JVMTI_VERBOSE_JNI:
1428       // Ignore.
1429       break;
1430     case JVMTI_VERBOSE_CLASS:
1431       gcj::verbose_class_flag = value;
1432       break;
1433     default:
1434       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1435     }
1436   return JVMTI_ERROR_NONE;
1437 }
1438
1439 static jvmtiError JNICALL
1440 _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object,
1441                          jlong *result)
1442 {
1443   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
1444   if (object == NULL)
1445     return JVMTI_ERROR_INVALID_OBJECT;
1446   NULL_CHECK (result);
1447
1448   jclass klass = object->getClass();
1449   if (klass->isArray())
1450     {
1451       jclass comp = klass->getComponentType();
1452       jint base
1453         = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL,
1454                                                                     klass->getComponentType());
1455       // FIXME: correct for primitive types?
1456       jint compSize = comp->size();
1457       __JArray *array = (__JArray *) object;
1458       *result = base + array->length * compSize;
1459     }
1460   else
1461     {
1462       // Note that if OBJECT is a String then it may (if
1463       // str->data==str) take more space.  Do we care?
1464       *result = klass->size();
1465     }
1466   return JVMTI_ERROR_NONE;
1467 }
1468
1469 /* An event is enabled only if it has both an event handler
1470    and it is enabled in the environment. */
1471 static void
1472 check_enabled_event (jvmtiEvent type)
1473 {
1474   bool *enabled;
1475   int offset;
1476
1477 #define GET_OFFSET(Event)                               \
1478   do                                                    \
1479     {                                                   \
1480       enabled = &JVMTI::Event;                          \
1481       offset = offsetof (jvmtiEventCallbacks, Event);   \
1482     }                                                   \
1483   while (0)
1484
1485   switch (type)
1486     {
1487     case JVMTI_EVENT_VM_INIT:
1488       GET_OFFSET (VMInit);
1489       break;
1490
1491     case JVMTI_EVENT_VM_DEATH:
1492       GET_OFFSET (VMDeath);
1493       break;
1494
1495     case JVMTI_EVENT_THREAD_START:
1496       GET_OFFSET (ThreadStart);
1497       break;
1498
1499     case JVMTI_EVENT_THREAD_END:
1500       GET_OFFSET (ThreadEnd);
1501       break;
1502
1503     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1504       GET_OFFSET (ClassFileLoadHook);
1505       break;
1506
1507     case JVMTI_EVENT_CLASS_LOAD:
1508       GET_OFFSET (ClassLoad);
1509       break;
1510
1511     case JVMTI_EVENT_CLASS_PREPARE:
1512       GET_OFFSET (ClassPrepare);
1513       break;
1514
1515     case JVMTI_EVENT_VM_START:
1516       GET_OFFSET (VMStart);
1517       break;
1518
1519     case JVMTI_EVENT_EXCEPTION:
1520       GET_OFFSET (Exception);
1521       break;
1522
1523     case JVMTI_EVENT_EXCEPTION_CATCH:
1524       GET_OFFSET (ExceptionCatch);
1525       break;
1526
1527     case JVMTI_EVENT_SINGLE_STEP:
1528       GET_OFFSET (SingleStep);
1529       break;
1530
1531     case JVMTI_EVENT_FRAME_POP:
1532       GET_OFFSET (FramePop);
1533       break;
1534
1535     case JVMTI_EVENT_BREAKPOINT:
1536       GET_OFFSET (Breakpoint);
1537       break;
1538
1539     case JVMTI_EVENT_FIELD_ACCESS:
1540       GET_OFFSET (FieldAccess);
1541       break;
1542
1543     case JVMTI_EVENT_FIELD_MODIFICATION:
1544       GET_OFFSET (FieldModification);
1545       break;
1546
1547     case JVMTI_EVENT_METHOD_ENTRY:
1548       GET_OFFSET (MethodEntry);
1549       break;
1550
1551     case JVMTI_EVENT_METHOD_EXIT:
1552       GET_OFFSET (MethodExit);
1553       break;
1554
1555     case JVMTI_EVENT_NATIVE_METHOD_BIND:
1556       GET_OFFSET (NativeMethodBind);
1557       break;
1558
1559     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1560       GET_OFFSET (CompiledMethodLoad);
1561       break;
1562
1563     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1564       GET_OFFSET (CompiledMethodUnload);
1565       break;
1566
1567     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1568       GET_OFFSET (DynamicCodeGenerated);
1569       break;
1570
1571     case JVMTI_EVENT_DATA_DUMP_REQUEST:
1572       GET_OFFSET (DataDumpRequest);
1573       break;
1574
1575     case JVMTI_EVENT_MONITOR_WAIT:
1576       GET_OFFSET (MonitorWait);
1577       break;
1578
1579     case JVMTI_EVENT_MONITOR_WAITED:
1580       GET_OFFSET (MonitorWaited);
1581       break;
1582
1583     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1584       GET_OFFSET (MonitorContendedEnter);
1585       break;
1586
1587     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1588       GET_OFFSET (MonitorContendedEntered);
1589       break;
1590
1591     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1592       GET_OFFSET (GarbageCollectionStart);
1593       break;
1594
1595     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1596       GET_OFFSET (GarbageCollectionFinish);
1597       break;
1598
1599     case JVMTI_EVENT_OBJECT_FREE:
1600       GET_OFFSET (ObjectFree);
1601       break;
1602
1603     case JVMTI_EVENT_VM_OBJECT_ALLOC:
1604       GET_OFFSET (VMObjectAlloc);
1605       break;
1606
1607     default:
1608       fprintf (stderr,
1609                "libgcj: check_enabled_event for unknown JVMTI event (%d)\n",
1610                (int) type);
1611       return;
1612     }
1613 #undef GET_OFFSET
1614
1615   int index = EVENT_INDEX (type); // safe since caller checks this
1616
1617   if (_jvmtiEnvironments != NULL)
1618     {
1619       _envListLock->readLock ()->lock ();
1620       struct jvmti_env_list *e;
1621       FOREACH_ENVIRONMENT (e)
1622         {
1623           char *addr
1624             = reinterpret_cast<char *> (&e->env->callbacks) + offset;
1625           void **callback = reinterpret_cast<void **> (addr);
1626           if (e->env->enabled[index] && *callback != NULL)
1627             {
1628               *enabled = true;
1629               _envListLock->readLock ()->unlock ();
1630               return;
1631             }
1632         }
1633
1634       _envListLock->readLock ()->unlock ();
1635     }
1636
1637   *enabled = false;
1638 }
1639
1640 static void
1641 check_enabled_events ()
1642 {
1643   check_enabled_event (JVMTI_EVENT_VM_INIT);
1644   check_enabled_event (JVMTI_EVENT_VM_DEATH);
1645   check_enabled_event (JVMTI_EVENT_THREAD_START);
1646   check_enabled_event (JVMTI_EVENT_THREAD_END);
1647   check_enabled_event (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK);
1648   check_enabled_event (JVMTI_EVENT_CLASS_LOAD);
1649   check_enabled_event (JVMTI_EVENT_CLASS_PREPARE);
1650   check_enabled_event (JVMTI_EVENT_VM_START);
1651   check_enabled_event (JVMTI_EVENT_EXCEPTION);
1652   check_enabled_event (JVMTI_EVENT_EXCEPTION_CATCH);
1653   check_enabled_event (JVMTI_EVENT_SINGLE_STEP);
1654   check_enabled_event (JVMTI_EVENT_FRAME_POP);
1655   check_enabled_event (JVMTI_EVENT_BREAKPOINT);
1656   check_enabled_event (JVMTI_EVENT_FIELD_ACCESS);
1657   check_enabled_event (JVMTI_EVENT_FIELD_MODIFICATION);
1658   check_enabled_event (JVMTI_EVENT_METHOD_ENTRY);
1659   check_enabled_event (JVMTI_EVENT_METHOD_EXIT);
1660   check_enabled_event (JVMTI_EVENT_NATIVE_METHOD_BIND);
1661   check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_LOAD);
1662   check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_UNLOAD);
1663   check_enabled_event (JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
1664   check_enabled_event (JVMTI_EVENT_DATA_DUMP_REQUEST);
1665   check_enabled_event (JVMTI_EVENT_MONITOR_WAIT);
1666   check_enabled_event (JVMTI_EVENT_MONITOR_WAITED);
1667   check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTER);
1668   check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED);
1669   check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_START);
1670   check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH);
1671   check_enabled_event (JVMTI_EVENT_OBJECT_FREE);
1672   check_enabled_event (JVMTI_EVENT_VM_OBJECT_ALLOC);
1673 }
1674
1675 static jvmtiError JNICALL
1676 _Jv_JVMTI_SetEventNotificationMode (jvmtiEnv *env, jvmtiEventMode mode,
1677                                     jvmtiEvent type, jthread event_thread, ...)
1678 {
1679   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1680
1681   if (event_thread != NULL)
1682     {
1683       THREAD_CHECK_VALID (event_thread);
1684       THREAD_CHECK_IS_ALIVE (event_thread);
1685     }
1686
1687   bool enabled;
1688   switch (mode)
1689     {
1690     case JVMTI_DISABLE:
1691       enabled = false;
1692       break;
1693     case JVMTI_ENABLE:
1694       enabled = true;
1695       break;
1696
1697     default:
1698       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1699     }
1700
1701   switch (type)
1702     {
1703     case JVMTI_EVENT_VM_INIT:
1704     case JVMTI_EVENT_VM_DEATH:
1705     case JVMTI_EVENT_THREAD_START:
1706     case JVMTI_EVENT_VM_START:
1707     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1708     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1709     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1710     case JVMTI_EVENT_DATA_DUMP_REQUEST:
1711       ILLEGAL_ARGUMENT (event_thread != NULL);
1712       break;
1713
1714     case JVMTI_EVENT_THREAD_END:
1715     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1716     case JVMTI_EVENT_CLASS_LOAD:
1717     case JVMTI_EVENT_CLASS_PREPARE:
1718     case JVMTI_EVENT_EXCEPTION:
1719     case JVMTI_EVENT_EXCEPTION_CATCH:
1720     case JVMTI_EVENT_SINGLE_STEP:
1721     case JVMTI_EVENT_FRAME_POP:
1722     case JVMTI_EVENT_BREAKPOINT:
1723     case JVMTI_EVENT_FIELD_ACCESS:
1724     case JVMTI_EVENT_FIELD_MODIFICATION:
1725     case JVMTI_EVENT_METHOD_ENTRY:
1726     case JVMTI_EVENT_METHOD_EXIT:
1727     case JVMTI_EVENT_NATIVE_METHOD_BIND:
1728     case JVMTI_EVENT_MONITOR_WAIT:
1729     case JVMTI_EVENT_MONITOR_WAITED:
1730     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1731     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1732     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1733     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1734     case JVMTI_EVENT_OBJECT_FREE:
1735     case JVMTI_EVENT_VM_OBJECT_ALLOC:
1736       break;
1737
1738     default:
1739       return JVMTI_ERROR_INVALID_EVENT_TYPE;
1740     }
1741
1742   env->thread[EVENT_INDEX(type)] = event_thread;
1743   env->enabled[EVENT_INDEX(type)] = enabled;
1744   check_enabled_event (type);
1745   return JVMTI_ERROR_NONE;
1746 }
1747
1748 static jvmtiError JNICALL
1749 _Jv_JVMTI_SetEventCallbacks (jvmtiEnv *env,
1750                              const jvmtiEventCallbacks *callbacks,
1751                              jint size_of_callbacks)
1752 {
1753   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1754   ILLEGAL_ARGUMENT (size_of_callbacks < 0);
1755
1756   // Copy the list of callbacks into the environment
1757   memcpy (&env->callbacks, callbacks, sizeof (jvmtiEventCallbacks));
1758
1759   /* Check which events are now enabeld (JVMTI makes no requirements
1760      about the order in which SetEventCallbacks and SetEventNotifications
1761      are called. So we must check all events here. */
1762   check_enabled_events ();
1763
1764   return JVMTI_ERROR_NONE;
1765 }
1766
1767 static jvmtiError JNICALL
1768 _Jv_JVMTI_GetErrorName (MAYBE_UNUSED jvmtiEnv *env, jvmtiError error,
1769                         char **name_ptr)
1770 {
1771   NULL_CHECK (name_ptr);
1772
1773   const char *name;
1774   switch (error)
1775     {
1776     case JVMTI_ERROR_NONE:
1777       name = "none";
1778       break;
1779
1780     case JVMTI_ERROR_NULL_POINTER:
1781       name = "null pointer";
1782       break;
1783
1784     case JVMTI_ERROR_OUT_OF_MEMORY:
1785       name = "out of memory";
1786       break;
1787
1788     case JVMTI_ERROR_ACCESS_DENIED:
1789       name = "access denied";
1790       break;
1791
1792     case JVMTI_ERROR_WRONG_PHASE:
1793       name = "wrong phase";
1794       break;
1795
1796     case JVMTI_ERROR_INTERNAL:
1797       name = "internal error";
1798       break;
1799
1800     case JVMTI_ERROR_UNATTACHED_THREAD:
1801       name = "unattached thread";
1802       break;
1803
1804     case JVMTI_ERROR_INVALID_ENVIRONMENT:
1805       name = "invalid environment";
1806       break;
1807
1808     case JVMTI_ERROR_INVALID_PRIORITY:
1809       name = "invalid priority";
1810       break;
1811
1812     case JVMTI_ERROR_THREAD_NOT_SUSPENDED:
1813       name = "thread not suspended";
1814       break;
1815
1816     case JVMTI_ERROR_THREAD_SUSPENDED:
1817       name = "thread suspended";
1818       break;
1819
1820     case JVMTI_ERROR_THREAD_NOT_ALIVE:
1821       name = "thread not alive";
1822       break;
1823
1824     case JVMTI_ERROR_CLASS_NOT_PREPARED:
1825       name = "class not prepared";
1826       break;
1827
1828     case JVMTI_ERROR_NO_MORE_FRAMES:
1829       name = "no more frames";
1830       break;
1831
1832     case JVMTI_ERROR_OPAQUE_FRAME:
1833       name = "opaque frame";
1834       break;
1835
1836     case JVMTI_ERROR_DUPLICATE:
1837       name = "duplicate";
1838       break;
1839
1840     case JVMTI_ERROR_NOT_FOUND:
1841       name = "not found";
1842       break;
1843
1844     case JVMTI_ERROR_NOT_MONITOR_OWNER:
1845       name = "not monitor owner";
1846       break;
1847
1848     case JVMTI_ERROR_INTERRUPT:
1849       name = "interrupted";
1850       break;
1851
1852     case JVMTI_ERROR_UNMODIFIABLE_CLASS:
1853       name = "unmodifiable class";
1854       break;
1855
1856     case JVMTI_ERROR_NOT_AVAILABLE:
1857       name = "not available";
1858       break;
1859
1860     case JVMTI_ERROR_ABSENT_INFORMATION:
1861       name = "absent information";
1862       break;
1863
1864     case JVMTI_ERROR_INVALID_EVENT_TYPE:
1865       name = "invalid event type";
1866       break;
1867
1868     case JVMTI_ERROR_NATIVE_METHOD:
1869       name = "native method";
1870       break;
1871
1872     case JVMTI_ERROR_INVALID_THREAD:
1873       name = "invalid thread";
1874       break;
1875
1876     case JVMTI_ERROR_INVALID_THREAD_GROUP:
1877       name = "invalid thread group";
1878       break;
1879
1880     case JVMTI_ERROR_INVALID_OBJECT:
1881       name = "invalid object";
1882       break;
1883
1884     case JVMTI_ERROR_INVALID_CLASS:
1885       name = "invalid class";
1886       break;
1887
1888     case JVMTI_ERROR_INVALID_METHODID:
1889       name = "invalid method ID";
1890       break;
1891
1892     case JVMTI_ERROR_INVALID_LOCATION:
1893       name = "invalid location";
1894       break;
1895
1896     case JVMTI_ERROR_INVALID_FIELDID:
1897       name = "invalid field ID";
1898       break;
1899
1900     case JVMTI_ERROR_TYPE_MISMATCH:
1901       name = "type mismatch";
1902       break;
1903
1904     case JVMTI_ERROR_INVALID_SLOT:
1905       name = "invalid slot";
1906       break;
1907
1908     case JVMTI_ERROR_INVALID_MONITOR:
1909       name = "invalid monitor";
1910       break;
1911
1912     case JVMTI_ERROR_INVALID_CLASS_FORMAT:
1913       name = "invalid class format";
1914       break;
1915
1916     case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION:
1917       name = "circular class definition";
1918       break;
1919
1920     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED:
1921       name = "unsupported redefinition: method added";
1922       break;
1923
1924     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED:
1925       name = "unsupported redefinition: schema changed";
1926       break;
1927
1928     case JVMTI_ERROR_INVALID_TYPESTATE:
1929       name = "invalid type state";
1930       break;
1931
1932     case JVMTI_ERROR_FAILS_VERIFICATION:
1933       name = "fails verification";
1934       break;
1935
1936     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED:
1937       name = "unsupported redefinition: hierarchy changed";
1938       break;
1939
1940     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED:
1941       name = "unsupported redefinition: method deleted";
1942       break;
1943
1944     case JVMTI_ERROR_UNSUPPORTED_VERSION:
1945       name = "unsupported version";
1946       break;
1947
1948     case JVMTI_ERROR_NAMES_DONT_MATCH:
1949       name = "names do not match";
1950       break;
1951
1952     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED:
1953       name = "unsupported redefinition: class modifiers changed";
1954       break;
1955
1956     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
1957       name = "unsupported redefinition: method modifiers changed";
1958       break;
1959
1960     case JVMTI_ERROR_MUST_POSSESS_CAPABILITY:
1961       name = "must possess capability";
1962       break;
1963
1964     case JVMTI_ERROR_ILLEGAL_ARGUMENT:
1965       name = "illegal argument";
1966       break;
1967
1968     default:
1969       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1970     }
1971
1972   *name_ptr = (char *) _Jv_MallocUnchecked (strlen (name) + 1);
1973   if (*name_ptr == NULL)
1974     return JVMTI_ERROR_OUT_OF_MEMORY;
1975
1976   strcpy (*name_ptr, name);
1977   return JVMTI_ERROR_NONE;
1978 }
1979
1980 #define RESERVED NULL
1981 #define UNIMPLEMENTED NULL
1982
1983 struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
1984 {
1985   RESERVED,                     // reserved1
1986   _Jv_JVMTI_SetEventNotificationMode, // SetEventNotificationMode
1987   RESERVED,                     // reserved3
1988   _Jv_JVMTI_GetAllThreads,              // GetAllThreads
1989   _Jv_JVMTI_SuspendThread,      // SuspendThread
1990   _Jv_JVMTI_ResumeThread,       // ResumeThread
1991   UNIMPLEMENTED,                // StopThread
1992   _Jv_JVMTI_InterruptThread,    // InterruptThread
1993   UNIMPLEMENTED,                // GetThreadInfo
1994   UNIMPLEMENTED,                // GetOwnedMonitorInfo
1995   UNIMPLEMENTED,                // GetCurrentContendedMonitor
1996   UNIMPLEMENTED,                // RunAgentThread
1997   UNIMPLEMENTED,                // GetTopThreadGroups
1998   UNIMPLEMENTED,                // GetThreadGroupInfo
1999   UNIMPLEMENTED,                // GetThreadGroupChildren
2000   _Jv_JVMTI_GetFrameCount,              // GetFrameCount
2001   UNIMPLEMENTED,                // GetThreadState
2002   RESERVED,                     // reserved18
2003   UNIMPLEMENTED,                // GetFrameLocation
2004   UNIMPLEMENTED,                // NotifyPopFrame
2005   _Jv_JVMTI_GetLocalObject,             // GetLocalObject
2006   _Jv_JVMTI_GetLocalInt,                // GetLocalInt
2007   _Jv_JVMTI_GetLocalLong,               // GetLocalLong
2008   _Jv_JVMTI_GetLocalFloat,              // GetLocalFloat
2009   _Jv_JVMTI_GetLocalDouble,             // GetLocalDouble
2010   _Jv_JVMTI_SetLocalObject,             // SetLocalObject
2011   _Jv_JVMTI_SetLocalInt,                // SetLocalInt
2012   _Jv_JVMTI_SetLocalLong,               // SetLocalLong
2013   _Jv_JVMTI_SetLocalFloat,              // SetLocalFloat
2014   _Jv_JVMTI_SetLocalDouble,             // SetLocalDouble
2015   _Jv_JVMTI_CreateRawMonitor,   // CreateRawMonitor
2016   _Jv_JVMTI_DestroyRawMonitor,  // DestroyRawMonitor
2017   _Jv_JVMTI_RawMonitorEnter,    // RawMonitorEnter
2018   _Jv_JVMTI_RawMonitorExit,     // RawMonitorExit
2019   _Jv_JVMTI_RawMonitorWait,     // RawMonitorWait
2020   _Jv_JVMTI_RawMonitorNotify,   // RawMonitorNotify
2021   _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll
2022   _Jv_JVMTI_SetBreakpoint,      // SetBreakpoint
2023   _Jv_JVMTI_ClearBreakpoint,    // ClearBreakpoint
2024   RESERVED,                     // reserved40
2025   UNIMPLEMENTED,                // SetFieldAccessWatch
2026   UNIMPLEMENTED,                // ClearFieldAccessWatch
2027   UNIMPLEMENTED,                // SetFieldModificationWatch
2028   UNIMPLEMENTED,                // ClearFieldModificationWatch
2029   RESERVED,                     // reserved45
2030   _Jv_JVMTI_Allocate,           // Allocate
2031   _Jv_JVMTI_Deallocate,         // Deallocate
2032   UNIMPLEMENTED,                // GetClassSignature
2033   _Jv_JVMTI_GetClassStatus,     // GetClassStatus
2034   UNIMPLEMENTED,                // GetSourceFileName
2035   _Jv_JVMTI_GetClassModifiers,  // GetClassModifiers
2036   _Jv_JVMTI_GetClassMethods,    // GetClassMethods
2037   UNIMPLEMENTED,                // GetClassFields
2038   UNIMPLEMENTED,                // GetImplementedInterfaces
2039   _Jv_JVMTI_IsInterface,        // IsInterface
2040   _Jv_JVMTI_IsArrayClass,       // IsArrayClass
2041   _Jv_JVMTI_GetClassLoader,     // GetClassLoader
2042   _Jv_JVMTI_GetObjectHashCode,  // GetObjectHashCode
2043   UNIMPLEMENTED,                // GetObjectMonitorUsage
2044   UNIMPLEMENTED,                // GetFieldName
2045   UNIMPLEMENTED,                // GetFieldDeclaringClass
2046   _Jv_JVMTI_GetFieldModifiers,  // GetFieldModifiers
2047   _Jv_JVMTI_IsFieldSynthetic,   // IsFieldSynthetic
2048   _Jv_JVMTI_GetMethodName,      // GetMethodName
2049   _Jv_JVMTI_GetMethodDeclaringClass,  // GetMethodDeclaringClass
2050   _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers
2051   RESERVED,                     // reserved67
2052   _Jv_JVMTI_GetMaxLocals,               // GetMaxLocals
2053   _Jv_JVMTI_GetArgumentsSize,           // GetArgumentsSize
2054   _Jv_JVMTI_GetLineNumberTable, // GetLineNumberTable
2055   UNIMPLEMENTED,                // GetMethodLocation
2056   _Jv_JVMTI_GetLocalVariableTable,              // GetLocalVariableTable
2057   RESERVED,                     // reserved73
2058   RESERVED,                     // reserved74
2059   UNIMPLEMENTED,                // GetBytecodes
2060   _Jv_JVMTI_IsMethodNative,     // IsMethodNative
2061   _Jv_JVMTI_IsMethodSynthetic,  // IsMethodSynthetic
2062   UNIMPLEMENTED,                // GetLoadedClasses
2063   _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses
2064   UNIMPLEMENTED,                // PopFrame
2065   RESERVED,                     // reserved81
2066   RESERVED,                     // reserved82
2067   RESERVED,                     // reserved83
2068   RESERVED,                     // reserved84
2069   RESERVED,                     // reserved85
2070   RESERVED,                     // reserved86
2071   UNIMPLEMENTED,                // RedefineClasses
2072   UNIMPLEMENTED,                // GetVersionNumber
2073   UNIMPLEMENTED,                // GetCapabilities
2074   UNIMPLEMENTED,                // GetSourceDebugExtension
2075   UNIMPLEMENTED,                // IsMethodObsolete
2076   UNIMPLEMENTED,                // SuspendThreadList
2077   UNIMPLEMENTED,                // ResumeThreadList
2078   RESERVED,                     // reserved94
2079   RESERVED,                     // reserved95
2080   RESERVED,                     // reserved96
2081   RESERVED,                     // reserved97
2082   RESERVED,                     // reserved98
2083   RESERVED,                     // reserved99
2084   UNIMPLEMENTED,                // GetAllStackTraces
2085   UNIMPLEMENTED,                // GetThreadListStackTraces
2086   UNIMPLEMENTED,                // GetThreadLocalStorage
2087   UNIMPLEMENTED,                // SetThreadLocalStorage
2088   _Jv_JVMTI_GetStackTrace,              // GetStackTrace
2089   RESERVED,                     // reserved105
2090   UNIMPLEMENTED,                // GetTag
2091   UNIMPLEMENTED,                // SetTag
2092   _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection
2093   UNIMPLEMENTED,                // IterateOverObjectsReachable
2094   UNIMPLEMENTED,                // IterateOverReachableObjects
2095   UNIMPLEMENTED,                // IterateOverHeap
2096   UNIMPLEMENTED,                // IterateOverInstanceOfClass
2097   RESERVED,                     // reserved113
2098   UNIMPLEMENTED,                // GetObjectsWithTags
2099   RESERVED,                     // reserved115
2100   RESERVED,                     // reserved116
2101   RESERVED,                     // reserved117
2102   RESERVED,                     // reserved118
2103   RESERVED,                     // reserved119
2104   _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable
2105   _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable
2106   _Jv_JVMTI_SetEventCallbacks,  // SetEventCallbacks
2107   UNIMPLEMENTED,                // GenerateEvents
2108   UNIMPLEMENTED,                // GetExtensionFunctions
2109   UNIMPLEMENTED,                // GetExtensionEvents
2110   UNIMPLEMENTED,                // SetExtensionEventCallback
2111   _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment
2112   _Jv_JVMTI_GetErrorName,       // GetErrorName
2113   UNIMPLEMENTED,                // GetJLocationFormat
2114   UNIMPLEMENTED,                // GetSystemProperties
2115   _Jv_JVMTI_GetSystemProperty,  // GetSystemProperty
2116   _Jv_JVMTI_SetSystemProperty,  // SetSystemProperty
2117   UNIMPLEMENTED,                // GetPhase
2118   UNIMPLEMENTED,                // GetCurrentThreadCpuTimerInfo
2119   UNIMPLEMENTED,                // GetCurrentThreadCpuTime
2120   UNIMPLEMENTED,                // GetThreadCpuTimerInfo
2121   UNIMPLEMENTED,                // GetThreadCpuTime
2122   UNIMPLEMENTED,                // GetTimerInfo
2123   _Jv_JVMTI_GetTime,            // GetTime
2124   UNIMPLEMENTED,                // GetPotentialCapabilities
2125   RESERVED,                     // reserved141
2126   UNIMPLEMENTED,                // AddCapabilities
2127   UNIMPLEMENTED,                // RelinquishCapabilities
2128   _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors
2129   RESERVED,                     // reserved145
2130   RESERVED,                     // reserved146
2131   UNIMPLEMENTED,                // GetEnvironmentLocalStorage
2132   UNIMPLEMENTED,                // SetEnvironmentLocalStorage
2133   _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch
2134   _Jv_JVMTI_SetVerboseFlag,     // SetVerboseFlag
2135   RESERVED,                     // reserved151
2136   RESERVED,                     // reserved152
2137   RESERVED,                     // reserved153
2138   _Jv_JVMTI_GetObjectSize       // GetObjectSize
2139 };
2140
2141 _Jv_JVMTIEnv *
2142 _Jv_GetJVMTIEnv (void)
2143 {
2144   _Jv_JVMTIEnv *env
2145     = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv));
2146   env->p = &_Jv_JVMTI_Interface;
2147   struct jvmti_env_list *element
2148     = (struct jvmti_env_list *) _Jv_MallocUnchecked (sizeof (struct jvmti_env_list));
2149   element->env = env;
2150   element->next = NULL;
2151
2152   _envListLock->writeLock ()->lock ();
2153   if (_jvmtiEnvironments == NULL)
2154     _jvmtiEnvironments = element;
2155   else
2156     {
2157       struct jvmti_env_list *e;
2158       for (e = _jvmtiEnvironments; e->next != NULL; e = e->next)
2159         ;
2160       e->next = element;
2161     }
2162   _envListLock->writeLock ()->unlock ();
2163
2164   /* Mark JVMTI active. This is used to force the interpreter
2165      to use either debugging or non-debugging code. Once JVMTI
2166      has been enabled, the non-debug interpreter cannot be used. */
2167   JVMTI::enabled = true;
2168   return env;
2169 }
2170
2171 void
2172 _Jv_JVMTI_Init ()
2173 {
2174   _jvmtiEnvironments = NULL;
2175   _envListLock
2176     = new java::util::concurrent::locks::ReentrantReadWriteLock ();
2177
2178   // No environments, so this should set all JVMTI:: members to false
2179   check_enabled_events ();
2180 }
2181
2182 static void
2183 post_event (jvmtiEnv *env, jvmtiEvent type, jthread event_thread, va_list args)
2184 {
2185 #define ARG(Type,Name) Type Name = (Type) va_arg (args, Type)
2186
2187 #define GET_BOOLEAN_ARG(Name)                   \
2188   ARG (int, b);                                 \
2189   jboolean Name = (b == 0) ? false : true
2190
2191 #define GET_CHAR_ARG(Name)                      \
2192   ARG (int, c);                                 \
2193   char Name = static_cast<char> (c)
2194
2195   switch (type)
2196     {
2197     case JVMTI_EVENT_VM_INIT:
2198       if (env->callbacks.VMInit != NULL)
2199         {
2200           ARG (JNIEnv *, jni_env);
2201           env->callbacks.VMInit (env, jni_env, event_thread);
2202         }
2203       break;
2204
2205     case JVMTI_EVENT_VM_DEATH:
2206       if (env->callbacks.VMDeath != NULL)
2207         {
2208           ARG (JNIEnv *, jni_env);
2209           env->callbacks.VMDeath (env, jni_env);
2210         }
2211       break;
2212
2213     case JVMTI_EVENT_THREAD_START:
2214       if (env->callbacks.ThreadStart != NULL)
2215         {
2216           ARG (JNIEnv *, jni_env);
2217           env->callbacks.ThreadStart (env, jni_env, event_thread);
2218         }
2219       break;
2220
2221     case JVMTI_EVENT_THREAD_END:
2222       if (env->callbacks.ThreadEnd != NULL)
2223         {
2224           ARG (JNIEnv *, jni_env);
2225           env->callbacks.ThreadEnd (env, jni_env, event_thread);
2226         }
2227       break;
2228
2229     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
2230       if (env->callbacks.ClassFileLoadHook != NULL)
2231         {
2232           ARG (JNIEnv *, jni_env);
2233           ARG (jclass, class_being_redefined);
2234           ARG (jobject, loader);
2235           ARG (const char *, name);
2236           ARG (jobject, protection_domain);
2237           ARG (jint, class_data_len);
2238           ARG (const unsigned char *, class_data);
2239           ARG (jint *, new_class_data_len);
2240           ARG (unsigned char **, new_class_data);
2241           env->callbacks.ClassFileLoadHook (env, jni_env,
2242                                             class_being_redefined, loader,
2243                                             name, protection_domain,
2244                                             class_data_len, class_data,
2245                                             new_class_data_len,
2246                                             new_class_data);
2247         }
2248       break;
2249
2250     case JVMTI_EVENT_CLASS_LOAD:
2251       if (env->callbacks.ClassLoad != NULL)
2252         {
2253           ARG (JNIEnv *, jni_env);
2254           ARG (jclass, klass);
2255           env->callbacks.ClassLoad (env, jni_env, event_thread, klass);
2256         }
2257       break;
2258
2259     case JVMTI_EVENT_CLASS_PREPARE:
2260       if (env->callbacks.ClassPrepare != NULL)
2261         {
2262           ARG (JNIEnv *, jni_env);
2263           ARG (jclass, klass);
2264           env->callbacks.ClassPrepare (env, jni_env, event_thread, klass);
2265         }
2266       break;
2267
2268     case JVMTI_EVENT_VM_START:
2269       if (env->callbacks.VMStart != NULL)
2270         {
2271           ARG (JNIEnv *, jni_env);
2272           env->callbacks.VMStart (env, jni_env);
2273         }
2274       break;
2275
2276     case JVMTI_EVENT_EXCEPTION:
2277       if (env->callbacks.Exception != NULL)
2278         {
2279           ARG (JNIEnv *, jni_env);
2280           ARG (jmethodID, method);
2281           ARG (jlocation, location);
2282           ARG (jobject, exception);
2283           ARG (jmethodID, catch_method);
2284           ARG (jlocation, catch_location);
2285           env->callbacks.Exception (env, jni_env, event_thread, method,
2286                                     location, exception, catch_method,
2287                                     catch_location);
2288         }
2289       break;
2290
2291     case JVMTI_EVENT_EXCEPTION_CATCH:
2292       if (env->callbacks.ExceptionCatch != NULL)
2293         {
2294           ARG (JNIEnv *, jni_env);
2295           ARG (jmethodID, method);
2296           ARG (jlocation, location);
2297           ARG (jobject, exception);
2298           env->callbacks.ExceptionCatch (env, jni_env, event_thread, method,
2299                                          location, exception);
2300         }
2301       break;
2302
2303     case JVMTI_EVENT_SINGLE_STEP:
2304       if (env->callbacks.SingleStep != NULL)
2305         {
2306           ARG (JNIEnv *, jni_env);
2307           ARG (jmethodID, method);
2308           ARG (jlocation, location);
2309           env->callbacks.SingleStep (env, jni_env, event_thread, method,
2310                                      location);
2311         }
2312       break;
2313
2314     case JVMTI_EVENT_FRAME_POP:
2315       if (env->callbacks.FramePop != NULL)
2316         {
2317           ARG (JNIEnv *, jni_env);
2318           ARG (jmethodID, method);
2319           GET_BOOLEAN_ARG (was_popped_by_exception);
2320           env->callbacks.FramePop (env, jni_env, event_thread, method,
2321                                    was_popped_by_exception);
2322         }
2323       break;
2324
2325     case JVMTI_EVENT_BREAKPOINT:
2326       if (env->callbacks.Breakpoint != NULL)
2327         {
2328           ARG (JNIEnv *, jni_env);
2329           ARG (jmethodID, method);
2330           ARG (jlocation, location);
2331           env->callbacks.Breakpoint (env, jni_env, event_thread, method,
2332                                      location);
2333         }
2334       break;
2335
2336     case JVMTI_EVENT_FIELD_ACCESS:
2337       if (env->callbacks.FieldAccess != NULL)
2338         {
2339           ARG (JNIEnv *, jni_env);
2340           ARG (jmethodID, method);
2341           ARG (jlocation, location);
2342           ARG (jclass, field_class);
2343           ARG (jobject, object);
2344           ARG (jfieldID, field);
2345           env->callbacks.FieldAccess (env, jni_env, event_thread, method,
2346                                       location, field_class, object, field);
2347         }
2348       break;
2349
2350     case JVMTI_EVENT_FIELD_MODIFICATION:
2351       if (env->callbacks.FieldModification != NULL)
2352         {
2353           ARG (JNIEnv *, jni_env);
2354           ARG (jmethodID, method);
2355           ARG (jlocation, location);
2356           ARG (jclass, field_class);
2357           ARG (jobject, object);
2358           ARG (jfieldID, field);
2359           GET_CHAR_ARG (signature_type);
2360           ARG (jvalue, new_value);
2361           env->callbacks.FieldModification (env, jni_env, event_thread, method,
2362                                             location, field_class, object,
2363                                             field, signature_type, new_value);
2364         }
2365       break;
2366
2367     case JVMTI_EVENT_METHOD_ENTRY:
2368       if (env->callbacks.MethodEntry != NULL)
2369         {
2370           ARG (JNIEnv *, jni_env);
2371           ARG (jmethodID, method);
2372           env->callbacks.MethodEntry (env, jni_env, event_thread, method);
2373         }
2374       break;
2375
2376     case JVMTI_EVENT_METHOD_EXIT:
2377       if (env->callbacks.MethodExit != NULL)
2378         {
2379           ARG (JNIEnv *, jni_env);
2380           ARG (jmethodID, method);
2381           GET_BOOLEAN_ARG (was_popped_by_exception);
2382           ARG (jvalue, return_value);
2383           env->callbacks.MethodExit (env, jni_env, event_thread, method,
2384                                      was_popped_by_exception, return_value);
2385         }
2386       break;
2387
2388     case JVMTI_EVENT_NATIVE_METHOD_BIND:
2389       if (env->callbacks.NativeMethodBind != NULL)
2390         {
2391           ARG (JNIEnv *, jni_env);
2392           ARG (jmethodID, method);
2393           ARG (void *, address);
2394           ARG (void **, new_address_ptr);
2395           env->callbacks.NativeMethodBind (env, jni_env, event_thread, method,
2396                                            address, new_address_ptr);
2397         }
2398       break;
2399
2400     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
2401       if (env->callbacks.CompiledMethodLoad != NULL)
2402         {
2403           ARG (jmethodID, method);
2404           ARG (jint, code_size);
2405           ARG (const void *, code_addr);
2406           ARG (jint, map_length);
2407           ARG (const jvmtiAddrLocationMap *, map);
2408           ARG (const void *, compile_info);
2409           env->callbacks.CompiledMethodLoad (env, method, code_size, code_addr,
2410                                              map_length, map, compile_info);
2411         }
2412       break;
2413
2414     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
2415       if (env->callbacks.CompiledMethodUnload != NULL)
2416         {
2417           ARG (jmethodID, method);
2418           ARG (const void *, code_addr);
2419           env->callbacks.CompiledMethodUnload (env, method, code_addr);
2420         }
2421       break;
2422
2423     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
2424       if (env->callbacks.DynamicCodeGenerated != NULL)
2425         {
2426           ARG (const char *, name);
2427           ARG (const void *, address);
2428           ARG (jint, length);
2429           env->callbacks.DynamicCodeGenerated (env, name, address, length);
2430         }
2431       break;
2432
2433     case JVMTI_EVENT_DATA_DUMP_REQUEST:
2434       if (env->callbacks.DataDumpRequest != NULL)
2435         {
2436           env->callbacks.DataDumpRequest (env);
2437         }
2438       break;
2439
2440     case JVMTI_EVENT_MONITOR_WAIT:
2441       if (env->callbacks.MonitorWait != NULL)
2442         {
2443           ARG (JNIEnv *, jni_env);
2444           ARG (jobject, object);
2445           ARG (jlong, timeout);
2446           env->callbacks.MonitorWait (env, jni_env, event_thread, object,
2447                                       timeout);
2448         }
2449       break;
2450
2451     case JVMTI_EVENT_MONITOR_WAITED:
2452       if (env->callbacks.MonitorWaited != NULL)
2453         {
2454           ARG (JNIEnv *, jni_env);
2455           ARG (jobject, object);
2456           GET_BOOLEAN_ARG (timed_out);
2457           env->callbacks.MonitorWaited (env, jni_env, event_thread, object,
2458                                         timed_out);
2459         }
2460       break;
2461
2462     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
2463       if (env->callbacks.MonitorContendedEnter != NULL)
2464         {
2465           ARG (JNIEnv *, jni_env);
2466           ARG (jobject, object);
2467           env->callbacks.MonitorContendedEnter (env, jni_env, event_thread,
2468                                                 object);
2469         }
2470       break;
2471
2472     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
2473       if (env->callbacks.MonitorContendedEntered != NULL)
2474         {
2475           ARG (JNIEnv *, jni_env);
2476           ARG (jobject, object);
2477           env->callbacks.MonitorContendedEntered (env, jni_env, event_thread,
2478                                                   object);
2479         }
2480       break;
2481
2482     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
2483       if (env->callbacks.GarbageCollectionStart != NULL)
2484         {
2485           env->callbacks.GarbageCollectionStart (env);
2486         }
2487       break;
2488
2489     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
2490       if (env->callbacks.GarbageCollectionFinish != NULL)
2491         {
2492           env->callbacks.GarbageCollectionFinish (env);
2493         }
2494       break;
2495
2496     case JVMTI_EVENT_OBJECT_FREE:
2497       if (env->callbacks.ObjectFree != NULL)
2498         {
2499           ARG (jlong, tag);
2500           env->callbacks.ObjectFree (env, tag);
2501         }
2502       break;
2503
2504     case JVMTI_EVENT_VM_OBJECT_ALLOC:
2505       if (env->callbacks.VMObjectAlloc != NULL)
2506         {
2507           ARG (JNIEnv *, jni_env);
2508           ARG (jobject, object);
2509           ARG (jclass, object_class);
2510           ARG (jlong, size);
2511           env->callbacks.VMObjectAlloc (env, jni_env, event_thread,
2512                                         object, object_class, size);
2513         }
2514       break;
2515
2516     default:
2517       fprintf (stderr, "libgcj: post of unknown JVMTI event (%d)\n",
2518                (int) type);
2519       break;
2520     }
2521   va_end (args);
2522 #undef ARG
2523 #undef GET_BOOLEAN_ARG
2524 #undef GET_CHAR_ARG
2525 }
2526
2527 /* Post an event to requesting JVMTI environments
2528  *
2529  * This function should not be called without consulting the
2530  * JVMTI_REQUESTED_EVENT macro first (for speed). It does no real
2531  * harm (other than kill speed), since this function will still
2532  * only send the event if it was properly requested by an environment.
2533  */ 
2534 void
2535 _Jv_JVMTI_PostEvent (jvmtiEvent type, jthread event_thread, ...)
2536 {
2537   va_list args;
2538   va_start (args, event_thread);
2539
2540   _envListLock->readLock ()->lock ();
2541   struct jvmti_env_list *e;
2542   FOREACH_ENVIRONMENT (e)
2543     {
2544       /* Events are only posted if the event was explicitly enabled,
2545          it has a registered event handler, and the event thread
2546          matches (either globally or restricted to a specific thread).
2547          Here we check all but the event handler, which will be handled
2548          by post_event. */
2549       if (e->env->enabled[EVENT_INDEX(type)]
2550           && (e->env->thread[EVENT_INDEX(type)] == NULL
2551               || e->env->thread[EVENT_INDEX(type)] == event_thread))
2552         {
2553           post_event (e->env, type, event_thread, args);
2554         }
2555     }
2556   _envListLock->readLock ()->unlock ();
2557   va_end (args);
2558 }