1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000 Red Hat, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
15 #pragma implementation "java-interp.h"
18 #include <java-cpool.h>
19 #include <java-interp.h>
20 #include <java/lang/fdlibm.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/StringBuffer.h>
25 #include <java/lang/Class.h>
26 #include <java/lang/reflect/Modifier.h>
27 #include <java/lang/ClassCastException.h>
28 #include <java/lang/VirtualMachineError.h>
29 #include <java/lang/InternalError.h>
30 #include <java/lang/NullPointerException.h>
31 #include <java/lang/ArithmeticException.h>
32 #include <java/lang/IncompatibleClassChangeError.h>
33 #include <java-insns.h>
34 #include <java-signal.h>
38 #include <gnu/gcj/runtime/MethodInvocation.h>
40 /* This should never happen. */
42 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
45 JvFail ("no interpreter");
50 #define ClassError _CL_Q34java4lang5Error
51 extern java::lang::Class ClassError;
53 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
55 static void throw_internal_error (char *msg)
56 __attribute__ ((__noreturn__));
57 static void throw_incompatible_class_change_error (jstring msg)
58 __attribute__ ((__noreturn__));
60 static void throw_null_pointer_exception ()
61 __attribute__ ((__noreturn__));
64 static void throw_arithmetic_exception ()
65 __attribute__ ((__noreturn__));
69 static inline void dupx (_Jv_word *sp, int n, int x)
71 // first "slide" n+x elements n to the right
73 for (int i = 0; i < n+x; i++)
75 sp[(top-i)] = sp[(top-i)-n];
78 // next, copy the n top elements, n+x down
79 for (int i = 0; i < n; i++)
81 sp[top-(n+x)-i] = sp[top-i];
87 #define PUSHA(V) (sp++)->o = (V)
88 #define PUSHI(V) (sp++)->i = (V)
89 #define PUSHF(V) (sp++)->f = (V)
90 #define PUSHL(V) ({ _Jv_word2 w2; w2.l=(V); \
91 (sp++)->ia[0] = w2.ia[0]; \
92 (sp++)->ia[0] = w2.ia[1]; })
93 #define PUSHD(V) ({ _Jv_word2 w2; w2.d=(V); \
94 (sp++)->ia[0] = w2.ia[0]; \
95 (sp++)->ia[0] = w2.ia[1]; })
97 #define POPA() ((--sp)->o)
98 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
99 #define POPF() ((jfloat) (--sp)->f)
100 #define POPL() ({ _Jv_word2 w2; \
101 w2.ia[1] = (--sp)->ia[0]; \
102 w2.ia[0] = (--sp)->ia[0]; w2.l; })
103 #define POPD() ({ _Jv_word2 w2; \
104 w2.ia[1] = (--sp)->ia[0]; \
105 w2.ia[0] = (--sp)->ia[0]; w2.d; })
107 #define LOADA(I) (sp++)->o = locals[I].o
108 #define LOADI(I) (sp++)->i = locals[I].i
109 #define LOADF(I) (sp++)->f = locals[I].f
110 #define LOADL(I) ({ jint __idx = (I); \
111 (sp++)->ia[0] = locals[__idx].ia[0]; \
112 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
114 #define LOADD(I) LOADL(I)
117 #define STOREA(I) locals[I].o = (--sp)->o
118 #define STOREI(I) locals[I].i = (--sp)->i
119 #define STOREF(I) locals[I].f = (--sp)->f
120 #define STOREL(I) ({ jint __idx = (I); \
121 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
122 locals[__idx].ia[0] = (--sp)->ia[0]; \
124 #define STORED(I) STOREL(I)
126 #define PEEKI(I) (locals+(I))->i
127 #define PEEKA(I) (locals+(I))->o
129 #define POKEI(I,V) ((locals+(I))->i = (V))
132 #define BINOPI(OP) { \
133 jint value2 = POPI(); \
134 jint value1 = POPI(); \
135 PUSHI(value1 OP value2); \
138 #define BINOPF(OP) { \
139 jfloat value2 = POPF(); \
140 jfloat value1 = POPF(); \
141 PUSHF(value1 OP value2); \
144 #define BINOPL(OP) { \
145 jlong value2 = POPL(); \
146 jlong value1 = POPL(); \
147 PUSHL(value1 OP value2); \
150 #define BINOPD(OP) { \
151 jdouble value2 = POPD(); \
152 jdouble value1 = POPD(); \
153 PUSHD(value1 OP value2); \
156 static inline jint get1s(unsigned char* loc) {
157 return *(signed char*)loc;
160 static inline jint get1u(unsigned char* loc) {
164 static inline jint get2s(unsigned char* loc) {
165 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
168 static inline jint get2u(unsigned char* loc) {
169 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
172 static jint get4(unsigned char* loc) {
173 return (((jint)(loc[0])) << 24)
174 | (((jint)(loc[1])) << 16)
175 | (((jint)(loc[2])) << 8)
176 | (((jint)(loc[3])) << 0);
183 #define NULLCHECK(X) \
184 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
190 #define ZEROCHECK(X) \
191 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
194 // this method starts the actual running of the method. It is inlined
195 // in three different variants in the static methods run_normal,
196 // run_sync_object and run_sync_class (see below). Those static methods
197 // are installed directly in the stub for this method (by
198 // _Jv_InterpMethod::ncode, in resolve.cc).
201 _Jv_InterpMethod::run (ffi_cif* cif,
204 _Jv_InterpMethodInvocation *inv)
207 inv->pc = bytecode ();
208 inv->sp = inv->stack_base ();
209 _Jv_word *locals = inv->local_base ();
211 /* Go straight at it! the ffi raw format matches the internal
212 stack representation exactly. At leat, that's the idea.
214 memcpy ((void*) locals, (void*) args, args_raw_size);
217 /* this will call the method _Jv_InterpMethod::continue0, see below */
219 gnu::gcj::runtime::MethodInvocation::continue0
220 ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
222 if (ex == 0) // no exception...
224 /* define sp locally, so the POP? macros will pick it up */
225 _Jv_word *sp = inv->sp;
226 int rtype = cif->rtype->type;
228 if (rtype == FFI_TYPE_POINTER)
231 *(jobject*) retp = r;
234 else if (rtype == FFI_TYPE_SINT32)
240 else if (rtype == FFI_TYPE_VOID)
253 case FFI_TYPE_DOUBLE:
261 case FFI_TYPE_UINT16:
262 case FFI_TYPE_UINT32:
264 case FFI_TYPE_SINT16:
271 case FFI_TYPE_SINT64:
279 throw_internal_error ("unknown return type");
284 /** handle an exception */
285 if ( find_exception (ex, inv) )
291 bool _Jv_InterpMethod::find_exception (jobject ex,
292 _Jv_InterpMethodInvocation *inv)
294 int logical_pc = inv->pc - bytecode ();
295 _Jv_InterpException *exc = exceptions ();
296 jclass exc_class = ex->getClass ();
298 for (int i = 0; i < exc_count; i++)
300 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
304 if (exc[i].handler_type != 0)
305 handler = (_Jv_ResolvePoolEntry (defining_class,
306 exc[i].handler_type)).clazz;
310 if (handler==NULL || handler->isAssignableFrom (exc_class))
312 inv->pc = bytecode () + exc[i].handler_pc;
313 inv->sp = inv->stack_base (); // reset stack
314 (inv->sp++)->o = ex; // push exception
322 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
327 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
329 // we do the alloca of the method invocation here, to allow the method
330 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
331 int storage_size = _this->max_stack+_this->max_locals;
332 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
333 alloca (sizeof (_Jv_InterpMethodInvocation)
334 + storage_size * sizeof (_Jv_word));
336 jobject ex = _this->run (cif, ret, args, inv);
337 if (ex != 0) _Jv_Throw (ex);
340 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
345 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
346 jobject rcv = (jobject)args[0].ptr;
348 int storage_size = _this->max_stack+_this->max_locals;
349 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
350 alloca (sizeof (_Jv_InterpMethodInvocation)
351 + storage_size * sizeof (_Jv_word));
353 _Jv_MonitorEnter (rcv);
354 jobject ex = _this->run (cif, ret, args, inv);
355 _Jv_MonitorExit (rcv);
357 if (ex != 0) _Jv_Throw (ex);
360 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
365 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
366 jclass sync = _this->defining_class;
368 int storage_size = _this->max_stack+_this->max_locals;
369 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
370 alloca (sizeof (_Jv_InterpMethodInvocation)
371 + storage_size * sizeof (_Jv_word));
373 _Jv_MonitorEnter (sync);
374 jobject ex = _this->run (cif, ret, args, inv);
375 _Jv_MonitorExit (sync);
377 if (ex != 0) _Jv_Throw (ex);
380 /* this is the exception handler hack, for the interpreter */
382 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
383 gnu::gcj::RawData *inv)
385 _Jv_InterpMethod *meth0 = (_Jv_InterpMethod*)meth;
386 _Jv_InterpMethodInvocation *inv0 = (_Jv_InterpMethodInvocation*)inv;
387 meth0->continue1 (inv0);
391 This proceeds execution, as designated in "inv". If an exception
392 happens, then it is simply thrown, and handled in Java. Thus, the pc
393 needs to be stored in the inv->pc at all times, so we can figure
394 out which handler (if any) to invoke.
396 One design issue, which I have not completely considered, is if it
397 should be possible to have interpreted classes linked in! Seldom used
398 (or non-critical) classes could reasonably be interpreted.
402 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
404 using namespace java::lang::reflect;
406 register _Jv_word *sp = inv->sp;
407 register unsigned char *pc = inv->pc;
408 _Jv_word *locals = inv->local_base ();
410 _Jv_word *pool_data = defining_class->constants.data;
412 /* these two are used in the invokeXXX instructions */
414 _Jv_ResolvedMethod* rmeth;
416 #define INSN_LABEL(op) &&insn_##op
417 #define GOTO_INSN(op) goto *(insn_target[op])
419 static const void *const insn_target[] =
422 INSN_LABEL(aconst_null),
423 INSN_LABEL(iconst_m1),
424 INSN_LABEL(iconst_0),
425 INSN_LABEL(iconst_1),
426 INSN_LABEL(iconst_2),
427 INSN_LABEL(iconst_3),
428 INSN_LABEL(iconst_4),
429 INSN_LABEL(iconst_5),
430 INSN_LABEL(lconst_0),
431 INSN_LABEL(lconst_1),
432 INSN_LABEL(fconst_0),
433 INSN_LABEL(fconst_1),
434 INSN_LABEL(fconst_2),
435 INSN_LABEL(dconst_0),
436 INSN_LABEL(dconst_1),
480 INSN_LABEL(istore_0),
481 INSN_LABEL(istore_1),
482 INSN_LABEL(istore_2),
483 INSN_LABEL(istore_3),
484 INSN_LABEL(lstore_0),
485 INSN_LABEL(lstore_1),
486 INSN_LABEL(lstore_2),
487 INSN_LABEL(lstore_3),
488 INSN_LABEL(fstore_0),
489 INSN_LABEL(fstore_1),
490 INSN_LABEL(fstore_2),
491 INSN_LABEL(fstore_3),
492 INSN_LABEL(dstore_0),
493 INSN_LABEL(dstore_1),
494 INSN_LABEL(dstore_2),
495 INSN_LABEL(dstore_3),
496 INSN_LABEL(astore_0),
497 INSN_LABEL(astore_1),
498 INSN_LABEL(astore_2),
499 INSN_LABEL(astore_3),
580 INSN_LABEL(if_icmpeq),
581 INSN_LABEL(if_icmpne),
582 INSN_LABEL(if_icmplt),
583 INSN_LABEL(if_icmpge),
584 INSN_LABEL(if_icmpgt),
585 INSN_LABEL(if_icmple),
586 INSN_LABEL(if_acmpeq),
587 INSN_LABEL(if_acmpne),
591 INSN_LABEL(tableswitch),
592 INSN_LABEL(lookupswitch),
599 INSN_LABEL(getstatic),
600 INSN_LABEL(putstatic),
601 INSN_LABEL(getfield),
602 INSN_LABEL(putfield),
603 INSN_LABEL(invokevirtual),
604 INSN_LABEL(invokespecial),
605 INSN_LABEL(invokestatic),
606 INSN_LABEL(invokeinterface),
607 0, /* op_xxxunusedxxx1, */
609 INSN_LABEL(newarray),
610 INSN_LABEL(anewarray),
611 INSN_LABEL(arraylength),
613 INSN_LABEL(checkcast),
614 INSN_LABEL(instanceof),
615 INSN_LABEL(monitorenter),
616 INSN_LABEL(monitorexit),
618 INSN_LABEL(multianewarray),
620 INSN_LABEL(ifnonnull),
624 INSN_LABEL(putfield_1),
625 INSN_LABEL(putfield_2),
626 INSN_LABEL(putfield_4),
627 INSN_LABEL(putfield_8),
628 INSN_LABEL(putfield_a),
630 INSN_LABEL(putstatic_1),
631 INSN_LABEL(putstatic_2),
632 INSN_LABEL(putstatic_4),
633 INSN_LABEL(putstatic_8),
634 INSN_LABEL(putstatic_a),
636 INSN_LABEL(getfield_1),
637 INSN_LABEL(getfield_2s),
638 INSN_LABEL(getfield_2u),
639 INSN_LABEL(getfield_4),
640 INSN_LABEL(getfield_8),
641 INSN_LABEL(getfield_a),
643 INSN_LABEL(getstatic_1),
644 INSN_LABEL(getstatic_2s),
645 INSN_LABEL(getstatic_2u),
646 INSN_LABEL(getstatic_4),
647 INSN_LABEL(getstatic_8),
648 INSN_LABEL(getstatic_a),
651 #define SAVE_PC inv->pc = pc-1
653 /* If the macro INLINE_SWITCH is not defined, then the main loop
654 operates as one big (normal) switch statement. If it is defined,
655 then the case selection is performed `inline' in the end of the
656 code for each case. The latter saves a native branch instruction
657 for each java-instruction, but expands the code size somewhat.
659 NOTE: On i386 defining INLINE_SWITCH improves over all
660 performance approximately seven percent, but it may be different
661 for other machines. At some point, this may be made into a proper
662 configuration parameter. */
664 #define INLINE_SWITCH
668 #define NEXT_INSN GOTO_INSN(*pc++)
672 #define NEXT_INSN goto next_insn
679 /* The first few instructions here are ordered according to their
680 frequency, in the hope that this will improve code locality a
683 insn_aload_0: // 0x2a
688 LOADI (get1u (pc++));
691 insn_getfield_4: // 0xd8
694 jobject obj = POPA();
696 jint field_offset = get2u (pc); pc += 2;
697 PUSHI (*(jint*) ((char*)obj + field_offset));
701 insn_iload_1: // 0x1b
705 insn_getfield_a: // 0xda
708 jobject obj = POPA();
710 jint field_offset = get2u (pc); pc += 2;
711 PUSHA(*(jobject*) ((char*)obj + field_offset));
715 insn_invokevirtual: // 0xb6
718 int index = get2u (pc); pc += 2;
720 /* _Jv_ResolvePoolEntry returns immediately if the value already
721 * is resolved. If we want to clutter up the code here to gain
722 * a little performance, then we can check the corresponding bit
723 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
724 * don't think it is worth it. */
726 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
728 sp -= rmeth->stack_item_count;
731 if (rmeth->vtable_index == -1)
733 // final methods do not appear in the vtable,
734 // if it does not appear in the superclass.
735 fun = (void (*) (...)) rmeth->method->ncode;
739 jobject rcv = sp[0].o;
740 _Jv_VTable *table = *(_Jv_VTable**)rcv;
741 fun = (void (*) (...))table->method[rmeth->vtable_index];
748 /* here goes the magic again... */
749 ffi_cif *cif = &rmeth->cif;
750 ffi_raw *raw = (ffi_raw*) sp;
754 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
756 int rtype = cif->rtype->type;
758 /* the likelyhood of object, int, or void return is very high,
759 * so those are checked before the switch */
760 if (rtype == FFI_TYPE_POINTER)
762 PUSHA (*(jobject*)&rvalue);
764 else if (rtype == FFI_TYPE_SINT32)
766 PUSHI (*(jint*)&rvalue);
768 else if (rtype == FFI_TYPE_VOID)
776 jbyte value = (*(jint*)&rvalue) & 0xff;
781 case FFI_TYPE_SINT16:
783 jshort value = (*(jint*)&rvalue) & 0xffff;
788 case FFI_TYPE_UINT16:
790 jint value = (*(jint*)&rvalue) & 0xffff;
796 PUSHF (*(jfloat*)&rvalue);
799 case FFI_TYPE_DOUBLE:
803 case FFI_TYPE_SINT64:
804 PUSHL (*(jlong*)&rvalue);
808 throw_internal_error ("unknown return type in invokeXXX");
883 PUSHI (get2s(pc)); pc += 2;
888 int index = get1u (pc++);
889 PUSHA(pool_data[index].o);
895 int index = get2u (pc); pc += 2;
896 PUSHA(pool_data[index].o);
902 int index = get2u (pc); pc += 2;
903 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
909 LOADL (get1u (pc++));
913 LOADF (get1u (pc++));
917 LOADD (get1u (pc++));
921 LOADA (get1u (pc++));
1000 jintArray arr = (jintArray) POPA();
1002 if (index < 0 || index >= arr->length)
1004 _Jv_ThrowBadArrayIndex (index);
1006 PUSHI( elements(arr)[index] );
1013 jint index = POPI();
1014 jlongArray arr = (jlongArray) POPA();
1016 if (index < 0 || index >= arr->length)
1018 _Jv_ThrowBadArrayIndex (index);
1020 PUSHL( elements(arr)[index] );
1027 jint index = POPI();
1028 jfloatArray arr = (jfloatArray) POPA();
1030 if (index < 0 || index >= arr->length)
1032 _Jv_ThrowBadArrayIndex (index);
1034 PUSHF( elements(arr)[index] );
1041 jint index = POPI();
1042 jdoubleArray arr = (jdoubleArray) POPA();
1044 if (index < 0 || index >= arr->length)
1046 _Jv_ThrowBadArrayIndex (index);
1048 PUSHD( elements(arr)[index] );
1055 jint index = POPI();
1056 jobjectArray arr = (jobjectArray) POPA();
1058 if (index < 0 || index >= arr->length)
1060 _Jv_ThrowBadArrayIndex (index);
1062 PUSHA( elements(arr)[index] );
1069 jint index = POPI();
1070 jbyteArray arr = (jbyteArray) POPA();
1072 if (index < 0 || index >= arr->length)
1074 _Jv_ThrowBadArrayIndex (index);
1076 PUSHI( elements(arr)[index] );
1083 jint index = POPI();
1084 jcharArray arr = (jcharArray) POPA();
1086 if (index < 0 || index >= arr->length)
1088 _Jv_ThrowBadArrayIndex (index);
1090 PUSHI( elements(arr)[index] );
1097 jint index = POPI();
1098 jshortArray arr = (jshortArray) POPA();
1100 if (index < 0 || index >= arr->length)
1102 _Jv_ThrowBadArrayIndex (index);
1104 PUSHI( elements(arr)[index] );
1109 STOREI (get1u (pc++));
1113 STOREL (get1u (pc++));
1117 STOREF (get1u (pc++));
1121 STORED (get1u (pc++));
1125 STOREI (get1u (pc++));
1211 jint value = POPI();
1212 jint index = POPI();
1213 jintArray arr = (jintArray) POPA();
1215 if (index < 0 || index >= arr->length)
1217 _Jv_ThrowBadArrayIndex (index);
1219 elements(arr)[index] = value;
1226 jlong value = POPL();
1227 jint index = POPI();
1228 jlongArray arr = (jlongArray) POPA();
1230 if (index < 0 || index >= arr->length)
1232 _Jv_ThrowBadArrayIndex (index);
1234 elements(arr)[index] = value;
1241 jfloat value = POPF();
1242 jint index = POPI();
1243 jfloatArray arr = (jfloatArray) POPA();
1245 if (index < 0 || index >= arr->length)
1247 _Jv_ThrowBadArrayIndex (index);
1249 elements(arr)[index] = value;
1256 jdouble value = POPD();
1257 jint index = POPI();
1258 jdoubleArray arr = (jdoubleArray) POPA();
1260 if (index < 0 || index >= arr->length)
1262 _Jv_ThrowBadArrayIndex (index);
1264 elements(arr)[index] = value;
1271 jobject value = POPA();
1272 jint index = POPI();
1273 jobjectArray arr = (jobjectArray) POPA();
1275 if (index < 0 || index >= arr->length)
1277 _Jv_ThrowBadArrayIndex (index);
1279 _Jv_CheckArrayStore (arr, value);
1280 elements(arr)[index] = value;
1287 jbyte value = (jbyte) POPI();
1288 jint index = POPI();
1289 jbyteArray arr = (jbyteArray) POPA();
1291 if (index < 0 || index >= arr->length)
1293 _Jv_ThrowBadArrayIndex (index);
1295 elements(arr)[index] = value;
1302 jchar value = (jchar) POPI();
1303 jint index = POPI();
1304 jcharArray arr = (jcharArray) POPA();
1306 if (index < 0 || index >= arr->length)
1308 _Jv_ThrowBadArrayIndex (index);
1310 elements(arr)[index] = value;
1317 jshort value = (jshort) POPI();
1318 jint index = POPI();
1319 jshortArray arr = (jshortArray) POPA();
1321 if (index < 0 || index >= arr->length)
1323 _Jv_ThrowBadArrayIndex (index);
1325 elements(arr)[index] = value;
1343 dupx (sp, 1, 1); sp+=1;
1347 dupx (sp, 1, 2); sp+=1;
1357 dupx (sp, 2, 1); sp+=2;
1361 dupx (sp, 2, 2); sp+=2;
1366 jobject tmp1 = POPA();
1367 jobject tmp2 = POPA();
1424 jint value2 = POPI();
1425 jint value1 = POPI();
1427 jint res = value1 / value2;
1435 jlong value2 = POPL();
1436 jlong value1 = POPL();
1438 jlong res = value1 / value2;
1446 jfloat value2 = POPF();
1447 jfloat value1 = POPF();
1449 jfloat res = value1 / value2;
1457 jdouble value2 = POPD();
1458 jdouble value1 = POPD();
1460 jdouble res = value1 / value2;
1468 jint value2 = POPI();
1469 jint value1 = POPI();
1471 jint res = value1 % value2;
1479 jlong value2 = POPL();
1480 jlong value1 = POPL();
1482 jlong res = value1 % value2;
1490 jfloat value2 = POPF();
1491 jfloat value1 = POPF();
1493 jfloat res = __ieee754_fmod (value1, value2);
1501 jdouble value2 = POPD();
1502 jdouble value1 = POPD();
1504 jdouble res = __ieee754_fmod (value1, value2);
1511 jint value = POPI();
1518 jlong value = POPL();
1525 jfloat value = POPF();
1532 jdouble value = POPD();
1539 jint shift = (POPI() & 0x1f);
1540 jint value = POPI();
1541 PUSHI (value << shift);
1547 jint shift = (POPI() & 0x3f);
1548 jlong value = POPL();
1549 PUSHL (value << shift);
1555 jint shift = (POPI() & 0x1f);
1556 jint value = POPI();
1557 PUSHI (value >> shift);
1563 jint shift = (POPI() & 0x3f);
1564 jlong value = POPL();
1565 PUSHL (value >> shift);
1571 jint shift = (POPI() & 0x1f);
1572 unsigned long value = POPI();
1573 PUSHI ((jint) (value >> shift));
1579 jint shift = (POPI() & 0x3f);
1580 UINT64 value = (UINT64) POPL();
1581 PUSHL ((value >> shift));
1611 jint index = get1u (pc++);
1612 jint amount = get1s (pc++);
1613 locals[index].i += amount;
1618 {jlong value = POPI(); PUSHL (value);}
1622 {jfloat value = POPI(); PUSHF (value);}
1626 {jdouble value = POPI(); PUSHD (value);}
1630 {jint value = POPL(); PUSHI (value);}
1634 {jfloat value = POPL(); PUSHF (value);}
1638 {jdouble value = POPL(); PUSHD (value);}
1642 { jint value = (jint)POPF (); PUSHI(value); }
1646 { jlong value = (jlong)POPF (); PUSHL(value); }
1650 { jdouble value = POPF (); PUSHD(value); }
1654 { jint value = (jint)POPD (); PUSHI(value); }
1658 { jlong value = (jlong)POPD (); PUSHL(value); }
1662 { jfloat value = POPD (); PUSHF(value); }
1666 { jbyte value = POPI (); PUSHI(value); }
1670 { jchar value = POPI (); PUSHI(value); }
1674 { jshort value = POPI (); PUSHI(value); }
1679 jlong value2 = POPL ();
1680 jlong value1 = POPL ();
1681 if (value1 > value2)
1683 else if (value1 == value2)
1693 jfloat value2 = POPF ();
1694 jfloat value1 = POPF ();
1695 if (value1 > value2)
1697 else if (value1 == value2)
1699 else if (value1 < value2)
1701 else if ((*(pc-1)) == op_fcmpg)
1711 jdouble value2 = POPD ();
1712 jdouble value1 = POPD ();
1713 if (value1 > value2)
1715 else if (value1 == value2)
1717 else if (value1 < value2)
1719 else if ((*(pc-1)) == op_dcmpg)
1728 jint offset = get2s (pc);
1738 jint offset = get2s (pc);
1748 jint offset = get2s (pc);
1758 jint offset = get2s (pc);
1768 jint offset = get2s (pc);
1778 jint offset = get2s (pc);
1788 jint offset = get2s (pc);
1789 jint value2 = POPI();
1790 jint value1 = POPI();
1791 if (value1 == value2)
1800 jint offset = get2s (pc);
1801 jint value2 = POPI();
1802 jint value1 = POPI();
1803 if (value1 != value2)
1812 jint offset = get2s (pc);
1813 jint value2 = POPI();
1814 jint value1 = POPI();
1815 if (value1 < value2)
1824 jint offset = get2s (pc);
1825 jint value2 = POPI();
1826 jint value1 = POPI();
1827 if (value1 >= value2)
1836 jint offset = get2s (pc);
1837 jint value2 = POPI();
1838 jint value1 = POPI();
1839 if (value1 > value2)
1848 jint offset = get2s (pc);
1849 jint value2 = POPI();
1850 jint value1 = POPI();
1851 if (value1 <= value2)
1860 jint offset = get2s (pc);
1861 jobject value2 = POPA();
1862 jobject value1 = POPA();
1863 if (value1 == value2)
1872 jint offset = get2s (pc);
1873 jobject value2 = POPA();
1874 jobject value1 = POPA();
1875 if (value1 != value2)
1884 jint offset = get2s (pc);
1891 unsigned char *base_pc = pc-1;
1892 jint offset = get2s (pc); pc += 2;
1893 PUSHA ((jobject)pc);
1894 pc = base_pc+offset;
1900 jint index = get1u (pc);
1901 pc = (unsigned char*) PEEKA (index);
1907 unsigned char *base_pc = pc-1;
1910 unsigned char* base = bytecode ();
1911 while ((pc-base) % 4 != 0)
1914 jint def = get4 (pc);
1915 jint low = get4 (pc+4);
1916 jint high = get4 (pc+8);
1918 if (index < low || index > high)
1921 pc = base_pc + get4 (pc+4*(index-low+3));
1927 unsigned char *base_pc = pc-1;
1930 unsigned char* base = bytecode ();
1931 while ((pc-base) % 4 != 0)
1934 jint def = get4 (pc);
1935 jint npairs = get4 (pc+4);
1940 // simple binary search...
1943 int half = (min+max)/2;
1944 int match = get4 (pc+ 4*(2 + 2*half));
1949 else if (index < match)
1956 if (index == get4 (pc+ 4*(2 + 2*min)))
1957 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1963 /* on return, just save the sp and return to caller */
1976 unsigned char *base_pc = pc-1;
1977 jint fieldref_index = get2u (pc); pc += 2;
1978 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1979 _Jv_Field *field = pool_data[fieldref_index].field;
1981 if ((field->flags & Modifier::STATIC) == 0)
1982 throw_incompatible_class_change_error
1983 (JvNewStringLatin1 ("field no longer static"));
1985 jclass type = field->type;
1987 if (type->isPrimitive ())
1989 switch (type->size_in_bytes)
1992 *base_pc = op_getstatic_1;
1996 if (type == JvPrimClass (char))
1997 *base_pc = op_getstatic_2u;
1999 *base_pc = op_getstatic_2s;
2003 *base_pc = op_getstatic_4;
2007 *base_pc = op_getstatic_8;
2013 *base_pc = op_getstatic_a;
2023 unsigned char *base_pc = pc-1;
2024 jint fieldref_index = get2u (pc); pc += 2;
2025 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2026 _Jv_Field *field = pool_data[fieldref_index].field;
2028 if ((field->flags & Modifier::STATIC) != 0)
2029 throw_incompatible_class_change_error
2030 (JvNewStringLatin1 ("field is static"));
2032 jclass type = field->type;
2034 if (type->isPrimitive ())
2036 switch (type->size_in_bytes)
2039 *base_pc = op_getfield_1;
2043 if (type == JvPrimClass (char))
2044 *base_pc = op_getfield_2u;
2046 *base_pc = op_getfield_2s;
2050 *base_pc = op_getfield_4;
2054 *base_pc = op_getfield_8;
2060 *base_pc = op_getfield_a;
2063 if (field->u.boffset > 0xffff)
2064 JvThrow (new java::lang::VirtualMachineError);
2066 base_pc[1] = (field->u.boffset>>8) & 0xff;
2067 base_pc[2] = field->u.boffset & 0xff;
2076 unsigned char* base_pc = pc-1;
2077 jint fieldref_index = get2u (pc); pc += 2;
2078 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2079 _Jv_Field *field = pool_data[fieldref_index].field;
2081 jclass type = field->type;
2083 // ResolvePoolEntry cannot check this
2084 if ((field->flags & Modifier::STATIC) == 0)
2085 throw_incompatible_class_change_error
2086 (JvNewStringLatin1 ("field no longer static"));
2088 /* if this is patented, then maybe we could install
2089 a function in the constant pool, to do the right thing */
2091 if (type->isPrimitive ())
2093 switch (type->size_in_bytes)
2096 *base_pc = op_putstatic_1;
2100 *base_pc = op_putstatic_2;
2104 *base_pc = op_putstatic_4;
2108 *base_pc = op_putstatic_8;
2114 *base_pc = op_putstatic_a;
2117 // do the instruction again!
2126 unsigned char* base_pc = pc-1;
2127 jint fieldref_index = get2u (pc); pc += 2;
2128 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2129 _Jv_Field *field = pool_data[fieldref_index].field;
2131 jclass type = field->type;
2133 if ((field->flags & Modifier::STATIC) != 0)
2134 throw_incompatible_class_change_error
2135 (JvNewStringLatin1 ("field is static"));
2137 if (type->isPrimitive ())
2139 switch (type->size_in_bytes)
2142 *base_pc = op_putfield_1;
2146 *base_pc = op_putfield_2;
2150 *base_pc = op_putfield_4;
2154 *base_pc = op_putfield_8;
2160 *base_pc = op_putfield_a;
2163 if (field->u.boffset > 0xffff)
2164 JvThrow (new java::lang::VirtualMachineError);
2166 base_pc[1] = (field->u.boffset>>8) & 0xff;
2167 base_pc[2] = field->u.boffset & 0xff;
2169 // do the instruction again!
2178 jobject obj = POPA();
2180 jint field_offset = get2u (pc); pc += 2;
2181 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2188 jobject obj = POPA();
2190 jint field_offset = get2u (pc); pc += 2;
2191 PUSHI (*(jshort*) ((char*)obj + field_offset));
2198 jobject obj = POPA();
2200 jint field_offset = get2u (pc); pc += 2;
2201 PUSHI (*(jchar*) ((char*)obj + field_offset));
2208 jobject obj = POPA();
2210 jint field_offset = get2u (pc); pc += 2;
2211 PUSHL(*(jlong*) ((char*)obj + field_offset));
2217 jint fieldref_index = get2u (pc); pc += 2;
2218 _Jv_Field *field = pool_data[fieldref_index].field;
2219 PUSHI (*(jbyte*) (field->u.addr));
2225 jint fieldref_index = get2u (pc); pc += 2;
2226 _Jv_Field *field = pool_data[fieldref_index].field;
2227 PUSHI(*(jshort*) (field->u.addr));
2233 jint fieldref_index = get2u (pc); pc += 2;
2234 _Jv_Field *field = pool_data[fieldref_index].field;
2235 PUSHI(*(jchar*) (field->u.addr));
2241 jint fieldref_index = get2u (pc); pc += 2;
2242 _Jv_Field *field = pool_data[fieldref_index].field;
2243 PUSHI(*(jint*) (field->u.addr));
2249 jint fieldref_index = get2u (pc); pc += 2;
2250 _Jv_Field *field = pool_data[fieldref_index].field;
2251 PUSHL(*(jlong*) (field->u.addr));
2257 jint fieldref_index = get2u (pc); pc += 2;
2258 _Jv_Field *field = pool_data[fieldref_index].field;
2259 PUSHA(*(jobject*) (field->u.addr));
2266 jint value = POPI();
2267 jobject obj = POPA();
2269 jint field_offset = get2u (pc); pc += 2;
2270 *(jbyte*) ((char*)obj + field_offset) = value;
2277 jint value = POPI();
2278 jobject obj = POPA();
2280 jint field_offset = get2u (pc); pc += 2;
2281 *(jchar*) ((char*)obj + field_offset) = value;
2288 jint value = POPI();
2289 jobject obj = POPA();
2291 jint field_offset = get2u (pc); pc += 2;
2292 *(jint*) ((char*)obj + field_offset) = value;
2299 jlong value = POPL();
2300 jobject obj = POPA();
2302 jint field_offset = get2u (pc); pc += 2;
2303 *(jlong*) ((char*)obj + field_offset) = value;
2310 jobject value = POPA();
2311 jobject obj = POPA();
2313 jint field_offset = get2u (pc); pc += 2;
2314 *(jobject*) ((char*)obj + field_offset) = value;
2320 jint value = POPI();
2321 jint fieldref_index = get2u (pc); pc += 2;
2322 _Jv_Field *field = pool_data[fieldref_index].field;
2323 *(jbyte*) (field->u.addr) = value;
2329 jint value = POPI();
2330 jint fieldref_index = get2u (pc); pc += 2;
2331 _Jv_Field *field = pool_data[fieldref_index].field;
2332 *(jchar*) (field->u.addr) = value;
2338 jint value = POPI();
2339 jint fieldref_index = get2u (pc); pc += 2;
2340 _Jv_Field *field = pool_data[fieldref_index].field;
2341 *(jint*) (field->u.addr) = value;
2347 jlong value = POPL();
2348 jint fieldref_index = get2u (pc); pc += 2;
2349 _Jv_Field *field = pool_data[fieldref_index].field;
2350 *(jlong*) (field->u.addr) = value;
2356 jobject value = POPA();
2357 jint fieldref_index = get2u (pc); pc += 2;
2358 _Jv_Field *field = pool_data[fieldref_index].field;
2359 *(jobject*) (field->u.addr) = value;
2366 int index = get2u (pc); pc += 2;
2368 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2370 sp -= rmeth->stack_item_count;
2374 fun = (void (*) (...))rmeth->method->ncode;
2376 goto perform_invoke;
2381 int index = get2u (pc); pc += 2;
2383 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2385 sp -= rmeth->stack_item_count;
2387 _Jv_InitClass (rmeth->klass);
2388 fun = (void (*) (...))rmeth->method->ncode;
2390 goto perform_invoke;
2392 insn_invokeinterface:
2395 int index = get2u (pc); pc += 2;
2397 // invokeinterface has two unused bytes...
2400 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2402 sp -= rmeth->stack_item_count;
2405 jobject rcv = sp[0].o;
2407 fun = (void (*) (...))
2408 _Jv_LookupInterfaceMethod (rcv->getClass (),
2409 rmeth->method->name,
2410 rmeth->method->signature);
2412 goto perform_invoke;
2418 int index = get2u (pc); pc += 2;
2419 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2420 _Jv_InitClass (klass);
2421 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2429 int atype = get1u (pc++);
2431 jobject result = _Jv_NewArray (atype, size);
2439 int index = get2u (pc); pc += 2;
2440 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2442 _Jv_InitClass (klass);
2443 jobject result = _Jv_NewObjectArray (size, klass, 0);
2451 __JArray *arr = (__JArray*)POPA();
2452 PUSHI (arr->length);
2459 jobject value = POPA();
2467 jobject value = POPA();
2468 jint index = get2u (pc); pc += 2;
2469 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2471 if (value != NULL && ! to->isInstance (value))
2473 JvThrow (new java::lang::ClassCastException
2484 jobject value = POPA();
2485 jint index = get2u (pc); pc += 2;
2486 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2487 PUSHI (to->isInstance (value));
2494 jobject value = POPA();
2496 _Jv_MonitorEnter (value);
2503 jobject value = POPA();
2505 _Jv_MonitorExit (value);
2511 unsigned char* base_pc = pc-1;
2512 jint offset = get2s (pc); pc += 2;
2513 jobject val = POPA();
2515 pc = base_pc+offset;
2521 unsigned char* base_pc = pc-1;
2522 jint offset = get2s (pc); pc += 2;
2523 jobject val = POPA();
2525 pc = base_pc+offset;
2532 jint the_mod_op = get1u (pc++);
2533 jint wide = get2u (pc); pc += 2;
2574 pc = (unsigned char*) PEEKA (wide);
2579 jint amount = get2s (pc); pc += 2;
2580 jint value = PEEKI (wide);
2581 POKEI (wide, value+amount);
2586 throw_internal_error ("illegal bytecode modified by wide");
2591 insn_multianewarray:
2594 int kind_index = get2u (pc); pc += 2;
2595 int dim = get1u (pc); pc += 1;
2598 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2599 _Jv_InitClass (type);
2600 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2602 for (int i = dim - 1; i >= 0; i--)
2607 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2615 unsigned char* base_pc = pc-1;
2616 int offset = get4 (pc); pc += 4;
2617 pc = base_pc+offset;
2623 unsigned char* base_pc = pc-1;
2624 int offset = get4 (pc); pc += 4;
2626 pc = base_pc+offset;
2633 throw_internal_error (char *msg)
2635 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2639 throw_incompatible_class_change_error (jstring msg)
2641 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2645 static java::lang::NullPointerException *null_pointer_exc;
2647 throw_null_pointer_exception ()
2649 if (null_pointer_exc == NULL)
2650 null_pointer_exc = new java::lang::NullPointerException;
2652 JvThrow (null_pointer_exc);
2657 static java::lang::ArithmeticException *arithmetic_exc;
2659 throw_arithmetic_exception ()
2661 if (arithmetic_exc == NULL)
2662 arithmetic_exc = new java::lang::ArithmeticException
2663 (JvNewStringLatin1 ("/ by zero"));
2665 JvThrow (arithmetic_exc);
2670 #endif // INTERPRETER