OSDN Git Service

* jvmti.cc (THREAD_DEFAULT_TO_CURRENT): Encapsulate in do..while loop.
[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 <jvmti.h>
18
19 #include <gcj/method.h>
20
21 #include <gnu/classpath/SystemProperties.h>
22 #include <gnu/gcj/runtime/BootClassLoader.h>
23 #include <java/lang/Class.h>
24 #include <java/lang/ClassLoader.h>
25 #include <java/lang/Object.h>
26 #include <java/lang/Thread.h>
27 #include <java/lang/Throwable.h>
28 #include <java/lang/VMClassLoader.h>
29 #include <java/lang/reflect/Field.h>
30 #include <java/lang/reflect/Modifier.h>
31 #include <java/util/Collection.h>
32 #include <java/util/HashMap.h>
33 #include <java/net/URL.h>
34
35 extern struct JNINativeInterface _Jv_JNIFunctions;
36
37 struct _Jv_rawMonitorID
38 {
39   _Jv_Mutex_t mutex;
40   _Jv_ConditionVariable_t condition;
41 };
42
43 /* A simple linked list of all JVMTI environments. Since
44    events must be delivered to environments in the order
45    in which the environments were created, new environments
46    are added to the end of the list. */
47 struct jvmti_env_list
48 {
49   jvmtiEnv *env;
50   struct jvmti_env_list *next;
51 };
52 static struct jvmti_env_list *_jvmtiEnvironments = NULL;
53 static java::lang::Object *_envListLock = NULL;
54 #define FOREACH_ENVIRONMENT(Ele) \
55   for (Ele = _jvmtiEnvironments; Ele != NULL; Ele = Ele->next)
56
57 // Some commonly-used checks
58
59 #define THREAD_DEFAULT_TO_CURRENT(jthread)              \
60   do                                                    \
61     {                                                   \
62       if (jthread == NULL)                              \
63         jthread = java::lang::Thread::currentThread (); \
64     }                                                   \
65   while (0)
66
67 #define THREAD_CHECK_VALID(jthread)                                     \
68   do                                                                    \
69     {                                                                   \
70       if (!java::lang::Thread::class$.isAssignableFrom (&(jthread->class$))) \
71         return JVMTI_ERROR_INVALID_THREAD;                              \
72     }                                                                   \
73   while (0)
74
75 #define THREAD_CHECK_IS_ALIVE(thread)        \
76   do                                         \
77     {                                        \
78       if (!thread->isAlive ())               \
79         return JVMTI_ERROR_THREAD_NOT_ALIVE; \
80     }                                        \
81   while (0)
82
83 // FIXME: if current phase is not set in Phases,
84 // return JVMTI_ERROR_WRONG_PHASE
85 #define REQUIRE_PHASE(Env, Phases)
86
87 #define NULL_CHECK(Ptr)                         \
88   do                                            \
89     {                                           \
90       if (Ptr == NULL)                          \
91         return JVMTI_ERROR_NULL_POINTER;        \
92     }                                           \
93   while (0)
94
95 #define ILLEGAL_ARGUMENT(Cond)                  \
96   do                                            \
97     {                                           \
98       if ((Cond))                               \
99         return JVMTI_ERROR_ILLEGAL_ARGUMENT;    \
100     }                                           \
101   while (0)
102
103 static jvmtiError JNICALL
104 _Jv_JVMTI_SuspendThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
105 {
106   using namespace java::lang;
107
108   THREAD_DEFAULT_TO_CURRENT (thread);
109   THREAD_CHECK_VALID (thread);
110
111   Thread *t = reinterpret_cast<Thread *> (thread);
112   THREAD_CHECK_IS_ALIVE (t);
113
114   _Jv_Thread_t *data = _Jv_ThreadGetData (t);
115   _Jv_SuspendThread (data);
116   return JVMTI_ERROR_NONE;
117 }
118
119 static jvmtiError JNICALL
120 _Jv_JVMTI_ResumeThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
121 {
122   using namespace java::lang;
123
124   THREAD_DEFAULT_TO_CURRENT (thread);
125   THREAD_CHECK_VALID (thread);
126
127   Thread *t = reinterpret_cast<Thread *> (thread);
128   THREAD_CHECK_IS_ALIVE (t);
129
130   _Jv_Thread_t *data = _Jv_ThreadGetData (t);
131   _Jv_ResumeThread (data);
132   return JVMTI_ERROR_NONE;
133 }
134
135 static jvmtiError JNICALL
136 _Jv_JVMTI_InterruptThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
137 {
138   using namespace java::lang;
139
140   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
141   // FIXME: capability handling?  'can_signal_thread'
142   if (thread == NULL)
143     return JVMTI_ERROR_INVALID_THREAD;
144   THREAD_CHECK_VALID (thread);
145   Thread *real_thread = reinterpret_cast<Thread *> (thread);
146   THREAD_CHECK_IS_ALIVE (real_thread);
147   real_thread->interrupt();
148   return JVMTI_ERROR_NONE;
149 }
150
151 static jvmtiError JNICALL
152 _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name,
153                             jrawMonitorID *result)
154 {
155   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
156   NULL_CHECK (name);
157   NULL_CHECK (result);
158   *result = (jrawMonitorID) _Jv_Malloc (sizeof (_Jv_rawMonitorID));
159   _Jv_MutexInit (&(*result)->mutex);
160   _Jv_CondInit (&(*result)->condition);
161   return JVMTI_ERROR_NONE;
162 }
163
164 static jvmtiError JNICALL
165 _Jv_JVMTI_DestroyRawMonitor (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
166 {
167   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
168   // Note we have no better way of knowing whether this object is
169   // really a raw monitor.
170   if (monitor == NULL)
171     return JVMTI_ERROR_INVALID_MONITOR;
172   // FIXME: perform checks on monitor, release it if this thread owns
173   // it.
174 #ifdef _Jv_HaveMutexDestroy
175   _Jv_MutexDestroy (&monitor->mutex);
176 #endif
177   _Jv_Free (monitor);
178   return JVMTI_ERROR_NONE;
179 }
180
181 static jvmtiError JNICALL
182 _Jv_JVMTI_RawMonitorEnter (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
183 {
184   if (monitor == NULL)
185     return JVMTI_ERROR_INVALID_MONITOR;
186   _Jv_MutexLock (&monitor->mutex);
187   return JVMTI_ERROR_NONE;
188 }
189
190 static jvmtiError JNICALL
191 _Jv_JVMTI_RawMonitorExit (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
192 {
193   if (monitor == NULL)
194     return JVMTI_ERROR_INVALID_MONITOR;
195   if (_Jv_MutexUnlock (&monitor->mutex))
196     return JVMTI_ERROR_NOT_MONITOR_OWNER;
197   return JVMTI_ERROR_NONE;
198 }
199
200 static jvmtiError JNICALL
201 _Jv_JVMTI_RawMonitorWait (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor,
202                           jlong millis)
203 {
204   if (monitor == NULL)
205     return JVMTI_ERROR_INVALID_MONITOR;
206   int r = _Jv_CondWait (&monitor->condition, &monitor->mutex, millis, 0);
207   if (r == _JV_NOT_OWNER)
208     return JVMTI_ERROR_NOT_MONITOR_OWNER;
209   if (r == _JV_INTERRUPTED)
210     return JVMTI_ERROR_INTERRUPT;
211   return JVMTI_ERROR_NONE;
212 }
213
214 static jvmtiError JNICALL
215 _Jv_JVMTI_RawMonitorNotify (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor)
216 {
217   if (monitor == NULL)
218     return JVMTI_ERROR_INVALID_MONITOR;
219   if (_Jv_CondNotify (&monitor->condition, &monitor->mutex) == _JV_NOT_OWNER)
220     return JVMTI_ERROR_NOT_MONITOR_OWNER;
221   return JVMTI_ERROR_NONE;
222 }
223
224 static jvmtiError JNICALL
225 _Jv_JVMTI_RawMonitorNotifyAll (MAYBE_UNUSED jvmtiEnv *env,
226                                jrawMonitorID monitor)
227 {
228   if (monitor == NULL)
229     return JVMTI_ERROR_INVALID_MONITOR;
230   if (_Jv_CondNotifyAll (&monitor->condition, &monitor->mutex)
231       == _JV_NOT_OWNER)
232     return JVMTI_ERROR_NOT_MONITOR_OWNER;
233   return JVMTI_ERROR_NONE;
234 }
235
236 static jvmtiError JNICALL
237 _Jv_JVMTI_Allocate (MAYBE_UNUSED jvmtiEnv *env, jlong size,
238                     unsigned char **result)
239 {
240   ILLEGAL_ARGUMENT (size < 0);
241   NULL_CHECK (result);
242   if (size == 0)
243     *result = NULL;
244   else
245     {
246       *result = (unsigned char *) _Jv_MallocUnchecked (size);
247       if (*result == NULL)
248         return JVMTI_ERROR_OUT_OF_MEMORY;
249     }
250   return JVMTI_ERROR_NONE;
251 }
252
253 static jvmtiError JNICALL
254 _Jv_JVMTI_Deallocate (MAYBE_UNUSED jvmtiEnv *env, unsigned char *mem)
255 {
256   if (mem != NULL)
257     _Jv_Free (mem);
258   return JVMTI_ERROR_NONE;
259 }
260
261 static jvmtiError JNICALL
262 _Jv_JVMTI_GetClassModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
263                              jint *mods)
264 {
265   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
266   // Don't bother checking KLASS' type.
267   if (klass == NULL)
268     return JVMTI_ERROR_INVALID_CLASS;
269   NULL_CHECK (mods);
270   *mods = klass->getModifiers();
271   return JVMTI_ERROR_NONE;
272 }
273
274 static jvmtiError JNICALL
275 _Jv_JVMTI_GetClassMethods (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
276                            jint *count_ptr, jmethodID **methods_ptr)
277 {
278   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
279   // FIXME: capability can_maintain_original_method_order
280   // Don't bother checking KLASS' type.
281   if (klass == NULL)
282     return JVMTI_ERROR_INVALID_CLASS;
283   NULL_CHECK (count_ptr);
284   NULL_CHECK (methods_ptr);
285   *count_ptr = JvNumMethods(klass);
286
287   *methods_ptr = (jmethodID *) _Jv_Malloc (*count_ptr * sizeof (jmethodID));
288   jmethodID start = JvGetFirstMethod (klass);
289   for (jint i = 0; i < *count_ptr; ++i)
290     // FIXME: correct?
291     (*methods_ptr)[i] = start + i;
292
293   return JVMTI_ERROR_NONE;
294 }
295
296 static jvmtiError JNICALL
297 _Jv_JVMTI_IsInterface (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
298                        jboolean *result)
299 {
300   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
301   if (klass == NULL)
302     return JVMTI_ERROR_INVALID_CLASS;
303   NULL_CHECK (result);
304   *result = klass->isInterface();
305   return JVMTI_ERROR_NONE;
306 }
307
308 static jvmtiError JNICALL
309 _Jv_JVMTI_IsArrayClass (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
310                         jboolean *result)
311 {
312   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
313   if (klass == NULL)
314     return JVMTI_ERROR_INVALID_CLASS;
315   NULL_CHECK (result);
316   *result = klass->isArray();
317   return JVMTI_ERROR_NONE;
318 }
319
320 static jvmtiError JNICALL
321 _Jv_JVMTI_GetClassLoader (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
322                           jobject *result)
323 {
324   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
325   if (klass == NULL)
326     return JVMTI_ERROR_INVALID_CLASS;
327   NULL_CHECK (result);
328   *result = klass->getClassLoaderInternal();
329   return JVMTI_ERROR_NONE;
330 }
331
332 static jvmtiError JNICALL
333 _Jv_JVMTI_GetObjectHashCode (MAYBE_UNUSED jvmtiEnv *env, jobject obj,
334                              jint *result)
335 {
336   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
337   if (obj == NULL)
338     return JVMTI_ERROR_INVALID_OBJECT;
339   NULL_CHECK (result);
340   *result = _Jv_HashCode (obj);
341   return JVMTI_ERROR_NONE;
342 }
343
344 static jvmtiError JNICALL
345 _Jv_JVMTI_GetFieldModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
346                              jfieldID field, jint *result)
347 {
348   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
349   if (klass == NULL)
350     return JVMTI_ERROR_INVALID_CLASS;
351   if (field == NULL)
352     return JVMTI_ERROR_INVALID_FIELDID;
353   NULL_CHECK (result);
354   *result = field->getModifiers();
355   return JVMTI_ERROR_NONE;
356 }
357
358 static jvmtiError JNICALL
359 _Jv_JVMTI_IsFieldSynthetic (MAYBE_UNUSED jvmtiEnv *env, jclass klass,
360                             jfieldID field, jboolean *result)
361 {
362   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
363   if (klass == NULL)
364     return JVMTI_ERROR_INVALID_CLASS;
365   if (field == NULL)
366     return JVMTI_ERROR_INVALID_FIELDID;
367   NULL_CHECK (result);
368
369   // FIXME: capability can_get_synthetic_attribute
370   *result = ((field->getModifiers() & java::lang::reflect::Modifier::SYNTHETIC)
371              != 0);
372   return JVMTI_ERROR_NONE;
373 }
374
375 static jvmtiError JNICALL
376 _Jv_JVMTI_GetMethodModifiers (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
377                               jint *result)
378 {
379   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
380   if (method == NULL)
381     return JVMTI_ERROR_INVALID_METHODID;
382   NULL_CHECK (result);
383
384   // FIXME: mask off some internal bits...
385   *result = method->accflags;
386   return JVMTI_ERROR_NONE;
387 }
388
389 static jvmtiError JNICALL
390 _Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
391                           jboolean *result)
392 {
393   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
394   if (method == NULL)
395     return JVMTI_ERROR_INVALID_METHODID;
396   NULL_CHECK (result);
397
398   *result = ((method->accflags & java::lang::reflect::Modifier::NATIVE) != 0);
399   return JVMTI_ERROR_NONE;
400 }
401
402 static jvmtiError JNICALL
403 _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
404                              jboolean *result)
405 {
406   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
407   if (method == NULL)
408     return JVMTI_ERROR_INVALID_METHODID;
409   NULL_CHECK (result);
410
411   // FIXME capability can_get_synthetic_attribute
412
413   *result = ((method->accflags & java::lang::reflect::Modifier::SYNTHETIC)
414              != 0);
415   return JVMTI_ERROR_NONE;
416 }
417
418 static jvmtiError JNICALL
419 _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env,
420                                  jobject init_loader,
421                                  jint *count_ptr,
422                                  jclass **result_ptr)
423 {
424   using namespace java::lang;
425   using namespace java::util;
426
427   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
428   NULL_CHECK (count_ptr);
429   NULL_CHECK (result_ptr);
430
431   ClassLoader *loader = (ClassLoader *) init_loader;
432   if (loader == NULL)
433     loader = VMClassLoader::bootLoader;
434
435   Collection *values = loader->loadedClasses->values();
436   jobjectArray array = values->toArray();
437   *count_ptr = array->length;
438   jobject *elts = elements (array);
439   jclass *result = (jclass *) _Jv_Malloc (*count_ptr * sizeof (jclass));
440   // FIXME: JNI references...
441   memcpy (result, elts, *count_ptr * sizeof (jclass));
442
443   *result_ptr = result;
444
445   return JVMTI_ERROR_NONE;
446 }
447
448 static jvmtiError JNICALL
449 _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env)
450 {
451   REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
452   _Jv_RunGC();
453   return JVMTI_ERROR_NONE;
454 }
455
456 static jvmtiError JNICALL
457 _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
458                                const jniNativeInterface *function_table)
459 {
460   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
461   NULL_CHECK (function_table);
462   memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface));
463   return JVMTI_ERROR_NONE;
464 }
465
466 static jvmtiError JNICALL
467 _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env,
468                                jniNativeInterface **function_table)
469 {
470   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
471   NULL_CHECK (function_table);
472   *function_table
473     = (jniNativeInterface *) _Jv_Malloc (sizeof (jniNativeInterface));
474   memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface));
475   return JVMTI_ERROR_NONE;
476 }
477
478 static jvmtiError JNICALL
479 _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env)
480 {
481   NULL_CHECK (env);
482
483   if (_jvmtiEnvironments == NULL)
484     return JVMTI_ERROR_INVALID_ENVIRONMENT;
485   else
486     {
487       JvSynchronize dummy (_envListLock);
488       if (_jvmtiEnvironments->env == env)
489         {
490           _Jv_Free (_jvmtiEnvironments);
491           _jvmtiEnvironments = _jvmtiEnvironments->next;
492         }
493       else
494         {
495           struct jvmti_env_list *e = _jvmtiEnvironments; 
496           while (e->next != NULL && e->next->env != env)
497             e = e->next;
498           if (e->next == NULL)
499             return JVMTI_ERROR_INVALID_ENVIRONMENT;
500
501           struct jvmti_env_list *next = e->next->next;
502           _Jv_Free (e->next);
503           e->next = next;
504         }
505     }
506
507   _Jv_Free (env);
508   return JVMTI_ERROR_NONE;
509 }
510
511 static jvmtiError JNICALL
512 _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
513                              char **result)
514 {
515   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE);
516   NULL_CHECK (property);
517   NULL_CHECK (result);
518
519   jstring name = JvNewStringUTF(property);
520   jstring result_str = gnu::classpath::SystemProperties::getProperty(name);
521
522   if (result_str == NULL)
523     return JVMTI_ERROR_NOT_AVAILABLE;
524
525   int len = JvGetStringUTFLength (result_str);
526   *result = (char *) _Jv_Malloc (len + 1);
527   JvGetStringUTFRegion (result_str, 0, result_str->length(), *result);
528   (*result)[len] = '\0';
529
530   return JVMTI_ERROR_NONE;
531 }
532
533 static jvmtiError JNICALL
534 _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property,
535                              const char *value)
536 {
537   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
538
539   NULL_CHECK (property);
540   if (value == NULL)
541     {
542       // FIXME: When would a property not be writeable?
543       return JVMTI_ERROR_NONE;
544     }
545
546   jstring prop_str = JvNewStringUTF(property);
547   jstring value_str = JvNewStringUTF(value);
548   gnu::classpath::SystemProperties::setProperty(prop_str, value_str);
549   return JVMTI_ERROR_NONE;
550 }
551
552 static jvmtiError JNICALL
553 _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr)
554 {
555   NULL_CHECK (nanos_ptr);
556   *nanos_ptr = _Jv_platform_nanotime();
557   return JVMTI_ERROR_NONE;
558 }
559
560 static jvmtiError JNICALL
561 _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env,
562                                   jint *nprocessors_ptr)
563 {
564   NULL_CHECK (nprocessors_ptr);
565 #ifdef _SC_NPROCESSORS_ONLN
566   *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN);
567 #else
568   *nprocessors_ptr = 1;
569 #endif
570   return JVMTI_ERROR_NONE;
571 }
572
573 static jvmtiError JNICALL
574 _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env,
575                                            const char *segment)
576 {
577   using namespace java::lang;
578   using namespace java::net;
579   using namespace gnu::gcj::runtime;
580
581   REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD);
582   NULL_CHECK (segment);
583
584   jstring str_segment = JvNewStringUTF(segment);
585   URL *url;
586   try
587     {
588       url = new URL(JvNewStringUTF("file"), NULL, str_segment);
589     }
590   catch (jthrowable ignore)
591     {
592       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
593     }
594
595   BootClassLoader *loader = VMClassLoader::bootLoader;
596   // Don't call this too early.
597   // assert (loader != NULL);
598   loader->addURL(url);
599   return JVMTI_ERROR_NONE;
600 }
601
602 static jvmtiError JNICALL
603 _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag,
604                           jboolean value)
605 {
606   switch (flag)
607     {
608     case JVMTI_VERBOSE_OTHER:
609     case JVMTI_VERBOSE_GC:
610     case JVMTI_VERBOSE_JNI:
611       // Ignore.
612       break;
613     case JVMTI_VERBOSE_CLASS:
614       gcj::verbose_class_flag = value;
615       break;
616     default:
617       return JVMTI_ERROR_ILLEGAL_ARGUMENT;
618     }
619   return JVMTI_ERROR_NONE;
620 }
621
622 static jvmtiError JNICALL
623 _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object,
624                          jlong *result)
625 {
626   REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
627   if (object == NULL)
628     return JVMTI_ERROR_INVALID_OBJECT;
629   NULL_CHECK (result);
630
631   jclass klass = object->getClass();
632   if (klass->isArray())
633     {
634       jclass comp = klass->getComponentType();
635       jint base
636         = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL,
637                                                                     klass->getComponentType());
638       // FIXME: correct for primitive types?
639       jint compSize = comp->size();
640       __JArray *array = (__JArray *) object;
641       *result = base + array->length * compSize;
642     }
643   else
644     {
645       // Note that if OBJECT is a String then it may (if
646       // str->data==str) take more space.  Do we care?
647       *result = klass->size();
648     }
649   return JVMTI_ERROR_NONE;
650 }
651
652 #define RESERVED NULL
653 #define UNIMPLEMENTED NULL
654
655 struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
656 {
657   RESERVED,                     // reserved1
658   UNIMPLEMENTED,                // SetEventNotification
659   RESERVED,                     // reserved3
660   UNIMPLEMENTED,                // GetAllThreads
661   _Jv_JVMTI_SuspendThread,      // SuspendThread
662   _Jv_JVMTI_ResumeThread,       // ResumeThread
663   UNIMPLEMENTED,                // StopThread
664   _Jv_JVMTI_InterruptThread,    // InterruptThread
665   UNIMPLEMENTED,                // GetThreadInfo
666   UNIMPLEMENTED,                // GetOwnedMonitorInfo
667   UNIMPLEMENTED,                // GetCurrentContendedMonitor
668   UNIMPLEMENTED,                // RunAgentThread
669   UNIMPLEMENTED,                // GetTopThreadGroups
670   UNIMPLEMENTED,                // GetThreadGroupInfo
671   UNIMPLEMENTED,                // GetThreadGroupChildren
672   UNIMPLEMENTED,                // GetFrameCount
673   UNIMPLEMENTED,                // GetThreadState
674   RESERVED,                     // reserved18
675   UNIMPLEMENTED,                // GetFrameLocation
676   UNIMPLEMENTED,                // NotifyPopFrame
677   UNIMPLEMENTED,                // GetLocalObject
678   UNIMPLEMENTED,                // GetLocalInt
679   UNIMPLEMENTED,                // GetLocalLong
680   UNIMPLEMENTED,                // GetLocalFloat
681   UNIMPLEMENTED,                // GetLocalDouble
682   UNIMPLEMENTED,                // SetLocalObject
683   UNIMPLEMENTED,                // SetLocalInt
684   UNIMPLEMENTED,                // SetLocalLong
685   UNIMPLEMENTED,                // SetLocalFloat
686   UNIMPLEMENTED,                // SetLocalDouble
687   _Jv_JVMTI_CreateRawMonitor,   // CreateRawMonitor
688   _Jv_JVMTI_DestroyRawMonitor,  // DestroyRawMonitor
689   _Jv_JVMTI_RawMonitorEnter,    // RawMonitorEnter
690   _Jv_JVMTI_RawMonitorExit,     // RawMonitorExit
691   _Jv_JVMTI_RawMonitorWait,     // RawMonitorWait
692   _Jv_JVMTI_RawMonitorNotify,   // RawMonitorNotify
693   _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll
694   UNIMPLEMENTED,                // SetBreakpoint
695   UNIMPLEMENTED,                // ClearBreakpoint
696   RESERVED,                     // reserved40
697   UNIMPLEMENTED,                // SetFieldAccessWatch
698   UNIMPLEMENTED,                // ClearFieldAccessWatch
699   UNIMPLEMENTED,                // SetFieldModificationWatch
700   UNIMPLEMENTED,                // ClearFieldModificationWatch
701   RESERVED,                     // reserved45
702   _Jv_JVMTI_Allocate,           // Allocate
703   _Jv_JVMTI_Deallocate,         // Deallocate
704   UNIMPLEMENTED,                // GetClassSignature
705   UNIMPLEMENTED,                // GetClassStatus
706   UNIMPLEMENTED,                // GetSourceFileName
707   _Jv_JVMTI_GetClassModifiers,  // GetClassModifiers
708   _Jv_JVMTI_GetClassMethods,    // GetClassMethods
709   UNIMPLEMENTED,                // GetClassFields
710   UNIMPLEMENTED,                // GetImplementedInterfaces
711   _Jv_JVMTI_IsInterface,        // IsInterface
712   _Jv_JVMTI_IsArrayClass,       // IsArrayClass
713   _Jv_JVMTI_GetClassLoader,     // GetClassLoader
714   _Jv_JVMTI_GetObjectHashCode,  // GetObjectHashCode
715   UNIMPLEMENTED,                // GetObjectMonitorUsage
716   UNIMPLEMENTED,                // GetFieldName
717   UNIMPLEMENTED,                // GetFieldDeclaringClass
718   _Jv_JVMTI_GetFieldModifiers,  // GetFieldModifiers
719   _Jv_JVMTI_IsFieldSynthetic,   // IsFieldSynthetic
720   UNIMPLEMENTED,                // GetMethodName
721   UNIMPLEMENTED,                // GetMethodDeclaringClass
722   _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers
723   RESERVED,                     // reserved67
724   UNIMPLEMENTED,                // GetMaxLocals
725   UNIMPLEMENTED,                // GetArgumentsSize
726   UNIMPLEMENTED,                // GetLineNumberTable
727   UNIMPLEMENTED,                // GetMethodLocation
728   UNIMPLEMENTED,                // GetLocalVariableTable
729   RESERVED,                     // reserved73
730   RESERVED,                     // reserved74
731   UNIMPLEMENTED,                // GetBytecodes
732   _Jv_JVMTI_IsMethodNative,     // IsMethodNative
733   _Jv_JVMTI_IsMethodSynthetic,  // IsMethodSynthetic
734   UNIMPLEMENTED,                // GetLoadedClasses
735   _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses
736   UNIMPLEMENTED,                // PopFrame
737   RESERVED,                     // reserved81
738   RESERVED,                     // reserved82
739   RESERVED,                     // reserved83
740   RESERVED,                     // reserved84
741   RESERVED,                     // reserved85
742   RESERVED,                     // reserved86
743   UNIMPLEMENTED,                // RedefineClasses
744   UNIMPLEMENTED,                // GetVersionNumber
745   UNIMPLEMENTED,                // GetCapabilities
746   UNIMPLEMENTED,                // GetSourceDebugExtension
747   UNIMPLEMENTED,                // IsMethodObsolete
748   UNIMPLEMENTED,                // SuspendThreadList
749   UNIMPLEMENTED,                // ResumeThreadList
750   RESERVED,                     // reserved94
751   RESERVED,                     // reserved95
752   RESERVED,                     // reserved96
753   RESERVED,                     // reserved97
754   RESERVED,                     // reserved98
755   RESERVED,                     // reserved99
756   UNIMPLEMENTED,                // GetAllStackTraces
757   UNIMPLEMENTED,                // GetThreadListStackTraces
758   UNIMPLEMENTED,                // GetThreadLocalStorage
759   UNIMPLEMENTED,                // SetThreadLocalStorage
760   UNIMPLEMENTED,                // GetStackTrace
761   RESERVED,                     // reserved105
762   UNIMPLEMENTED,                // GetTag
763   UNIMPLEMENTED,                // SetTag
764   _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection
765   UNIMPLEMENTED,                // IterateOverObjectsReachable
766   UNIMPLEMENTED,                // IterateOverReachableObjects
767   UNIMPLEMENTED,                // IterateOverHeap
768   UNIMPLEMENTED,                // IterateOverInstanceOfClass
769   RESERVED,                     // reserved113
770   UNIMPLEMENTED,                // GetObjectsWithTags
771   RESERVED,                     // reserved115
772   RESERVED,                     // reserved116
773   RESERVED,                     // reserved117
774   RESERVED,                     // reserved118
775   RESERVED,                     // reserved119
776   _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable
777   _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable
778   UNIMPLEMENTED,                // SetEventCallbacks
779   UNIMPLEMENTED,                // GenerateEvents
780   UNIMPLEMENTED,                // GetExtensionFunctions
781   UNIMPLEMENTED,                // GetExtensionEvents
782   UNIMPLEMENTED,                // SetExtensionEventCallback
783   _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment
784   UNIMPLEMENTED,                // GetErrorName
785   UNIMPLEMENTED,                // GetJLocationFormat
786   UNIMPLEMENTED,                // GetSystemProperties
787   _Jv_JVMTI_GetSystemProperty,  // GetSystemProperty
788   _Jv_JVMTI_SetSystemProperty,  // SetSystemProperty
789   UNIMPLEMENTED,                // GetPhase
790   UNIMPLEMENTED,                // GetCurrentThreadCpuTimerInfo
791   UNIMPLEMENTED,                // GetCurrentThreadCpuTime
792   UNIMPLEMENTED,                // GetThreadCpuTimerInfo
793   UNIMPLEMENTED,                // GetThreadCpuTime
794   UNIMPLEMENTED,                // GetTimerInfo
795   _Jv_JVMTI_GetTime,            // GetTime
796   UNIMPLEMENTED,                // GetPotentialCapabilities
797   RESERVED,                     // reserved141
798   UNIMPLEMENTED,                // AddCapabilities
799   UNIMPLEMENTED,                // RelinquishCapabilities
800   _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors
801   RESERVED,                     // reserved145
802   RESERVED,                     // reserved146
803   UNIMPLEMENTED,                // GetEnvironmentLocalStorage
804   UNIMPLEMENTED,                // SetEnvironmentLocalStorage
805   _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch
806   _Jv_JVMTI_SetVerboseFlag,     // SetVerboseFlag
807   RESERVED,                     // reserved151
808   RESERVED,                     // reserved152
809   RESERVED,                     // reserved153
810   _Jv_JVMTI_GetObjectSize       // GetObjectSize
811 };
812
813 _Jv_JVMTIEnv *
814 _Jv_GetJVMTIEnv (void)
815 {
816   _Jv_JVMTIEnv *env
817     = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv));
818   env->p = &_Jv_JVMTI_Interface;
819
820   {
821     JvSynchronize dummy (_envListLock);
822     struct jvmti_env_list *element
823       = (struct jvmti_env_list *) _Jv_MallocUnchecked (sizeof (struct jvmti_env_list));
824     element->env = env;
825     element->next = NULL;
826
827     if (_jvmtiEnvironments == NULL)
828       _jvmtiEnvironments = element;
829     else
830       {
831         struct jvmti_env_list *e;
832         for (e = _jvmtiEnvironments; e->next != NULL; e = e->next)
833           ;
834         e->next = element;
835       }
836   }
837
838   return env;
839 }
840
841 void
842 _Jv_JVMTI_Init ()
843 {
844   _jvmtiEnvironments = NULL;
845   _envListLock = new java::lang::Object ();
846 }