OSDN Git Service

* gnu/gcj/jvmti/Location.java: New file.
[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_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
511                           jboolean *result)
512 {
513   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
514   if (method == NULL)
515     return JVMTI_ERROR_INVALID_METHODID;
516   NULL_CHECK (result);
517
518   *result = ((method->accflags & java::lang::reflect::Modifier::NATIVE) != 0);
519   return JVMTI_ERROR_NONE;
520 }
521
522 static jvmtiError JNICALL
523 _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
524                              jboolean *result)
525 {
526   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
527   if (method == NULL)
528     return JVMTI_ERROR_INVALID_METHODID;
529   NULL_CHECK (result);
530
531   // FIXME capability can_get_synthetic_attribute
532
533   *result = ((method->accflags & java::lang::reflect::Modifier::SYNTHETIC)
534              != 0);
535   return JVMTI_ERROR_NONE;
536 }
537
538 static jvmtiError JNICALL
539 _Jv_JVMTI_GetMethodDeclaringClass (MAYBE_UNUSED jvmtiEnv *env,
540                                    jmethodID method,
541                                    jclass *declaring_class_ptr)
542 {
543   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
544   NULL_CHECK (declaring_class_ptr);
545
546   jclass klass = _Jv_GetMethodDeclaringClass (method);
547   if (klass != NULL)
548     {
549       *declaring_class_ptr = klass;
550       return JVMTI_ERROR_NONE;
551     }
552
553   return JVMTI_ERROR_INVALID_METHODID;
554 }
555
556 static jvmtiError JNICALL
557 _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env,
558                                  jobject init_loader,
559                                  jint *count_ptr,
560                                  jclass **result_ptr)
561 {
562   using namespace java::lang;
563   using namespace java::util;
564
565   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
566   NULL_CHECK (count_ptr);
567   NULL_CHECK (result_ptr);
568
569   ClassLoader *loader = (ClassLoader *) init_loader;
570   if (loader == NULL)
571     loader = VMClassLoader::bootLoader;
572
573   Collection *values = loader->loadedClasses->values();
574   jobjectArray array = values->toArray();
575   *count_ptr = array->length;
576   jobject *elts = elements (array);
577   jclass *result
578     = (jclass *) _Jv_MallocUnchecked (*count_ptr * sizeof (jclass));
579   if (result == NULL)
580     return JVMTI_ERROR_OUT_OF_MEMORY;
581
582   // FIXME: JNI references...
583   memcpy (result, elts, *count_ptr * sizeof (jclass));
584
585   *result_ptr = result;
586
587   return JVMTI_ERROR_NONE;
588 }
589
590 static jvmtiError JNICALL
591 _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env)
592 {
593   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
594   _Jv_RunGC();
595   return JVMTI_ERROR_NONE;
596 }
597
598 static jvmtiError JNICALL
599 _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
600                                const jniNativeInterface *function_table)
601 {
602   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
603   NULL_CHECK (function_table);
604   memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface));
605   return JVMTI_ERROR_NONE;
606 }
607
608 static jvmtiError JNICALL
609 _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
610                                jniNativeInterface **function_table)
611 {
612   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
613   NULL_CHECK (function_table);
614   *function_table
615     = (jniNativeInterface *) _Jv_MallocUnchecked (sizeof (jniNativeInterface));
616   if (*function_table == NULL)
617     return JVMTI_ERROR_OUT_OF_MEMORY;
618   memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface));
619   return JVMTI_ERROR_NONE;
620 }
621
622 static jvmtiError JNICALL
623 _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env)
624 {
625   NULL_CHECK (env);
626
627   if (_jvmtiEnvironments == NULL)
628     return JVMTI_ERROR_INVALID_ENVIRONMENT;
629   else
630     {
631       JvSynchronize dummy (_envListLock);
632       if (_jvmtiEnvironments->env == env)
633         {
634           struct jvmti_env_list *next = _jvmtiEnvironments->next;
635           _Jv_Free (_jvmtiEnvironments);
636           _jvmtiEnvironments = next;
637         }
638       else
639         {
640           struct jvmti_env_list *e = _jvmtiEnvironments; 
641           while (e->next != NULL && e->next->env != env)
642             e = e->next;
643           if (e->next == NULL)
644             return JVMTI_ERROR_INVALID_ENVIRONMENT;
645
646           struct jvmti_env_list *next = e->next->next;
647           _Jv_Free (e->next);
648           e->next = next;
649         }
650     }
651
652   _Jv_Free (env);
653
654   check_enabled_events ();
655
656   return JVMTI_ERROR_NONE;
657 }
658
659 static jvmtiError JNICALL
660 _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
661                              char **result)
662 {
663   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
664   NULL_CHECK (property);
665   NULL_CHECK (result);
666
667   jstring name = JvNewStringUTF(property);
668   jstring result_str = gnu::classpath::SystemProperties::getProperty(name);
669
670   if (result_str == NULL)
671     return JVMTI_ERROR_NOT_AVAILABLE;
672
673   int len = JvGetStringUTFLength (result_str);
674   *result = (char *) _Jv_MallocUnchecked (len + 1);
675   if (*result == NULL)
676     return JVMTI_ERROR_OUT_OF_MEMORY;
677   JvGetStringUTFRegion (result_str, 0, result_str->length(), *result);
678   (*result)[len] = '\0';
679
680   return JVMTI_ERROR_NONE;
681 }
682
683 static jvmtiError JNICALL
684 _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
685                              const char *value)
686 {
687   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
688
689   NULL_CHECK (property);
690   if (value == NULL)
691     {
692       // FIXME: When would a property not be writeable?
693       return JVMTI_ERROR_NONE;
694     }
695
696   jstring prop_str = JvNewStringUTF(property);
697   jstring value_str = JvNewStringUTF(value);
698   gnu::classpath::SystemProperties::setProperty(prop_str, value_str);
699   return JVMTI_ERROR_NONE;
700 }
701
702 static jvmtiError JNICALL
703 _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr)
704 {
705   NULL_CHECK (nanos_ptr);
706   *nanos_ptr = _Jv_platform_nanotime();
707   return JVMTI_ERROR_NONE;
708 }
709
710 static jvmtiError JNICALL
711 _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env,
712                                   jint *nprocessors_ptr)
713 {
714   NULL_CHECK (nprocessors_ptr);
715 #ifdef _SC_NPROCESSORS_ONLN
716   *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN);
717 #else
718   *nprocessors_ptr = 1;
719 #endif
720   return JVMTI_ERROR_NONE;
721 }
722
723 static jvmtiError JNICALL
724 _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env,
725                                            const char *segment)
726 {
727   using namespace java::lang;
728   using namespace java::net;
729   using namespace gnu::gcj::runtime;
730
731   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
732   NULL_CHECK (segment);
733
734   jstring str_segment = JvNewStringUTF(segment);
735   URL *url;
736   try
737     {
738       url = new URL(JvNewStringUTF("file"), NULL, str_segment);
739     }
740   catch (jthrowable ignore)
741     {
742       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
743     }
744
745   BootClassLoader *loader = VMClassLoader::bootLoader;
746   // Don't call this too early.
747   // assert (loader != NULL);
748   loader->addURL(url);
749   return JVMTI_ERROR_NONE;
750 }
751
752 static jvmtiError JNICALL
753 _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag,
754                           jboolean value)
755 {
756   switch (flag)
757     {
758     case JVMTI_VERBOSE_OTHER:
759     case JVMTI_VERBOSE_GC:
760     case JVMTI_VERBOSE_JNI:
761       // Ignore.
762       break;
763     case JVMTI_VERBOSE_CLASS:
764       gcj::verbose_class_flag = value;
765       break;
766     default:
767       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
768     }
769   return JVMTI_ERROR_NONE;
770 }
771
772 static jvmtiError JNICALL
773 _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object,
774                          jlong *result)
775 {
776   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
777   if (object == NULL)
778     return JVMTI_ERROR_INVALID_OBJECT;
779   NULL_CHECK (result);
780
781   jclass klass = object->getClass();
782   if (klass->isArray())
783     {
784       jclass comp = klass->getComponentType();
785       jint base
786         = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL,
787                                                                     klass->getComponentType());
788       // FIXME: correct for primitive types?
789       jint compSize = comp->size();
790       __JArray *array = (__JArray *) object;
791       *result = base + array->length * compSize;
792     }
793   else
794     {
795       // Note that if OBJECT is a String then it may (if
796       // str->data==str) take more space.  Do we care?
797       *result = klass->size();
798     }
799   return JVMTI_ERROR_NONE;
800 }
801
802 /* An event is enabled only if it has both an event handler
803    and it is enabled in the environment. */
804 static void
805 check_enabled_event (jvmtiEvent type)
806 {
807   bool *enabled;
808   int offset;
809
810 #define GET_OFFSET(Event)                               \
811   do                                                    \
812     {                                                   \
813       enabled = &JVMTI::Event;                          \
814       offset = offsetof (jvmtiEventCallbacks, Event);   \
815     }                                                   \
816   while (0)
817
818   switch (type)
819     {
820     case JVMTI_EVENT_VM_INIT:
821       GET_OFFSET (VMInit);
822       break;
823
824     case JVMTI_EVENT_VM_DEATH:
825       GET_OFFSET (VMDeath);
826       break;
827
828     case JVMTI_EVENT_THREAD_START:
829       GET_OFFSET (ThreadStart);
830       break;
831
832     case JVMTI_EVENT_THREAD_END:
833       GET_OFFSET (ThreadEnd);
834       break;
835
836     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
837       GET_OFFSET (ClassFileLoadHook);
838       break;
839
840     case JVMTI_EVENT_CLASS_LOAD:
841       GET_OFFSET (ClassLoad);
842       break;
843
844     case JVMTI_EVENT_CLASS_PREPARE:
845       GET_OFFSET (ClassPrepare);
846       break;
847
848     case JVMTI_EVENT_VM_START:
849       GET_OFFSET (VMStart);
850       break;
851
852     case JVMTI_EVENT_EXCEPTION:
853       GET_OFFSET (Exception);
854       break;
855
856     case JVMTI_EVENT_EXCEPTION_CATCH:
857       GET_OFFSET (ExceptionCatch);
858       break;
859
860     case JVMTI_EVENT_SINGLE_STEP:
861       GET_OFFSET (SingleStep);
862       break;
863
864     case JVMTI_EVENT_FRAME_POP:
865       GET_OFFSET (FramePop);
866       break;
867
868     case JVMTI_EVENT_BREAKPOINT:
869       GET_OFFSET (Breakpoint);
870       break;
871
872     case JVMTI_EVENT_FIELD_ACCESS:
873       GET_OFFSET (FieldAccess);
874       break;
875
876     case JVMTI_EVENT_FIELD_MODIFICATION:
877       GET_OFFSET (FieldModification);
878       break;
879
880     case JVMTI_EVENT_METHOD_ENTRY:
881       GET_OFFSET (MethodEntry);
882       break;
883
884     case JVMTI_EVENT_METHOD_EXIT:
885       GET_OFFSET (MethodExit);
886       break;
887
888     case JVMTI_EVENT_NATIVE_METHOD_BIND:
889       GET_OFFSET (NativeMethodBind);
890       break;
891
892     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
893       GET_OFFSET (CompiledMethodLoad);
894       break;
895
896     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
897       GET_OFFSET (CompiledMethodUnload);
898       break;
899
900     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
901       GET_OFFSET (DynamicCodeGenerated);
902       break;
903
904     case JVMTI_EVENT_DATA_DUMP_REQUEST:
905       GET_OFFSET (DataDumpRequest);
906       break;
907
908     case JVMTI_EVENT_MONITOR_WAIT:
909       GET_OFFSET (MonitorWait);
910       break;
911
912     case JVMTI_EVENT_MONITOR_WAITED:
913       GET_OFFSET (MonitorWaited);
914       break;
915
916     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
917       GET_OFFSET (MonitorContendedEnter);
918       break;
919
920     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
921       GET_OFFSET (MonitorContendedEntered);
922       break;
923
924     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
925       GET_OFFSET (GarbageCollectionStart);
926       break;
927
928     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
929       GET_OFFSET (GarbageCollectionFinish);
930       break;
931
932     case JVMTI_EVENT_OBJECT_FREE:
933       GET_OFFSET (ObjectFree);
934       break;
935
936     case JVMTI_EVENT_VM_OBJECT_ALLOC:
937       GET_OFFSET (VMObjectAlloc);
938       break;
939
940     default:
941       fprintf (stderr,
942                "libgcj: check_enabled_event for unknown JVMTI event (%d)\n",
943                (int) type);
944       return;
945     }
946 #undef GET_OFFSET
947
948   int index = EVENT_INDEX (type); // safe since caller checks this
949
950   JvSynchronize dummy (_envListLock);
951   struct jvmti_env_list *e;
952   FOREACH_ENVIRONMENT (e)
953     {
954       char *addr
955         = reinterpret_cast<char *> (&e->env->callbacks) + offset;
956       void **callback = reinterpret_cast<void **> (addr);
957       if (e->env->enabled[index] && *callback != NULL)
958         {
959           *enabled = true;
960           return;
961         }
962     }
963
964   *enabled = false;
965 }
966
967 static void
968 check_enabled_events ()
969 {
970   check_enabled_event (JVMTI_EVENT_VM_INIT);
971   check_enabled_event (JVMTI_EVENT_VM_DEATH);
972   check_enabled_event (JVMTI_EVENT_THREAD_START);
973   check_enabled_event (JVMTI_EVENT_THREAD_END);
974   check_enabled_event (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK);
975   check_enabled_event (JVMTI_EVENT_CLASS_LOAD);
976   check_enabled_event (JVMTI_EVENT_CLASS_PREPARE);
977   check_enabled_event (JVMTI_EVENT_VM_START);
978   check_enabled_event (JVMTI_EVENT_EXCEPTION);
979   check_enabled_event (JVMTI_EVENT_EXCEPTION_CATCH);
980   check_enabled_event (JVMTI_EVENT_SINGLE_STEP);
981   check_enabled_event (JVMTI_EVENT_FRAME_POP);
982   check_enabled_event (JVMTI_EVENT_BREAKPOINT);
983   check_enabled_event (JVMTI_EVENT_FIELD_ACCESS);
984   check_enabled_event (JVMTI_EVENT_FIELD_MODIFICATION);
985   check_enabled_event (JVMTI_EVENT_METHOD_ENTRY);
986   check_enabled_event (JVMTI_EVENT_METHOD_EXIT);
987   check_enabled_event (JVMTI_EVENT_NATIVE_METHOD_BIND);
988   check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_LOAD);
989   check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_UNLOAD);
990   check_enabled_event (JVMTI_EVENT_DYNAMIC_CODE_GENERATED);
991   check_enabled_event (JVMTI_EVENT_DATA_DUMP_REQUEST);
992   check_enabled_event (JVMTI_EVENT_MONITOR_WAIT);
993   check_enabled_event (JVMTI_EVENT_MONITOR_WAITED);
994   check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTER);
995   check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED);
996   check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_START);
997   check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH);
998   check_enabled_event (JVMTI_EVENT_OBJECT_FREE);
999   check_enabled_event (JVMTI_EVENT_VM_OBJECT_ALLOC);
1000 }
1001
1002 static jvmtiError JNICALL
1003 _Jv_JVMTI_SetEventNotificationMode (jvmtiEnv *env, jvmtiEventMode mode,
1004                                     jvmtiEvent type, jthread event_thread, ...)
1005 {
1006   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1007
1008   if (event_thread != NULL)
1009     {
1010       using namespace java::lang;
1011       Thread *t = reinterpret_cast<Thread *> (event_thread);
1012       THREAD_CHECK_VALID (t);
1013       THREAD_CHECK_IS_ALIVE (t);
1014     }
1015
1016   bool enabled;
1017   switch (mode)
1018     {
1019     case JVMTI_DISABLE:
1020       enabled = false;
1021       break;
1022     case JVMTI_ENABLE:
1023       enabled = true;
1024       break;
1025
1026     default:
1027       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1028     }
1029
1030   switch (type)
1031     {
1032     case JVMTI_EVENT_VM_INIT:
1033     case JVMTI_EVENT_VM_DEATH:
1034     case JVMTI_EVENT_THREAD_START:
1035     case JVMTI_EVENT_VM_START:
1036     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1037     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1038     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1039     case JVMTI_EVENT_DATA_DUMP_REQUEST:
1040       ILLEGAL_ARGUMENT (event_thread != NULL);
1041       break;
1042
1043     case JVMTI_EVENT_THREAD_END:
1044     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1045     case JVMTI_EVENT_CLASS_LOAD:
1046     case JVMTI_EVENT_CLASS_PREPARE:
1047     case JVMTI_EVENT_EXCEPTION:
1048     case JVMTI_EVENT_EXCEPTION_CATCH:
1049     case JVMTI_EVENT_SINGLE_STEP:
1050     case JVMTI_EVENT_FRAME_POP:
1051     case JVMTI_EVENT_BREAKPOINT:
1052     case JVMTI_EVENT_FIELD_ACCESS:
1053     case JVMTI_EVENT_FIELD_MODIFICATION:
1054     case JVMTI_EVENT_METHOD_ENTRY:
1055     case JVMTI_EVENT_METHOD_EXIT:
1056     case JVMTI_EVENT_NATIVE_METHOD_BIND:
1057     case JVMTI_EVENT_MONITOR_WAIT:
1058     case JVMTI_EVENT_MONITOR_WAITED:
1059     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1060     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1061     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1062     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1063     case JVMTI_EVENT_OBJECT_FREE:
1064     case JVMTI_EVENT_VM_OBJECT_ALLOC:
1065       break;
1066
1067     default:
1068       return JVMTI_ERROR_INVALID_EVENT_TYPE;
1069     }
1070
1071   env->thread[EVENT_INDEX(type)] = event_thread;
1072   env->enabled[EVENT_INDEX(type)] = enabled;
1073   check_enabled_event (type);
1074   return JVMTI_ERROR_NONE;
1075 }
1076
1077 static jvmtiError JNICALL
1078 _Jv_JVMTI_SetEventCallbacks (jvmtiEnv *env,
1079                              const jvmtiEventCallbacks *callbacks,
1080                              jint size_of_callbacks)
1081 {
1082   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
1083   ILLEGAL_ARGUMENT (size_of_callbacks < 0);
1084
1085   // Copy the list of callbacks into the environment
1086   memcpy (&env->callbacks, callbacks, sizeof (jvmtiEventCallbacks));
1087
1088   /* Check which events are now enabeld (JVMTI makes no requirements
1089      about the order in which SetEventCallbacks and SetEventNotifications
1090      are called. So we must check all events here. */
1091   check_enabled_events ();
1092
1093   return JVMTI_ERROR_NONE;
1094 }
1095
1096 static jvmtiError JNICALL
1097 _Jv_JVMTI_GetErrorName (MAYBE_UNUSED jvmtiEnv *env, jvmtiError error,
1098                         char **name_ptr)
1099 {
1100   NULL_CHECK (name_ptr);
1101
1102   const char *name;
1103   switch (error)
1104     {
1105     case JVMTI_ERROR_NONE:
1106       name = "none";
1107       break;
1108
1109     case JVMTI_ERROR_NULL_POINTER:
1110       name = "null pointer";
1111       break;
1112
1113     case JVMTI_ERROR_OUT_OF_MEMORY:
1114       name = "out of memory";
1115       break;
1116
1117     case JVMTI_ERROR_ACCESS_DENIED:
1118       name = "access denied";
1119       break;
1120
1121     case JVMTI_ERROR_WRONG_PHASE:
1122       name = "wrong phase";
1123       break;
1124
1125     case JVMTI_ERROR_INTERNAL:
1126       name = "internal error";
1127       break;
1128
1129     case JVMTI_ERROR_UNATTACHED_THREAD:
1130       name = "unattached thread";
1131       break;
1132
1133     case JVMTI_ERROR_INVALID_ENVIRONMENT:
1134       name = "invalid environment";
1135       break;
1136
1137     case JVMTI_ERROR_INVALID_PRIORITY:
1138       name = "invalid priority";
1139       break;
1140
1141     case JVMTI_ERROR_THREAD_NOT_SUSPENDED:
1142       name = "thread not suspended";
1143       break;
1144
1145     case JVMTI_ERROR_THREAD_SUSPENDED:
1146       name = "thread suspended";
1147       break;
1148
1149     case JVMTI_ERROR_THREAD_NOT_ALIVE:
1150       name = "thread not alive";
1151       break;
1152
1153     case JVMTI_ERROR_CLASS_NOT_PREPARED:
1154       name = "class not prepared";
1155       break;
1156
1157     case JVMTI_ERROR_NO_MORE_FRAMES:
1158       name = "no more frames";
1159       break;
1160
1161     case JVMTI_ERROR_OPAQUE_FRAME:
1162       name = "opaque frame";
1163       break;
1164
1165     case JVMTI_ERROR_DUPLICATE:
1166       name = "duplicate";
1167       break;
1168
1169     case JVMTI_ERROR_NOT_FOUND:
1170       name = "not found";
1171       break;
1172
1173     case JVMTI_ERROR_NOT_MONITOR_OWNER:
1174       name = "not monitor owner";
1175       break;
1176
1177     case JVMTI_ERROR_INTERRUPT:
1178       name = "interrupted";
1179       break;
1180
1181     case JVMTI_ERROR_UNMODIFIABLE_CLASS:
1182       name = "unmodifiable class";
1183       break;
1184
1185     case JVMTI_ERROR_NOT_AVAILABLE:
1186       name = "not available";
1187       break;
1188
1189     case JVMTI_ERROR_ABSENT_INFORMATION:
1190       name = "absent information";
1191       break;
1192
1193     case JVMTI_ERROR_INVALID_EVENT_TYPE:
1194       name = "invalid event type";
1195       break;
1196
1197     case JVMTI_ERROR_NATIVE_METHOD:
1198       name = "native method";
1199       break;
1200
1201     case JVMTI_ERROR_INVALID_THREAD:
1202       name = "invalid thread";
1203       break;
1204
1205     case JVMTI_ERROR_INVALID_THREAD_GROUP:
1206       name = "invalid thread group";
1207       break;
1208
1209     case JVMTI_ERROR_INVALID_OBJECT:
1210       name = "invalid object";
1211       break;
1212
1213     case JVMTI_ERROR_INVALID_CLASS:
1214       name = "invalid class";
1215       break;
1216
1217     case JVMTI_ERROR_INVALID_METHODID:
1218       name = "invalid method ID";
1219       break;
1220
1221     case JVMTI_ERROR_INVALID_LOCATION:
1222       name = "invalid location";
1223       break;
1224
1225     case JVMTI_ERROR_INVALID_FIELDID:
1226       name = "invalid field ID";
1227       break;
1228
1229     case JVMTI_ERROR_TYPE_MISMATCH:
1230       name = "type mismatch";
1231       break;
1232
1233     case JVMTI_ERROR_INVALID_SLOT:
1234       name = "invalid slot";
1235       break;
1236
1237     case JVMTI_ERROR_INVALID_MONITOR:
1238       name = "invalid monitor";
1239       break;
1240
1241     case JVMTI_ERROR_INVALID_CLASS_FORMAT:
1242       name = "invalid class format";
1243       break;
1244
1245     case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION:
1246       name = "circular class definition";
1247       break;
1248
1249     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED:
1250       name = "unsupported redefinition: method added";
1251       break;
1252
1253     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED:
1254       name = "unsupported redefinition: schema changed";
1255       break;
1256
1257     case JVMTI_ERROR_INVALID_TYPESTATE:
1258       name = "invalid type state";
1259       break;
1260
1261     case JVMTI_ERROR_FAILS_VERIFICATION:
1262       name = "fails verification";
1263       break;
1264
1265     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED:
1266       name = "unsupported redefinition: hierarchy changed";
1267       break;
1268
1269     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED:
1270       name = "unsupported redefinition: method deleted";
1271       break;
1272
1273     case JVMTI_ERROR_UNSUPPORTED_VERSION:
1274       name = "unsupported version";
1275       break;
1276
1277     case JVMTI_ERROR_NAMES_DONT_MATCH:
1278       name = "names do not match";
1279       break;
1280
1281     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED:
1282       name = "unsupported redefinition: class modifiers changed";
1283       break;
1284
1285     case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
1286       name = "unsupported redefinition: method modifiers changed";
1287       break;
1288
1289     case JVMTI_ERROR_MUST_POSSESS_CAPABILITY:
1290       name = "must possess capability";
1291       break;
1292
1293     case JVMTI_ERROR_ILLEGAL_ARGUMENT:
1294       name = "illegal argument";
1295       break;
1296
1297     default:
1298       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
1299     }
1300
1301   *name_ptr = (char *) _Jv_MallocUnchecked (strlen (name) + 1);
1302   if (*name_ptr == NULL)
1303     return JVMTI_ERROR_OUT_OF_MEMORY;
1304
1305   strcpy (*name_ptr, name);
1306   return JVMTI_ERROR_NONE;
1307 }
1308
1309 #define RESERVED NULL
1310 #define UNIMPLEMENTED NULL
1311
1312 struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
1313 {
1314   RESERVED,                     // reserved1
1315   _Jv_JVMTI_SetEventNotificationMode, // SetEventNotificationMode
1316   RESERVED,                     // reserved3
1317   UNIMPLEMENTED,                // GetAllThreads
1318   _Jv_JVMTI_SuspendThread,      // SuspendThread
1319   _Jv_JVMTI_ResumeThread,       // ResumeThread
1320   UNIMPLEMENTED,                // StopThread
1321   _Jv_JVMTI_InterruptThread,    // InterruptThread
1322   UNIMPLEMENTED,                // GetThreadInfo
1323   UNIMPLEMENTED,                // GetOwnedMonitorInfo
1324   UNIMPLEMENTED,                // GetCurrentContendedMonitor
1325   UNIMPLEMENTED,                // RunAgentThread
1326   UNIMPLEMENTED,                // GetTopThreadGroups
1327   UNIMPLEMENTED,                // GetThreadGroupInfo
1328   UNIMPLEMENTED,                // GetThreadGroupChildren
1329   UNIMPLEMENTED,                // GetFrameCount
1330   UNIMPLEMENTED,                // GetThreadState
1331   RESERVED,                     // reserved18
1332   UNIMPLEMENTED,                // GetFrameLocation
1333   UNIMPLEMENTED,                // NotifyPopFrame
1334   UNIMPLEMENTED,                // GetLocalObject
1335   UNIMPLEMENTED,                // GetLocalInt
1336   UNIMPLEMENTED,                // GetLocalLong
1337   UNIMPLEMENTED,                // GetLocalFloat
1338   UNIMPLEMENTED,                // GetLocalDouble
1339   UNIMPLEMENTED,                // SetLocalObject
1340   UNIMPLEMENTED,                // SetLocalInt
1341   UNIMPLEMENTED,                // SetLocalLong
1342   UNIMPLEMENTED,                // SetLocalFloat
1343   UNIMPLEMENTED,                // SetLocalDouble
1344   _Jv_JVMTI_CreateRawMonitor,   // CreateRawMonitor
1345   _Jv_JVMTI_DestroyRawMonitor,  // DestroyRawMonitor
1346   _Jv_JVMTI_RawMonitorEnter,    // RawMonitorEnter
1347   _Jv_JVMTI_RawMonitorExit,     // RawMonitorExit
1348   _Jv_JVMTI_RawMonitorWait,     // RawMonitorWait
1349   _Jv_JVMTI_RawMonitorNotify,   // RawMonitorNotify
1350   _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll
1351   _Jv_JVMTI_SetBreakpoint,      // SetBreakpoint
1352   _Jv_JVMTI_ClearBreakpoint,    // ClearBreakpoint
1353   RESERVED,                     // reserved40
1354   UNIMPLEMENTED,                // SetFieldAccessWatch
1355   UNIMPLEMENTED,                // ClearFieldAccessWatch
1356   UNIMPLEMENTED,                // SetFieldModificationWatch
1357   UNIMPLEMENTED,                // ClearFieldModificationWatch
1358   RESERVED,                     // reserved45
1359   _Jv_JVMTI_Allocate,           // Allocate
1360   _Jv_JVMTI_Deallocate,         // Deallocate
1361   UNIMPLEMENTED,                // GetClassSignature
1362   UNIMPLEMENTED,                // GetClassStatus
1363   UNIMPLEMENTED,                // GetSourceFileName
1364   _Jv_JVMTI_GetClassModifiers,  // GetClassModifiers
1365   _Jv_JVMTI_GetClassMethods,    // GetClassMethods
1366   UNIMPLEMENTED,                // GetClassFields
1367   UNIMPLEMENTED,                // GetImplementedInterfaces
1368   _Jv_JVMTI_IsInterface,        // IsInterface
1369   _Jv_JVMTI_IsArrayClass,       // IsArrayClass
1370   _Jv_JVMTI_GetClassLoader,     // GetClassLoader
1371   _Jv_JVMTI_GetObjectHashCode,  // GetObjectHashCode
1372   UNIMPLEMENTED,                // GetObjectMonitorUsage
1373   UNIMPLEMENTED,                // GetFieldName
1374   UNIMPLEMENTED,                // GetFieldDeclaringClass
1375   _Jv_JVMTI_GetFieldModifiers,  // GetFieldModifiers
1376   _Jv_JVMTI_IsFieldSynthetic,   // IsFieldSynthetic
1377   UNIMPLEMENTED,                // GetMethodName
1378   _Jv_JVMTI_GetMethodDeclaringClass,  // GetMethodDeclaringClass
1379   _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers
1380   RESERVED,                     // reserved67
1381   UNIMPLEMENTED,                // GetMaxLocals
1382   UNIMPLEMENTED,                // GetArgumentsSize
1383   UNIMPLEMENTED,                // GetLineNumberTable
1384   UNIMPLEMENTED,                // GetMethodLocation
1385   UNIMPLEMENTED,                // GetLocalVariableTable
1386   RESERVED,                     // reserved73
1387   RESERVED,                     // reserved74
1388   UNIMPLEMENTED,                // GetBytecodes
1389   _Jv_JVMTI_IsMethodNative,     // IsMethodNative
1390   _Jv_JVMTI_IsMethodSynthetic,  // IsMethodSynthetic
1391   UNIMPLEMENTED,                // GetLoadedClasses
1392   _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses
1393   UNIMPLEMENTED,                // PopFrame
1394   RESERVED,                     // reserved81
1395   RESERVED,                     // reserved82
1396   RESERVED,                     // reserved83
1397   RESERVED,                     // reserved84
1398   RESERVED,                     // reserved85
1399   RESERVED,                     // reserved86
1400   UNIMPLEMENTED,                // RedefineClasses
1401   UNIMPLEMENTED,                // GetVersionNumber
1402   UNIMPLEMENTED,                // GetCapabilities
1403   UNIMPLEMENTED,                // GetSourceDebugExtension
1404   UNIMPLEMENTED,                // IsMethodObsolete
1405   UNIMPLEMENTED,                // SuspendThreadList
1406   UNIMPLEMENTED,                // ResumeThreadList
1407   RESERVED,                     // reserved94
1408   RESERVED,                     // reserved95
1409   RESERVED,                     // reserved96
1410   RESERVED,                     // reserved97
1411   RESERVED,                     // reserved98
1412   RESERVED,                     // reserved99
1413   UNIMPLEMENTED,                // GetAllStackTraces
1414   UNIMPLEMENTED,                // GetThreadListStackTraces
1415   UNIMPLEMENTED,                // GetThreadLocalStorage
1416   UNIMPLEMENTED,                // SetThreadLocalStorage
1417   UNIMPLEMENTED,                // GetStackTrace
1418   RESERVED,                     // reserved105
1419   UNIMPLEMENTED,                // GetTag
1420   UNIMPLEMENTED,                // SetTag
1421   _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection
1422   UNIMPLEMENTED,                // IterateOverObjectsReachable
1423   UNIMPLEMENTED,                // IterateOverReachableObjects
1424   UNIMPLEMENTED,                // IterateOverHeap
1425   UNIMPLEMENTED,                // IterateOverInstanceOfClass
1426   RESERVED,                     // reserved113
1427   UNIMPLEMENTED,                // GetObjectsWithTags
1428   RESERVED,                     // reserved115
1429   RESERVED,                     // reserved116
1430   RESERVED,                     // reserved117
1431   RESERVED,                     // reserved118
1432   RESERVED,                     // reserved119
1433   _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable
1434   _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable
1435   _Jv_JVMTI_SetEventCallbacks,  // SetEventCallbacks
1436   UNIMPLEMENTED,                // GenerateEvents
1437   UNIMPLEMENTED,                // GetExtensionFunctions
1438   UNIMPLEMENTED,                // GetExtensionEvents
1439   UNIMPLEMENTED,                // SetExtensionEventCallback
1440   _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment
1441   _Jv_JVMTI_GetErrorName,       // GetErrorName
1442   UNIMPLEMENTED,                // GetJLocationFormat
1443   UNIMPLEMENTED,                // GetSystemProperties
1444   _Jv_JVMTI_GetSystemProperty,  // GetSystemProperty
1445   _Jv_JVMTI_SetSystemProperty,  // SetSystemProperty
1446   UNIMPLEMENTED,                // GetPhase
1447   UNIMPLEMENTED,                // GetCurrentThreadCpuTimerInfo
1448   UNIMPLEMENTED,                // GetCurrentThreadCpuTime
1449   UNIMPLEMENTED,                // GetThreadCpuTimerInfo
1450   UNIMPLEMENTED,                // GetThreadCpuTime
1451   UNIMPLEMENTED,                // GetTimerInfo
1452   _Jv_JVMTI_GetTime,            // GetTime
1453   UNIMPLEMENTED,                // GetPotentialCapabilities
1454   RESERVED,                     // reserved141
1455   UNIMPLEMENTED,                // AddCapabilities
1456   UNIMPLEMENTED,                // RelinquishCapabilities
1457   _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors
1458   RESERVED,                     // reserved145
1459   RESERVED,                     // reserved146
1460   UNIMPLEMENTED,                // GetEnvironmentLocalStorage
1461   UNIMPLEMENTED,                // SetEnvironmentLocalStorage
1462   _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch
1463   _Jv_JVMTI_SetVerboseFlag,     // SetVerboseFlag
1464   RESERVED,                     // reserved151
1465   RESERVED,                     // reserved152
1466   RESERVED,                     // reserved153
1467   _Jv_JVMTI_GetObjectSize       // GetObjectSize
1468 };
1469
1470 _Jv_JVMTIEnv *
1471 _Jv_GetJVMTIEnv (void)
1472 {
1473   _Jv_JVMTIEnv *env
1474     = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv));
1475   env->p = &_Jv_JVMTI_Interface;
1476
1477   {
1478     JvSynchronize dummy (_envListLock);
1479     struct jvmti_env_list *element
1480       = (struct jvmti_env_list *) _Jv_MallocUnchecked (sizeof (struct jvmti_env_list));
1481     element->env = env;
1482     element->next = NULL;
1483
1484     if (_jvmtiEnvironments == NULL)
1485       _jvmtiEnvironments = element;
1486     else
1487       {
1488         struct jvmti_env_list *e;
1489         for (e = _jvmtiEnvironments; e->next != NULL; e = e->next)
1490           ;
1491         e->next = element;
1492       }
1493   }
1494
1495   return env;
1496 }
1497
1498 void
1499 _Jv_JVMTI_Init ()
1500 {
1501   _jvmtiEnvironments = NULL;
1502   _envListLock = new java::lang::Object ();
1503
1504   // No environments, so this should set all JVMTI:: members to false
1505   check_enabled_events ();
1506 }
1507
1508 static void
1509 post_event (jvmtiEnv *env, jvmtiEvent type, jthread event_thread, va_list args)
1510 {
1511 #define ARG(Type,Name) Type Name = (Type) va_arg (args, Type)
1512
1513 #define GET_BOOLEAN_ARG(Name)                   \
1514   ARG (int, b);                                 \
1515   jboolean Name = (b == 0) ? false : true
1516
1517 #define GET_CHAR_ARG(Name)                      \
1518   ARG (int, c);                                 \
1519   char Name = static_cast<char> (c)
1520
1521   switch (type)
1522     {
1523     case JVMTI_EVENT_VM_INIT:
1524       if (env->callbacks.VMInit != NULL)
1525         {
1526           ARG (JNIEnv *, jni_env);
1527           env->callbacks.VMInit (env, jni_env, event_thread);
1528         }
1529       break;
1530
1531     case JVMTI_EVENT_VM_DEATH:
1532       if (env->callbacks.VMDeath != NULL)
1533         {
1534           ARG (JNIEnv *, jni_env);
1535           env->callbacks.VMDeath (env, jni_env);
1536         }
1537       break;
1538
1539     case JVMTI_EVENT_THREAD_START:
1540       if (env->callbacks.ThreadStart != NULL)
1541         {
1542           ARG (JNIEnv *, jni_env);
1543           env->callbacks.ThreadStart (env, jni_env, event_thread);
1544         }
1545       break;
1546
1547     case JVMTI_EVENT_THREAD_END:
1548       if (env->callbacks.ThreadEnd != NULL)
1549         {
1550           ARG (JNIEnv *, jni_env);
1551           env->callbacks.ThreadEnd (env, jni_env, event_thread);
1552         }
1553       break;
1554
1555     case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK:
1556       if (env->callbacks.ClassFileLoadHook != NULL)
1557         {
1558           ARG (JNIEnv *, jni_env);
1559           ARG (jclass, class_being_redefined);
1560           ARG (jobject, loader);
1561           ARG (const char *, name);
1562           ARG (jobject, protection_domain);
1563           ARG (jint, class_data_len);
1564           ARG (const unsigned char *, class_data);
1565           ARG (jint *, new_class_data_len);
1566           ARG (unsigned char **, new_class_data);
1567           env->callbacks.ClassFileLoadHook (env, jni_env,
1568                                             class_being_redefined, loader,
1569                                             name, protection_domain,
1570                                             class_data_len, class_data,
1571                                             new_class_data_len,
1572                                             new_class_data);
1573         }
1574       break;
1575
1576     case JVMTI_EVENT_CLASS_LOAD:
1577       if (env->callbacks.ClassLoad != NULL)
1578         {
1579           ARG (JNIEnv *, jni_env);
1580           ARG (jclass, klass);
1581           env->callbacks.ClassLoad (env, jni_env, event_thread, klass);
1582         }
1583       break;
1584
1585     case JVMTI_EVENT_CLASS_PREPARE:
1586       if (env->callbacks.ClassPrepare != NULL)
1587         {
1588           ARG (JNIEnv *, jni_env);
1589           ARG (jclass, klass);
1590           env->callbacks.ClassPrepare (env, jni_env, event_thread, klass);
1591         }
1592       break;
1593
1594     case JVMTI_EVENT_VM_START:
1595       if (env->callbacks.VMStart != NULL)
1596         {
1597           ARG (JNIEnv *, jni_env);
1598           env->callbacks.VMStart (env, jni_env);
1599         }
1600       break;
1601
1602     case JVMTI_EVENT_EXCEPTION:
1603       if (env->callbacks.Exception != NULL)
1604         {
1605           ARG (JNIEnv *, jni_env);
1606           ARG (jmethodID, method);
1607           ARG (jlocation, location);
1608           ARG (jobject, exception);
1609           ARG (jmethodID, catch_method);
1610           ARG (jlocation, catch_location);
1611           env->callbacks.Exception (env, jni_env, event_thread, method,
1612                                     location, exception, catch_method,
1613                                     catch_location);
1614         }
1615       break;
1616
1617     case JVMTI_EVENT_EXCEPTION_CATCH:
1618       if (env->callbacks.ExceptionCatch != NULL)
1619         {
1620           ARG (JNIEnv *, jni_env);
1621           ARG (jmethodID, method);
1622           ARG (jlocation, location);
1623           ARG (jobject, exception);
1624           env->callbacks.ExceptionCatch (env, jni_env, event_thread, method,
1625                                          location, exception);
1626         }
1627       break;
1628
1629     case JVMTI_EVENT_SINGLE_STEP:
1630       if (env->callbacks.SingleStep != NULL)
1631         {
1632           ARG (JNIEnv *, jni_env);
1633           ARG (jmethodID, method);
1634           ARG (jlocation, location);
1635           env->callbacks.SingleStep (env, jni_env, event_thread, method,
1636                                      location);
1637         }
1638       break;
1639
1640     case JVMTI_EVENT_FRAME_POP:
1641       if (env->callbacks.FramePop != NULL)
1642         {
1643           ARG (JNIEnv *, jni_env);
1644           ARG (jmethodID, method);
1645           GET_BOOLEAN_ARG (was_popped_by_exception);
1646           env->callbacks.FramePop (env, jni_env, event_thread, method,
1647                                    was_popped_by_exception);
1648         }
1649       break;
1650
1651     case JVMTI_EVENT_BREAKPOINT:
1652       if (env->callbacks.Breakpoint != NULL)
1653         {
1654           ARG (JNIEnv *, jni_env);
1655           ARG (jmethodID, method);
1656           ARG (jlocation, location);
1657           env->callbacks.Breakpoint (env, jni_env, event_thread, method,
1658                                      location);
1659         }
1660       break;
1661
1662     case JVMTI_EVENT_FIELD_ACCESS:
1663       if (env->callbacks.FieldAccess != NULL)
1664         {
1665           ARG (JNIEnv *, jni_env);
1666           ARG (jmethodID, method);
1667           ARG (jlocation, location);
1668           ARG (jclass, field_class);
1669           ARG (jobject, object);
1670           ARG (jfieldID, field);
1671           env->callbacks.FieldAccess (env, jni_env, event_thread, method,
1672                                       location, field_class, object, field);
1673         }
1674       break;
1675
1676     case JVMTI_EVENT_FIELD_MODIFICATION:
1677       if (env->callbacks.FieldModification != NULL)
1678         {
1679           ARG (JNIEnv *, jni_env);
1680           ARG (jmethodID, method);
1681           ARG (jlocation, location);
1682           ARG (jclass, field_class);
1683           ARG (jobject, object);
1684           ARG (jfieldID, field);
1685           GET_CHAR_ARG (signature_type);
1686           ARG (jvalue, new_value);
1687           env->callbacks.FieldModification (env, jni_env, event_thread, method,
1688                                             location, field_class, object,
1689                                             field, signature_type, new_value);
1690         }
1691       break;
1692
1693     case JVMTI_EVENT_METHOD_ENTRY:
1694       if (env->callbacks.MethodEntry != NULL)
1695         {
1696           ARG (JNIEnv *, jni_env);
1697           ARG (jmethodID, method);
1698           env->callbacks.MethodEntry (env, jni_env, event_thread, method);
1699         }
1700       break;
1701
1702     case JVMTI_EVENT_METHOD_EXIT:
1703       if (env->callbacks.MethodExit != NULL)
1704         {
1705           ARG (JNIEnv *, jni_env);
1706           ARG (jmethodID, method);
1707           GET_BOOLEAN_ARG (was_popped_by_exception);
1708           ARG (jvalue, return_value);
1709           env->callbacks.MethodExit (env, jni_env, event_thread, method,
1710                                      was_popped_by_exception, return_value);
1711         }
1712       break;
1713
1714     case JVMTI_EVENT_NATIVE_METHOD_BIND:
1715       if (env->callbacks.NativeMethodBind != NULL)
1716         {
1717           ARG (JNIEnv *, jni_env);
1718           ARG (jmethodID, method);
1719           ARG (void *, address);
1720           ARG (void **, new_address_ptr);
1721           env->callbacks.NativeMethodBind (env, jni_env, event_thread, method,
1722                                            address, new_address_ptr);
1723         }
1724       break;
1725
1726     case JVMTI_EVENT_COMPILED_METHOD_LOAD:
1727       if (env->callbacks.CompiledMethodLoad != NULL)
1728         {
1729           ARG (jmethodID, method);
1730           ARG (jint, code_size);
1731           ARG (const void *, code_addr);
1732           ARG (jint, map_length);
1733           ARG (const jvmtiAddrLocationMap *, map);
1734           ARG (const void *, compile_info);
1735           env->callbacks.CompiledMethodLoad (env, method, code_size, code_addr,
1736                                              map_length, map, compile_info);
1737         }
1738       break;
1739
1740     case JVMTI_EVENT_COMPILED_METHOD_UNLOAD:
1741       if (env->callbacks.CompiledMethodUnload != NULL)
1742         {
1743           ARG (jmethodID, method);
1744           ARG (const void *, code_addr);
1745           env->callbacks.CompiledMethodUnload (env, method, code_addr);
1746         }
1747       break;
1748
1749     case JVMTI_EVENT_DYNAMIC_CODE_GENERATED:
1750       if (env->callbacks.DynamicCodeGenerated != NULL)
1751         {
1752           ARG (const char *, name);
1753           ARG (const void *, address);
1754           ARG (jint, length);
1755           env->callbacks.DynamicCodeGenerated (env, name, address, length);
1756         }
1757       break;
1758
1759     case JVMTI_EVENT_DATA_DUMP_REQUEST:
1760       if (env->callbacks.DataDumpRequest != NULL)
1761         {
1762           env->callbacks.DataDumpRequest (env);
1763         }
1764       break;
1765
1766     case JVMTI_EVENT_MONITOR_WAIT:
1767       if (env->callbacks.MonitorWait != NULL)
1768         {
1769           ARG (JNIEnv *, jni_env);
1770           ARG (jobject, object);
1771           ARG (jlong, timeout);
1772           env->callbacks.MonitorWait (env, jni_env, event_thread, object,
1773                                       timeout);
1774         }
1775       break;
1776
1777     case JVMTI_EVENT_MONITOR_WAITED:
1778       if (env->callbacks.MonitorWaited != NULL)
1779         {
1780           ARG (JNIEnv *, jni_env);
1781           ARG (jobject, object);
1782           GET_BOOLEAN_ARG (timed_out);
1783           env->callbacks.MonitorWaited (env, jni_env, event_thread, object,
1784                                         timed_out);
1785         }
1786       break;
1787
1788     case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
1789       if (env->callbacks.MonitorContendedEnter != NULL)
1790         {
1791           ARG (JNIEnv *, jni_env);
1792           ARG (jobject, object);
1793           env->callbacks.MonitorContendedEnter (env, jni_env, event_thread,
1794                                                 object);
1795         }
1796       break;
1797
1798     case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
1799       if (env->callbacks.MonitorContendedEntered != NULL)
1800         {
1801           ARG (JNIEnv *, jni_env);
1802           ARG (jobject, object);
1803           env->callbacks.MonitorContendedEntered (env, jni_env, event_thread,
1804                                                   object);
1805         }
1806       break;
1807
1808     case JVMTI_EVENT_GARBAGE_COLLECTION_START:
1809       if (env->callbacks.GarbageCollectionStart != NULL)
1810         {
1811           env->callbacks.GarbageCollectionStart (env);
1812         }
1813       break;
1814
1815     case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
1816       if (env->callbacks.GarbageCollectionFinish != NULL)
1817         {
1818           env->callbacks.GarbageCollectionFinish (env);
1819         }
1820       break;
1821
1822     case JVMTI_EVENT_OBJECT_FREE:
1823       if (env->callbacks.ObjectFree != NULL)
1824         {
1825           ARG (jlong, tag);
1826           env->callbacks.ObjectFree (env, tag);
1827         }
1828       break;
1829
1830     case JVMTI_EVENT_VM_OBJECT_ALLOC:
1831       if (env->callbacks.VMObjectAlloc != NULL)
1832         {
1833           ARG (JNIEnv *, jni_env);
1834           ARG (jobject, object);
1835           ARG (jclass, object_class);
1836           ARG (jlong, size);
1837           env->callbacks.VMObjectAlloc (env, jni_env, event_thread,
1838                                         object, object_class, size);
1839         }
1840       break;
1841
1842     default:
1843       fprintf (stderr, "libgcj: post of unknown JVMTI event (%d)\n",
1844                (int) type);
1845       break;
1846     }
1847   va_end (args);
1848 #undef ARG
1849 #undef GET_BOOLEAN_ARG
1850 #undef GET_CHAR_ARG
1851 }
1852
1853 /* Post an event to requesting JVMTI environments
1854  *
1855  * This function should not be called without consulting the
1856  * JVMTI_REQUESTED_EVENT macro first (for speed). It does no real
1857  * harm (other than kill speed), since this function will still
1858  * only send the event if it was properly requested by an environment.
1859  */ 
1860 void
1861 _Jv_JVMTI_PostEvent (jvmtiEvent type, jthread event_thread, ...)
1862 {
1863   va_list args;
1864   va_start (args, event_thread);
1865
1866   JvSynchronize dummy (_envListLock);
1867   struct jvmti_env_list *e;
1868   FOREACH_ENVIRONMENT (e)
1869     {
1870       /* Events are only posted if the event was explicitly enabled,
1871          it has a registered event handler, and the event thread
1872          matches (either globally or restricted to a specific thread).
1873          Here we check all but the event handler, which will be handled
1874          by post_event. */
1875       if (e->env->enabled[EVENT_INDEX(type)]
1876           && (e->env->thread[EVENT_INDEX(type)] == NULL
1877               || e->env->thread[EVENT_INDEX(type)] == event_thread))
1878         {
1879           post_event (e->env, type, event_thread, args);
1880         }
1881     }
1882
1883   va_end (args);
1884 }