OSDN Git Service

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