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 extern "C" double __ieee754_fmod __P((double,double));
71 static inline void dupx (_Jv_word *sp, int n, int x)
73 // first "slide" n+x elements n to the right
75 for (int i = 0; i < n+x; i++)
77 sp[(top-i)] = sp[(top-i)-n];
80 // next, copy the n top elements, n+x down
81 for (int i = 0; i < n; i++)
83 sp[top-(n+x)-i] = sp[top-i];
89 #define PUSHA(V) (sp++)->o = (V)
90 #define PUSHI(V) (sp++)->i = (V)
91 #define PUSHF(V) (sp++)->f = (V)
92 #define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
93 (sp++)->ia[0] = w2.ia[0]; \
94 (sp++)->ia[0] = w2.ia[1]; } while (0)
95 #define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
96 (sp++)->ia[0] = w2.ia[0]; \
97 (sp++)->ia[0] = w2.ia[1]; } while (0)
99 #define POPA() ((--sp)->o)
100 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
101 #define POPF() ((jfloat) (--sp)->f)
102 #define POPL() ({ _Jv_word2 w2; \
103 w2.ia[1] = (--sp)->ia[0]; \
104 w2.ia[0] = (--sp)->ia[0]; w2.l; })
105 #define POPD() ({ _Jv_word2 w2; \
106 w2.ia[1] = (--sp)->ia[0]; \
107 w2.ia[0] = (--sp)->ia[0]; w2.d; })
109 #define LOADA(I) (sp++)->o = locals[I].o
110 #define LOADI(I) (sp++)->i = locals[I].i
111 #define LOADF(I) (sp++)->f = locals[I].f
112 #define LOADL(I) do { jint __idx = (I); \
113 (sp++)->ia[0] = locals[__idx].ia[0]; \
114 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
116 #define LOADD(I) LOADL(I)
119 #define STOREA(I) locals[I].o = (--sp)->o
120 #define STOREI(I) locals[I].i = (--sp)->i
121 #define STOREF(I) locals[I].f = (--sp)->f
122 #define STOREL(I) do { jint __idx = (I); \
123 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
124 locals[__idx].ia[0] = (--sp)->ia[0]; \
126 #define STORED(I) STOREL(I)
128 #define PEEKI(I) (locals+(I))->i
129 #define PEEKA(I) (locals+(I))->o
131 #define POKEI(I,V) ((locals+(I))->i = (V))
134 #define BINOPI(OP) { \
135 jint value2 = POPI(); \
136 jint value1 = POPI(); \
137 PUSHI(value1 OP value2); \
140 #define BINOPF(OP) { \
141 jfloat value2 = POPF(); \
142 jfloat value1 = POPF(); \
143 PUSHF(value1 OP value2); \
146 #define BINOPL(OP) { \
147 jlong value2 = POPL(); \
148 jlong value1 = POPL(); \
149 PUSHL(value1 OP value2); \
152 #define BINOPD(OP) { \
153 jdouble value2 = POPD(); \
154 jdouble value1 = POPD(); \
155 PUSHD(value1 OP value2); \
158 static inline jint get1s(unsigned char* loc) {
159 return *(signed char*)loc;
162 static inline jint get1u(unsigned char* loc) {
166 static inline jint get2s(unsigned char* loc) {
167 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
170 static inline jint get2u(unsigned char* loc) {
171 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
174 static jint get4(unsigned char* loc) {
175 return (((jint)(loc[0])) << 24)
176 | (((jint)(loc[1])) << 16)
177 | (((jint)(loc[2])) << 8)
178 | (((jint)(loc[3])) << 0);
185 #define NULLCHECK(X) \
186 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
192 #define ZEROCHECK(X) \
193 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
196 // this method starts the actual running of the method. It is inlined
197 // in three different variants in the static methods run_normal,
198 // run_sync_object and run_sync_class (see below). Those static methods
199 // are installed directly in the stub for this method (by
200 // _Jv_InterpMethod::ncode, in resolve.cc).
203 _Jv_InterpMethod::run (ffi_cif* cif,
206 _Jv_InterpMethodInvocation *inv)
209 inv->pc = bytecode ();
210 inv->sp = inv->stack_base ();
211 _Jv_word *locals = inv->local_base ();
213 /* Go straight at it! the ffi raw format matches the internal
214 stack representation exactly. At leat, that's the idea.
216 memcpy ((void*) locals, (void*) args, args_raw_size);
219 /* this will call the method _Jv_InterpMethod::continue0, see below */
221 gnu::gcj::runtime::MethodInvocation::continue0
222 ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
224 if (ex == 0) // no exception...
226 /* define sp locally, so the POP? macros will pick it up */
227 _Jv_word *sp = inv->sp;
228 int rtype = cif->rtype->type;
230 if (rtype == FFI_TYPE_POINTER)
233 *(jobject*) retp = r;
236 else if (rtype == FFI_TYPE_SINT32)
242 else if (rtype == FFI_TYPE_VOID)
255 case FFI_TYPE_DOUBLE:
263 case FFI_TYPE_UINT16:
264 case FFI_TYPE_UINT32:
266 case FFI_TYPE_SINT16:
273 case FFI_TYPE_SINT64:
281 throw_internal_error ("unknown return type");
286 /** handle an exception */
287 if ( find_exception (ex, inv) )
293 bool _Jv_InterpMethod::find_exception (jobject ex,
294 _Jv_InterpMethodInvocation *inv)
296 int logical_pc = inv->pc - bytecode ();
297 _Jv_InterpException *exc = exceptions ();
298 jclass exc_class = ex->getClass ();
300 for (int i = 0; i < exc_count; i++)
302 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
306 if (exc[i].handler_type != 0)
307 handler = (_Jv_ResolvePoolEntry (defining_class,
308 exc[i].handler_type)).clazz;
312 if (handler==NULL || handler->isAssignableFrom (exc_class))
314 inv->pc = bytecode () + exc[i].handler_pc;
315 inv->sp = inv->stack_base (); // reset stack
316 (inv->sp++)->o = ex; // push exception
324 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
329 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
331 // we do the alloca of the method invocation here, to allow the method
332 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
333 int storage_size = _this->max_stack+_this->max_locals;
334 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
335 alloca (sizeof (_Jv_InterpMethodInvocation)
336 + storage_size * sizeof (_Jv_word));
338 jobject ex = _this->run (cif, ret, args, inv);
339 if (ex != 0) _Jv_Throw (ex);
342 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
347 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
348 jobject rcv = (jobject)args[0].ptr;
350 int storage_size = _this->max_stack+_this->max_locals;
351 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
352 alloca (sizeof (_Jv_InterpMethodInvocation)
353 + storage_size * sizeof (_Jv_word));
355 _Jv_MonitorEnter (rcv);
356 jobject ex = _this->run (cif, ret, args, inv);
357 _Jv_MonitorExit (rcv);
359 if (ex != 0) _Jv_Throw (ex);
362 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
367 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
368 jclass sync = _this->defining_class;
370 int storage_size = _this->max_stack+_this->max_locals;
371 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
372 alloca (sizeof (_Jv_InterpMethodInvocation)
373 + storage_size * sizeof (_Jv_word));
375 _Jv_MonitorEnter (sync);
376 jobject ex = _this->run (cif, ret, args, inv);
377 _Jv_MonitorExit (sync);
379 if (ex != 0) _Jv_Throw (ex);
382 /* this is the exception handler hack, for the interpreter */
384 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
385 gnu::gcj::RawData *inv)
387 _Jv_InterpMethod *meth0 = (_Jv_InterpMethod*)meth;
388 _Jv_InterpMethodInvocation *inv0 = (_Jv_InterpMethodInvocation*)inv;
389 meth0->continue1 (inv0);
393 This proceeds execution, as designated in "inv". If an exception
394 happens, then it is simply thrown, and handled in Java. Thus, the pc
395 needs to be stored in the inv->pc at all times, so we can figure
396 out which handler (if any) to invoke.
398 One design issue, which I have not completely considered, is if it
399 should be possible to have interpreted classes linked in! Seldom used
400 (or non-critical) classes could reasonably be interpreted.
404 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
406 using namespace java::lang::reflect;
408 register _Jv_word *sp = inv->sp;
409 register unsigned char *pc = inv->pc;
410 _Jv_word *locals = inv->local_base ();
412 _Jv_word *pool_data = defining_class->constants.data;
414 /* these two are used in the invokeXXX instructions */
416 _Jv_ResolvedMethod* rmeth;
418 #define INSN_LABEL(op) &&insn_##op
419 #define GOTO_INSN(op) goto *(insn_target[op])
421 static const void *const insn_target[] =
424 INSN_LABEL(aconst_null),
425 INSN_LABEL(iconst_m1),
426 INSN_LABEL(iconst_0),
427 INSN_LABEL(iconst_1),
428 INSN_LABEL(iconst_2),
429 INSN_LABEL(iconst_3),
430 INSN_LABEL(iconst_4),
431 INSN_LABEL(iconst_5),
432 INSN_LABEL(lconst_0),
433 INSN_LABEL(lconst_1),
434 INSN_LABEL(fconst_0),
435 INSN_LABEL(fconst_1),
436 INSN_LABEL(fconst_2),
437 INSN_LABEL(dconst_0),
438 INSN_LABEL(dconst_1),
482 INSN_LABEL(istore_0),
483 INSN_LABEL(istore_1),
484 INSN_LABEL(istore_2),
485 INSN_LABEL(istore_3),
486 INSN_LABEL(lstore_0),
487 INSN_LABEL(lstore_1),
488 INSN_LABEL(lstore_2),
489 INSN_LABEL(lstore_3),
490 INSN_LABEL(fstore_0),
491 INSN_LABEL(fstore_1),
492 INSN_LABEL(fstore_2),
493 INSN_LABEL(fstore_3),
494 INSN_LABEL(dstore_0),
495 INSN_LABEL(dstore_1),
496 INSN_LABEL(dstore_2),
497 INSN_LABEL(dstore_3),
498 INSN_LABEL(astore_0),
499 INSN_LABEL(astore_1),
500 INSN_LABEL(astore_2),
501 INSN_LABEL(astore_3),
582 INSN_LABEL(if_icmpeq),
583 INSN_LABEL(if_icmpne),
584 INSN_LABEL(if_icmplt),
585 INSN_LABEL(if_icmpge),
586 INSN_LABEL(if_icmpgt),
587 INSN_LABEL(if_icmple),
588 INSN_LABEL(if_acmpeq),
589 INSN_LABEL(if_acmpne),
593 INSN_LABEL(tableswitch),
594 INSN_LABEL(lookupswitch),
601 INSN_LABEL(getstatic),
602 INSN_LABEL(putstatic),
603 INSN_LABEL(getfield),
604 INSN_LABEL(putfield),
605 INSN_LABEL(invokevirtual),
606 INSN_LABEL(invokespecial),
607 INSN_LABEL(invokestatic),
608 INSN_LABEL(invokeinterface),
609 0, /* op_xxxunusedxxx1, */
611 INSN_LABEL(newarray),
612 INSN_LABEL(anewarray),
613 INSN_LABEL(arraylength),
615 INSN_LABEL(checkcast),
616 INSN_LABEL(instanceof),
617 INSN_LABEL(monitorenter),
618 INSN_LABEL(monitorexit),
620 INSN_LABEL(multianewarray),
622 INSN_LABEL(ifnonnull),
627 #define SAVE_PC inv->pc = pc-1
629 /* If the macro INLINE_SWITCH is not defined, then the main loop
630 operates as one big (normal) switch statement. If it is defined,
631 then the case selection is performed `inline' in the end of the
632 code for each case. The latter saves a native branch instruction
633 for each java-instruction, but expands the code size somewhat.
635 NOTE: On i386 defining INLINE_SWITCH improves over all
636 performance approximately seven percent, but it may be different
637 for other machines. At some point, this may be made into a proper
638 configuration parameter. */
640 #define INLINE_SWITCH
644 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
650 #define NEXT_INSN goto next_insn
657 /* The first few instructions here are ordered according to their
658 frequency, in the hope that this will improve code locality a
661 insn_aload_0: // 0x2a
666 LOADI (get1u (pc++));
669 insn_iload_1: // 0x1b
673 insn_invokevirtual: // 0xb6
676 int index = get2u (pc); pc += 2;
678 /* _Jv_ResolvePoolEntry returns immediately if the value already
679 * is resolved. If we want to clutter up the code here to gain
680 * a little performance, then we can check the corresponding bit
681 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
682 * don't think it is worth it. */
684 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
686 sp -= rmeth->stack_item_count;
689 if (rmeth->vtable_index == -1)
691 // final methods do not appear in the vtable,
692 // if it does not appear in the superclass.
693 fun = (void (*) (...)) rmeth->method->ncode;
697 jobject rcv = sp[0].o;
698 _Jv_VTable *table = *(_Jv_VTable**)rcv;
699 fun = (void (*) (...))table->method[rmeth->vtable_index];
706 /* here goes the magic again... */
707 ffi_cif *cif = &rmeth->cif;
708 ffi_raw *raw = (ffi_raw*) sp;
712 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
714 int rtype = cif->rtype->type;
716 /* the likelyhood of object, int, or void return is very high,
717 * so those are checked before the switch */
718 if (rtype == FFI_TYPE_POINTER)
720 PUSHA (*(jobject*)&rvalue);
722 else if (rtype == FFI_TYPE_SINT32)
724 PUSHI (*(jint*)&rvalue);
726 else if (rtype == FFI_TYPE_VOID)
734 jbyte value = (*(jint*)&rvalue) & 0xff;
739 case FFI_TYPE_SINT16:
741 jshort value = (*(jint*)&rvalue) & 0xffff;
746 case FFI_TYPE_UINT16:
748 jint value = (*(jint*)&rvalue) & 0xffff;
754 PUSHF (*(jfloat*)&rvalue);
757 case FFI_TYPE_DOUBLE:
761 case FFI_TYPE_SINT64:
762 PUSHL (*(jlong*)&rvalue);
766 throw_internal_error ("unknown return type in invokeXXX");
841 PUSHI (get2s(pc)); pc += 2;
846 int index = get1u (pc++);
847 PUSHA(pool_data[index].o);
853 int index = get2u (pc); pc += 2;
854 PUSHA(pool_data[index].o);
860 int index = get2u (pc); pc += 2;
861 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
867 LOADL (get1u (pc++));
871 LOADF (get1u (pc++));
875 LOADD (get1u (pc++));
879 LOADA (get1u (pc++));
958 jintArray arr = (jintArray) POPA();
960 if (index < 0 || index >= arr->length)
962 _Jv_ThrowBadArrayIndex (index);
964 PUSHI( elements(arr)[index] );
972 jlongArray arr = (jlongArray) POPA();
974 if (index < 0 || index >= arr->length)
976 _Jv_ThrowBadArrayIndex (index);
978 PUSHL( elements(arr)[index] );
986 jfloatArray arr = (jfloatArray) POPA();
988 if (index < 0 || index >= arr->length)
990 _Jv_ThrowBadArrayIndex (index);
992 PUSHF( elements(arr)[index] );
1000 jdoubleArray arr = (jdoubleArray) POPA();
1002 if (index < 0 || index >= arr->length)
1004 _Jv_ThrowBadArrayIndex (index);
1006 PUSHD( elements(arr)[index] );
1013 jint index = POPI();
1014 jobjectArray arr = (jobjectArray) POPA();
1016 if (index < 0 || index >= arr->length)
1018 _Jv_ThrowBadArrayIndex (index);
1020 PUSHA( elements(arr)[index] );
1027 jint index = POPI();
1028 jbyteArray arr = (jbyteArray) POPA();
1030 if (index < 0 || index >= arr->length)
1032 _Jv_ThrowBadArrayIndex (index);
1034 PUSHI( elements(arr)[index] );
1041 jint index = POPI();
1042 jcharArray arr = (jcharArray) POPA();
1044 if (index < 0 || index >= arr->length)
1046 _Jv_ThrowBadArrayIndex (index);
1048 PUSHI( elements(arr)[index] );
1055 jint index = POPI();
1056 jshortArray arr = (jshortArray) POPA();
1058 if (index < 0 || index >= arr->length)
1060 _Jv_ThrowBadArrayIndex (index);
1062 PUSHI( elements(arr)[index] );
1067 STOREI (get1u (pc++));
1071 STOREL (get1u (pc++));
1075 STOREF (get1u (pc++));
1079 STORED (get1u (pc++));
1083 STOREI (get1u (pc++));
1169 jint value = POPI();
1170 jint index = POPI();
1171 jintArray arr = (jintArray) POPA();
1173 if (index < 0 || index >= arr->length)
1175 _Jv_ThrowBadArrayIndex (index);
1177 elements(arr)[index] = value;
1184 jlong value = POPL();
1185 jint index = POPI();
1186 jlongArray arr = (jlongArray) POPA();
1188 if (index < 0 || index >= arr->length)
1190 _Jv_ThrowBadArrayIndex (index);
1192 elements(arr)[index] = value;
1199 jfloat value = POPF();
1200 jint index = POPI();
1201 jfloatArray arr = (jfloatArray) POPA();
1203 if (index < 0 || index >= arr->length)
1205 _Jv_ThrowBadArrayIndex (index);
1207 elements(arr)[index] = value;
1214 jdouble value = POPD();
1215 jint index = POPI();
1216 jdoubleArray arr = (jdoubleArray) POPA();
1218 if (index < 0 || index >= arr->length)
1220 _Jv_ThrowBadArrayIndex (index);
1222 elements(arr)[index] = value;
1229 jobject value = POPA();
1230 jint index = POPI();
1231 jobjectArray arr = (jobjectArray) POPA();
1233 if (index < 0 || index >= arr->length)
1235 _Jv_ThrowBadArrayIndex (index);
1237 _Jv_CheckArrayStore (arr, value);
1238 elements(arr)[index] = value;
1245 jbyte value = (jbyte) POPI();
1246 jint index = POPI();
1247 jbyteArray arr = (jbyteArray) POPA();
1249 if (index < 0 || index >= arr->length)
1251 _Jv_ThrowBadArrayIndex (index);
1253 elements(arr)[index] = value;
1260 jchar value = (jchar) POPI();
1261 jint index = POPI();
1262 jcharArray arr = (jcharArray) POPA();
1264 if (index < 0 || index >= arr->length)
1266 _Jv_ThrowBadArrayIndex (index);
1268 elements(arr)[index] = value;
1275 jshort value = (jshort) POPI();
1276 jint index = POPI();
1277 jshortArray arr = (jshortArray) POPA();
1279 if (index < 0 || index >= arr->length)
1281 _Jv_ThrowBadArrayIndex (index);
1283 elements(arr)[index] = value;
1301 dupx (sp, 1, 1); sp+=1;
1305 dupx (sp, 1, 2); sp+=1;
1315 dupx (sp, 2, 1); sp+=2;
1319 dupx (sp, 2, 2); sp+=2;
1324 jobject tmp1 = POPA();
1325 jobject tmp2 = POPA();
1382 jint value2 = POPI();
1383 jint value1 = POPI();
1385 jint res = value1 / value2;
1393 jlong value2 = POPL();
1394 jlong value1 = POPL();
1396 jlong res = value1 / value2;
1404 jfloat value2 = POPF();
1405 jfloat value1 = POPF();
1407 jfloat res = value1 / value2;
1415 jdouble value2 = POPD();
1416 jdouble value1 = POPD();
1418 jdouble res = value1 / value2;
1426 jint value2 = POPI();
1427 jint value1 = POPI();
1429 jint res = value1 % value2;
1437 jlong value2 = POPL();
1438 jlong value1 = POPL();
1440 jlong res = value1 % value2;
1448 jfloat value2 = POPF();
1449 jfloat value1 = POPF();
1451 jfloat res = __ieee754_fmod (value1, value2);
1459 jdouble value2 = POPD();
1460 jdouble value1 = POPD();
1462 jdouble res = __ieee754_fmod (value1, value2);
1469 jint value = POPI();
1476 jlong value = POPL();
1483 jfloat value = POPF();
1490 jdouble value = POPD();
1497 jint shift = (POPI() & 0x1f);
1498 jint value = POPI();
1499 PUSHI (value << shift);
1505 jint shift = (POPI() & 0x3f);
1506 jlong value = POPL();
1507 PUSHL (value << shift);
1513 jint shift = (POPI() & 0x1f);
1514 jint value = POPI();
1515 PUSHI (value >> shift);
1521 jint shift = (POPI() & 0x3f);
1522 jlong value = POPL();
1523 PUSHL (value >> shift);
1529 jint shift = (POPI() & 0x1f);
1530 unsigned long value = POPI();
1531 PUSHI ((jint) (value >> shift));
1537 jint shift = (POPI() & 0x3f);
1538 UINT64 value = (UINT64) POPL();
1539 PUSHL ((value >> shift));
1569 jint index = get1u (pc++);
1570 jint amount = get1s (pc++);
1571 locals[index].i += amount;
1576 {jlong value = POPI(); PUSHL (value);}
1580 {jfloat value = POPI(); PUSHF (value);}
1584 {jdouble value = POPI(); PUSHD (value);}
1588 {jint value = POPL(); PUSHI (value);}
1592 {jfloat value = POPL(); PUSHF (value);}
1596 {jdouble value = POPL(); PUSHD (value);}
1600 { jint value = (jint)POPF (); PUSHI(value); }
1604 { jlong value = (jlong)POPF (); PUSHL(value); }
1608 { jdouble value = POPF (); PUSHD(value); }
1612 { jint value = (jint)POPD (); PUSHI(value); }
1616 { jlong value = (jlong)POPD (); PUSHL(value); }
1620 { jfloat value = POPD (); PUSHF(value); }
1624 { jbyte value = POPI (); PUSHI(value); }
1628 { jchar value = POPI (); PUSHI(value); }
1632 { jshort value = POPI (); PUSHI(value); }
1637 jlong value2 = POPL ();
1638 jlong value1 = POPL ();
1639 if (value1 > value2)
1641 else if (value1 == value2)
1651 jfloat value2 = POPF ();
1652 jfloat value1 = POPF ();
1653 if (value1 > value2)
1655 else if (value1 == value2)
1657 else if (value1 < value2)
1659 else if ((*(pc-1)) == op_fcmpg)
1669 jdouble value2 = POPD ();
1670 jdouble value1 = POPD ();
1671 if (value1 > value2)
1673 else if (value1 == value2)
1675 else if (value1 < value2)
1677 else if ((*(pc-1)) == op_dcmpg)
1686 jint offset = get2s (pc);
1696 jint offset = get2s (pc);
1706 jint offset = get2s (pc);
1716 jint offset = get2s (pc);
1726 jint offset = get2s (pc);
1736 jint offset = get2s (pc);
1746 jint offset = get2s (pc);
1747 jint value2 = POPI();
1748 jint value1 = POPI();
1749 if (value1 == value2)
1758 jint offset = get2s (pc);
1759 jint value2 = POPI();
1760 jint value1 = POPI();
1761 if (value1 != value2)
1770 jint offset = get2s (pc);
1771 jint value2 = POPI();
1772 jint value1 = POPI();
1773 if (value1 < value2)
1782 jint offset = get2s (pc);
1783 jint value2 = POPI();
1784 jint value1 = POPI();
1785 if (value1 >= value2)
1794 jint offset = get2s (pc);
1795 jint value2 = POPI();
1796 jint value1 = POPI();
1797 if (value1 > value2)
1806 jint offset = get2s (pc);
1807 jint value2 = POPI();
1808 jint value1 = POPI();
1809 if (value1 <= value2)
1818 jint offset = get2s (pc);
1819 jobject value2 = POPA();
1820 jobject value1 = POPA();
1821 if (value1 == value2)
1830 jint offset = get2s (pc);
1831 jobject value2 = POPA();
1832 jobject value1 = POPA();
1833 if (value1 != value2)
1842 jint offset = get2s (pc);
1849 unsigned char *base_pc = pc-1;
1850 jint offset = get2s (pc); pc += 2;
1851 PUSHA ((jobject)pc);
1852 pc = base_pc+offset;
1858 jint index = get1u (pc);
1859 pc = (unsigned char*) PEEKA (index);
1865 unsigned char *base_pc = pc-1;
1868 unsigned char* base = bytecode ();
1869 while ((pc-base) % 4 != 0)
1872 jint def = get4 (pc);
1873 jint low = get4 (pc+4);
1874 jint high = get4 (pc+8);
1876 if (index < low || index > high)
1879 pc = base_pc + get4 (pc+4*(index-low+3));
1885 unsigned char *base_pc = pc-1;
1888 unsigned char* base = bytecode ();
1889 while ((pc-base) % 4 != 0)
1892 jint def = get4 (pc);
1893 jint npairs = get4 (pc+4);
1898 // simple binary search...
1901 int half = (min+max)/2;
1902 int match = get4 (pc+ 4*(2 + 2*half));
1907 else if (index < match)
1914 if (index == get4 (pc+ 4*(2 + 2*min)))
1915 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1921 /* on return, just save the sp and return to caller */
1934 jint fieldref_index = get2u (pc); pc += 2;
1935 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1936 _Jv_Field *field = pool_data[fieldref_index].field;
1938 if ((field->flags & Modifier::STATIC) == 0)
1939 throw_incompatible_class_change_error
1940 (JvNewStringLatin1 ("field no longer static"));
1942 jclass type = field->type;
1944 if (type->isPrimitive ())
1946 switch (type->size_in_bytes)
1949 PUSHI (*(jbyte*) (field->u.addr));
1952 if (type == JvPrimClass (char))
1953 PUSHI(*(jchar*) (field->u.addr));
1955 PUSHI(*(jshort*) (field->u.addr));
1959 PUSHI(*(jint*) (field->u.addr));
1963 PUSHL(*(jlong*) (field->u.addr));
1969 PUSHA(*(jobject*) (field->u.addr));
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 is static"));
1985 jclass type = field->type;
1986 jint field_offset = field->u.boffset;
1987 if (field_offset > 0xffff)
1988 JvThrow (new java::lang::VirtualMachineError);
1990 jobject obj = POPA();
1993 if (type->isPrimitive ())
1995 switch (type->size_in_bytes)
1998 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2002 if (type == JvPrimClass (char))
2003 PUSHI (*(jchar*) ((char*)obj + field_offset));
2005 PUSHI (*(jshort*) ((char*)obj + field_offset));
2009 PUSHI (*(jint*) ((char*)obj + field_offset));
2013 PUSHL(*(jlong*) ((char*)obj + field_offset));
2019 PUSHA(*(jobject*) ((char*)obj + field_offset));
2027 jint fieldref_index = get2u (pc); pc += 2;
2028 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2029 _Jv_Field *field = pool_data[fieldref_index].field;
2031 jclass type = field->type;
2033 // ResolvePoolEntry cannot check this
2034 if ((field->flags & Modifier::STATIC) == 0)
2035 throw_incompatible_class_change_error
2036 (JvNewStringLatin1 ("field no longer static"));
2038 if (type->isPrimitive ())
2040 switch (type->size_in_bytes)
2044 jint value = POPI();
2045 *(jbyte*) (field->u.addr) = value;
2051 jint value = POPI();
2052 *(jchar*) (field->u.addr) = value;
2058 jint value = POPI();
2059 *(jint*) (field->u.addr) = value;
2065 jlong value = POPL();
2066 *(jlong*) (field->u.addr) = value;
2073 jobject value = POPA();
2074 *(jobject*) (field->u.addr) = value;
2083 jint fieldref_index = get2u (pc); pc += 2;
2084 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2085 _Jv_Field *field = pool_data[fieldref_index].field;
2087 jclass type = field->type;
2089 if ((field->flags & Modifier::STATIC) != 0)
2090 throw_incompatible_class_change_error
2091 (JvNewStringLatin1 ("field is static"));
2093 jint field_offset = field->u.boffset;
2094 if (field_offset > 0xffff)
2095 JvThrow (new java::lang::VirtualMachineError);
2097 if (type->isPrimitive ())
2099 switch (type->size_in_bytes)
2103 jint value = POPI();
2104 jobject obj = POPA();
2106 *(jbyte*) ((char*)obj + field_offset) = value;
2112 jint value = POPI();
2113 jobject obj = POPA();
2115 *(jchar*) ((char*)obj + field_offset) = value;
2121 jint value = POPI();
2122 jobject obj = POPA();
2124 *(jint*) ((char*)obj + field_offset) = value;
2130 jlong value = POPL();
2131 jobject obj = POPA();
2133 *(jlong*) ((char*)obj + field_offset) = value;
2140 jobject value = POPA();
2141 jobject obj = POPA();
2143 *(jobject*) ((char*)obj + field_offset) = value;
2151 int index = get2u (pc); pc += 2;
2153 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2155 sp -= rmeth->stack_item_count;
2159 fun = (void (*) (...))rmeth->method->ncode;
2161 goto perform_invoke;
2166 int index = get2u (pc); pc += 2;
2168 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2170 sp -= rmeth->stack_item_count;
2172 _Jv_InitClass (rmeth->klass);
2173 fun = (void (*) (...))rmeth->method->ncode;
2175 goto perform_invoke;
2177 insn_invokeinterface:
2180 int index = get2u (pc); pc += 2;
2182 // invokeinterface has two unused bytes...
2185 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2187 sp -= rmeth->stack_item_count;
2190 jobject rcv = sp[0].o;
2192 fun = (void (*) (...))
2193 _Jv_LookupInterfaceMethod (rcv->getClass (),
2194 rmeth->method->name,
2195 rmeth->method->signature);
2197 goto perform_invoke;
2203 int index = get2u (pc); pc += 2;
2204 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2205 _Jv_InitClass (klass);
2206 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2214 int atype = get1u (pc++);
2216 jobject result = _Jv_NewArray (atype, size);
2224 int index = get2u (pc); pc += 2;
2225 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2227 _Jv_InitClass (klass);
2228 jobject result = _Jv_NewObjectArray (size, klass, 0);
2236 __JArray *arr = (__JArray*)POPA();
2237 PUSHI (arr->length);
2244 jobject value = POPA();
2252 jobject value = POPA();
2253 jint index = get2u (pc); pc += 2;
2254 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2256 if (value != NULL && ! to->isInstance (value))
2258 JvThrow (new java::lang::ClassCastException
2269 jobject value = POPA();
2270 jint index = get2u (pc); pc += 2;
2271 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2272 PUSHI (to->isInstance (value));
2279 jobject value = POPA();
2281 _Jv_MonitorEnter (value);
2288 jobject value = POPA();
2290 _Jv_MonitorExit (value);
2296 unsigned char* base_pc = pc-1;
2297 jint offset = get2s (pc); pc += 2;
2298 jobject val = POPA();
2300 pc = base_pc+offset;
2306 unsigned char* base_pc = pc-1;
2307 jint offset = get2s (pc); pc += 2;
2308 jobject val = POPA();
2310 pc = base_pc+offset;
2317 jint the_mod_op = get1u (pc++);
2318 jint wide = get2u (pc); pc += 2;
2359 pc = (unsigned char*) PEEKA (wide);
2364 jint amount = get2s (pc); pc += 2;
2365 jint value = PEEKI (wide);
2366 POKEI (wide, value+amount);
2371 throw_internal_error ("illegal bytecode modified by wide");
2376 insn_multianewarray:
2379 int kind_index = get2u (pc); pc += 2;
2380 int dim = get1u (pc); pc += 1;
2383 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2384 _Jv_InitClass (type);
2385 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2387 for (int i = dim - 1; i >= 0; i--)
2392 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2400 unsigned char* base_pc = pc-1;
2401 int offset = get4 (pc); pc += 4;
2402 pc = base_pc+offset;
2408 unsigned char* base_pc = pc-1;
2409 int offset = get4 (pc); pc += 4;
2411 pc = base_pc+offset;
2418 throw_internal_error (char *msg)
2420 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2424 throw_incompatible_class_change_error (jstring msg)
2426 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2430 static java::lang::NullPointerException *null_pointer_exc;
2432 throw_null_pointer_exception ()
2434 if (null_pointer_exc == NULL)
2435 null_pointer_exc = new java::lang::NullPointerException;
2437 JvThrow (null_pointer_exc);
2442 static java::lang::ArithmeticException *arithmetic_exc;
2444 throw_arithmetic_exception ()
2446 if (arithmetic_exc == NULL)
2447 arithmetic_exc = new java::lang::ArithmeticException
2448 (JvNewStringLatin1 ("/ by zero"));
2450 JvThrow (arithmetic_exc);
2455 #endif // INTERPRETER