jamvm

view src/natives.c @ 406:2f855beaaf73

Document VM differences.

2008-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>

* src/natives.c:
Document VM differences.
author andrew
date Tue Aug 05 06:28:05 2008 +0100 (2008-08-05)
parents f70700d622a8
children
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 /* VMDIFF: GNU Classpath support needs direct access to the
52 protection domain field in java.lang.Class as this is stored
53 by the library, not the VM as in OpenJDK. OpenJDK needs
54 libjava.so to be loaded. */
55 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
56 FieldBlock *pd = findField(java_lang_Class, SYMBOL(pd),
57 SYMBOL(sig_java_security_ProtectionDomain));
59 if(pd == NULL) {
60 jam_fprintf(stderr, "Error initialising VM (initialiseNatives)\n");
61 exitVM(1);
62 }
63 pd_offset = pd->offset;
64 #elif WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
65 char *name = getDllName("java");
66 char *bootpath = getBootDllPath();
67 char *buff = sysMalloc(strlen(name) + strlen(bootpath) + 2);
68 sprintf(buff, "%s/%s", bootpath, name);
69 resolveDll(buff, NULL);
70 sysFree(buff);
71 #endif
72 }
74 /* java.lang.VMObject */
76 uintptr_t *getClass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
77 Object *ob = (Object*)*ostack;
78 *ostack++ = (uintptr_t)ob->class;
79 return ostack;
80 }
82 uintptr_t *jamClone(Class *class, MethodBlock *mb, uintptr_t *ostack) {
83 Object *ob = (Object*)*ostack;
84 *ostack++ = (uintptr_t)cloneObject(ob);
85 return ostack;
86 }
88 /* static method wait(Ljava/lang/Object;JI)V */
89 uintptr_t *jamWait(Class *class, MethodBlock *mb, uintptr_t *ostack) {
90 Object *obj = (Object *)ostack[0];
91 long long ms = *((long long *)&ostack[1]);
92 int ns = ostack[3];
94 objectWait(obj, ms, ns);
95 return ostack;
96 }
98 /* static method notify(Ljava/lang/Object;)V */
99 uintptr_t *notify(Class *class, MethodBlock *mb, uintptr_t *ostack) {
100 Object *obj = (Object *)*ostack;
101 objectNotify(obj);
102 return ostack;
103 }
105 /* static method notifyAll(Ljava/lang/Object;)V */
106 uintptr_t *notifyAll(Class *class, MethodBlock *mb, uintptr_t *ostack) {
107 Object *obj = (Object *)*ostack;
108 objectNotifyAll(obj);
109 return ostack;
110 }
112 /* java.lang.VMSystem */
114 /* arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V */
115 uintptr_t *arraycopy(Class *class, MethodBlock *mb, uintptr_t *ostack) {
116 Object *src = (Object *)ostack[0];
117 int start1 = ostack[1];
118 Object *dest = (Object *)ostack[2];
119 int start2 = ostack[3];
120 int length = ostack[4];
122 if((src == NULL) || (dest == NULL))
123 signalException(java_lang_NullPointerException, NULL);
124 else {
125 ClassBlock *scb = CLASS_CB(src->class);
126 ClassBlock *dcb = CLASS_CB(dest->class);
127 char *sdata = ARRAY_DATA(src);
128 char *ddata = ARRAY_DATA(dest);
130 if((scb->name[0] != '[') || (dcb->name[0] != '['))
131 goto storeExcep;
133 if((start1 < 0) || (start2 < 0) || (length < 0)
134 || ((start1 + length) > ARRAY_LEN(src))
135 || ((start2 + length) > ARRAY_LEN(dest))) {
136 signalException(java_lang_ArrayIndexOutOfBoundsException, NULL);
137 return ostack;
138 }
140 if(isInstanceOf(dest->class, src->class)) {
141 int size;
143 switch(scb->name[1]) {
144 case 'B':
145 case 'Z':
146 size = 1;
147 break;
148 case 'C':
149 case 'S':
150 size = 2;
151 break;
152 case 'I':
153 case 'F':
154 size = 4;
155 break;
156 case 'L':
157 case '[':
158 size = sizeof(Object*);
159 break;
160 case 'J':
161 case 'D':
162 default:
163 size = 8;
164 break;
165 }
167 memmove(ddata + start2*size, sdata + start1*size, length*size);
168 } else {
169 Object **sob, **dob;
170 int i;
172 if(!(((scb->name[1] == 'L') || (scb->name[1] == '[')) &&
173 ((dcb->name[1] == 'L') || (dcb->name[1] == '['))))
174 goto storeExcep;
176 /* Not compatible array types, but elements may be compatible...
177 e.g. src = [Ljava/lang/Object, dest = [Ljava/lang/String, but
178 all src = Strings - check one by one...
179 */
181 if(scb->dim > dcb->dim)
182 goto storeExcep;
184 sob = &((Object**)sdata)[start1];
185 dob = &((Object**)ddata)[start2];
187 for(i = 0; i < length; i++) {
188 if((*sob != NULL) && !arrayStoreCheck(dest->class, (*sob)->class))
189 goto storeExcep;
190 *dob++ = *sob++;
191 }
192 }
193 }
194 return ostack;
196 storeExcep:
197 signalException(java_lang_ArrayStoreException, NULL);
198 return ostack;
199 }
201 uintptr_t *identityHashCode(Class *class, MethodBlock *mb, uintptr_t *ostack) {
202 Object *ob = (Object*)*ostack;
203 uintptr_t addr = ob == NULL ? 0 : getObjectHashcode(ob);
205 *ostack++ = addr & 0xffffffff;
206 return ostack;
207 }
209 /* java.lang.VMRuntime */
211 uintptr_t *availableProcessors(Class *class, MethodBlock *mb, uintptr_t *ostack) {
212 *ostack++ = nativeAvailableProcessors();
213 return ostack;
214 }
216 uintptr_t *freeMemory(Class *class, MethodBlock *mb, uintptr_t *ostack) {
217 *(u8*)ostack = freeHeapMem();
218 return ostack + 2;
219 }
221 uintptr_t *totalMemory(Class *class, MethodBlock *mb, uintptr_t *ostack) {
222 *(u8*)ostack = totalHeapMem();
223 return ostack + 2;
224 }
226 uintptr_t *maxMemory(Class *class, MethodBlock *mb, uintptr_t *ostack) {
227 *(u8*)ostack = maxHeapMem();
228 return ostack + 2;
229 }
231 uintptr_t *gc(Class *class, MethodBlock *mb, uintptr_t *ostack) {
232 gc1();
233 return ostack;
234 }
236 uintptr_t *runFinalization(Class *class, MethodBlock *mb, uintptr_t *ostack) {
237 runFinalizers();
238 return ostack;
239 }
241 uintptr_t *exitInternal(Class *class, MethodBlock *mb, uintptr_t *ostack) {
242 int status = ostack[0];
243 jamvm_exit(status);
244 /* keep compiler happy */
245 return 0;
246 }
248 uintptr_t *nativeLoad(Class *class, MethodBlock *mb, uintptr_t *ostack) {
249 char *name = String2Cstr((Object*)ostack[0]);
250 Object *class_loader = (Object *)ostack[1];
252 ostack[0] = resolveDll(name, class_loader);
253 sysFree(name);
255 return ostack+1;
256 }
258 uintptr_t *mapLibraryName(Class *class, MethodBlock *mb, uintptr_t *ostack) {
259 char *name = String2Cstr((Object*)ostack[0]);
260 char *lib = getDllName(name);
261 sysFree(name);
263 *ostack++ = (uintptr_t)Cstr2String(lib);
264 sysFree(lib);
266 return ostack;
267 }
269 uintptr_t *propertiesPreInit(Class *class, MethodBlock *mb, uintptr_t *ostack) {
270 Object *properties = (Object *)*ostack;
271 addDefaultProperties(properties);
272 return ostack;
273 }
275 uintptr_t *propertiesPostInit(Class *class, MethodBlock *mb, uintptr_t *ostack) {
276 Object *properties = (Object *)*ostack;
277 addCommandLineProperties(properties);
278 return ostack;
279 }
281 /* java.lang.VMClass */
283 #define GET_CLASS(vmClass) (Class*)vmClass
285 uintptr_t *isInstance(Class *class, MethodBlock *mb, uintptr_t *ostack) {
286 Class *clazz = GET_CLASS(ostack[0]);
287 Object *ob = (Object*)ostack[1];
289 *ostack++ = ob == NULL ? FALSE : (uintptr_t)isInstanceOf(clazz, ob->class);
290 return ostack;
291 }
293 uintptr_t *isAssignableFrom(Class *class, MethodBlock *mb, uintptr_t *ostack) {
294 Class *clazz = GET_CLASS(ostack[0]);
295 Class *clazz2 = (Class*)ostack[1];
297 if(clazz2 == NULL)
298 signalException(java_lang_NullPointerException, NULL);
299 else
300 *ostack++ = (uintptr_t)isInstanceOf(clazz, clazz2);
302 return ostack;
303 }
305 uintptr_t *isInterface(Class *class, MethodBlock *mb, uintptr_t *ostack) {
306 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
307 *ostack++ = IS_INTERFACE(cb) ? TRUE : FALSE;
308 return ostack;
309 }
311 uintptr_t *isPrimitive(Class *class, MethodBlock *mb, uintptr_t *ostack) {
312 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
313 *ostack++ = IS_PRIMITIVE(cb) ? TRUE : FALSE;
314 return ostack;
315 }
317 uintptr_t *isArray(Class *class, MethodBlock *mb, uintptr_t *ostack) {
318 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
319 *ostack++ = IS_ARRAY(cb) ? TRUE : FALSE;
320 return ostack;
321 }
323 uintptr_t *isMember(Class *class, MethodBlock *mb, uintptr_t *ostack) {
324 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
325 *ostack++ = IS_MEMBER(cb) ? TRUE : FALSE;
326 return ostack;
327 }
329 uintptr_t *isLocal(Class *class, MethodBlock *mb, uintptr_t *ostack) {
330 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
331 *ostack++ = IS_LOCAL(cb) ? TRUE : FALSE;
332 return ostack;
333 }
335 uintptr_t *isAnonymous(Class *class, MethodBlock *mb, uintptr_t *ostack) {
336 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
337 *ostack++ = IS_ANONYMOUS(cb) ? TRUE : FALSE;
338 return ostack;
339 }
341 uintptr_t *getEnclosingClass0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
342 Class *clazz = GET_CLASS(ostack[0]);
343 *ostack++ = (uintptr_t) getEnclosingClass(clazz);
344 return ostack;
345 }
347 uintptr_t *getEnclosingMethod0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
348 Class *clazz = GET_CLASS(ostack[0]);
349 *ostack++ = (uintptr_t) getEnclosingMethodObject(clazz);
350 return ostack;
351 }
353 uintptr_t *getEnclosingConstructor(Class *class, MethodBlock *mb, uintptr_t *ostack) {
354 Class *clazz = GET_CLASS(ostack[0]);
355 *ostack++ = (uintptr_t) getEnclosingConstructorObject(clazz);
356 return ostack;
357 }
359 uintptr_t *getClassSignature(Class *class, MethodBlock *mb, uintptr_t *ostack) {
360 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
361 Object *string = NULL;
363 if(cb->signature != NULL) {
364 char *dot_name = slash2dots(cb->signature);
365 string = createString(dot_name);
366 sysFree(dot_name);
367 }
369 *ostack++ = (uintptr_t)string;
370 return ostack;
371 }
373 uintptr_t *getSuperclass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
374 ClassBlock *cb = CLASS_CB(GET_CLASS(ostack[0]));
375 *ostack++ = (uintptr_t) (IS_PRIMITIVE(cb) || IS_INTERFACE(cb) ? NULL : cb->super);
376 return ostack;
377 }
379 uintptr_t *getComponentType(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
380 Class *class = GET_CLASS(ostack[0]);
381 ClassBlock *cb = CLASS_CB(class);
382 Class *componentType = NULL;
384 if(IS_ARRAY(cb))
385 switch(cb->name[1]) {
386 case '[':
387 componentType = findArrayClassFromClass(&cb->name[1], class);
388 break;
390 default:
391 componentType = cb->element_class;
392 break;
393 }
395 *ostack++ = (uintptr_t) componentType;
396 return ostack;
397 }
399 uintptr_t *getName(Class *class, MethodBlock *mb, uintptr_t *ostack) {
400 char *dot_name = slash2dots(CLASS_CB((GET_CLASS(*ostack)))->name);
401 Object *string = createString(dot_name);
402 *ostack++ = (uintptr_t)string;
403 sysFree(dot_name);
404 return ostack;
405 }
407 uintptr_t *getDeclaredClasses(Class *class, MethodBlock *mb, uintptr_t *ostack) {
408 Class *clazz = GET_CLASS(ostack[0]);
409 int public = ostack[1];
410 *ostack++ = (uintptr_t) getClassClasses(clazz, public);
411 return ostack;
412 }
414 uintptr_t *getDeclaringClass0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
415 Class *clazz = GET_CLASS(ostack[0]);
416 *ostack++ = (uintptr_t) getDeclaringClass(clazz);
417 return ostack;
418 }
420 uintptr_t *getDeclaredConstructors(Class *class, MethodBlock *mb, uintptr_t *ostack) {
421 Class *clazz = GET_CLASS(ostack[0]);
422 int public = ostack[1];
423 *ostack++ = (uintptr_t) getClassConstructors(clazz, public);
424 return ostack;
425 }
427 uintptr_t *getDeclaredMethods(Class *class, MethodBlock *mb, uintptr_t *ostack) {
428 Class *clazz = GET_CLASS(ostack[0]);
429 int public = ostack[1];
430 *ostack++ = (uintptr_t) getClassMethods(clazz, public);
431 return ostack;
432 }
434 uintptr_t *getDeclaredFields(Class *class, MethodBlock *mb, uintptr_t *ostack) {
435 Class *clazz = GET_CLASS(ostack[0]);
436 int public = ostack[1];
437 *ostack++ = (uintptr_t) getClassFields(clazz, public);
438 return ostack;
439 }
441 uintptr_t *getClassDeclaredAnnotations(Class *class, MethodBlock *mb, uintptr_t *ostack) {
442 Class *clazz = GET_CLASS(ostack[0]);
443 *ostack++ = (uintptr_t) getClassAnnotations(clazz);
444 return ostack;
445 }
447 uintptr_t *getInterfaces(Class *class, MethodBlock *mb, uintptr_t *ostack) {
448 Class *clazz = GET_CLASS(ostack[0]);
449 *ostack++ = (uintptr_t) getClassInterfaces(clazz);
450 return ostack;
451 }
453 uintptr_t *getClassLoader(Class *class, MethodBlock *mb, uintptr_t *ostack) {
454 Class *clazz = GET_CLASS(*ostack);
455 *ostack++ = (uintptr_t)CLASS_CB(clazz)->class_loader;
456 return ostack;
457 }
459 uintptr_t *getClassModifiers(Class *class, MethodBlock *mb, uintptr_t *ostack) {
460 Class *clazz = GET_CLASS(ostack[0]);
461 int ignore_inner_attrs = ostack[1];
462 ClassBlock *cb = CLASS_CB(clazz);
464 if(!ignore_inner_attrs && cb->declaring_class)
465 *ostack++ = (uintptr_t)cb->inner_access_flags;
466 else
467 *ostack++ = (uintptr_t)cb->access_flags;
469 return ostack;
470 }
472 uintptr_t *forName0(uintptr_t *ostack, int resolve, Object *loader) {
473 Object *string = (Object *)ostack[0];
474 Class *class = NULL;
475 int len, i = 0;
476 char *cstr;
478 if(string == NULL) {
479 signalException(java_lang_NullPointerException, NULL);
480 return ostack;
481 }
483 cstr = String2Utf8(string);
484 len = strlen(cstr);
486 /* Check the classname to see if it's valid. It can be
487 a 'normal' class or an array class, starting with a [ */
489 if(cstr[0] == '[') {
490 for(; cstr[i] == '['; i++);
491 switch(cstr[i]) {
492 case 'Z':
493 case 'B':
494 case 'C':
495 case 'S':
496 case 'I':
497 case 'F':
498 case 'J':
499 case 'D':
500 if(len-i != 1)
501 goto out;
502 break;
503 case 'L':
504 if(cstr[i+1] == '[' || cstr[len-1] != ';')
505 goto out;
506 break;
507 default:
508 goto out;
509 break;
510 }
511 }
513 /* Scan the classname and convert it to internal form
514 by converting dots to slashes. Reject classnames
515 containing slashes, as this is an invalid character */
517 for(; i < len; i++) {
518 if(cstr[i] == '/')
519 goto out;
520 if(cstr[i] == '.')
521 cstr[i] = '/';
522 }
524 class = findClassFromClassLoader(cstr, loader);
526 out:
527 if(class == NULL) {
528 Object *e = exceptionOccurred();
529 clearException();
530 signalChainedException(java_lang_ClassNotFoundException, cstr, e);
531 } else
532 if(resolve)
533 initClass(class);
535 sysFree(cstr);
536 *ostack++ = (uintptr_t)class;
537 return ostack;
538 }
540 uintptr_t *forName(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
541 int init = ostack[1];
542 Object *loader = (Object*)ostack[2];
543 return forName0(ostack, init, loader);
544 }
546 uintptr_t *throwException(Class *class, MethodBlock *mb, uintptr_t *ostack) {
547 Object *excep = (Object *)ostack[0];
548 setException(excep);
549 return ostack;
550 }
552 uintptr_t *hasClassInitializer(Class *class, MethodBlock *mb, uintptr_t *ostack) {
553 Class *clazz = (Class*)ostack[0];
554 *ostack++ = findMethod(clazz, SYMBOL(class_init),
555 SYMBOL(___V)) == NULL ? FALSE : TRUE;
556 return ostack;
557 }
559 /* java.lang.VMThrowable */
561 uintptr_t *fillInStackTrace(Class *class, MethodBlock *mb, uintptr_t *ostack) {
562 *ostack++ = (uintptr_t) setStackTrace();
563 return ostack;
564 }
566 uintptr_t *getStackTrace(Class *class, MethodBlock *m, uintptr_t *ostack) {
567 Object *this = (Object *)*ostack;
568 *ostack++ = (uintptr_t) convertStackTrace(this);
569 return ostack;
570 }
572 /* gnu.classpath.VMStackWalker */
574 uintptr_t *getCallingClass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
575 *ostack++ = (uintptr_t) getCallerCallerClass();
576 return ostack;
577 }
579 uintptr_t *getCallingClassLoader(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
580 Class *class = getCallerCallerClass();
582 *ostack++ = (uintptr_t) (class ? CLASS_CB(class)->class_loader : NULL);
583 return ostack;
584 }
586 uintptr_t *getClassContext(Class *class, MethodBlock *mb, uintptr_t *ostack) {
587 Class *class_class = findArrayClass("[Ljava/lang/Class;");
588 Object *array;
589 Frame *last;
591 if(class_class == NULL)
592 return ostack;
594 if((last = getCallerFrame(getExecEnv()->last_frame)) == NULL)
595 array = allocArray(class_class, 0, sizeof(Class*));
596 else {
597 Frame *bottom = last;
598 int depth = 0;
600 do {
601 for(; last->mb != NULL; last = last->prev, depth++);
602 } while((last = last->prev)->prev != NULL);
604 array = allocArray(class_class, depth, sizeof(Class*));
606 if(array != NULL) {
607 Class **data = ARRAY_DATA(array);
609 do {
610 for(; bottom->mb != NULL; bottom = bottom->prev)
611 *data++ = bottom->mb->class;
612 } while((bottom = bottom->prev)->prev != NULL);
613 }
614 }
616 *ostack++ = (uintptr_t)array;
617 return ostack;
618 }
620 uintptr_t *firstNonNullClassLoader(Class *class, MethodBlock *mb, uintptr_t *ostack) {
621 Frame *last = getExecEnv()->last_frame;
622 Object *loader = NULL;
624 do {
625 for(; last->mb != NULL; last = last->prev)
626 if((loader = CLASS_CB(last->mb->class)->class_loader) != NULL)
627 goto out;
628 } while((last = last->prev)->prev != NULL);
630 out:
631 *ostack++ = (uintptr_t)loader;
632 return ostack;
633 }
635 /* java.lang.VMClassLoader */
637 /* loadClass(Ljava/lang/String;I)Ljava/lang/Class; */
638 uintptr_t *loadClass(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
639 int resolve = ostack[1];
640 return forName0(ostack, resolve, NULL);
641 }
643 /* getPrimitiveClass(C)Ljava/lang/Class; */
644 uintptr_t *getPrimitiveClass(Class *class, MethodBlock *mb, uintptr_t *ostack) {
645 char prim_type = *ostack;
646 *ostack++ = (uintptr_t)findPrimitiveClass(prim_type);
647 return ostack;
648 }
650 uintptr_t *defineClass0(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
651 Object *class_loader = (Object *)ostack[0];
652 Object *string = (Object *)ostack[1];
653 Object *array = (Object *)ostack[2];
654 int offset = ostack[3];
655 int data_len = ostack[4];
656 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
657 uintptr_t pd = ostack[5];
658 #elif WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
659 Object* pd = ostack[5];
660 #endif
661 Class *class = NULL;
663 if(array == NULL)
664 signalException(java_lang_NullPointerException, NULL);
665 else
666 if((offset < 0) || (data_len < 0) ||
667 ((offset + data_len) > ARRAY_LEN(array)))
668 signalException(java_lang_ArrayIndexOutOfBoundsException, NULL);
669 else {
670 char *data = ARRAY_DATA(array);
671 char *cstr = string ? String2Utf8(string) : NULL;
672 int len = string ? strlen(cstr) : 0;
673 int i;
675 for(i = 0; i < len; i++)
676 if(cstr[i]=='.') cstr[i]='/';
678 #ifdef WITH_JAVA_RUNTIME_LIBRARY_CLASSPATH
679 if((class = defineClass(cstr, data, offset, data_len, class_loader, NULL)) != NULL) {
680 INST_DATA(class)[pd_offset] = pd;
681 #elif WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
682 if((class = defineClass(cstr, data, offset, data_len, class_loader, pd)) != NULL) {
683 #endif
684 linkClass(class);
685 }
687 sysFree(cstr);
688 }
690 *ostack++ = (uintptr_t) class;
691 return ostack;
692 }
694 uintptr_t *findLoadedClass(Class *clazz, MethodBlock *mb, uintptr_t *ostack) {
695 Object *class_loader = (Object *)ostack[0];
696 Object *string = (Object *)ostack[1];
697 Class *class;
698 char *cstr;
699 int len, i;
701 if(string == NULL) {
702 signalException(java_lang_NullPointerException, NULL);
703 return ostack;
704 }
706 cstr = String2Cstr(string);
707 len = strlen(cstr);
709 for(i = 0; i < len; i++)
710 if(cstr[i]=='.') cstr[i]='/';
712 class = findHashedClass(cstr, class_loader);
714 sysFree(cstr);
715 *ostack++ = (uintptr_t) class;
716 return ostack;
717 }
719 uintptr_t *resolveClass0(Class *class, MethodBlock *mb, uintptr_t *ostack) {
720 Class *clazz = (Class *)*ostack;
722 if(clazz == NULL)
723 signalException(java_lang_NullPointerException, NULL);
724 else
725 initClass(clazz);
727 return ostack;
728 }
730 uintptr_t *getBootClassPathSize(Class *class, MethodBlock *mb, uintptr_t *ostack) {
731 *ostack++ = bootClassPathSize();
732 return ostack;
733 }
735 uintptr_t *getBootClassPathResource(Class *class, MethodBlock *mb, uintptr_t *ostack) {
736 Object *string = (Object *) ostack[0];
737 char *filename = String2Cstr(string);
738 int index = ostack[1];
740 *ostack++ = (uintptr_t) bootClassPathResource(filename, index);
741 return ostack;
742 }
744 /* java.lang.reflect.Constructor */
746 uintptr_t *constructNative(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
747 Object *array = (Object*)ostack[1];
748 Class *decl_class = (Class*)ostack[2];
749 Object *param_types = (Object*)ostack[3];
750 ClassBlock *cb = CLASS_CB(decl_class);
751 MethodBlock *mb = &(cb->methods[ostack[4]]);
752 int no_access_check = ostack[5];
753 Object *ob;
755 if(cb->access_flags & ACC_ABSTRACT) {
756 signalException(java_lang_InstantiationError, cb->name);
757 return ostack;
758 }
760 /* Creating an instance of the class is an
761 active use; make sure it is initialised */
762 if(initClass(decl_class) == NULL)
763 return ostack;
765 if((ob = allocObject(decl_class)) != NULL) {
766 invoke(ob, mb, array, param_types, !no_access_check);
767 *ostack++ = (uintptr_t) ob;
768 }
770 return ostack;
771 }
773 uintptr_t *getMethodModifiers(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
774 Class *decl_class = (Class*)ostack[1];
775 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
776 *ostack++ = (uintptr_t) mb->access_flags;
777 return ostack;
778 }
780 uintptr_t *getMethodSignature(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
781 Class *decl_class = (Class*)ostack[1];
782 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
783 Object *string = NULL;
785 if(mb->signature != NULL) {
786 char *dot_name = slash2dots(mb->signature);
787 string = createString(dot_name);
788 sysFree(dot_name);
789 }
791 *ostack++ = (uintptr_t)string;
792 return ostack;
793 }
795 uintptr_t *getDefaultValue(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
796 Class *decl_class = (Class*)ostack[1];
797 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
798 *ostack++ = (uintptr_t)getMethodDefaultValue(mb);
799 return ostack;
800 }
802 uintptr_t *getMethodDeclaredAnnotations(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
803 Class *decl_class = (Class*)ostack[1];
804 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
805 *ostack++ = (uintptr_t)getMethodAnnotations(mb);
806 return ostack;
807 }
809 uintptr_t *getParameterAnnotations(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
810 Class *decl_class = (Class*)ostack[1];
811 MethodBlock *mb = &(CLASS_CB(decl_class)->methods[ostack[2]]);
812 *ostack++ = (uintptr_t)getMethodParameterAnnotations(mb);
813 return ostack;
814 }
816 uintptr_t *getFieldModifiers(Class *class, MethodBlock *mb, uintptr_t *ostack) {
817 Class *decl_class = (Class*)ostack[1];
818 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[2]]);
819 *ostack++ = (uintptr_t) fb->access_flags;
820 return ostack;
821 }
823 uintptr_t *getFieldSignature(Class *class, MethodBlock *mb, uintptr_t *ostack) {
824 Class *decl_class = (Class*)ostack[1];
825 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[2]]);
826 Object *string = NULL;
828 if(fb->signature != NULL) {
829 char *dot_name = slash2dots(fb->signature);
830 string = createString(dot_name);
831 sysFree(dot_name);
832 }
834 *ostack++ = (uintptr_t)string;
835 return ostack;
836 }
838 uintptr_t *getFieldDeclaredAnnotations(Class *class, MethodBlock *mb, uintptr_t *ostack) {
839 Class *decl_class = (Class*)ostack[1];
840 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[2]]);
841 *ostack++ = (uintptr_t)getFieldAnnotations(fb);
842 return ostack;
843 }
845 Object *getAndCheckObject(uintptr_t *ostack, Class *type) {
846 Object *ob = (Object*)ostack[1];
848 if(ob == NULL) {
849 signalException(java_lang_NullPointerException, NULL);
850 return NULL;
851 }
853 if(!isInstanceOf(type, ob->class)) {
854 signalException(java_lang_IllegalArgumentException,
855 "object is not an instance of declaring class");
856 return NULL;
857 }
859 return ob;
860 }
862 uintptr_t *getPntr2Field(uintptr_t *ostack) {
863 Class *decl_class = (Class *)ostack[2];
864 FieldBlock *fb = &(CLASS_CB(decl_class)->fields[ostack[4]]);
865 int no_access_check = ostack[5];
866 Object *ob;
868 if(!no_access_check) {
869 Class *caller = getCallerCallerClass();
870 if(!checkClassAccess(decl_class, caller) || !checkFieldAccess(fb, caller)) {
871 signalException(java_lang_IllegalAccessException, "field is not accessible");
872 return NULL;
873 }
874 }
876 if(fb->access_flags & ACC_STATIC) {
877 /* Setting/getting a static field of a class is an
878 active use; make sure it is initialised */
879 if(initClass(decl_class) == NULL)
880 return NULL;
881 return &fb->static_value;
882 }
884 if((ob = getAndCheckObject(ostack, decl_class)) == NULL)
885 return NULL;
887 return &(INST_DATA(ob)[fb->offset]);
888 }
890 uintptr_t *getField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
891 Class *field_type = (Class *)ostack[3];
892 uintptr_t *field;
894 /* If field is static, getPntr2Field also initialises the field's declaring class */
895 if((field = getPntr2Field(ostack)) != NULL)
896 *ostack++ = (uintptr_t) getReflectReturnObject(field_type, field);
898 return ostack;
899 }
901 uintptr_t *getPrimitiveField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
902 Class *field_type = (Class *)ostack[3];
903 int type_no = ostack[6];
905 ClassBlock *type_cb = CLASS_CB(field_type);
906 uintptr_t *field;
908 /* If field is static, getPntr2Field also initialises the field's declaring class */
909 if(((field = getPntr2Field(ostack)) != NULL) && (!(IS_PRIMITIVE(type_cb)) ||
910 ((ostack = widenPrimitiveValue(getPrimTypeIndex(type_cb), type_no, field, ostack)) == NULL)))
911 signalException(java_lang_IllegalArgumentException, "field type mismatch");
913 return ostack;
914 }
916 uintptr_t *setField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
917 Class *field_type = (Class *)ostack[3];
918 Object *value = (Object*)ostack[6];
919 uintptr_t *field;
921 /* If field is static, getPntr2Field also initialises the field's declaring class */
922 if(((field = getPntr2Field(ostack)) != NULL) &&
923 (unwrapAndWidenObject(field_type, value, field) == NULL))
924 signalException(java_lang_IllegalArgumentException, "field type mismatch");
926 return ostack;
927 }
929 uintptr_t *setPrimitiveField(Class *class, MethodBlock *mb, uintptr_t *ostack) {
930 Class *field_type = (Class *)ostack[3];
931 int type_no = ostack[6];
933 ClassBlock *type_cb = CLASS_CB(field_type);
934 uintptr_t *field;
936 /* If field is static, getPntr2Field also initialises the field's declaring class */
937 if(((field = getPntr2Field(ostack)) != NULL) && (!(IS_PRIMITIVE(type_cb)) ||
938 (widenPrimitiveValue(type_no, getPrimTypeIndex(type_cb), &ostack[7], field) == NULL)))
939 signalException(java_lang_IllegalArgumentException, "field type mismatch");
941 return ostack;
942 }
944 /* java.lang.reflect.Method */
946 uintptr_t *invokeNative(Class *class, MethodBlock *mb2, uintptr_t *ostack) {
947 Object *array = (Object*)ostack[2];
948 Class *decl_class = (Class*)ostack[3];
949 Object *param_types = (Object*)ostack[4];
950 Class *ret_type = (Class*)ostack[5];
951 ClassBlock *cb = CLASS_CB(decl_class);
952 MethodBlock *mb = &(cb->methods[ostack[6]]);
953 int no_access_check = ostack[7];
954 Object *ob = NULL;
955 uintptr_t *ret;
957 /* If it's a static method, class may not be initialised;
958 interfaces are also not normally initialised. */
959 if((mb->access_flags & ACC_STATIC) || IS_INTERFACE(cb))
960 if(initClass(decl_class) == NULL)
961 return ostack;
963 if(!(mb->access_flags & ACC_STATIC))
964 if(((ob = getAndCheckObject(ostack, decl_class)) == NULL) ||
965 ((mb = lookupVirtualMethod(ob, mb)) == NULL))
966 return ostack;
968 if((ret = (uintptr_t*) invoke(ob, mb, array, param_types, !no_access_check)) != NULL)
969 *ostack++ = (uintptr_t) getReflectReturnObject(ret_type, ret);
971 return ostack;
972 }
974 /* java.lang.VMString */
976 /* static method - intern(Ljava/lang/String;)Ljava/lang/String; */
977 uintptr_t *intern(Class *class, MethodBlock *mb, uintptr_t *ostack) {
978 Object *string = (Object*)ostack[0];
979 ostack[0] = (uintptr_t)findInternedString(string);
980 return ostack+1;
981 }
983 /* java.lang.VMThread */
985 /* static method currentThread()Ljava/lang/Thread; */
986 uintptr_t *currentThread(Class *class, MethodBlock *mb, uintptr_t *ostack) {
987 *ostack++ = (uintptr_t)getExecEnv()->thread;
988 return ostack;
989 }
991 /* static method create(Ljava/lang/Thread;J)V */
992 uintptr_t *create(Class *class, MethodBlock *mb, uintptr_t *ostack) {
993 Object *this = (Object *)ostack[0];
994 long long stack_size = *((long long*)&ostack[1]);
995 createJavaThread(this, stack_size);
996 return ostack;
997 }
999 /* static method sleep(JI)V */
1000 uintptr_t *jamSleep(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1001 long long ms = *((long long *)&ostack[0]);
1002 int ns = ostack[2];
1003 Thread *thread = threadSelf();
1005 threadSleep(thread, ms, ns);
1006 return ostack;
1009 /* instance method interrupt()V */
1010 uintptr_t *interrupt(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1011 Object *this = (Object *)*ostack;
1012 Thread *thread = threadSelf0(this);
1013 if(thread)
1014 threadInterrupt(thread);
1015 return ostack;
1018 /* instance method isAlive()Z */
1019 uintptr_t *isAlive(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1020 Object *this = (Object *)*ostack;
1021 Thread *thread = threadSelf0(this);
1022 *ostack++ = thread ? threadIsAlive(thread) : FALSE;
1023 return ostack;
1026 /* static method yield()V */
1027 uintptr_t *yield(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1028 Thread *thread = threadSelf();
1029 threadYield(thread);
1030 return ostack;
1033 /* instance method isInterrupted()Z */
1034 uintptr_t *isInterrupted(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1035 Object *this = (Object *)*ostack;
1036 Thread *thread = threadSelf0(this);
1037 *ostack++ = thread ? threadIsInterrupted(thread) : FALSE;
1038 return ostack;
1041 /* static method interrupted()Z */
1042 uintptr_t *interrupted(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1043 Thread *thread = threadSelf();
1044 *ostack++ = threadInterrupted(thread);
1045 return ostack;
1048 /* instance method nativeSetPriority(I)V */
1049 uintptr_t *nativeSetPriority(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1050 return ostack+1;
1053 /* instance method holdsLock(Ljava/lang/Object;)Z */
1054 uintptr_t *holdsLock(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1055 Object *ob = (Object *)ostack[0];
1056 if(ob == NULL)
1057 signalException(java_lang_NullPointerException, NULL);
1058 else
1059 *ostack++ = objectLockedByCurrent(ob);
1060 return ostack;
1063 /* instance method getState()Ljava/lang/String; */
1064 uintptr_t *getState(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1065 Object *this = (Object *)*ostack;
1066 Thread *thread = threadSelf0(this);
1067 char *state = thread ? getThreadStateString(thread) : "TERMINATED";
1069 *ostack++ = (uintptr_t)Cstr2String(state);
1070 return ostack;
1073 /* java.security.VMAccessController */
1075 /* instance method getStack()[[Ljava/lang/Object; */
1076 uintptr_t *getStack(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1077 Class *object_class = findArrayClass("[[Ljava/lang/Object;");
1078 Class *class_class = findArrayClass("[Ljava/lang/Class;");
1079 Class *string_class = findArrayClass("[Ljava/lang/String;");
1080 Object *stack, *names, *classes;
1081 Frame *frame;
1082 int depth;
1084 if(object_class == NULL || class_class == NULL || string_class == NULL)
1085 return ostack;
1087 frame = getExecEnv()->last_frame;
1088 depth = 0;
1090 do {
1091 for(; frame->mb != NULL; frame = frame->prev, depth++);
1092 } while((frame = frame->prev)->prev != NULL);
1094 stack = allocArray(object_class, 2, sizeof(Object*));
1095 classes = allocArray(class_class, depth, sizeof(Object*));
1096 names = allocArray(string_class, depth, sizeof(Object*));
1098 if(stack != NULL && names != NULL && classes != NULL) {
1099 Class **dcl = ARRAY_DATA(classes);
1100 Object **dnm = ARRAY_DATA(names);
1101 Object **stk = ARRAY_DATA(stack);
1103 frame = getExecEnv()->last_frame;
1105 do {
1106 for(; frame->mb != NULL; frame = frame->prev) {
1107 *dcl++ = frame->mb->class;
1108 *dnm++ = createString(frame->mb->name);
1110 } while((frame = frame->prev)->prev != NULL);
1112 stk[0] = classes;
1113 stk[1] = names;
1116 *ostack++ = (uintptr_t) stack;
1117 return ostack;
1120 uintptr_t *getThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1121 *ostack++ = getThreadsCount();
1122 return ostack;
1125 uintptr_t *getPeakThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1126 *ostack++ = getPeakThreadsCount();
1127 return ostack;
1130 uintptr_t *getTotalStartedThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1131 *(u8*)ostack = getTotalStartedThreadsCount();
1132 return ostack + 2;
1135 uintptr_t *resetPeakThreadCount(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1136 resetPeakThreadsCount();
1137 return ostack;
1140 uintptr_t *findMonitorDeadlockedThreads(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1141 *ostack++ = (uintptr_t)NULL;
1142 return ostack;
1145 uintptr_t *getThreadInfoForId(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1146 long long id = *((long long *)&ostack[0]);
1147 int max_depth = ostack[2];
1149 Thread *thread = findThreadById(id);
1150 Object *info = NULL;
1152 if(thread != NULL) {
1153 Class *info_class = findSystemClass("java/lang/management/ThreadInfo");
1155 if(info_class != NULL) {
1156 MethodBlock *init = findMethod(info_class, SYMBOL(object_init),
1157 newUtf8("(Ljava/lang/Thread;JJLjava/lang/Object;"
1158 "Ljava/lang/Thread;JJZZ[Ljava/lang/StackTraceElement;)V"));
1159 if(init != NULL) {
1160 Frame *last;
1161 int in_native;
1162 Object *vmthrowable;
1163 int self = thread == threadSelf();
1165 if(!self)
1166 suspendThread(thread);
1168 vmthrowable = setStackTrace0(thread->ee, max_depth);
1170 last = thread->ee->last_frame;
1171 in_native = last->prev == NULL || last->mb->access_flags & ACC_NATIVE;
1173 if(!self)
1174 resumeThread(thread);
1176 if(vmthrowable != NULL) {
1177 Object *trace;
1178 if((info = allocObject(info_class)) != NULL &&
1179 (trace = convertStackTrace(vmthrowable)) != NULL) {
1181 Monitor *mon = thread->blocked_mon;
1182 Object *lock = mon != NULL ? mon->obj : NULL;
1183 Thread *owner = mon != NULL ? mon->owner : NULL;
1184 Object *lock_owner = owner != NULL ? owner->ee->thread : NULL;
1186 executeMethod(info, init, thread->ee->thread, thread->blocked_count, 0LL, lock,
1187 lock_owner, thread->waited_count, 0LL, in_native, FALSE, trace);
1194 *ostack++ = (uintptr_t)info;
1195 return ostack;
1198 /* sun.misc.Unsafe */
1200 static volatile uintptr_t spinlock = 0;
1202 void lockSpinLock() {
1203 while(!LOCKWORD_COMPARE_AND_SWAP(&spinlock, 0, 1));
1206 void unlockSpinLock() {
1207 LOCKWORD_WRITE(&spinlock, 0);
1210 uintptr_t *objectFieldOffset(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1211 FieldBlock *fb = fbFromReflectObject((Object*)ostack[1]);
1213 *(long long*)ostack = (long long)(uintptr_t)&INST_DATA((Object*)NULL)[fb->offset];
1214 return ostack + 2;
1217 uintptr_t *compareAndSwapInt(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1218 long long offset = *((long long *)&ostack[2]);
1219 uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1220 uintptr_t expect = ostack[4];
1221 uintptr_t update = ostack[5];
1222 int result;
1224 #ifdef COMPARE_AND_SWAP
1225 result = COMPARE_AND_SWAP(addr, expect, update);
1226 #else
1227 lockSpinLock();
1228 if((result = (*addr == expect)))
1229 *addr = update;
1230 unlockSpinLock();
1231 #endif
1233 *ostack++ = result;
1234 return ostack;
1237 uintptr_t *compareAndSwapLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1238 long long offset = *((long long *)&ostack[2]);
1239 long long *addr = (long long*)((char*)ostack[1] + offset);
1240 long long expect = *((long long *)&ostack[4]);
1241 long long update = *((long long *)&ostack[6]);
1242 int result;
1244 #ifdef COMPARE_AND_SWAP_64
1245 result = COMPARE_AND_SWAP_64(addr, expect, update);
1246 #else
1247 lockSpinLock();
1248 if((result = (*addr == expect)))
1249 *addr = update;
1250 unlockSpinLock();
1251 #endif
1253 *ostack++ = result;
1254 return ostack;
1257 uintptr_t *putOrderedInt(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1258 long long offset = *((long long *)&ostack[2]);
1259 volatile uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1260 uintptr_t value = ostack[4];
1262 *addr = value;
1263 return ostack;
1266 uintptr_t *putOrderedLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1267 long long offset = *((long long *)&ostack[2]);
1268 long long value = *((long long *)&ostack[4]);
1269 volatile long long *addr = (long long*)((char*)ostack[1] + offset);
1271 if(sizeof(uintptr_t) == 8)
1272 *addr = value;
1273 else {
1274 lockSpinLock();
1275 *addr = value;
1276 unlockSpinLock();
1279 return ostack;
1282 uintptr_t *putIntVolatile(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1283 long long offset = *((long long *)&ostack[2]);
1284 volatile uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1285 uintptr_t value = ostack[4];
1287 MBARRIER();
1288 *addr = value;
1290 return ostack;
1293 uintptr_t *getIntVolatile(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1294 long long offset = *((long long *)&ostack[2]);
1295 volatile uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1297 *ostack++ = *addr;
1298 MBARRIER();
1300 return ostack;
1303 uintptr_t *putLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1304 long long offset = *((long long *)&ostack[2]);
1305 long long value = *((long long *)&ostack[4]);
1306 long long *addr = (long long*)((char*)ostack[1] + offset);
1308 if(sizeof(uintptr_t) == 8)
1309 *addr = value;
1310 else {
1311 lockSpinLock();
1312 *addr = value;
1313 unlockSpinLock();
1316 return ostack;
1319 uintptr_t *getLongVolatile(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1320 long long offset = *((long long *)&ostack[2]);
1321 volatile long long *addr = (long long*)((char*)ostack[1] + offset);
1323 if(sizeof(uintptr_t) == 8)
1324 *(long long*)ostack = *addr;
1325 else {
1326 lockSpinLock();
1327 *(long long*)ostack = *addr;
1328 unlockSpinLock();
1331 return ostack + 2;
1334 uintptr_t *getLong(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1335 long long offset = *((long long *)&ostack[2]);
1336 long long *addr = (long long*)((char*)ostack[1] + offset);
1338 if(sizeof(uintptr_t) == 8)
1339 *(long long*)ostack = *addr;
1340 else {
1341 lockSpinLock();
1342 *(long long*)ostack = *addr;
1343 unlockSpinLock();
1346 return ostack + 2;
1349 uintptr_t *putObject(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1350 long long offset = *((long long *)&ostack[2]);
1351 uintptr_t *addr = (uintptr_t*)((char *)ostack[1] + offset);
1352 uintptr_t value = ostack[4];
1354 *addr = value;
1355 return ostack;
1358 uintptr_t *arrayBaseOffset(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1359 *ostack++ = (uintptr_t) ARRAY_DATA((Object*)NULL);
1360 return ostack;
1363 uintptr_t *arrayIndexScale(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1364 Class *array_class = (Class*)ostack[1];
1365 ClassBlock *cb = CLASS_CB(array_class);
1366 int scale = 0;
1368 if(cb->name[0] == '[')
1369 switch(cb->name[1]) {
1370 case 'I':
1371 case 'F':
1372 scale = 4;
1373 break;
1375 case '[':
1376 case 'L':
1377 scale = sizeof(Object*);
1378 break;
1380 case 'J':
1381 case 'D':
1382 scale = 8;
1383 break;
1386 *ostack++ = scale;
1387 return ostack;
1390 uintptr_t *unpark(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1391 return ostack;
1394 uintptr_t *park(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1395 return ostack;
1398 uintptr_t *vmSupportsCS8(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1399 *ostack++ = FALSE;
1400 return ostack;
1403 /* jamvm.java.lang.VMClassLoaderData */
1405 uintptr_t *nativeUnloadDll(Class *class, MethodBlock *mb, uintptr_t *ostack) {
1406 unloaderUnloadDll((uintptr_t)*(long long*)&ostack[1]);
1407 return ostack;
1410 VMMethod vm_object[] = {
1411 {"getClass", getClass},
1412 {"clone", jamClone},
1413 {"wait", jamWait},
1414 {"notify", notify},
1415 {"notifyAll", notifyAll},
1416 {NULL, NULL}
1417 };
1419 VMMethod vm_system[] = {
1420 {"arraycopy", arraycopy},
1421 {"identityHashCode", identityHashCode},
1422 {NULL, NULL}
1423 };
1425 VMMethod vm_runtime[] = {
1426 {"availableProcessors", availableProcessors},
1427 {"freeMemory", freeMemory},
1428 {"totalMemory", totalMemory},
1429 {"maxMemory", maxMemory},
1430 {"gc", gc},
1431 {"runFinalization", runFinalization},
1432 {"exit", exitInternal},
1433 {"nativeLoad", nativeLoad},
1434 {"mapLibraryName", mapLibraryName},
1435 {NULL, NULL}
1436 };
1438 VMMethod vm_class[] = {
1439 {"isInstance", isInstance},
1440 {"isAssignableFrom", isAssignableFrom},
1441 {"isInterface", isInterface},
1442 {"isPrimitive", isPrimitive},
1443 {"isArray", isArray},
1444 {"isMemberClass", isMember},
1445 {"isLocalClass", isLocal},
1446 {"isAnonymousClass", isAnonymous},
1447 {"getEnclosingClass", getEnclosingClass0},
1448 {"getEnclosingMethod", getEnclosingMethod0},
1449 {"getEnclosingConstructor", getEnclosingConstructor},
1450 {"getClassSignature", getClassSignature},
1451 {"getSuperclass", getSuperclass},
1452 {"getComponentType", getComponentType},
1453 {"getName", getName},
1454 {"getDeclaredClasses", getDeclaredClasses},
1455 {"getDeclaringClass", getDeclaringClass0},
1456 {"getDeclaredConstructors", getDeclaredConstructors},
1457 {"getDeclaredMethods", getDeclaredMethods},
1458 {"getDeclaredFields", getDeclaredFields},
1459 {"getInterfaces", getInterfaces},
1460 {"getClassLoader", getClassLoader},
1461 {"getModifiers", getClassModifiers},
1462 {"forName", forName},
1463 {"throwException", throwException},
1464 {"hasClassInitializer", hasClassInitializer},
1465 {"getDeclaredAnnotations", getClassDeclaredAnnotations},
1466 {NULL, NULL}
1467 };
1469 VMMethod vm_string[] = {
1470 {"intern", intern},
1471 {NULL, NULL}
1472 };
1474 VMMethod vm_thread[] = {
1475 {"currentThread", currentThread},
1476 {"create", create},
1477 {"sleep", jamSleep},
1478 {"interrupt", interrupt},
1479 {"isAlive", isAlive},
1480 {"yield", yield},
1481 {"isInterrupted", isInterrupted},
1482 {"interrupted", interrupted},
1483 {"nativeSetPriority", nativeSetPriority},
1484 {"holdsLock", holdsLock},
1485 {"getState", getState},
1486 {NULL, NULL}
1487 };
1489 VMMethod vm_throwable[] = {
1490 {"fillInStackTrace", fillInStackTrace},
1491 {"getStackTrace", getStackTrace},
1492 {NULL, NULL}
1493 };
1495 VMMethod vm_classloader[] = {
1496 {"loadClass", loadClass},
1497 {"getPrimitiveClass", getPrimitiveClass},
1498 {"defineClass", defineClass0},
1499 {"findLoadedClass", findLoadedClass},
1500 {"resolveClass", resolveClass0},
1501 {"getBootClassPathSize", getBootClassPathSize},
1502 {"getBootClassPathResource", getBootClassPathResource},
1503 {NULL, NULL}
1504 };
1506 VMMethod vm_reflect_constructor[] = {
1507 {"constructNative", constructNative},
1508 {"getConstructorModifiers", getMethodModifiers},
1509 {"getSignature", getMethodSignature},
1510 {"getDeclaredAnnotationsNative", getMethodDeclaredAnnotations},
1511 {"getParameterAnnotationsNative", getParameterAnnotations},
1512 {NULL, NULL}
1513 };
1515 VMMethod vm_reflect_method[] = {
1516 {"invokeNative", invokeNative},
1517 {"getMethodModifiers", getMethodModifiers},
1518 {"getSignature", getMethodSignature},
1519 {"getDefaultValueNative", getDefaultValue},
1520 {"getDeclaredAnnotationsNative", getMethodDeclaredAnnotations},
1521 {"getParameterAnnotationsNative", getParameterAnnotations},
1522 {NULL, NULL}
1523 };
1525 VMMethod vm_reflect_field[] = {
1526 {"getFieldModifiers", getFieldModifiers},
1527 {"getSignature", getFieldSignature},
1528 {"getDeclaredAnnotationsNative", getFieldDeclaredAnnotations},
1529 {"getField", getField},
1530 {"setField", setField},
1531 {"setZField", setPrimitiveField},
1532 {"setBField", setPrimitiveField},
1533 {"setCField", setPrimitiveField},
1534 {"setSField", setPrimitiveField},
1535 {"setIField", setPrimitiveField},
1536 {"setFField", setPrimitiveField},
1537 {"setJField", setPrimitiveField},
1538 {"setDField", setPrimitiveField},
1539 {"getZField", getPrimitiveField},
1540 {"getBField", getPrimitiveField},
1541 {"getCField", getPrimitiveField},
1542 {"getSField", getPrimitiveField},
1543 {"getIField", getPrimitiveField},
1544 {"getFField", getPrimitiveField},
1545 {"getJField", getPrimitiveField},
1546 {"getDField", getPrimitiveField},
1547 {NULL, NULL}
1548 };
1550 VMMethod vm_system_properties[] = {
1551 {"preInit", propertiesPreInit},
1552 {"postInit", propertiesPostInit},
1553 {NULL, NULL}
1554 };
1556 VMMethod vm_stack_walker[] = {
1557 {"getClassContext", getClassContext},
1558 {"getCallingClass", getCallingClass},
1559 {"getCallingClassLoader", getCallingClassLoader},
1560 {"firstNonNullClassLoader", firstNonNullClassLoader},
1561 {NULL, NULL}
1562 };
1564 VMMethod sun_misc_unsafe[] = {
1565 {"objectFieldOffset", objectFieldOffset},
1566 {"compareAndSwapInt", compareAndSwapInt},
1567 {"compareAndSwapLong", compareAndSwapLong},
1568 {"compareAndSwapObject", compareAndSwapInt},
1569 {"putOrderedInt", putOrderedInt},
1570 {"putOrderedLong", putOrderedLong},
1571 {"putOrderedObject", putOrderedInt},
1572 {"putIntVolatile", putIntVolatile},
1573 {"getIntVolatile", getIntVolatile},
1574 {"putLongVolatile", putOrderedLong},
1575 {"putLong", putLong},
1576 {"getLongVolatile", getLongVolatile},
1577 {"getLong", getLong},
1578 {"putObjectVolatile", putIntVolatile},
1579 {"putObject", putObject},
1580 {"getObjectVolatile", getIntVolatile},
1581 {"arrayBaseOffset", arrayBaseOffset},
1582 {"arrayIndexScale", arrayIndexScale},
1583 {"unpark", unpark},
1584 {"park", park},
1585 {NULL, NULL}
1586 };
1588 VMMethod vm_access_controller[] = {
1589 {"getStack", getStack},
1590 {NULL, NULL}
1591 };
1593 VMMethod vm_threadmx_bean_impl[] = {
1594 {"getThreadCount", getThreadCount},
1595 {"getPeakThreadCount", getPeakThreadCount},
1596 {"getTotalStartedThreadCount", getTotalStartedThreadCount},
1597 {"resetPeakThreadCount", resetPeakThreadCount},
1598 {"getThreadInfoForId", getThreadInfoForId},
1599 {"findMonitorDeadlockedThreads",findMonitorDeadlockedThreads},
1600 {NULL, NULL}
1601 };
1603 VMMethod concurrent_atomic_long[] = {
1604 {"VMSupportsCS8", vmSupportsCS8},
1605 {NULL, NULL}
1606 };
1608 VMMethod vm_class_loader_data[] = {
1609 {"nativeUnloadDll", nativeUnloadDll},
1610 {NULL, NULL}
1611 };
1613 VMClass native_methods[] = {
1614 {"java/lang/VMClass", vm_class},
1615 {"java/lang/VMObject", vm_object},
1616 {"java/lang/VMThread", vm_thread},
1617 {"java/lang/VMSystem", vm_system},
1618 {"java/lang/VMString", vm_string},
1619 {"java/lang/VMRuntime", vm_runtime},
1620 {"java/lang/VMThrowable", vm_throwable},
1621 {"java/lang/VMClassLoader", vm_classloader},
1622 {"java/lang/reflect/Field", vm_reflect_field},
1623 {"java/lang/reflect/Method", vm_reflect_method},
1624 {"java/lang/reflect/Constructor", vm_reflect_constructor},
1625 {"java/security/VMAccessController", vm_access_controller},
1626 {"gnu/classpath/VMSystemProperties", vm_system_properties},
1627 {"gnu/classpath/VMStackWalker", vm_stack_walker},
1628 {"gnu/java/lang/management/VMThreadMXBeanImpl", vm_threadmx_bean_impl},
1629 {"sun/misc/Unsafe", sun_misc_unsafe},
1630 {"jamvm/java/lang/VMClassLoaderData$Unloader", vm_class_loader_data},
1631 {"java/util/concurrent/atomic/AtomicLong", concurrent_atomic_long},
1632 {NULL, NULL}
1633 };