jamvm
view src/natives.c @ 404:f70700d622a8
Load libjava.so when using OpenJDK.
2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* src/natives.c:
Add support for OpenJDK loading of libjava.so.
2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* src/natives.c:
Add support for OpenJDK loading of libjava.so.
| author | andrew |
|---|---|
| date | Tue Aug 05 06:07:38 2008 +0100 (2008-08-05) |
| parents | 907df5a02819 |
| children | 2f855beaaf73 |
line source
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
3 * Robert Lougher <rob@lougher.org.uk>.
4 *
5 * This file is part of JamVM.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
22 #ifdef NO_JNI
23 #error to use classpath, Jam must be compiled with JNI!
24 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <errno.h>
32 #include "jam.h"
33 #include "alloc.h"
34 #include "thread.h"
35 #include "lock.h"
36 #include "natives.h"
37 #include "symbol.h"
38 #include "excep.h"
40 /* Trace native method handling */
41 #ifdef TRACENATIVE
42 #define TRACE(fmt, ...) jam_printf(fmt, ## __VA_ARGS__)
43 #define TRACE(fmt, ...)
44 #endif
46 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
47 static int pd_offset;
48 #endif
50 void initialiseNatives() {
51 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
52 FieldBlock *pd = findField(java_lang_Class, SYMBOL(pd),
53 SYMBOL(sig_java_security_ProtectionDomain));
55 if(pd == NULL) {
56 jam_fprintf(stderr, "Error initialising VM (initialiseNatives)\n");
57 exitVM(1);
58 }
59 pd_offset = pd->offset;
60 #elif WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
61 char *name = getDllName("java");
62 char *bootpath = getBootDllPath();
63 char *buff = sysMalloc(strlen(name) + strlen(bootpath) + 2);
64 sprintf(buff, "%s/%s", bootpath, name);
65 resolveDll(buff, NULL);
66 sysFree(buff);
67 #endif
68 }
70 /* java.lang.VMObject */
72 uintptr_t *getClass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
73 Object *ob = (Object*)*ostack;
74 *ostack++ = (uintptr_t)ob->class;
75 return ostack;
76 }
78 uintptr_t *jamClone(Class *class, MethodBlock *mb, uintptr_t *ostack) {
79 Object *ob = (Object*)*ostack;
80 *ostack++ = (uintptr_t)cloneObject(ob);
81 return ostack;
82 }
84 /* static method wait(Ljava/lang/Object;JI)V */
85 uintptr_t *jamWait(Class *class, MethodBlock *mb, uintptr_t *ostack) {
86 Object *obj = (Object *)ostack[0];
87 long long ms = *((long long *)&ostack[1]);
88 int ns = ostack[3];
90 objectWait(obj, ms, ns);
91 return ostack;
92 }
94 /* static method notify(Ljava/lang/Object;)V */
95 uintptr_t *notify(Class *class, MethodBlock *mb, uintptr_t *ostack) {
96 Object *obj = (Object *)*ostack;
97 objectNotify(obj);
98 return ostack;
99 }
101 /* static method notifyAll(Ljava/lang/Object;)V */
102 uintptr_t *notifyAll(Class *class, MethodBlock *mb, uintptr_t *ostack) {
103 Object *obj = (Object *)*ostack;
104 objectNotifyAll(obj);
105 return ostack;
106 }
108 /* java.lang.VMSystem */
110 /* arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V */
111 uintptr_t *arraycopy(Class *class, MethodBlock *mb, uintptr_t *ostack) {
112 Object *src = (Object *)ostack[0];
113 int start1 = ostack[1];
114 Object *dest = (Object *)ostack[2];
115 int start2 = ostack[3];
116 int length = ostack[4];
118 if((src == NULL) || (dest == NULL))
119 signalException(java_lang_NullPointerException, NULL);
120 else {
121 ClassBlock *scb = CLASS_CB(src->class);
122 ClassBlock *dcb = CLASS_CB(dest->class);
123 char *sdata = ARRAY_DATA(src);
124 char *ddata = ARRAY_DATA(dest);
126 if((scb->name[0] != '[') || (dcb->name[0] != '['))
127 goto storeExcep;
129 if((start1 < 0) || (start2 < 0) || (length < 0)
130 || ((start1 + length) > ARRAY_LEN(src))
131 || ((start2 + length) > ARRAY_LEN(dest))) {
132 signalException(java_lang_ArrayIndexOutOfBoundsException, NULL);
133 return ostack;
134 }
136 if(isInstanceOf(dest->class, src->class)) {
137 int size;
139 switch(scb->name[1]) {
140 case 'B':
141 case 'Z':
142 size = 1;
143 break;
144 case 'C':
145 case 'S':
146 size = 2;
147 break;
148 case 'I':
149 case 'F':
150 size = 4;
151 break;
152 case 'L':
153 case '[':
154 size = sizeof(Object*);
155 break;
156 case 'J':
157 case 'D':
158 default:
159 size = 8;
160 break;
161 }
163 memmove(ddata + start2*size, sdata + start1*size, length*size);
164 } else {
165 Object **sob, **dob;
166 int i;
168 if(!(((scb->name[1] == 'L') || (scb->name[1] == '[')) &&
169 ((dcb->name[1] == 'L') || (dcb->name[1] == '['))))
170 goto storeExcep;
172 /* Not compatible array types, but elements may be compatible...
173 e.g. src = [Ljava/lang/Object, dest = [Ljava/lang/String, but
174 all src = Strings - check one by one...
175 */
177 if(scb->dim > dcb->dim)
178 goto storeExcep;
180 sob = &((Object**)sdata)[start1];
181 dob = &((Object**)ddata)[start2];
183 for(i = 0; i < length; i++) {
184 if((*sob != NULL) && !arrayStoreCheck(dest->class, (*sob)->class))
185 goto storeExcep;
186 *dob++ = *sob++;
187 }
188 }
189 }
190 return ostack;
192 storeExcep:
193 signalException(java_lang_ArrayStoreException, NULL);
194 return ostack;
195 }
197 uintptr_t *identityHashCode(Class *class, MethodBlock *mb, uintptr_t *ostack) {
198 Object *ob = (Object*)*ostack;
199 uintptr_t addr = ob == NULL ? 0 : getObjectHashcode(ob);
201 *ostack++ = addr & 0xffffffff;
202 return ostack;
203 }
205 /* java.lang.VMRuntime */
207 uintptr_t *availableProcessors(Class *class, MethodBlock *mb, uintptr_t *ostack) {
208 *ostack++ = nativeAvailableProcessors();
209 return ostack;
210 }
212 uintptr_t *freeMemory(Class *class, MethodBlock *mb, uintptr_t *ostack) {
213 *(u8*)ostack = freeHeapMem();
214 return ostack + 2;
215 }
217 uintptr_t *totalMemory(Class *class, MethodBlock *mb, uintptr_t *ostack) {
218 *(u8*)ostack = totalHeapMem();
219 return ostack + 2;
220 }
222 uintptr_t *maxMemory(Class *class, MethodBlock *mb, uintptr_t *ostack) {
223 *(u8*)ostack = maxHeapMem();
224 return ostack + 2;
225 }
227 uintptr_t *gc(Class *class, MethodBlock *mb, uintptr_t *ostack) {
228 gc1();
229 return ostack;
230 }
232 uintptr_t *runFinalization(Class *class, MethodBlock *mb, uintptr_t *ostack) {
233 runFinalizers();
234 return ostack;
235 }
237 uintptr_t *exitInternal(Class *class, MethodBlock *mb, uintptr_t *ostack) {
238 int status = ostack[0];
239 jamvm_exit(status);
240 /* keep compiler happy */
241 return 0;
242 }
244 uintptr_t *nativeLoad(Class *class, MethodBlock *mb, uintptr_t *ostack) {
245 char *name = String2Cstr((Object*)ostack[0]);
246 Object *class_loader = (Object *)ostack[1];
248 ostack[0] = resolveDll(name, class_loader);
249 sysFree(name);
251 return ostack+1;
252 }
254 uintptr_t *mapLibraryName(Class *class, MethodBlock *mb, uintptr_t *ostack) {
255 char *name = String2Cstr((Object*)ostack[0]);
256 char *lib = getDllName(name);
257 sysFree(name);
259 *ostack++ = (uintptr_t)Cstr2String(lib);
260 sysFree(lib);
262 return ostack;
263 }
265 uintptr_t *propertiesPreInit(Class *class, MethodBlock *mb, uintptr_t *ostack) {
266 Object *properties = (Object *)*ostack;
267 addDefaultProperties(properties);
268 return ostack;
269 }
271 uintptr_t *propertiesPostInit(Class *class, MethodBlock *mb, uintptr_t *ostack) {
272 Object *properties = (Object *)*ostack;
273 addCommandLineProperties(properties);
274 return ostack;
275 }
277 /* java.lang.VMClass */
279 #define GET_CLASS(vmClass) (Class*)vmClass
281 uintptr_t *isInstance(Class *class, MethodBlock *mb, uintptr_t *ostack) {
282 Class *clazz = GET_CLASS(ostack[0]);
283 Object *ob = (Object*)ostack[1];
285 *ostack++ = ob == NULL ? FALSE : (uintptr_t)isInstanceOf(clazz, ob->class);
286 return ostack;
287 }
289 uintptr_t *isAssignableFrom(Class *class, MethodBlock *mb, uintptr_t *ostack) {
290 Class *clazz = GET_CLASS(ostack[0]);
291 Class *clazz2 = (Class*)ostack[1];
293 if(clazz2 == NULL)
294 signalException(java_lang_NullPointerException, NULL);
295 else
296 *ostack++ = (uintptr_t)isInstanceOf(clazz, clazz2);
298 return ostack;
299 }
301 uintptr_t *isInterface(Class *class, MethodBlock *mb, uintptr_t *ostack) {
302 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
303 *ostack++ = IS_INTERFACE(cb) ? TRUE : FALSE;
304 return ostack;
305 }
307 uintptr_t *isPrimitive(Class *class, MethodBlock *mb, uintptr_t *ostack) {
308 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
309 *ostack++ = IS_PRIMITIVE(cb) ? TRUE : FALSE;
310 return ostack;
311 }
313 uintptr_t *isArray(Class *class, MethodBlock *mb, uintptr_t *ostack) {
314 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
315 *ostack++ = IS_ARRAY(cb) ? TRUE : FALSE;
316 return ostack;
317 }
319 uintptr_t *isMember(Class *class, MethodBlock *mb, uintptr_t *ostack) {
320 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
321 *ostack++ = IS_MEMBER(cb) ? TRUE : FALSE;
322 return ostack;
323 }
325 uintptr_t *isLocal(Class *class, MethodBlock *mb, uintptr_t *ostack) {
326 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
327 *ostack++ = IS_LOCAL(cb) ? TRUE : FALSE;
328 return ostack;
329 }
331 uintptr_t *isAnonymous(Class *class, MethodBlock *mb, uintptr_t *ostack) {
332 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
333 *ostack++ = IS_ANONYMOUS(cb) ? TRUE : FALSE;
334 return ostack;
335 }
337 uintptr_t *getEnclosingClass0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
338 Class *clazz = GET_CLASS(ostack[0]);
339 *ostack++ = (uintptr_t) getEnclosingClass(clazz);
340 return ostack;
341 }
343 uintptr_t *getEnclosingMethod0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
344 Class *clazz = GET_CLASS(ostack[0]);
345 *ostack++ = (uintptr_t) getEnclosingMethodObject(clazz);
346 return ostack;
347 }
349 uintptr_t *getEnclosingConstructor(Class *class, MethodBlock *mb, uintptr_t *ostack) {
350 Class *clazz = GET_CLASS(ostack[0]);
351 *ostack++ = (uintptr_t) getEnclosingConstructorObject(clazz);
352 return ostack;
353 }
355 uintptr_t *getClassSignature(Class *class, MethodBlock *mb, uintptr_t *ostack) {
356 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
357 Object *string = NULL;
359 if(cb->signature != NULL) {
360 char *dot_name = slash2dots(cb->signature);
361 string = createString(dot_name);
362 sysFree(dot_name);
363 }
365 *ostack++ = (uintptr_t)string;
366 return ostack;
367 }
369 uintptr_t *getSuperclass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
370 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
371 *ostack++ = (uintptr_t) (IS_PRIMITIVE(cb) || IS_INTERFACE(cb) ? NULL : cb->super);
372 return ostack;
373 }
375 uintptr_t *getComponentType(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
376 Class *class = GET_CLASS(ostack[0]);
377 ClassBlock *cb = CLASS_CB(class);
378 Class *componentType = NULL;
380 if(IS_ARRAY(cb))
381 switch(cb->name[1]) {
382 case '[':
383 componentType = findArrayClassFromClass(&cb->name[1], class);
384 break;
386 default:
387 componentType = cb->element_class;
388 break;
389 }
391 *ostack++ = (uintptr_t) componentType;
392 return ostack;
393 }
395 uintptr_t *getName(Class *class, MethodBlock *mb, uintptr_t *ostack) {
396 char *dot_name = slash2dots(CLASS_CB((GET_CLASS(*ostack)))->name);
397 Object *string = createString(dot_name);
398 *ostack++ = (uintptr_t)string;
399 sysFree(dot_name);
400 return ostack;
401 }
403 uintptr_t *getDeclaredClasses(Class *class, MethodBlock *mb, uintptr_t *ostack) {
404 Class *clazz = GET_CLASS(ostack[0]);
405 int public = ostack[1];
406 *ostack++ = (uintptr_t) getClassClasses(clazz, public);
407 return ostack;
408 }
410 uintptr_t *getDeclaringClass0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
411 Class *clazz = GET_CLASS(ostack[0]);
412 *ostack++ = (uintptr_t) getDeclaringClass(clazz);
413 return ostack;
414 }
416 uintptr_t *getDeclaredConstructors(Class *class, MethodBlock *mb, uintptr_t *ostack) {
417 Class *clazz = GET_CLASS(ostack[0]);
418 int public = ostack[1];
419 *ostack++ = (uintptr_t) getClassConstructors(clazz, public);
420 return ostack;
421 }
423 uintptr_t *getDeclaredMethods(Class *class, MethodBlock *mb, uintptr_t *ostack) {
424 Class *clazz = GET_CLASS(ostack[0]);
425 int public = ostack[1];
426 *ostack++ = (uintptr_t) getClassMethods(clazz, public);
427 return ostack;
428 }
430 uintptr_t *getDeclaredFields(Class *class, MethodBlock *mb, uintptr_t *ostack) {
431 Class *clazz = GET_CLASS(ostack[0]);
432 int public = ostack[1];
433 *ostack++ = (uintptr_t) getClassFields(clazz, public);
434 return ostack;
435 }
437 uintptr_t *getClassDeclaredAnnotations(Class *class, MethodBlock *mb, uintptr_t *ostack) {
438 Class *clazz = GET_CLASS(ostack[0]);
439 *ostack++ = (uintptr_t) getClassAnnotations(clazz);
440 return ostack;
441 }
443 uintptr_t *getInterfaces(Class *class, MethodBlock *mb, uintptr_t *ostack) {
444 Class *clazz = GET_CLASS(ostack[0]);
445 *ostack++ = (uintptr_t) getClassInterfaces(clazz);
446 return ostack;
447 }
449 uintptr_t *getClassLoader(Class *class, MethodBlock *mb, uintptr_t *ostack) {
450 Class *clazz = GET_CLASS(*ostack);
451 *ostack++ = (uintptr_t)CLASS_CB(clazz)->class_loader;
452 return ostack;
453 }
455 uintptr_t *getClassModifiers(Class *class, MethodBlock *mb, uintptr_t *ostack) {
456 Class *clazz = GET_CLASS(ostack[0]);
457 int ignore_inner_attrs = ostack[1];
458 ClassBlock *cb = CLASS_CB(clazz);
460 if(!ignore_inner_attrs && cb->declaring_class)
461 *ostack++ = (uintptr_t)cb->inner_access_flags;
462 else
463 *ostack++ = (uintptr_t)cb->access_flags;
465 return ostack;
466 }
468 uintptr_t *forName0(uintptr_t *ostack, int resolve, Object *loader) {
469 Object *string = (Object *)ostack[0];
470 Class *class = NULL;
471 int len, i = 0;
472 char *cstr;
474 if(string == NULL) {
475 signalException(java_lang_NullPointerException, NULL);
476 return ostack;
477 }
479 cstr = String2Utf8(string);
480 len = strlen(cstr);
482 /* Check the classname to see if it's valid. It can be
483 a 'normal' class or an array class, starting with a [ */
485 if(cstr[0] == '[') {
486 for(; cstr[i] == '['; i++);
487 switch(cstr[i]) {
488 case 'Z':
489 case 'B':
490 case 'C':
491 case 'S':
492 case 'I':
493 case 'F':
494 case 'J':
495 case 'D':
496 if(len-i != 1)
497 goto out;
498 break;
499 case 'L':
500 if(cstr[i+1] == '[' || cstr[len-1] != ';')
501 goto out;
502 break;
503 default:
504 goto out;
505 break;
506 }
507 }
509 /* Scan the classname and convert it to internal form
510 by converting dots to slashes. Reject classnames
511 containing slashes, as this is an invalid character */
513 for(; i < len; i++) {
514 if(cstr[i] == '/')
515 goto out;
516 if(cstr[i] == '.')
517 cstr[i] = '/';
518 }
520 class = findClassFromClassLoader(cstr, loader);
522 out:
523 if(class == NULL) {
524 Object *e = exceptionOccurred();
525 clearException();
526 signalChainedException(java_lang_ClassNotFoundException, cstr, e);
527 } else
528 if(resolve)
529 initClass(class);
531 sysFree(cstr);
532 *ostack++ = (uintptr_t)class;
533 return ostack;
534 }
536 uintptr_t *forName(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
537 int init = ostack[1];
538 Object *loader = (Object*)ostack[2];
539 return forName0(ostack, init, loader);
540 }
542 uintptr_t *throwException(Class *class, MethodBlock *mb, uintptr_t *ostack) {
543 Object *excep = (Object *)ostack[0];
544 setException(excep);
545 return ostack;
546 }
548 uintptr_t *hasClassInitializer(Class *class, MethodBlock *mb, uintptr_t *ostack) {
549 Class *clazz = (Class*)ostack[0];
550 *ostack++ = findMethod(clazz, SYMBOL(class_init),
551 SYMBOL(___V)) == NULL ? FALSE : TRUE;
552 return ostack;
553 }
555 /* java.lang.VMThrowable */
557 uintptr_t *fillInStackTrace(Class *class, MethodBlock *mb, uintptr_t *ostack) {
558 *ostack++ = (uintptr_t) setStackTrace();
559 return ostack;
560 }
562 uintptr_t *getStackTrace(Class *class, MethodBlock *m, uintptr_t *ostack) {
563 Object *this = (Object *)*ostack;
564 *ostack++ = (uintptr_t) convertStackTrace(this);
565 return ostack;
566 }
568 /* gnu.classpath.VMStackWalker */
570 uintptr_t *getCallingClass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
571 *ostack++ = (uintptr_t) getCallerCallerClass();
572 return ostack;
573 }
575 uintptr_t *getCallingClassLoader(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
576 Class *class = getCallerCallerClass();
578 *ostack++ = (uintptr_t) (class ? CLASS_CB(class)->class_loader : NULL);
579 return ostack;
580 }
582 uintptr_t *getClassContext(Class *class, MethodBlock *mb, uintptr_t *ostack) {
583 Class *class_class = findArrayClass("[Ljava/lang/Class;");
584 Object *array;
585 Frame *last;
587 if(class_class == NULL)
588 return ostack;
590 if((last = getCallerFrame(getExecEnv()->last_frame)) == NULL)
591 array = allocArray(class_class, 0, sizeof(Class*));
592 else {
593 Frame *bottom = last;
594 int depth = 0;
596 do {
597 for(; last->mb != NULL; last = last->prev, depth++);
598 } while((last = last->prev)->prev != NULL);
600 array = allocArray(class_class, depth, sizeof(Class*));
602 if(array != NULL) {
603 Class **data = ARRAY_DATA(array);
605 do {
606 for(; bottom->mb != NULL; bottom = bottom->prev)
607 *data++ = bottom->mb->class;
608 } while((bottom = bottom->prev)->prev != NULL);
609 }
610 }
612 *ostack++ = (uintptr_t)array;
613 return ostack;
614 }
616 uintptr_t *firstNonNullClassLoader(Class *class, MethodBlock *mb, uintptr_t *ostack) {
617 Frame *last = getExecEnv()->last_frame;
618 Object *loader = NULL;
620 do {
621 for(; last->mb != NULL; last = last->prev)
622 if((loader = CLASS_CB(last->mb->class)->class_loader) != NULL)
623 goto out;
624 } while((last = last->prev)->prev != NULL);
626 out:
627 *ostack++ = (uintptr_t)loader;
628 return ostack;
629 }
631 /* java.lang.VMClassLoader */
633 /* loadClass(Ljava/lang/String;I)Ljava/lang/Class; */
634 uintptr_t *loadClass(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
635 int resolve = ostack[1];
636 return forName0(ostack, resolve, NULL);
637 }
639 /* getPrimitiveClass(C)Ljava/lang/Class; */
640 uintptr_t *getPrimitiveClass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
641 char prim_type = *ostack;
642 *ostack++ = (uintptr_t)findPrimitiveClass(prim_type);
643 return ostack;
644 }
646 uintptr_t *defineClass0(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
647 Object *class_loader = (Object *)ostack[0];
648 Object *string = (Object *)ostack[1];
649 Object *array = (Object *)ostack[2];
650 int offset = ostack[3];
651 int data_len = ostack[4];
652 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
653 uintptr_t pd = ostack[5];
654 #elif WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
655 Object* pd = ostack[5];
656 #endif
657 Class *class = NULL;
659 if(array == NULL)
660 signalException(java_lang_NullPointerException, NULL);
661 else
662 if((offset < 0) || (data_len < 0) ||
663 ((offset + data_len) > ARRAY_LEN(array)))
664 signalException(java_lang_ArrayIndexOutOfBoundsException, NULL);
665 else {
666 char *data = ARRAY_DATA(array);
667 char *cstr = string ? String2Utf8(string) : NULL;
668 int len = string ? strlen(cstr) : 0;
669 int i;
671 for(i = 0; i < len; i++)
672 if(cstr[i]=='.') cstr[i]='/';
674 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
675 if((class = defineClass(cstr, data, offset, data_len, class_loader, NULL)) != NULL) {
676 INST_DATA(class)[pd_offset] = pd;
677 #elif WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
678 if((class = defineClass(cstr, data, offset, data_len, class_loader, pd)) != NULL) {
679 #endif
680 linkClass(class);
681 }
683 sysFree(cstr);
684 }
686 *ostack++ = (uintptr_t) class;
687 return ostack;
688 }
690 uintptr_t *findLoadedClass(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
691 Object *class_loader = (Object *)ostack[0];
692 Object *string = (Object *)ostack[1];
693 Class *class;
694 char *cstr;
695 int len, i;
697 if(string == NULL) {
698 signalException(java_lang_NullPointerException, NULL);
699 return ostack;
700 }
702 cstr = String2Cstr(string);
703 len = strlen(cstr);
705 for(i = 0; i < len; i++)
706 if(cstr[i]=='.') cstr[i]='/';
708 class = findHashedClass(cstr, class_loader);
710 sysFree(cstr);
711 *ostack++ = (uintptr_t) class;
712 return ostack;
713 }
715 uintptr_t *resolveClass0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
716 Class *clazz = (Class *)*ostack;
718 if(clazz == NULL)
719 signalException(java_lang_NullPointerException, NULL);
720 else
721 initClass(clazz);
723 return ostack;
724 }
726 uintptr_t *getBootClassPathSize(Class *class, MethodBlock *mb, uintptr_t *ostack) {
727 *ostack++ = bootClassPathSize();
728 return ostack;
729 }
731 uintptr_t *getBootClassPathResource(Class *class, MethodBlock *mb, uintptr_t *ostack) {
732 Object *string = (Object *) ostack[0];
733 char *filename = String2Cstr(string);
734 int index = ostack[1];
736 *ostack++ = (uintptr_t) bootClassPathResource(filename, index);
737 return ostack;
738 }
740 /* java.lang.reflect.Constructor */
742 uintptr_t *constructNative(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
743 Object *array = (Object*)ostack[1];
744 Class *decl_class = (Class*)ostack[2];
745 Object *param_types = (Object*)ostack[3];
746 ClassBlock *cb = CLASS_CB(decl_class);
747 MethodBlock *mb = &(cb->methods[ostack[4]]);
748 int no_access_check = ostack[5];
749 Object *ob;
751 if(cb->access_flags & ACC_ABSTRACT) {
752 signalException(java_lang_InstantiationError, cb->name);
753 return ostack;
754 }
756 /* Creating an instance of the class is an
757 active use; make sure it is initialised */
758 if(initClass(decl_class) == NULL)
759 return ostack;
761 if((ob = allocObject(decl_class)) != NULL) {
762 invoke(ob, mb, array, param_types, !no_access_check);
763 *ostack++ = (uintptr_t) ob;
764 }
766 return ostack;
767 }
769 uintptr_t *getMethodModifiers(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
770 Class *decl_class = (Class*)ostack[1];
771 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
772 *ostack++ = (uintptr_t) mb->access_flags;
773 return ostack;
774 }
776 uintptr_t *getMethodSignature(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
777 Class *decl_class = (Class*)ostack[1];
778 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
779 Object *string = NULL;
781 if(mb->signature != NULL) {
782 char *dot_name = slash2dots(mb->signature);
783 string = createString(dot_name);
784 sysFree(dot_name);
785 }
787 *ostack++ = (uintptr_t)string;
788 return ostack;
789 }
791 uintptr_t *getDefaultValue(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
792 Class *decl_class = (Class*)ostack[1];
793 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
794 *ostack++ = (uintptr_t)getMethodDefaultValue(mb);
795 return ostack;
796 }
798 uintptr_t *getMethodDeclaredAnnotations(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
799 Class *decl_class = (Class*)ostack[1];
800 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
801 *ostack++ = (uintptr_t)getMethodAnnotations(mb);
802 return ostack;
803 }
805 uintptr_t *getParameterAnnotations(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
806 Class *decl_class = (Class*)ostack[1];
807 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
808 *ostack++ = (uintptr_t)getMethodParameterAnnotations(mb);
809 return ostack;
810 }
812 uintptr_t *getFieldModifiers(Class *class, MethodBlock *mb, uintptr_t *ostack) {
813 Class *decl_class = (Class*)ostack[1];
814 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[2]]);
815 *ostack++ = (uintptr_t) fb->access_flags;
816 return ostack;
817 }
819 uintptr_t *getFieldSignature(Class *class, MethodBlock *mb, uintptr_t *ostack) {
820 Class *decl_class = (Class*)ostack[1];
821 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[2]]);
822 Object *string = NULL;
824 if(fb->signature != NULL) {
825 char *dot_name = slash2dots(fb->signature);
826 string = createString(dot_name);
827 sysFree(dot_name);
828 }
830 *ostack++ = (uintptr_t)string;
831 return ostack;
832 }
834 uintptr_t *getFieldDeclaredAnnotations(Class *class, MethodBlock *mb, uintptr_t *ostack) {
835 Class *decl_class = (Class*)ostack[1];
836 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[2]]);
837 *ostack++ = (uintptr_t)getFieldAnnotations(fb);
838 return ostack;
839 }
841 Object *getAndCheckObject(uintptr_t *ostack, Class *type) {
842 Object *ob = (Object*)ostack[1];
844 if(ob == NULL) {
845 signalException(java_lang_NullPointerException, NULL);
846 return NULL;
847 }
849 if(!isInstanceOf(type, ob->class)) {
850 signalException(java_lang_IllegalArgumentException,
851 "object is not an instance of declaring class");
852 return NULL;
853 }
855 return ob;
856 }
858 uintptr_t *getPntr2Field(uintptr_t *ostack) {
859 Class *decl_class = (Class *)ostack[2];
860 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[4]]);
861 int no_access_check = ostack[5];
862 Object *ob;
864 if(!no_access_check) {
865 Class *caller = getCallerCallerClass();
866 if(!checkClassAccess(decl_class, caller) || !checkFieldAccess(fb, caller)) {
867 signalException(java_lang_IllegalAccessException, "field is not accessible");
868 return NULL;
869 }
870 }
872 if(fb->access_flags & ACC_STATIC) {
873 /* Setting/getting a static field of a class is an
874 active use; make sure it is initialised */
875 if(initClass(decl_class) == NULL)
876 return NULL;
877 return &fb->static_value;
878 }
880 if((ob = getAndCheckObject(ostack, decl_class)) == NULL)
881 return NULL;
883 return &(INST_DATA(ob)[fb->offset]);
884 }
886 uintptr_t *getField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
887 Class *field_type = (Class *)ostack[3];
888 uintptr_t *field;
890 /* If field is static, getPntr2Field also initialises the field's declaring class */
891 if((field = getPntr2Field(ostack)) != NULL)
892 *ostack++ = (uintptr_t) getReflectReturnObject(field_type, field);
894 return ostack;
895 }
897 uintptr_t *getPrimitiveField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
898 Class *field_type = (Class *)ostack[3];
899 int type_no = ostack[6];
901 ClassBlock *type_cb = CLASS_CB(field_type);
902 uintptr_t *field;
904 /* If field is static, getPntr2Field also initialises the field's declaring class */
905 if(((field = getPntr2Field(ostack)) != NULL) && (!(IS_PRIMITIVE(type_cb)) ||
906 ((ostack = widenPrimitiveValue(getPrimTypeIndex(type_cb), type_no, field, ostack)) == NULL)))
907 signalException(java_lang_IllegalArgumentException, "field type mismatch");
909 return ostack;
910 }
912 uintptr_t *setField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
913 Class *field_type = (Class *)ostack[3];
914 Object *value = (Object*)ostack[6];
915 uintptr_t *field;
917 /* If field is static, getPntr2Field also initialises the field's declaring class */
918 if(((field = getPntr2Field(ostack)) != NULL) &&
919 (unwrapAndWidenObject(field_type, value, field) == NULL))
920 signalException(java_lang_IllegalArgumentException, "field type mismatch");
922 return ostack;
923 }
925 uintptr_t *setPrimitiveField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
926 Class *field_type = (Class *)ostack[3];
927 int type_no = ostack[6];
929 ClassBlock *type_cb = CLASS_CB(field_type);
930 uintptr_t *field;
932 /* If field is static, getPntr2Field also initialises the field's declaring class */
933 if(((field = getPntr2Field(ostack)) != NULL) && (!(IS_PRIMITIVE(type_cb)) ||
934 (widenPrimitiveValue(type_no, getPrimTypeIndex(type_cb), &ostack[7], field) == NULL)))
935 signalException(java_lang_IllegalArgumentException, "field type mismatch");
937 return ostack;
938 }
940 /* java.lang.reflect.Method */
942 uintptr_t *invokeNative(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
943 Object *array = (Object*)ostack[2];
944 Class *decl_class = (Class*)ostack[3];
945 Object *param_types = (Object*)ostack[4];
946 Class *ret_type = (Class*)ostack[5];
947 ClassBlock *cb = CLASS_CB(decl_class);
948 MethodBlock *mb = &(cb->methods[ostack[6]]);
949 int no_access_check = ostack[7];
950 Object *ob = NULL;
951 uintptr_t *ret;
953 /* If it's a static method, class may not be initialised;
954 interfaces are also not normally initialised. */
955 if((mb->access_flags & ACC_STATIC) || IS_INTERFACE(cb))
956 if(initClass(decl_class) == NULL)
957 return ostack;
959 if(!(mb->access_flags & ACC_STATIC))
960 if(((ob = getAndCheckObject(ostack, decl_class)) == NULL) ||
961 ((mb = lookupVirtualMethod(ob, mb)) == NULL))
962 return ostack;
964 if((ret = (uintptr_t*) invoke(ob, mb, array, param_types, !no_access_check)) != NULL)
965 *ostack++ = (uintptr_t) getReflectReturnObject(ret_type, ret);
967 return ostack;
968 }
970 /* java.lang.VMString */
972 /* static method - intern(Ljava/lang/String;)Ljava/lang/String; */
973 uintptr_t *intern(Class *class, MethodBlock *mb, uintptr_t *ostack) {
974 Object *string = (Object*)ostack[0];
975 ostack[0] = (uintptr_t)findInternedString(string);
976 return ostack+1;
977 }
979 /* java.lang.VMThread */
981 /* static method currentThread()Ljava/lang/Thread; */
982 uintptr_t *currentThread(Class *class, MethodBlock *mb, uintptr_t *ostack) {
983 *ostack++ = (uintptr_t)getExecEnv()->thread;
984 return ostack;
985 }
987 /* static method create(Ljava/lang/Thread;J)V */
988 uintptr_t *create(Class *class, MethodBlock *mb, uintptr_t *ostack) {
989 Object *this = (Object *)ostack[0];
990 long long stack_size = *((long long*)&ostack[1]);
991 createJavaThread(this, stack_size);
992 return ostack;
993 }
995 /* static method sleep(JI)V */
996 uintptr_t *jamSleep(Class *class, MethodBlock *mb, uintptr_t *ostack) {
997 long long ms = *((long long *)&ostack[0]);
998 int ns = ostack[2];
999 Thread *thread = threadSelf();
1001 threadSleep(thread, ms, ns);
1002 return ostack;
1003 }
1005 /* instance method interrupt()V */
1006 uintptr_t *interrupt(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1007 Object *this = (Object *)*ostack;
1008 Thread *thread = threadSelf0(this);
1009 if(thread)
1010 threadInterrupt(thread);
1011 return ostack;
1012 }
1014 /* instance method isAlive()Z */
1015 uintptr_t *isAlive(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1016 Object *this = (Object *)*ostack;
1017 Thread *thread = threadSelf0(this);
1018 *ostack++ = thread ? threadIsAlive(thread) : FALSE;
1019 return ostack;
1020 }
1022 /* static method yield()V */
1023 uintptr_t *yield(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1024 Thread *thread = threadSelf();
1025 threadYield(thread);
1026 return ostack;
1027 }
1029 /* instance method isInterrupted()Z */
1030 uintptr_t *isInterrupted(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1031 Object *this = (Object *)*ostack;
1032 Thread *thread = threadSelf0(this);
1033 *ostack++ = thread ? threadIsInterrupted(thread) : FALSE;
1034 return ostack;
1035 }
1037 /* static method interrupted()Z */
1038 uintptr_t *interrupted(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1039 Thread *thread = threadSelf();
1040 *ostack++ = threadInterrupted(thread);
1041 return ostack;
1042 }
1044 /* instance method nativeSetPriority(I)V */
1045 uintptr_t *nativeSetPriority(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1046 return ostack+1;
1047 }
1049 /* instance method holdsLock(Ljava/lang/Object;)Z */
1050 uintptr_t *holdsLock(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1051 Object *ob = (Object *)ostack[0];
1052 if(ob == NULL)
1053 signalException(java_lang_NullPointerException, NULL);
1054 else
1055 *ostack++ = objectLockedByCurrent(ob);
1056 return ostack;
1057 }
1059 /* instance method getState()Ljava/lang/String; */
1060 uintptr_t *getState(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1061 Object *this = (Object *)*ostack;
1062 Thread *thread = threadSelf0(this);
1063 char *state = thread ? getThreadStateString(thread) : "TERMINATED";
1065 *ostack++ = (uintptr_t)Cstr2String(state);
1066 return ostack;
1067 }
1069 /* java.security.VMAccessController */
1071 /* instance method getStack()[[Ljava/lang/Object; */
1072 uintptr_t *getStack(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1073 Class *object_class = findArrayClass("[[Ljava/lang/Object;");
1074 Class *class_class = findArrayClass("[Ljava/lang/Class;");
1075 Class *string_class = findArrayClass("[Ljava/lang/String;");
1076 Object *stack, *names, *classes;
1077 Frame *frame;
1078 int depth;
1080 if(object_class == NULL || class_class == NULL || string_class == NULL)
1081 return ostack;
1083 frame = getExecEnv()->last_frame;
1084 depth = 0;
1086 do {
1087 for(; frame->mb != NULL; frame = frame->prev, depth++);
1088 } while((frame = frame->prev)->prev != NULL);
1090 stack = allocArray(object_class, 2, sizeof(Object*));
1091 classes = allocArray(class_class, depth, sizeof(Object*));
1092 names = allocArray(string_class, depth, sizeof(Object*));
1094 if(stack != NULL && names != NULL && classes != NULL) {
1095 Class **dcl = ARRAY_DATA(classes);
1096 Object **dnm = ARRAY_DATA(names);
1097 Object **stk = ARRAY_DATA(stack);
1099 frame = getExecEnv()->last_frame;
1101 do {
1102 for(; frame->mb != NULL; frame = frame->prev) {
1103 *dcl++ = frame->mb->class;
1104 *dnm++ = createString(frame->mb->name);
1105 }
1106 } while((frame = frame->prev)->prev != NULL);
1108 stk[0] = classes;
1109 stk[1] = names;
1110 }
1112 *ostack++ = (uintptr_t) stack;
1113 return ostack;
1114 }
1116 uintptr_t *getThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1117 *ostack++ = getThreadsCount();
1118 return ostack;
1119 }
1121 uintptr_t *getPeakThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1122 *ostack++ = getPeakThreadsCount();
1123 return ostack;
1124 }
1126 uintptr_t *getTotalStartedThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1127 *(u8*)ostack = getTotalStartedThreadsCount();
1128 return ostack + 2;
1129 }
1131 uintptr_t *resetPeakThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1132 resetPeakThreadsCount();
1133 return ostack;
1134 }
1136 uintptr_t *findMonitorDeadlockedThreads(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1137 *ostack++ = (uintptr_t)NULL;
1138 return ostack;
1139 }
1141 uintptr_t *getThreadInfoForId(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1142 long long id = *((long long *)&ostack[0]);
1143 int max_depth = ostack[2];
1145 Thread *thread = findThreadById(id);
1146 Object *info = NULL;
1148 if(thread != NULL) {
1149 Class *info_class = findSystemClass("java/lang/management/ThreadInfo");
1151 if(info_class != NULL) {
1152 MethodBlock *init = findMethod(info_class, SYMBOL(object_init),
1153 newUtf8("(Ljava/lang/Thread;JJLjava/lang/Object;"
1154 "Ljava/lang/Thread;JJZZ[Ljava/lang/StackTraceElement;)V"));
1155 if(init != NULL) {
1156 Frame *last;
1157 int in_native;
1158 Object *vmthrowable;
1159 int self = thread == threadSelf();
1161 if(!self)
1162 suspendThread(thread);
1164 vmthrowable = setStackTrace0(thread->ee, max_depth);
1166 last = thread->ee->last_frame;
1167 in_native = last->prev == NULL || last->mb->access_flags & ACC_NATIVE;
1169 if(!self)
1170 resumeThread(thread);
1172 if(vmthrowable != NULL) {
1173 Object *trace;
1174 if((info = allocObject(info_class)) != NULL &&
1175 (trace = convertStackTrace(vmthrowable)) != NULL) {
1177 Monitor *mon = thread->blocked_mon;
1178 Object *lock = mon != NULL ? mon->obj : NULL;
1179 Thread *owner = mon != NULL ? mon->owner : NULL;
1180 Object *lock_owner = owner != NULL ? owner->ee->thread : NULL;
1182 executeMethod(info, init, thread->ee->thread, thread->blocked_count, 0LL, lock,
1183 lock_owner, thread->waited_count, 0LL, in_native, FALSE, trace);
1184 }
1185 }
1186 }
1187 }
1188 }
1190 *ostack++ = (uintptr_t)info;
1191 return ostack;
1192 }
1194 /* sun.misc.Unsafe */
1196 static volatile uintptr_t spinlock = 0;
1198 void lockSpinLock() {
1199 while(!LOCKWORD_COMPARE_AND_SWAP(&spinlock, 0, 1));
1200 }
1202 void unlockSpinLock() {
1203 LOCKWORD_WRITE(&spinlock, 0);
1204 }
1206 uintptr_t *objectFieldOffset(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1207 FieldBlock *fb = fbFromReflectObject((Object*)ostack[1]);
1209 *(long long*)ostack = (long long)(uintptr_t)&INST_DATA((Object*)NULL)[fb->offset];
1210 return ostack + 2;
1211 }
1213 uintptr_t *compareAndSwapInt(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1214 long long offset = *((long long *)&ostack[2]);
1215 uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1216 uintptr_t expect = ostack[4];
1217 uintptr_t update = ostack[5];
1218 int result;
1220 #ifdef COMPARE_AND_SWAP
1221 result = COMPARE_AND_SWAP(addr, expect, update);
1222 #else
1223 lockSpinLock();
1224 if((result = (*addr == expect)))
1225 *addr = update;
1226 unlockSpinLock();
1227 #endif
1229 *ostack++ = result;
1230 return ostack;
1231 }
1233 uintptr_t *compareAndSwapLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1234 long long offset = *((long long *)&ostack[2]);
1235 long long *addr = (long long*)((char*)ostack[1] + offset);
1236 long long expect = *((long long *)&ostack[4]);
1237 long long update = *((long long *)&ostack[6]);
1238 int result;
1240 #ifdef COMPARE_AND_SWAP_64
1241 result = COMPARE_AND_SWAP_64(addr, expect, update);
1242 #else
1243 lockSpinLock();
1244 if((result = (*addr == expect)))
1245 *addr = update;
1246 unlockSpinLock();
1247 #endif
1249 *ostack++ = result;
1250 return ostack;
1251 }
1253 uintptr_t *putOrderedInt(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1254 long long offset = *((long long *)&ostack[2]);
1255 volatile uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1256 uintptr_t value = ostack[4];
1258 *addr = value;
1259 return ostack;
1260 }
1262 uintptr_t *putOrderedLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1263 long long offset = *((long long *)&ostack[2]);
1264 long long value = *((long long *)&ostack[4]);
1265 volatile long long *addr = (long long*)((char*)ostack[1] + offset);
1267 if(sizeof(uintptr_t) == 8)
1268 *addr = value;
1269 else {
1270 lockSpinLock();
1271 *addr = value;
1272 unlockSpinLock();
1273 }
1275 return ostack;
1276 }
1278 uintptr_t *putIntVolatile(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1279 long long offset = *((long long *)&ostack[2]);
1280 volatile uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1281 uintptr_t value = ostack[4];
1283 MBARRIER();
1284 *addr = value;
1286 return ostack;
1287 }
1289 uintptr_t *getIntVolatile(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1290 long long offset = *((long long *)&ostack[2]);
1291 volatile uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1293 *ostack++ = *addr;
1294 MBARRIER();
1296 return ostack;
1297 }
1299 uintptr_t *putLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1300 long long offset = *((long long *)&ostack[2]);
1301 long long value = *((long long *)&ostack[4]);
1302 long long *addr = (long long*)((char*)ostack[1] + offset);
1304 if(sizeof(uintptr_t) == 8)
1305 *addr = value;
1306 else {
1307 lockSpinLock();
1308 *addr = value;
1309 unlockSpinLock();
1310 }
1312 return ostack;
1313 }
1315 uintptr_t *getLongVolatile(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1316 long long offset = *((long long *)&ostack[2]);
1317 volatile long long *addr = (long long*)((char*)ostack[1] + offset);
1319 if(sizeof(uintptr_t) == 8)
1320 *(long long*)ostack = *addr;
1321 else {
1322 lockSpinLock();
1323 *(long long*)ostack = *addr;
1324 unlockSpinLock();
1325 }
1327 return ostack + 2;
1328 }
1330 uintptr_t *getLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1331 long long offset = *((long long *)&ostack[2]);
1332 long long *addr = (long long*)((char*)ostack[1] + offset);
1334 if(sizeof(uintptr_t) == 8)
1335 *(long long*)ostack = *addr;
1336 else {
1337 lockSpinLock();
1338 *(long long*)ostack = *addr;
1339 unlockSpinLock();
1340 }
1342 return ostack + 2;
1343 }
1345 uintptr_t *putObject(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1346 long long offset = *((long long *)&ostack[2]);
1347 uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1348 uintptr_t value = ostack[4];
1350 *addr = value;
1351 return ostack;
1352 }
1354 uintptr_t *arrayBaseOffset(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1355 *ostack++ = (uintptr_t) ARRAY_DATA((Object*)NULL);
1356 return ostack;
1357 }
1359 uintptr_t *arrayIndexScale(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1360 Class *array_class = (Class*)ostack[1];
1361 ClassBlock *cb = CLASS_CB(array_class);
1362 int scale = 0;
1364 if(cb->name[0] == '[')
1365 switch(cb->name[1]) {
1366 case 'I':
1367 case 'F':
1368 scale = 4;
1369 break;
1371 case '[':
1372 case 'L':
1373 scale = sizeof(Object*);
1374 break;
1376 case 'J':
1377 case 'D':
1378 scale = 8;
1379 break;
1380 }
1382 *ostack++ = scale;
1383 return ostack;
1384 }
1386 uintptr_t *unpark(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1387 return ostack;
1388 }
1390 uintptr_t *park(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1391 return ostack;
1392 }
1394 uintptr_t *vmSupportsCS8(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1395 *ostack++ = FALSE;
1396 return ostack;
1397 }
1399 /* jamvm.java.lang.VMClassLoaderData */
1401 uintptr_t *nativeUnloadDll(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1402 unloaderUnloadDll((uintptr_t)*(long long*)&ostack[1]);
1403 return ostack;
1404 }
1406 VMMethod vm_object[] = {
1407 {"getClass", getClass},
1408 {"clone", jamClone},
1409 {"wait", jamWait},
1410 {"notify", notify},
1411 {"notifyAll", notifyAll},
1412 {NULL, NULL}
1413 };
1415 VMMethod vm_system[] = {
1416 {"arraycopy", arraycopy},
1417 {"identityHashCode", identityHashCode},
1418 {NULL, NULL}
1419 };
1421 VMMethod vm_runtime[] = {
1422 {"availableProcessors", availableProcessors},
1423 {"freeMemory", freeMemory},
1424 {"totalMemory", totalMemory},
1425 {"maxMemory", maxMemory},
1426 {"gc", gc},
1427 {"runFinalization", runFinalization},
1428 {"exit", exitInternal},
1429 {"nativeLoad", nativeLoad},
1430 {"mapLibraryName", mapLibraryName},
1431 {NULL, NULL}
1432 };
1434 VMMethod vm_class[] = {
1435 {"isInstance", isInstance},
1436 {"isAssignableFrom", isAssignableFrom},
1437 {"isInterface", isInterface},
1438 {"isPrimitive", isPrimitive},
1439 {"isArray", isArray},
1440 {"isMemberClass", isMember},
1441 {"isLocalClass", isLocal},
1442 {"isAnonymousClass", isAnonymous},
1443 {"getEnclosingClass", getEnclosingClass0},
1444 {"getEnclosingMethod", getEnclosingMethod0},
1445 {"getEnclosingConstructor", getEnclosingConstructor},
1446 {"getClassSignature", getClassSignature},
1447 {"getSuperclass", getSuperclass},
1448 {"getComponentType", getComponentType},
1449 {"getName", getName},
1450 {"getDeclaredClasses", getDeclaredClasses},
1451 {"getDeclaringClass", getDeclaringClass0},
1452 {"getDeclaredConstructors", getDeclaredConstructors},
1453 {"getDeclaredMethods", getDeclaredMethods},
1454 {"getDeclaredFields", getDeclaredFields},
1455 {"getInterfaces", getInterfaces},
1456 {"getClassLoader", getClassLoader},
1457 {"getModifiers", getClassModifiers},
1458 {"forName", forName},
1459 {"throwException", throwException},
1460 {"hasClassInitializer", hasClassInitializer},
1461 {"getDeclaredAnnotations", getClassDeclaredAnnotations},
1462 {NULL, NULL}
1463 };
1465 VMMethod vm_string[] = {
1466 {"intern", intern},
1467 {NULL, NULL}
1468 };
1470 VMMethod vm_thread[] = {
1471 {"currentThread", currentThread},
1472 {"create", create},
1473 {"sleep", jamSleep},
1474 {"interrupt", interrupt},
1475 {"isAlive", isAlive},
1476 {"yield", yield},
1477 {"isInterrupted", isInterrupted},
1478 {"interrupted", interrupted},
1479 {"nativeSetPriority", nativeSetPriority},
1480 {"holdsLock", holdsLock},
1481 {"getState", getState},
1482 {NULL, NULL}
1483 };
1485 VMMethod vm_throwable[] = {
1486 {"fillInStackTrace", fillInStackTrace},
1487 {"getStackTrace", getStackTrace},
1488 {NULL, NULL}
1489 };
1491 VMMethod vm_classloader[] = {
1492 {"loadClass", loadClass},
1493 {"getPrimitiveClass", getPrimitiveClass},
1494 {"defineClass", defineClass0},
1495 {"findLoadedClass", findLoadedClass},
1496 {"resolveClass", resolveClass0},
1497 {"getBootClassPathSize", getBootClassPathSize},
1498 {"getBootClassPathResource", getBootClassPathResource},
1499 {NULL, NULL}
1500 };
1502 VMMethod vm_reflect_constructor[] = {
1503 {"constructNative", constructNative},
1504 {"getConstructorModifiers", getMethodModifiers},
1505 {"getSignature", getMethodSignature},
1506 {"getDeclaredAnnotationsNative", getMethodDeclaredAnnotations},
1507 {"getParameterAnnotationsNative", getParameterAnnotations},
1508 {NULL, NULL}
1509 };
1511 VMMethod vm_reflect_method[] = {
1512 {"invokeNative", invokeNative},
1513 {"getMethodModifiers", getMethodModifiers},
1514 {"getSignature", getMethodSignature},
1515 {"getDefaultValueNative", getDefaultValue},
1516 {"getDeclaredAnnotationsNative", getMethodDeclaredAnnotations},
1517 {"getParameterAnnotationsNative", getParameterAnnotations},
1518 {NULL, NULL}
1519 };
1521 VMMethod vm_reflect_field[] = {
1522 {"getFieldModifiers", getFieldModifiers},
1523 {"getSignature", getFieldSignature},
1524 {"getDeclaredAnnotationsNative", getFieldDeclaredAnnotations},
1525 {"getField", getField},
1526 {"setField", setField},
1527 {"setZField", setPrimitiveField},
1528 {"setBField", setPrimitiveField},
1529 {"setCField", setPrimitiveField},
1530 {"setSField", setPrimitiveField},
1531 {"setIField", setPrimitiveField},
1532 {"setFField", setPrimitiveField},
1533 {"setJField", setPrimitiveField},
1534 {"setDField", setPrimitiveField},
1535 {"getZField", getPrimitiveField},
1536 {"getBField", getPrimitiveField},
1537 {"getCField", getPrimitiveField},
1538 {"getSField", getPrimitiveField},
1539 {"getIField", getPrimitiveField},
1540 {"getFField", getPrimitiveField},
1541 {"getJField", getPrimitiveField},
1542 {"getDField", getPrimitiveField},
1543 {NULL, NULL}
1544 };
1546 VMMethod vm_system_properties[] = {
1547 {"preInit", propertiesPreInit},
1548 {"postInit", propertiesPostInit},
1549 {NULL, NULL}
1550 };
1552 VMMethod vm_stack_walker[] = {
1553 {"getClassContext", getClassContext},
1554 {"getCallingClass", getCallingClass},
1555 {"getCallingClassLoader", getCallingClassLoader},
1556 {"firstNonNullClassLoader", firstNonNullClassLoader},
1557 {NULL, NULL}
1558 };
1560 VMMethod sun_misc_unsafe[] = {
1561 {"objectFieldOffset", objectFieldOffset},
1562 {"compareAndSwapInt", compareAndSwapInt},
1563 {"compareAndSwapLong", compareAndSwapLong},
1564 {"compareAndSwapObject", compareAndSwapInt},
1565 {"putOrderedInt", putOrderedInt},
1566 {"putOrderedLong", putOrderedLong},
1567 {"putOrderedObject", putOrderedInt},
1568 {"putIntVolatile", putIntVolatile},
1569 {"getIntVolatile", getIntVolatile},
1570 {"putLongVolatile", putOrderedLong},
1571 {"putLong", putLong},
1572 {"getLongVolatile", getLongVolatile},
1573 {"getLong", getLong},
1574 {"putObjectVolatile", putIntVolatile},
1575 {"putObject", putObject},
1576 {"getObjectVolatile", getIntVolatile},
1577 {"arrayBaseOffset", arrayBaseOffset},
1578 {"arrayIndexScale", arrayIndexScale},
1579 {"unpark", unpark},
1580 {"park", park},
1581 {NULL, NULL}
1582 };
1584 VMMethod vm_access_controller[] = {
1585 {"getStack", getStack},
1586 {NULL, NULL}
1587 };
1589 VMMethod vm_threadmx_bean_impl[] = {
1590 {"getThreadCount", getThreadCount},
1591 {"getPeakThreadCount", getPeakThreadCount},
1592 {"getTotalStartedThreadCount", getTotalStartedThreadCount},
1593 {"resetPeakThreadCount", resetPeakThreadCount},
1594 {"getThreadInfoForId", getThreadInfoForId},
1595 {"findMonitorDeadlockedThreads",findMonitorDeadlockedThreads},
1596 {NULL, NULL}
1597 };
1599 VMMethod concurrent_atomic_long[] = {
1600 {"VMSupportsCS8", vmSupportsCS8},
1601 {NULL, NULL}
1602 };
1604 VMMethod vm_class_loader_data[] = {
1605 {"nativeUnloadDll", nativeUnloadDll},
1606 {NULL, NULL}
1607 };
1609 VMClass native_methods[] = {
1610 {"java/lang/VMClass", vm_class},
1611 {"java/lang/VMObject", vm_object},
1612 {"java/lang/VMThread", vm_thread},
1613 {"java/lang/VMSystem", vm_system},
1614 {"java/lang/VMString", vm_string},
1615 {"java/lang/VMRuntime", vm_runtime},
1616 {"java/lang/VMThrowable", vm_throwable},
1617 {"java/lang/VMClassLoader", vm_classloader},
1618 {"java/lang/reflect/Field", vm_reflect_field},
1619 {"java/lang/reflect/Method", vm_reflect_method},
1620 {"java/lang/reflect/Constructor", vm_reflect_constructor},
1621 {"java/security/VMAccessController", vm_access_controller},
1622 {"gnu/classpath/VMSystemProperties", vm_system_properties},
1623 {"gnu/classpath/VMStackWalker", vm_stack_walker},
1624 {"gnu/java/lang/management/VMThreadMXBeanImpl", vm_threadmx_bean_impl},
1625 {"sun/misc/Unsafe", sun_misc_unsafe},
1626 {"jamvm/java/lang/VMClassLoaderData$Unloader", vm_class_loader_data},
1627 {"java/util/concurrent/atomic/AtomicLong", concurrent_atomic_long},
1628 {NULL, NULL}
1629 };
