OSDN Git Service

2007-01-10 Matthias Klose <doko@debian.org>
[pf3gnuchains/gcc-fork.git] / libjava / jvmti.cc
1 // jvmti.cc - JVMTI implementation
2
3 /* Copyright (C) 2006 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/Object.h>
31 #include <java/lang/Thread.h>
32 #include <java/lang/Throwable.h>
33 #include <java/lang/VMClassLoader.h>
34 #include <java/lang/reflect/Field.h>
35 #include <java/lang/reflect/Modifier.h>
36 #include <java/util/Collection.h>
37 #include <java/util/HashMap.h>
38 #include <java/net/URL.h>
39
40 static void check_enabled_events (void);
41 static void check_enabled_event (jvmtiEvent);
42
43 namespace JVMTI
44 {
45   bool VMInit = false;
46   bool VMDeath = false;
47   bool ThreadStart = false;
48   bool ThreadEnd = false;
49   bool ClassFileLoadHook = false;
50   bool ClassLoad = false;
51   bool ClassPrepare = false;
52   bool VMStart = false;
53   bool Exception = false;
54   bool ExceptionCatch = false;
55   bool SingleStep = false;
56   bool FramePop = false;
57   bool Breakpoint = false;
58   bool FieldAccess = false;
59   bool FieldModification = false;
60   bool MethodEntry = false;
61   bool MethodExit = false;
62   bool NativeMethodBind = false;
63   bool CompiledMethodLoad = false;
64   bool CompiledMethodUnload = false;
65   bool DynamicCodeGenerated = false;
66   bool DataDumpRequest = false;
67   bool reserved72 = false;
68   bool MonitorWait = false;
69   bool MonitorWaited = false;
70   bool MonitorContendedEnter = false;
71   bool MonitorContendedEntered = false;
72   bool reserved77 = false;
73   bool reserved78 = false;
74   bool reserved79 = false;
75   bool reserved80 = false;
76   bool GarbageCollectionStart = false;
77   bool GarbageCollectionFinish = false;
78   bool ObjectFree = false;
79   bool VMObjectAlloc = false;
80 };
81
82 extern struct JNINativeInterface _Jv_JNIFunctions;
83
84 struct _Jv_rawMonitorID
85 {
86   _Jv_Mutex_t mutex;
87   _Jv_ConditionVariable_t condition;
88 };
89
90 /* A simple linked list of all JVMTI environments. Since
91    events must be delivered to environments in the order
92    in which the environments were created, new environments
93    are added to the end of the list. */
94 struct jvmti_env_list
95 {
96   jvmtiEnv *env;
97   struct jvmti_env_list *next;
98 };
99 static struct jvmti_env_list *_jvmtiEnvironments = NULL;
100 static java::lang::Object *_envListLock = NULL;
101 #define FOREACH_ENVIRONMENT(Ele) \
102   for (Ele = _jvmtiEnvironments; Ele != NULL; Ele = Ele->next)
103
104 // Some commonly-used checks
105
106 #define THREAD_DEFAULT_TO_CURRENT(Ajthread)             \
107   do                                                    \
108     {                                                   \
109       if (Ajthread == NULL)                             \
110         Ajthread = java::lang::Thread::currentThread ();        \
111     }                                                   \
112   while (0)
113
114 #define THREAD_CHECK_VALID(Athread)                                     \
115   do                                                                    \
116     {                                                                   \
117       if (!java::lang::Thread::class$.isAssignableFrom (&(Athread->class$))) \
118         return JVMTI_ERROR_INVALID_THREAD;                              \
119     }                                                                   \
120   while (0)
121
122 #define THREAD_CHECK_IS_ALIVE(Athread)       \
123   do                                         \
124     {                                        \
125       if (!Athread->isAlive ())              \
126         return JVMTI_ERROR_THREAD_NOT_ALIVE; \
127     }                                        \
128   while (0)
129
130 // FIXME: if current phase is not set in Phases,
131 // return JVMTI_ERROR_WRONG_PHASE
132 #define REQUIRE_PHASE(Env, Phases)
133
134 #define NULL_CHECK(Ptr)                         \
135   do                                            \
136     {                                           \
137       if (Ptr == NULL)                          \
138         return JVMTI_ERROR_NULL_POINTER;        \
139     }                                           \
140   while (0)
141
142 #define ILLEGAL_ARGUMENT(Cond)                  \
143   do                                            \
144     {                                           \
145       if ((Cond))                               \
146         return JVMTI_ERROR_ILLEGAL_ARGUMENT;    \
147     }                                           \
148   while (0)
149
150 static jvmtiError JNICALL
151 _Jv_JVMTI_SuspendThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
152 {
153   using namespace java::lang;
154
155   THREAD_DEFAULT_TO_CURRENT (thread);
156  
157   Thread *t = reinterpret_cast<Thread *> (thread);
158   THREAD_CHECK_VALID (t);
159   THREAD_CHECK_IS_ALIVE (t);
160
161   _Jv_Thread_t *data = _Jv_ThreadGetData (t);
162   _Jv_SuspendThread (data);
163   return JVMTI_ERROR_NONE;
164 }
165
166 static jvmtiError JNICALL
167 _Jv_JVMTI_ResumeThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
168 {
169   using namespace java::lang;
170
171   THREAD_DEFAULT_TO_CURRENT (thread);
172
173   Thread *t = reinterpret_cast<Thread *> (thread);
174   THREAD_CHECK_VALID (t);
175   THREAD_CHECK_IS_ALIVE (t);
176
177   _Jv_Thread_t *data = _Jv_ThreadGetData (t);
178   _Jv_ResumeThread (data);
179   return JVMTI_ERROR_NONE;
180 }
181
182 static jvmtiError JNICALL
183 _Jv_JVMTI_InterruptThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
184 {
185   using namespace java::lang;
186
187   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
188   // FIXME: capability handling?  'can_signal_thread'
189   if (thread == NULL)
190     return JVMTI_ERROR_INVALID_THREAD;
191
192   Thread *real_thread = reinterpret_cast<Thread *> (thread);
193   THREAD_CHECK_VALID (real_thread);
194   THREAD_CHECK_IS_ALIVE (real_thread);
195   real_thread->interrupt();
196   return JVMTI_ERROR_NONE;
197 }
198
199 static jvmtiError JNICALL
200 _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name,
201                             jrawMonitorID *result)
202 {
203   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
204   NULL_CHECK (name);
205   NULL_CHECK (result);
206   *result = (jrawMonitorID) _Jv_MallocUnchecked (sizeof (_Jv_rawMonitorID));
207   if (*result == NULL)
208     return JVMTI_ERROR_OUT_OF_MEMORY;
209   _Jv_MutexInit (&(*result)->mutex);
210   _Jv_CondInit (&(*result)->condition);
211   return JVMTI_ERROR_NONE;
212 }
213
214 static jvmtiError JNICALL
215 _Jv_JVMTI_DestroyRawMonitor (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
216 {
217   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
218   // Note we have no better way of knowing whether this object is
219   // really a raw monitor.
220   if (monitor == NULL)
221     return JVMTI_ERROR_INVALID_MONITOR;
222   // FIXME: perform checks on monitor, release it if this thread owns
223   // it.
224 #ifdef _Jv_HaveMutexDestroy
225   _Jv_MutexDestroy (&monitor->mutex);
226 #endif
227   _Jv_Free (monitor);
228   return JVMTI_ERROR_NONE;
229 }
230
231 static jvmtiError JNICALL
232 _Jv_JVMTI_RawMonitorEnter (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
233 {
234   if (monitor == NULL)
235     return JVMTI_ERROR_INVALID_MONITOR;
236   _Jv_MutexLock (&monitor->mutex);
237   return JVMTI_ERROR_NONE;
238 }
239
240 static jvmtiError JNICALL
241 _Jv_JVMTI_RawMonitorExit (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
242 {
243   if (monitor == NULL)
244     return JVMTI_ERROR_INVALID_MONITOR;
245   if (_Jv_MutexUnlock (&monitor->mutex))
246     return JVMTI_ERROR_NOT_MONITOR_OWNER;
247   return JVMTI_ERROR_NONE;
248 }
249
250 static jvmtiError JNICALL
251 _Jv_JVMTI_RawMonitorWait (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor,
252                           jlong millis)
253 {
254   if (monitor == NULL)
255     return JVMTI_ERROR_INVALID_MONITOR;
256   int r = _Jv_CondWait (&monitor->condition, &monitor->mutex, millis, 0);
257   if (r == _JV_NOT_OWNER)
258     return JVMTI_ERROR_NOT_MONITOR_OWNER;
259   if (r == _JV_INTERRUPTED)
260     return JVMTI_ERROR_INTERRUPT;
261   return JVMTI_ERROR_NONE;
262 }
263
264 static jvmtiError JNICALL
265 _Jv_JVMTI_RawMonitorNotify (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
266 {
267   if (monitor == NULL)
268     return JVMTI_ERROR_INVALID_MONITOR;
269   if (_Jv_CondNotify (&monitor->condition, &monitor->mutex) == _JV_NOT_OWNER)
270     return JVMTI_ERROR_NOT_MONITOR_OWNER;
271   return JVMTI_ERROR_NONE;
272 }
273
274 static jvmtiError JNICALL
275 _Jv_JVMTI_RawMonitorNotifyAll (MAYBE_UNUSED jvmtiEnv *env,
276                                jrawMonitorID monitor)
277 {
278   if (monitor == NULL)
279     return JVMTI_ERROR_INVALID_MONITOR;
280   if (_Jv_CondNotifyAll (&monitor->condition, &monitor->mutex)
281       == _JV_NOT_OWNER)
282     return JVMTI_ERROR_NOT_MONITOR_OWNER;
283   return JVMTI_ERROR_NONE;
284 }
285
286 static jvmtiError JNICALL
287 _Jv_JVMTI_SetBreakpoint (jvmtiEnv *env, jmethodID method, jlocation location)
288 {
289   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
290
291   using namespace gnu::gcj::jvmti;
292   Breakpoint *bp
293     = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
294                                         location);
295   if (bp == NULL)
296     {
297       jclass klass;
298       jvmtiError err = env->GetMethodDeclaringClass (method, &klass);
299       if (err != JVMTI_ERROR_NONE)
300         return err;
301
302       if (!_Jv_IsInterpretedClass (klass))
303         return JVMTI_ERROR_INVALID_CLASS;
304
305       _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method);
306       if (base == NULL)
307         return JVMTI_ERROR_INVALID_METHODID;
308
309       jint flags;
310       err = env->GetMethodModifiers (method, &flags);
311       if (err != JVMTI_ERROR_NONE)
312         return err;
313
314       if (flags & java::lang::reflect::Modifier::NATIVE)
315         return JVMTI_ERROR_NATIVE_METHOD;
316
317       _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base);
318       if (imeth->get_insn (location) == NULL)
319         return JVMTI_ERROR_INVALID_LOCATION;
320
321       // Now the breakpoint can be safely installed
322       bp = BreakpointManager::newBreakpoint (reinterpret_cast<jlong> (method),
323                                              location);
324     }
325   else
326     {
327       // Duplicate breakpoints are not permitted by JVMTI
328       return JVMTI_ERROR_DUPLICATE;
329     }
330
331   return JVMTI_ERROR_NONE;
332 }
333
334 static jvmtiError JNICALL
335 _Jv_JVMTI_ClearBreakpoint (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
336                            jlocation location)
337 {
338   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
339
340   using namespace gnu::gcj::jvmti;
341
342   Breakpoint *bp
343     = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
344                                         location);
345   if (bp == NULL)
346     return JVMTI_ERROR_NOT_FOUND;
347
348   BreakpointManager::deleteBreakpoint (reinterpret_cast<jlong> (method), location);
349   return JVMTI_ERROR_NONE;
350 }
351
352 static jvmtiError JNICALL
353 _Jv_JVMTI_Allocate (MAYBE_UNUSED jvmtiEnv *env, jlong size,
354                     unsigned char **result)
355 {
356   ILLEGAL_ARGUMENT (size < 0);
357   NULL_CHECK (result);
358   if (size == 0)
359     *result = NULL;
360   else
361     {
362       *result = (unsigned char *) _Jv_MallocUnchecked (size);
363       if (*result == NULL)
364         return JVMTI_ERROR_OUT_OF_MEMORY;
365     }
366   return JVMTI_ERROR_NONE;
367 }
368
369 static jvmtiError JNICALL
370 _Jv_JVMTI_Deallocate (MAYBE_UNUSED jvmtiEnv *env, unsigned char *mem)
371 {
372   if (mem != NULL)
373     _Jv_Free (mem);
374   return JVMTI_ERROR_NONE;
375 }
376
377 static jvmtiError JNICALL
378 _Jv_JVMTI_GetClassModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
379                              jint *mods)
380 {
381   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
382   // Don't bother checking KLASS' type.
383   if (klass == NULL)
384     return JVMTI_ERROR_INVALID_CLASS;
385   NULL_CHECK (mods);
386   *mods = klass->getModifiers();
387   return JVMTI_ERROR_NONE;
388 }
389
390 static jvmtiError JNICALL
391 _Jv_JVMTI_GetClassMethods (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
392                            jint *count_ptr, jmethodID **methods_ptr)
393 {
394   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
395   // FIXME: capability can_maintain_original_method_order
396   // Don't bother checking KLASS' type.
397   if (klass == NULL)
398     return JVMTI_ERROR_INVALID_CLASS;
399   NULL_CHECK (count_ptr);
400   NULL_CHECK (methods_ptr);
401   *count_ptr = JvNumMethods(klass);
402
403   *methods_ptr
404     = (jmethodID *) _Jv_MallocUnchecked (*count_ptr * sizeof (jmethodID));
405   if (*methods_ptr == NULL)
406     return JVMTI_ERROR_OUT_OF_MEMORY;
407
408   jmethodID start = JvGetFirstMethod (klass);
409   for (jint i = 0; i < *count_ptr; ++i)
410     // FIXME: correct?
411     (*methods_ptr)[i] = start + i;
412
413   return JVMTI_ERROR_NONE;
414 }
415
416 static jvmtiError JNICALL
417 _Jv_JVMTI_IsInterface (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
418                        jboolean *result)
419 {
420   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
421   if (klass == NULL)
422     return JVMTI_ERROR_INVALID_CLASS;
423   NULL_CHECK (result);
424   *result = klass->isInterface();
425   return JVMTI_ERROR_NONE;
426 }
427
428 static jvmtiError JNICALL
429 _Jv_JVMTI_IsArrayClass (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
430                         jboolean *result)
431 {
432   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
433   if (klass == NULL)
434     return JVMTI_ERROR_INVALID_CLASS;
435   NULL_CHECK (result);
436   *result = klass->isArray();
437   return JVMTI_ERROR_NONE;
438 }
439
440 static jvmtiError JNICALL
441 _Jv_JVMTI_GetClassLoader (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
442                           jobject *result)
443 {
444   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
445   if (klass == NULL)
446     return JVMTI_ERROR_INVALID_CLASS;
447   NULL_CHECK (result);
448   *result = klass->getClassLoaderInternal();
449   return JVMTI_ERROR_NONE;
450 }
451
452 static jvmtiError JNICALL
453 _Jv_JVMTI_GetObjectHashCode (MAYBE_UNUSED jvmtiEnv *env, jobject obj,
454                              jint *result)
455 {
456   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
457   if (obj == NULL)
458     return JVMTI_ERROR_INVALID_OBJECT;
459   NULL_CHECK (result);
460   *result = _Jv_HashCode (obj);
461   return JVMTI_ERROR_NONE;
462 }
463
464 static jvmtiError JNICALL
465 _Jv_JVMTI_GetFieldModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
466                              jfieldID field, jint *result)
467 {
468   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
469   if (klass == NULL)
470     return JVMTI_ERROR_INVALID_CLASS;
471   if (field == NULL)
472     return JVMTI_ERROR_INVALID_FIELDID;
473   NULL_CHECK (result);
474   *result = field->getModifiers();
475   return JVMTI_ERROR_NONE;
476 }
477
478 static jvmtiError JNICALL
479 _Jv_JVMTI_IsFieldSynthetic (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
480                             jfieldID field, jboolean *result)
481 {
482   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
483   if (klass == NULL)
484     return JVMTI_ERROR_INVALID_CLASS;
485   if (field == NULL)
486     return JVMTI_ERROR_INVALID_FIELDID;
487   NULL_CHECK (result);
488
489   // FIXME: capability can_get_synthetic_attribute
490   *result = ((field->getModifiers() & java::lang::reflect::Modifier::SYNTHETIC)
491              != 0);
492   return JVMTI_ERROR_NONE;
493 }
494
495 static jvmtiError JNICALL
496 _Jv_JVMTI_GetMethodModifiers (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
497                               jint *result)
498 {
499   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
500   if (method == NULL)
501     return JVMTI_ERROR_INVALID_METHODID;
502   NULL_CHECK (result);
503
504   // FIXME: mask off some internal bits...
505   *result = method->accflags;
506   return JVMTI_ERROR_NONE;
507 }
508
509 static jvmtiError JNICALL
510 _Jv_JVMTI_GetLineNumberTable (jvmtiEnv *env, jmethodID method,
511                               jint *entry_count_ptr,
512                               jvmtiLineNumberEntry **table_ptr)
513 {
514   NULL_CHECK (entry_count_ptr);
515   NULL_CHECK (table_ptr);
516
517   jclass klass;
518   jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass);
519   if (jerr != JVMTI_ERROR_NONE)
520     return jerr;
521
522   _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method);
523   if (base == NULL)
524     return JVMTI_ERROR_INVALID_METHODID;
525
526   if (java::lang::reflect::Modifier::isNative (method->accflags)
527       || !_Jv_IsInterpretedClass (klass))
528     return JVMTI_ERROR_NATIVE_METHOD;
529
530   _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base);
531   jlong start, end;
532   jintArray lines = NULL;
533   jlongArray indices = NULL;
534   imeth->get_line_table (start, end, lines, indices);
535   if (lines == NULL)
536     return JVMTI_ERROR_ABSENT_INFORMATION;
537
538   jvmtiLineNumberEntry *table;
539   jsize len = lines->length * sizeof (jvmtiLineNumberEntry);
540   table = (jvmtiLineNumberEntry *) _Jv_MallocUnchecked (len);
541   if (table == NULL)
542     return JVMTI_ERROR_OUT_OF_MEMORY;
543   
544   jint *line = elements (lines);
545   jlong *index = elements (indices);
546   for (int i = 0; i < lines->length; ++i)
547     {
548       table[i].start_location = index[i];
549       table[i].line_number = line[i];
550     }
551
552   *table_ptr = table;
553   *entry_count_ptr = lines->length;
554   return JVMTI_ERROR_NONE;
555 }
556
557 static jvmtiError JNICALL
558 _Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
559                           jboolean *result)
560 {
561   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
562   if (method == NULL)
563     return JVMTI_ERROR_INVALID_METHODID;
564   NULL_CHECK (result);
565
566   *result = ((method->accflags & java::lang::reflect::Modifier::NATIVE) != 0);
567   return JVMTI_ERROR_NONE;
568 }
569
570 static jvmtiError JNICALL
571 _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
572                              jboolean *result)
573 {
574   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
575   if (method == NULL)
576     return JVMTI_ERROR_INVALID_METHODID;
577   NULL_CHECK (result);
578
579   // FIXME capability can_get_synthetic_attribute
580
581   *result = ((method->accflags & java::lang::reflect::Modifier::SYNTHETIC)
582              != 0);
583   return JVMTI_ERROR_NONE;
584 }
585
586 static jvmtiError JNICALL
587 _Jv_JVMTI_GetMethodDeclaringClass (MAYBE_UNUSED jvmtiEnv *env,
588                                    jmethodID method,
589                                    jclass *declaring_class_ptr)
590 {
591   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
592   NULL_CHECK (declaring_class_ptr);
593
594   jclass klass = _Jv_GetMethodDeclaringClass (method);
595   if (klass != NULL)
596     {
597       *declaring_class_ptr = klass;
598       return JVMTI_ERROR_NONE;
599     }
600
601   return JVMTI_ERROR_INVALID_METHODID;
602 }
603
604 static jvmtiError JNICALL
605 _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env,
606                                  jobject init_loader,
607                                  jint *count_ptr,
608                                  jclass **result_ptr)
609 {
610   using namespace java::lang;
611   using namespace java::util;
612
613   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
614   NULL_CHECK (count_ptr);
615   NULL_CHECK (result_ptr);
616
617   ClassLoader *loader = (ClassLoader *) init_loader;
618   if (loader == NULL)
619     loader = VMClassLoader::bootLoader;
620
621   Collection *values = loader->loadedClasses->values();
622   jobjectArray array = values->toArray();
623   *count_ptr = array->length;
624   jobject *elts = elements (array);
625   jclass *result
626     = (jclass *) _Jv_MallocUnchecked (*count_ptr * sizeof (jclass));
627   if (result == NULL)
628     return JVMTI_ERROR_OUT_OF_MEMORY;
629
630   // FIXME: JNI references...
631   memcpy (result, elts, *count_ptr * sizeof (jclass));
632
633   *result_ptr = result;
634
635   return JVMTI_ERROR_NONE;
636 }
637
638 static jvmtiError JNICALL
639 _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env)
640 {
641   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
642   _Jv_RunGC();
643   return JVMTI_ERROR_NONE;
644 }
645
646 static jvmtiError JNICALL
647 _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
648                                const jniNativeInterface *function_table)
649 {
650   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
651   NULL_CHECK (function_table);
652   memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface));
653   return JVMTI_ERROR_NONE;
654 }
655
656 static jvmtiError JNICALL
657 _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
658                                jniNativeInterface **function_table)
659 {
660   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
661   NULL_CHECK (function_table);
662   *function_table
663     = (jniNativeInterface *) _Jv_MallocUnchecked (sizeof (jniNativeInterface));
664   if (*function_table == NULL)
665     return JVMTI_ERROR_OUT_OF_MEMORY;
666   memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface));
667   return JVMTI_ERROR_NONE;
668 }
669
670 static jvmtiError JNICALL
671 _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env)
672 {
673   NULL_CHECK (env);
674
675   if (_jvmtiEnvironments == NULL)
676     return JVMTI_ERROR_INVALID_ENVIRONMENT;
677   else
678     {
679       JvSynchronize dummy (_envListLock);
680       if (_jvmtiEnvironments->env == env)
681         {
682           struct jvmti_env_list *next = _jvmtiEnvironments->next;
683           _Jv_Free (_jvmtiEnvironments);
684           _jvmtiEnvironments = next;
685         }
686       else
687         {
688           struct jvmti_env_list *e = _jvmtiEnvironments; 
689           while (e->next != NULL && e->next->env != env)
690             e = e->next;
691           if (e->next == NULL)
692             return JVMTI_ERROR_INVALID_ENVIRONMENT;
693
694           struct jvmti_env_list *next = e->next->next;
695           _Jv_Free (e->next);
696           e->next = next;
697         }
698     }
699
700   _Jv_Free (env);
701
702   check_enabled_events ();
703
704   return JVMTI_ERROR_NONE;
705 }
706
707 static jvmtiError JNICALL
708 _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
709                              char **result)
710 {
711   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
712   NULL_CHECK (property);
713   NULL_CHECK (result);
714
715   jstring name = JvNewStringUTF(property);
716   jstring result_str = gnu::classpath::SystemProperties::getProperty(name);
717
718   if (result_str == NULL)
719     return JVMTI_ERROR_NOT_AVAILABLE;
720
721   int len = JvGetStringUTFLength (result_str);
722   *result = (char *) _Jv_MallocUnchecked (len + 1);
723   if (*result == NULL)
724     return JVMTI_ERROR_OUT_OF_MEMORY;
725   JvGetStringUTFRegion (result_str, 0, result_str->length(), *result);
726   (*result)[len] = '\0';
727
728   return JVMTI_ERROR_NONE;
729 }
730
731 static jvmtiError JNICALL
732 _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
733                              const char *value)
734 {
735   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
736
737   NULL_CHECK (property);
738   if (value == NULL)
739     {
740       // FIXME: When would a property not be writeable?
741       return JVMTI_ERROR_NONE;
742     }
743
744   jstring prop_str = JvNewStringUTF(property);
745   jstring value_str = JvNewStringUTF(value);
746   gnu::classpath::SystemProperties::setProperty(prop_str, value_str);
747   return JVMTI_ERROR_NONE;
748 }
749
750 static jvmtiError JNICALL
751 _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr)
752 {
753   NULL_CHECK (nanos_ptr);
754   *nanos_ptr = _Jv_platform_nanotime();
755   return JVMTI_ERROR_NONE;
756 }
757
758 static jvmtiError JNICALL
759 _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env,
760                                   jint *nprocessors_ptr)
761 {
762   NULL_CHECK (nprocessors_ptr);
763 #ifdef _SC_NPROCESSORS_ONLN
764   *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN);
765 #else
766   *nprocessors_ptr = 1;
767 #endif
768   return JVMTI_ERROR_NONE;
769 }
770
771 static jvmtiError JNICALL
772 _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env,
773                                            const char *segment)
774 {
775   using namespace java::lang;
776   using namespace java::net;
777   using namespace gnu::gcj::runtime;
778
779   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
780   NULL_CHECK (segment);
781
782   jstring str_segment = JvNewStringUTF(segment);
783   URL *url;
784   try
785     {
786       url = new URL(JvNewStringUTF("file"), NULL, str_segment);
787     }
788   catch (jthrowable ignore)
789     {
790       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
791     }
792
793   BootClassLoader *loader = VMClassLoader::bootLoader;
794   // Don't call this too early.
795   // assert (loader != NULL);
796   loader->addURL(url);
797   return JVMTI_ERROR_NONE;
798 }
799
800 static jvmtiError JNICALL
801 _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag,
802                           jboolean value)
803 {
804   switch (flag)
805     {
806     case JVMTI_VERBOSE_OTHER:
807     case JVMTI_VERBOSE_GC:
808     case JVMTI_VERBOSE_JNI:
809       // Ignore.
810       break;
811     case JVMTI_VERBOSE_CLASS:
812       gcj::verbose_class_flag = value;
813       break;
814     default:
815       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
816     }
817   return JVMTI_ERROR_NONE;
818 }
819
820 static jvmtiError JNICALL
821 _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object,
822                          jlong *result)
823 {
824   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
825   if (object == NULL)
826     return JVMTI_ERROR_INVALID_OBJECT;
827   NULL_CHECK (result);
828
829   jclass klass = object->getClass();
830   if (klass->isArray())
831     {
832       jclass comp = klass->getComponentType();
833       jint base
834         = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL,
835                                                                     klass->getComponentType());
836       // FIXME: correct for primitive types?
837       jint compSize = comp->size();
838       __JArray *array = (__JArray *) object;
839       *result = base + array->length * compSize;
840     }
841   else
842     {
843       // Note that if OBJECT is a String then it may (if
844       // str->data==str) take more space.  Do we care?
845       *result = klass->size();
846     }
847   return JVMTI_ERROR_NONE;
848 }
849
850 /* An event is enabled only if it has both an event handler
851    and it is enabled in the environment. */
852 static void
853 check_enabled_event (jvmtiEvent type)
854 {
855   bool *enabled;
856   int offset;
857
858 #define GET_OFFSET(Event)                               \
859   do                                                    \
860     {                                                   \
861       enabled = &JVMTI::Event;                          \
862       offset = offsetof (jvmtiEventCallbacks, Event);   \
863     }                                                   \
864   while (0)
865
866   switch (type)
867     {
868     case JVMTI_EVENT_VM_INIT:
869       GET_OFFSET (VMInit);
870       break;
871
872     case JVMTI_EVENT_VM_DEATH:
873       GET_OFFSET (VMDeath);
874       break;
875
876     case JVMTI_EVENT_THREAD_START:
877       GET_OFFSET (ThreadStart);
878       break;
879
880     case JVMTI_EVENT_THREAD_END:
881       GET_OFFSET (ThreadEnd);
882       break;
883
884     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
885       GET_OFFSET (ClassFileLoadHook);
886       break;
887
888     case JVMTI_EVENT_CLASS_LOAD:
889       GET_OFFSET (ClassLoad);
890       break;
891
892     case JVMTI_EVENT_CLASS_PREPARE:
893       GET_OFFSET (ClassPrepare);
894       break;
895
896     case JVMTI_EVENT_VM_START:
897       GET_OFFSET (VMStart);
898       break;
899
900     case JVMTI_EVENT_EXCEPTION:
901       GET_OFFSET (Exception);
902       break;
903
904     case JVMTI_EVENT_EXCEPTION_CATCH:
905       GET_OFFSET (ExceptionCatch);
906       break;
907
908     case JVMTI_EVENT_SINGLE_STEP:
909       GET_OFFSET (SingleStep);
910       break;
911
912     case JVMTI_EVENT_FRAME_POP:
913       GET_OFFSET (FramePop);
914       break;
915
916     case JVMTI_EVENT_BREAKPOINT:
917       GET_OFFSET (Breakpoint);
918       break;
919
920     case JVMTI_EVENT_FIELD_ACCESS:
921       GET_OFFSET (FieldAccess);
922       break;
923
924     case JVMTI_EVENT_FIELD_MODIFICATION:
925       GET_OFFSET (FieldModification);
926       break;
927
928     case JVMTI_EVENT_METHOD_ENTRY:
929       GET_OFFSET (MethodEntry);
930       break;
931
932     case JVMTI_EVENT_METHOD_EXIT:
933       GET_OFFSET (MethodExit);
934       break;
935
936     case JVMTI_EVENT_NATIVE_METHOD_BIND:
937       GET_OFFSET (NativeMethodBind);
938       break;
939
940     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
941       GET_OFFSET (CompiledMethodLoad);
942       break;
943
944     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
945       GET_OFFSET (CompiledMethodUnload);
946       break;
947
948     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
949       GET_OFFSET (DynamicCodeGenerated);
950       break;
951
952     case JVMTI_EVENT_DATA_DUMP_REQUEST:
953       GET_OFFSET (DataDumpRequest);
954       break;
955
956     case JVMTI_EVENT_MONITOR_WAIT:
957       GET_OFFSET (MonitorWait);
958       break;
959
960     case JVMTI_EVENT_MONITOR_WAITED:
961       GET_OFFSET (MonitorWaited);
962       break;
963
964     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
965       GET_OFFSET (MonitorContendedEnter);
966       break;
967
968     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
969       GET_OFFSET (MonitorContendedEntered);
970       break;
971
972     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
973       GET_OFFSET (GarbageCollectionStart);
974       break;
975
976     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
977       GET_OFFSET (GarbageCollectionFinish);
978       break;
979
980     case JVMTI_EVENT_OBJECT_FREE:
981       GET_OFFSET (ObjectFree);
982       break;
983
984     case JVMTI_EVENT_VM_OBJECT_ALLOC:
985       GET_OFFSET (VMObjectAlloc);
986       break;
987
988     default:
989       fprintf (stderr,
990                "libgcj: check_enabled_event for unknown JVMTI event (%d)\n",
991                (int) type);
992       return;
993     }
994 #undef GET_OFFSET
995
996   int index = EVENT_INDEX (type); // safe since caller checks this
997
998   JvSynchronize dummy (_envListLock);
999   struct jvmti_env_list *e;
1000   FOREACH_ENVIRONMENT (e)
1001     {
1002       char *addr
1003         = reinterpret_cast<char *> (&e->env->callbacks) + offset;
1004       void **callback = reinterpret_cast<void **> (addr);
1005       if (e->env->enabled[index] && *callback != NULL)
1006         {
1007           *enabled = true;
1008           return;
1009         }
1010     }
1011
1012   *enabled = false;
1013 }
1014
1015 static void
1016 check_enabled_events ()
1017 {
1018   check_enabled_event (JVMTI_EVENT_VM_INIT);
1019   check_enabled_event (JVMTI_EVENT_VM_DEATH);
1020   check_enabled_event (JVMTI_EVENT_THREAD_START);
1021   check_enabled_event (JVMTI_EVENT_THREAD_END);
1022   check_enabled_event (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK);
1023   check_enabled_event (JVMTI_EVENT_CLASS_LOAD);
1024   check_enabled_event (JVMTI_EVENT_CLASS_PREPARE);
1025   check_enabled_event (JVMTI_EVENT_VM_START);
1026   check_enabled_event (JVMTI_EVENT_EXCEPTION);
1027   check_enabled_event (JVMTI_EVENT_EXCEPTION_CATCH);
1028   check_enabled_event (JVMTI_EVENT_SINGLE_STEP);
1029   check_enabled_event (JVMTI_EVENT_FRAME_POP);
1030   check_enabled_event (JVMTI_EVENT_BREAKPOINT);
1031   check_enabled_event (JVMTI_EVENT_FIELD_ACCESS);
1032   check_enabled_event (JVMTI_EVENT_FIELD_MODIFICATION);
1033   check_enabled_event (JVMTI_EVENT_METHOD_ENTRY);
1034   check_enabled_event (JVMTI_EVENT_METHOD_EXIT);
1035   check_enabled_event (JVMTI_EVENT_NATIVE_METHOD_BIND);
1036   check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_LOAD);
1037   check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_UNLOAD);
1038   check_enabled_event (JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
1039   check_enabled_event (JVMTI_EVENT_DATA_DUMP_REQUEST);
1040   check_enabled_event (JVMTI_EVENT_MONITOR_WAIT);
1041   check_enabled_event (JVMTI_EVENT_MONITOR_WAITED);
1042   check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTER);
1043   check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED);
1044   check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_START);
1045   check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH);
1046   check_enabled_event (JVMTI_EVENT_OBJECT_FREE);
1047   check_enabled_event (JVMTI_EVENT_VM_OBJECT_ALLOC);
1048 }
1049
1050 static jvmtiError JNICALL
1051 _Jv_JVMTI_SetEventNotificationMode (jvmtiEnv *env, jvmtiEventMode mode,
1052                                     jvmtiEvent type, jthread event_thread, ...)
1053 {
1054   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1055
1056   if (event_thread != NULL)
1057     {
1058       using namespace java::lang;
1059       Thread *t = reinterpret_cast<Thread *> (event_thread);
1060       THREAD_CHECK_VALID (t);
1061       THREAD_CHECK_IS_ALIVE (t);
1062     }
1063
1064   bool enabled;
1065   switch (mode)
1066     {
1067     case JVMTI_DISABLE:
1068       enabled = false;
1069       break;
1070     case JVMTI_ENABLE:
1071       enabled = true;
1072       break;
1073
1074     default:
1075       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1076     }
1077
1078   switch (type)
1079     {
1080     case JVMTI_EVENT_VM_INIT:
1081     case JVMTI_EVENT_VM_DEATH:
1082     case JVMTI_EVENT_THREAD_START:
1083     case JVMTI_EVENT_VM_START:
1084     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1085     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1086     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1087     case JVMTI_EVENT_DATA_DUMP_REQUEST:
1088       ILLEGAL_ARGUMENT (event_thread != NULL);
1089       break;
1090
1091     case JVMTI_EVENT_THREAD_END:
1092     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1093     case JVMTI_EVENT_CLASS_LOAD:
1094     case JVMTI_EVENT_CLASS_PREPARE:
1095     case JVMTI_EVENT_EXCEPTION:
1096     case JVMTI_EVENT_EXCEPTION_CATCH:
1097     case JVMTI_EVENT_SINGLE_STEP:
1098     case JVMTI_EVENT_FRAME_POP:
1099     case JVMTI_EVENT_BREAKPOINT:
1100     case JVMTI_EVENT_FIELD_ACCESS:
1101     case JVMTI_EVENT_FIELD_MODIFICATION:
1102     case JVMTI_EVENT_METHOD_ENTRY:
1103     case JVMTI_EVENT_METHOD_EXIT:
1104     case JVMTI_EVENT_NATIVE_METHOD_BIND:
1105     case JVMTI_EVENT_MONITOR_WAIT:
1106     case JVMTI_EVENT_MONITOR_WAITED:
1107     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1108     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1109     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1110     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1111     case JVMTI_EVENT_OBJECT_FREE:
1112     case JVMTI_EVENT_VM_OBJECT_ALLOC:
1113       break;
1114
1115     default:
1116       return JVMTI_ERROR_INVALID_EVENT_TYPE;
1117     }
1118
1119   env->thread[EVENT_INDEX(type)] = event_thread;
1120   env->enabled[EVENT_INDEX(type)] = enabled;
1121   check_enabled_event (type);
1122   return JVMTI_ERROR_NONE;
1123 }
1124
1125 static jvmtiError JNICALL
1126 _Jv_JVMTI_SetEventCallbacks (jvmtiEnv *env,
1127                              const jvmtiEventCallbacks *callbacks,
1128                              jint size_of_callbacks)
1129 {
1130   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1131   ILLEGAL_ARGUMENT (size_of_callbacks < 0);
1132
1133   // Copy the list of callbacks into the environment
1134   memcpy (&env->callbacks, callbacks, sizeof (jvmtiEventCallbacks));
1135
1136   /* Check which events are now enabeld (JVMTI makes no requirements
1137      about the order in which SetEventCallbacks and SetEventNotifications
1138      are called. So we must check all events here. */
1139   check_enabled_events ();
1140
1141   return JVMTI_ERROR_NONE;
1142 }
1143
1144 static jvmtiError JNICALL
1145 _Jv_JVMTI_GetErrorName (MAYBE_UNUSED jvmtiEnv *env, jvmtiError error,
1146                         char **name_ptr)
1147 {
1148   NULL_CHECK (name_ptr);
1149
1150   const char *name;
1151   switch (error)
1152     {
1153     case JVMTI_ERROR_NONE:
1154       name = "none";
1155       break;
1156
1157     case JVMTI_ERROR_NULL_POINTER:
1158       name = "null pointer";
1159       break;
1160
1161     case JVMTI_ERROR_OUT_OF_MEMORY:
1162       name = "out of memory";
1163       break;
1164
1165     case JVMTI_ERROR_ACCESS_DENIED:
1166       name = "access denied";
1167       break;
1168
1169     case JVMTI_ERROR_WRONG_PHASE:
1170       name = "wrong phase";
1171       break;
1172
1173     case JVMTI_ERROR_INTERNAL:
1174       name = "internal error";
1175       break;
1176
1177     case JVMTI_ERROR_UNATTACHED_THREAD:
1178       name = "unattached thread";
1179       break;
1180
1181     case JVMTI_ERROR_INVALID_ENVIRONMENT:
1182       name = "invalid environment";
1183       break;
1184
1185     case JVMTI_ERROR_INVALID_PRIORITY:
1186       name = "invalid priority";
1187       break;
1188
1189     case JVMTI_ERROR_THREAD_NOT_SUSPENDED:
1190       name = "thread not suspended";
1191       break;
1192
1193     case JVMTI_ERROR_THREAD_SUSPENDED:
1194       name = "thread suspended";
1195       break;
1196
1197     case JVMTI_ERROR_THREAD_NOT_ALIVE:
1198       name = "thread not alive";
1199       break;
1200
1201     case JVMTI_ERROR_CLASS_NOT_PREPARED:
1202       name = "class not prepared";
1203       break;
1204
1205     case JVMTI_ERROR_NO_MORE_FRAMES:
1206       name = "no more frames";
1207       break;
1208
1209     case JVMTI_ERROR_OPAQUE_FRAME:
1210       name = "opaque frame";
1211       break;
1212
1213     case JVMTI_ERROR_DUPLICATE:
1214       name = "duplicate";
1215       break;
1216
1217     case JVMTI_ERROR_NOT_FOUND:
1218       name = "not found";
1219       break;
1220
1221     case JVMTI_ERROR_NOT_MONITOR_OWNER:
1222       name = "not monitor owner";
1223       break;
1224
1225     case JVMTI_ERROR_INTERRUPT:
1226       name = "interrupted";
1227       break;
1228
1229     case JVMTI_ERROR_UNMODIFIABLE_CLASS:
1230       name = "unmodifiable class";
1231       break;
1232
1233     case JVMTI_ERROR_NOT_AVAILABLE:
1234       name = "not available";
1235       break;
1236
1237     case JVMTI_ERROR_ABSENT_INFORMATION:
1238       name = "absent information";
1239       break;
1240
1241     case JVMTI_ERROR_INVALID_EVENT_TYPE:
1242       name = "invalid event type";
1243       break;
1244
1245     case JVMTI_ERROR_NATIVE_METHOD:
1246       name = "native method";
1247       break;
1248
1249     case JVMTI_ERROR_INVALID_THREAD:
1250       name = "invalid thread";
1251       break;
1252
1253     case JVMTI_ERROR_INVALID_THREAD_GROUP:
1254       name = "invalid thread group";
1255       break;
1256
1257     case JVMTI_ERROR_INVALID_OBJECT:
1258       name = "invalid object";
1259       break;
1260
1261     case JVMTI_ERROR_INVALID_CLASS:
1262       name = "invalid class";
1263       break;
1264
1265     case JVMTI_ERROR_INVALID_METHODID:
1266       name = "invalid method ID";
1267       break;
1268
1269     case JVMTI_ERROR_INVALID_LOCATION:
1270       name = "invalid location";
1271       break;
1272
1273     case JVMTI_ERROR_INVALID_FIELDID:
1274       name = "invalid field ID";
1275       break;
1276
1277     case JVMTI_ERROR_TYPE_MISMATCH:
1278       name = "type mismatch";
1279       break;
1280
1281     case JVMTI_ERROR_INVALID_SLOT:
1282       name = "invalid slot";
1283       break;
1284
1285     case JVMTI_ERROR_INVALID_MONITOR:
1286       name = "invalid monitor";
1287       break;
1288
1289     case JVMTI_ERROR_INVALID_CLASS_FORMAT:
1290       name = "invalid class format";
1291       break;
1292
1293     case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION:
1294       name = "circular class definition";
1295       break;
1296
1297     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED:
1298       name = "unsupported redefinition: method added";
1299       break;
1300
1301     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED:
1302       name = "unsupported redefinition: schema changed";
1303       break;
1304
1305     case JVMTI_ERROR_INVALID_TYPESTATE:
1306       name = "invalid type state";
1307       break;
1308
1309     case JVMTI_ERROR_FAILS_VERIFICATION:
1310       name = "fails verification";
1311       break;
1312
1313     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED:
1314       name = "unsupported redefinition: hierarchy changed";
1315       break;
1316
1317     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED:
1318       name = "unsupported redefinition: method deleted";
1319       break;
1320
1321     case JVMTI_ERROR_UNSUPPORTED_VERSION:
1322       name = "unsupported version";
1323       break;
1324
1325     case JVMTI_ERROR_NAMES_DONT_MATCH:
1326       name = "names do not match";
1327       break;
1328
1329     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED:
1330       name = "unsupported redefinition: class modifiers changed";
1331       break;
1332
1333     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
1334       name = "unsupported redefinition: method modifiers changed";
1335       break;
1336
1337     case JVMTI_ERROR_MUST_POSSESS_CAPABILITY:
1338       name = "must possess capability";
1339       break;
1340
1341     case JVMTI_ERROR_ILLEGAL_ARGUMENT:
1342       name = "illegal argument";
1343       break;
1344
1345     default:
1346       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1347     }
1348
1349   *name_ptr = (char *) _Jv_MallocUnchecked (strlen (name) + 1);
1350   if (*name_ptr == NULL)
1351     return JVMTI_ERROR_OUT_OF_MEMORY;
1352
1353   strcpy (*name_ptr, name);
1354   return JVMTI_ERROR_NONE;
1355 }
1356
1357 #define RESERVED NULL
1358 #define UNIMPLEMENTED NULL
1359
1360 struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
1361 {
1362   RESERVED,                     // reserved1
1363   _Jv_JVMTI_SetEventNotificationMode, // SetEventNotificationMode
1364   RESERVED,                     // reserved3
1365   UNIMPLEMENTED,                // GetAllThreads
1366   _Jv_JVMTI_SuspendThread,      // SuspendThread
1367   _Jv_JVMTI_ResumeThread,       // ResumeThread
1368   UNIMPLEMENTED,                // StopThread
1369   _Jv_JVMTI_InterruptThread,    // InterruptThread
1370   UNIMPLEMENTED,                // GetThreadInfo
1371   UNIMPLEMENTED,                // GetOwnedMonitorInfo
1372   UNIMPLEMENTED,                // GetCurrentContendedMonitor
1373   UNIMPLEMENTED,                // RunAgentThread
1374   UNIMPLEMENTED,                // GetTopThreadGroups
1375   UNIMPLEMENTED,                // GetThreadGroupInfo
1376   UNIMPLEMENTED,                // GetThreadGroupChildren
1377   UNIMPLEMENTED,                // GetFrameCount
1378   UNIMPLEMENTED,                // GetThreadState
1379   RESERVED,                     // reserved18
1380   UNIMPLEMENTED,                // GetFrameLocation
1381   UNIMPLEMENTED,                // NotifyPopFrame
1382   UNIMPLEMENTED,                // GetLocalObject
1383   UNIMPLEMENTED,                // GetLocalInt
1384   UNIMPLEMENTED,                // GetLocalLong
1385   UNIMPLEMENTED,                // GetLocalFloat
1386   UNIMPLEMENTED,                // GetLocalDouble
1387   UNIMPLEMENTED,                // SetLocalObject
1388   UNIMPLEMENTED,                // SetLocalInt
1389   UNIMPLEMENTED,                // SetLocalLong
1390   UNIMPLEMENTED,                // SetLocalFloat
1391   UNIMPLEMENTED,                // SetLocalDouble
1392   _Jv_JVMTI_CreateRawMonitor,   // CreateRawMonitor
1393   _Jv_JVMTI_DestroyRawMonitor,  // DestroyRawMonitor
1394   _Jv_JVMTI_RawMonitorEnter,    // RawMonitorEnter
1395   _Jv_JVMTI_RawMonitorExit,     // RawMonitorExit
1396   _Jv_JVMTI_RawMonitorWait,     // RawMonitorWait
1397   _Jv_JVMTI_RawMonitorNotify,   // RawMonitorNotify
1398   _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll
1399   _Jv_JVMTI_SetBreakpoint,      // SetBreakpoint
1400   _Jv_JVMTI_ClearBreakpoint,    // ClearBreakpoint
1401   RESERVED,                     // reserved40
1402   UNIMPLEMENTED,                // SetFieldAccessWatch
1403   UNIMPLEMENTED,                // ClearFieldAccessWatch
1404   UNIMPLEMENTED,                // SetFieldModificationWatch
1405   UNIMPLEMENTED,                // ClearFieldModificationWatch
1406   RESERVED,                     // reserved45
1407   _Jv_JVMTI_Allocate,           // Allocate
1408   _Jv_JVMTI_Deallocate,         // Deallocate
1409   UNIMPLEMENTED,                // GetClassSignature
1410   UNIMPLEMENTED,                // GetClassStatus
1411   UNIMPLEMENTED,                // GetSourceFileName
1412   _Jv_JVMTI_GetClassModifiers,  // GetClassModifiers
1413   _Jv_JVMTI_GetClassMethods,    // GetClassMethods
1414   UNIMPLEMENTED,                // GetClassFields
1415   UNIMPLEMENTED,                // GetImplementedInterfaces
1416   _Jv_JVMTI_IsInterface,        // IsInterface
1417   _Jv_JVMTI_IsArrayClass,       // IsArrayClass
1418   _Jv_JVMTI_GetClassLoader,     // GetClassLoader
1419   _Jv_JVMTI_GetObjectHashCode,  // GetObjectHashCode
1420   UNIMPLEMENTED,                // GetObjectMonitorUsage
1421   UNIMPLEMENTED,                // GetFieldName
1422   UNIMPLEMENTED,                // GetFieldDeclaringClass
1423   _Jv_JVMTI_GetFieldModifiers,  // GetFieldModifiers
1424   _Jv_JVMTI_IsFieldSynthetic,   // IsFieldSynthetic
1425   UNIMPLEMENTED,                // GetMethodName
1426   _Jv_JVMTI_GetMethodDeclaringClass,  // GetMethodDeclaringClass
1427   _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers
1428   RESERVED,                     // reserved67
1429   UNIMPLEMENTED,                // GetMaxLocals
1430   UNIMPLEMENTED,                // GetArgumentsSize
1431   _Jv_JVMTI_GetLineNumberTable, // GetLineNumberTable
1432   UNIMPLEMENTED,                // GetMethodLocation
1433   UNIMPLEMENTED,                // GetLocalVariableTable
1434   RESERVED,                     // reserved73
1435   RESERVED,                     // reserved74
1436   UNIMPLEMENTED,                // GetBytecodes
1437   _Jv_JVMTI_IsMethodNative,     // IsMethodNative
1438   _Jv_JVMTI_IsMethodSynthetic,  // IsMethodSynthetic
1439   UNIMPLEMENTED,                // GetLoadedClasses
1440   _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses
1441   UNIMPLEMENTED,                // PopFrame
1442   RESERVED,                     // reserved81
1443   RESERVED,                     // reserved82
1444   RESERVED,                     // reserved83
1445   RESERVED,                     // reserved84
1446   RESERVED,                     // reserved85
1447   RESERVED,                     // reserved86
1448   UNIMPLEMENTED,                // RedefineClasses
1449   UNIMPLEMENTED,                // GetVersionNumber
1450   UNIMPLEMENTED,                // GetCapabilities
1451   UNIMPLEMENTED,                // GetSourceDebugExtension
1452   UNIMPLEMENTED,                // IsMethodObsolete
1453   UNIMPLEMENTED,                // SuspendThreadList
1454   UNIMPLEMENTED,                // ResumeThreadList
1455   RESERVED,                     // reserved94
1456   RESERVED,                     // reserved95
1457   RESERVED,                     // reserved96
1458   RESERVED,                     // reserved97
1459   RESERVED,                     // reserved98
1460   RESERVED,                     // reserved99
1461   UNIMPLEMENTED,                // GetAllStackTraces
1462   UNIMPLEMENTED,                // GetThreadListStackTraces
1463   UNIMPLEMENTED,                // GetThreadLocalStorage
1464   UNIMPLEMENTED,                // SetThreadLocalStorage
1465   UNIMPLEMENTED,                // GetStackTrace
1466   RESERVED,                     // reserved105
1467   UNIMPLEMENTED,                // GetTag
1468   UNIMPLEMENTED,                // SetTag
1469   _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection
1470   UNIMPLEMENTED,                // IterateOverObjectsReachable
1471   UNIMPLEMENTED,                // IterateOverReachableObjects
1472   UNIMPLEMENTED,                // IterateOverHeap
1473   UNIMPLEMENTED,                // IterateOverInstanceOfClass
1474   RESERVED,                     // reserved113
1475   UNIMPLEMENTED,                // GetObjectsWithTags
1476   RESERVED,                     // reserved115
1477   RESERVED,                     // reserved116
1478   RESERVED,                     // reserved117
1479   RESERVED,                     // reserved118
1480   RESERVED,                     // reserved119
1481   _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable
1482   _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable
1483   _Jv_JVMTI_SetEventCallbacks,  // SetEventCallbacks
1484   UNIMPLEMENTED,                // GenerateEvents
1485   UNIMPLEMENTED,                // GetExtensionFunctions
1486   UNIMPLEMENTED,                // GetExtensionEvents
1487   UNIMPLEMENTED,                // SetExtensionEventCallback
1488   _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment
1489   _Jv_JVMTI_GetErrorName,       // GetErrorName
1490   UNIMPLEMENTED,                // GetJLocationFormat
1491   UNIMPLEMENTED,                // GetSystemProperties
1492   _Jv_JVMTI_GetSystemProperty,  // GetSystemProperty
1493   _Jv_JVMTI_SetSystemProperty,  // SetSystemProperty
1494   UNIMPLEMENTED,                // GetPhase
1495   UNIMPLEMENTED,                // GetCurrentThreadCpuTimerInfo
1496   UNIMPLEMENTED,                // GetCurrentThreadCpuTime
1497   UNIMPLEMENTED,                // GetThreadCpuTimerInfo
1498   UNIMPLEMENTED,                // GetThreadCpuTime
1499   UNIMPLEMENTED,                // GetTimerInfo
1500   _Jv_JVMTI_GetTime,            // GetTime
1501   UNIMPLEMENTED,                // GetPotentialCapabilities
1502   RESERVED,                     // reserved141
1503   UNIMPLEMENTED,                // AddCapabilities
1504   UNIMPLEMENTED,                // RelinquishCapabilities
1505   _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors
1506   RESERVED,                     // reserved145
1507   RESERVED,                     // reserved146
1508   UNIMPLEMENTED,                // GetEnvironmentLocalStorage
1509   UNIMPLEMENTED,                // SetEnvironmentLocalStorage
1510   _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch
1511   _Jv_JVMTI_SetVerboseFlag,     // SetVerboseFlag
1512   RESERVED,                     // reserved151
1513   RESERVED,                     // reserved152
1514   RESERVED,                     // reserved153
1515   _Jv_JVMTI_GetObjectSize       // GetObjectSize
1516 };
1517
1518 _Jv_JVMTIEnv *
1519 _Jv_GetJVMTIEnv (void)
1520 {
1521   _Jv_JVMTIEnv *env
1522     = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv));
1523   env->p = &_Jv_JVMTI_Interface;
1524
1525   {
1526     JvSynchronize dummy (_envListLock);
1527     struct jvmti_env_list *element
1528       = (struct jvmti_env_list *) _Jv_MallocUnchecked (sizeof (struct jvmti_env_list));
1529     element->env = env;
1530     element->next = NULL;
1531
1532     if (_jvmtiEnvironments == NULL)
1533       _jvmtiEnvironments = element;
1534     else
1535       {
1536         struct jvmti_env_list *e;
1537         for (e = _jvmtiEnvironments; e->next != NULL; e = e->next)
1538           ;
1539         e->next = element;
1540       }
1541   }
1542
1543   return env;
1544 }
1545
1546 void
1547 _Jv_JVMTI_Init ()
1548 {
1549   _jvmtiEnvironments = NULL;
1550   _envListLock = new java::lang::Object ();
1551
1552   // No environments, so this should set all JVMTI:: members to false
1553   check_enabled_events ();
1554 }
1555
1556 static void
1557 post_event (jvmtiEnv *env, jvmtiEvent type, jthread event_thread, va_list args)
1558 {
1559 #define ARG(Type,Name) Type Name = (Type) va_arg (args, Type)
1560
1561 #define GET_BOOLEAN_ARG(Name)                   \
1562   ARG (int, b);                                 \
1563   jboolean Name = (b == 0) ? false : true
1564
1565 #define GET_CHAR_ARG(Name)                      \
1566   ARG (int, c);                                 \
1567   char Name = static_cast<char> (c)
1568
1569   switch (type)
1570     {
1571     case JVMTI_EVENT_VM_INIT:
1572       if (env->callbacks.VMInit != NULL)
1573         {
1574           ARG (JNIEnv *, jni_env);
1575           env->callbacks.VMInit (env, jni_env, event_thread);
1576         }
1577       break;
1578
1579     case JVMTI_EVENT_VM_DEATH:
1580       if (env->callbacks.VMDeath != NULL)
1581         {
1582           ARG (JNIEnv *, jni_env);
1583           env->callbacks.VMDeath (env, jni_env);
1584         }
1585       break;
1586
1587     case JVMTI_EVENT_THREAD_START:
1588       if (env->callbacks.ThreadStart != NULL)
1589         {
1590           ARG (JNIEnv *, jni_env);
1591           env->callbacks.ThreadStart (env, jni_env, event_thread);
1592         }
1593       break;
1594
1595     case JVMTI_EVENT_THREAD_END:
1596       if (env->callbacks.ThreadEnd != NULL)
1597         {
1598           ARG (JNIEnv *, jni_env);
1599           env->callbacks.ThreadEnd (env, jni_env, event_thread);
1600         }
1601       break;
1602
1603     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1604       if (env->callbacks.ClassFileLoadHook != NULL)
1605         {
1606           ARG (JNIEnv *, jni_env);
1607           ARG (jclass, class_being_redefined);
1608           ARG (jobject, loader);
1609           ARG (const char *, name);
1610           ARG (jobject, protection_domain);
1611           ARG (jint, class_data_len);
1612           ARG (const unsigned char *, class_data);
1613           ARG (jint *, new_class_data_len);
1614           ARG (unsigned char **, new_class_data);
1615           env->callbacks.ClassFileLoadHook (env, jni_env,
1616                                             class_being_redefined, loader,
1617                                             name, protection_domain,
1618                                             class_data_len, class_data,
1619                                             new_class_data_len,
1620                                             new_class_data);
1621         }
1622       break;
1623
1624     case JVMTI_EVENT_CLASS_LOAD:
1625       if (env->callbacks.ClassLoad != NULL)
1626         {
1627           ARG (JNIEnv *, jni_env);
1628           ARG (jclass, klass);
1629           env->callbacks.ClassLoad (env, jni_env, event_thread, klass);
1630         }
1631       break;
1632
1633     case JVMTI_EVENT_CLASS_PREPARE:
1634       if (env->callbacks.ClassPrepare != NULL)
1635         {
1636           ARG (JNIEnv *, jni_env);
1637           ARG (jclass, klass);
1638           env->callbacks.ClassPrepare (env, jni_env, event_thread, klass);
1639         }
1640       break;
1641
1642     case JVMTI_EVENT_VM_START:
1643       if (env->callbacks.VMStart != NULL)
1644         {
1645           ARG (JNIEnv *, jni_env);
1646           env->callbacks.VMStart (env, jni_env);
1647         }
1648       break;
1649
1650     case JVMTI_EVENT_EXCEPTION:
1651       if (env->callbacks.Exception != NULL)
1652         {
1653           ARG (JNIEnv *, jni_env);
1654           ARG (jmethodID, method);
1655           ARG (jlocation, location);
1656           ARG (jobject, exception);
1657           ARG (jmethodID, catch_method);
1658           ARG (jlocation, catch_location);
1659           env->callbacks.Exception (env, jni_env, event_thread, method,
1660                                     location, exception, catch_method,
1661                                     catch_location);
1662         }
1663       break;
1664
1665     case JVMTI_EVENT_EXCEPTION_CATCH:
1666       if (env->callbacks.ExceptionCatch != NULL)
1667         {
1668           ARG (JNIEnv *, jni_env);
1669           ARG (jmethodID, method);
1670           ARG (jlocation, location);
1671           ARG (jobject, exception);
1672           env->callbacks.ExceptionCatch (env, jni_env, event_thread, method,
1673                                          location, exception);
1674         }
1675       break;
1676
1677     case JVMTI_EVENT_SINGLE_STEP:
1678       if (env->callbacks.SingleStep != NULL)
1679         {
1680           ARG (JNIEnv *, jni_env);
1681           ARG (jmethodID, method);
1682           ARG (jlocation, location);
1683           env->callbacks.SingleStep (env, jni_env, event_thread, method,
1684                                      location);
1685         }
1686       break;
1687
1688     case JVMTI_EVENT_FRAME_POP:
1689       if (env->callbacks.FramePop != NULL)
1690         {
1691           ARG (JNIEnv *, jni_env);
1692           ARG (jmethodID, method);
1693           GET_BOOLEAN_ARG (was_popped_by_exception);
1694           env->callbacks.FramePop (env, jni_env, event_thread, method,
1695                                    was_popped_by_exception);
1696         }
1697       break;
1698
1699     case JVMTI_EVENT_BREAKPOINT:
1700       if (env->callbacks.Breakpoint != NULL)
1701         {
1702           ARG (JNIEnv *, jni_env);
1703           ARG (jmethodID, method);
1704           ARG (jlocation, location);
1705           env->callbacks.Breakpoint (env, jni_env, event_thread, method,
1706                                      location);
1707         }
1708       break;
1709
1710     case JVMTI_EVENT_FIELD_ACCESS:
1711       if (env->callbacks.FieldAccess != NULL)
1712         {
1713           ARG (JNIEnv *, jni_env);
1714           ARG (jmethodID, method);
1715           ARG (jlocation, location);
1716           ARG (jclass, field_class);
1717           ARG (jobject, object);
1718           ARG (jfieldID, field);
1719           env->callbacks.FieldAccess (env, jni_env, event_thread, method,
1720                                       location, field_class, object, field);
1721         }
1722       break;
1723
1724     case JVMTI_EVENT_FIELD_MODIFICATION:
1725       if (env->callbacks.FieldModification != NULL)
1726         {
1727           ARG (JNIEnv *, jni_env);
1728           ARG (jmethodID, method);
1729           ARG (jlocation, location);
1730           ARG (jclass, field_class);
1731           ARG (jobject, object);
1732           ARG (jfieldID, field);
1733           GET_CHAR_ARG (signature_type);
1734           ARG (jvalue, new_value);
1735           env->callbacks.FieldModification (env, jni_env, event_thread, method,
1736                                             location, field_class, object,
1737                                             field, signature_type, new_value);
1738         }
1739       break;
1740
1741     case JVMTI_EVENT_METHOD_ENTRY:
1742       if (env->callbacks.MethodEntry != NULL)
1743         {
1744           ARG (JNIEnv *, jni_env);
1745           ARG (jmethodID, method);
1746           env->callbacks.MethodEntry (env, jni_env, event_thread, method);
1747         }
1748       break;
1749
1750     case JVMTI_EVENT_METHOD_EXIT:
1751       if (env->callbacks.MethodExit != NULL)
1752         {
1753           ARG (JNIEnv *, jni_env);
1754           ARG (jmethodID, method);
1755           GET_BOOLEAN_ARG (was_popped_by_exception);
1756           ARG (jvalue, return_value);
1757           env->callbacks.MethodExit (env, jni_env, event_thread, method,
1758                                      was_popped_by_exception, return_value);
1759         }
1760       break;
1761
1762     case JVMTI_EVENT_NATIVE_METHOD_BIND:
1763       if (env->callbacks.NativeMethodBind != NULL)
1764         {
1765           ARG (JNIEnv *, jni_env);
1766           ARG (jmethodID, method);
1767           ARG (void *, address);
1768           ARG (void **, new_address_ptr);
1769           env->callbacks.NativeMethodBind (env, jni_env, event_thread, method,
1770                                            address, new_address_ptr);
1771         }
1772       break;
1773
1774     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1775       if (env->callbacks.CompiledMethodLoad != NULL)
1776         {
1777           ARG (jmethodID, method);
1778           ARG (jint, code_size);
1779           ARG (const void *, code_addr);
1780           ARG (jint, map_length);
1781           ARG (const jvmtiAddrLocationMap *, map);
1782           ARG (const void *, compile_info);
1783           env->callbacks.CompiledMethodLoad (env, method, code_size, code_addr,
1784                                              map_length, map, compile_info);
1785         }
1786       break;
1787
1788     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1789       if (env->callbacks.CompiledMethodUnload != NULL)
1790         {
1791           ARG (jmethodID, method);
1792           ARG (const void *, code_addr);
1793           env->callbacks.CompiledMethodUnload (env, method, code_addr);
1794         }
1795       break;
1796
1797     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1798       if (env->callbacks.DynamicCodeGenerated != NULL)
1799         {
1800           ARG (const char *, name);
1801           ARG (const void *, address);
1802           ARG (jint, length);
1803           env->callbacks.DynamicCodeGenerated (env, name, address, length);
1804         }
1805       break;
1806
1807     case JVMTI_EVENT_DATA_DUMP_REQUEST:
1808       if (env->callbacks.DataDumpRequest != NULL)
1809         {
1810           env->callbacks.DataDumpRequest (env);
1811         }
1812       break;
1813
1814     case JVMTI_EVENT_MONITOR_WAIT:
1815       if (env->callbacks.MonitorWait != NULL)
1816         {
1817           ARG (JNIEnv *, jni_env);
1818           ARG (jobject, object);
1819           ARG (jlong, timeout);
1820           env->callbacks.MonitorWait (env, jni_env, event_thread, object,
1821                                       timeout);
1822         }
1823       break;
1824
1825     case JVMTI_EVENT_MONITOR_WAITED:
1826       if (env->callbacks.MonitorWaited != NULL)
1827         {
1828           ARG (JNIEnv *, jni_env);
1829           ARG (jobject, object);
1830           GET_BOOLEAN_ARG (timed_out);
1831           env->callbacks.MonitorWaited (env, jni_env, event_thread, object,
1832                                         timed_out);
1833         }
1834       break;
1835
1836     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1837       if (env->callbacks.MonitorContendedEnter != NULL)
1838         {
1839           ARG (JNIEnv *, jni_env);
1840           ARG (jobject, object);
1841           env->callbacks.MonitorContendedEnter (env, jni_env, event_thread,
1842                                                 object);
1843         }
1844       break;
1845
1846     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1847       if (env->callbacks.MonitorContendedEntered != NULL)
1848         {
1849           ARG (JNIEnv *, jni_env);
1850           ARG (jobject, object);
1851           env->callbacks.MonitorContendedEntered (env, jni_env, event_thread,
1852                                                   object);
1853         }
1854       break;
1855
1856     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1857       if (env->callbacks.GarbageCollectionStart != NULL)
1858         {
1859           env->callbacks.GarbageCollectionStart (env);
1860         }
1861       break;
1862
1863     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1864       if (env->callbacks.GarbageCollectionFinish != NULL)
1865         {
1866           env->callbacks.GarbageCollectionFinish (env);
1867         }
1868       break;
1869
1870     case JVMTI_EVENT_OBJECT_FREE:
1871       if (env->callbacks.ObjectFree != NULL)
1872         {
1873           ARG (jlong, tag);
1874           env->callbacks.ObjectFree (env, tag);
1875         }
1876       break;
1877
1878     case JVMTI_EVENT_VM_OBJECT_ALLOC:
1879       if (env->callbacks.VMObjectAlloc != NULL)
1880         {
1881           ARG (JNIEnv *, jni_env);
1882           ARG (jobject, object);
1883           ARG (jclass, object_class);
1884           ARG (jlong, size);
1885           env->callbacks.VMObjectAlloc (env, jni_env, event_thread,
1886                                         object, object_class, size);
1887         }
1888       break;
1889
1890     default:
1891       fprintf (stderr, "libgcj: post of unknown JVMTI event (%d)\n",
1892                (int) type);
1893       break;
1894     }
1895   va_end (args);
1896 #undef ARG
1897 #undef GET_BOOLEAN_ARG
1898 #undef GET_CHAR_ARG
1899 }
1900
1901 /* Post an event to requesting JVMTI environments
1902  *
1903  * This function should not be called without consulting the
1904  * JVMTI_REQUESTED_EVENT macro first (for speed). It does no real
1905  * harm (other than kill speed), since this function will still
1906  * only send the event if it was properly requested by an environment.
1907  */ 
1908 void
1909 _Jv_JVMTI_PostEvent (jvmtiEvent type, jthread event_thread, ...)
1910 {
1911   va_list args;
1912   va_start (args, event_thread);
1913
1914   JvSynchronize dummy (_envListLock);
1915   struct jvmti_env_list *e;
1916   FOREACH_ENVIRONMENT (e)
1917     {
1918       /* Events are only posted if the event was explicitly enabled,
1919          it has a registered event handler, and the event thread
1920          matches (either globally or restricted to a specific thread).
1921          Here we check all but the event handler, which will be handled
1922          by post_event. */
1923       if (e->env->enabled[EVENT_INDEX(type)]
1924           && (e->env->thread[EVENT_INDEX(type)] == NULL
1925               || e->env->thread[EVENT_INDEX(type)] == event_thread))
1926         {
1927           post_event (e->env, type, event_thread, args);
1928         }
1929     }
1930
1931   va_end (args);
1932 }