1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000 Free Software Foundation
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>
42 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
44 static void throw_internal_error (char *msg)
45 __attribute__ ((__noreturn__));
46 static void throw_incompatible_class_change_error (jstring msg)
47 __attribute__ ((__noreturn__));
49 static void throw_null_pointer_exception ()
50 __attribute__ ((__noreturn__));
53 extern "C" double __ieee754_fmod (double,double);
55 static inline void dupx (_Jv_word *sp, int n, int x)
57 // first "slide" n+x elements n to the right
59 for (int i = 0; i < n+x; i++)
61 sp[(top-i)] = sp[(top-i)-n];
64 // next, copy the n top elements, n+x down
65 for (int i = 0; i < n; i++)
67 sp[top-(n+x)-i] = sp[top-i];
73 #define PUSHA(V) (sp++)->o = (V)
74 #define PUSHI(V) (sp++)->i = (V)
75 #define PUSHF(V) (sp++)->f = (V)
76 #if SIZEOF_VOID_P == 8
77 # define PUSHL(V) (sp->l = (V), sp += 2)
78 # define PUSHD(V) (sp->d = (V), sp += 2)
80 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
81 (sp++)->ia[0] = w2.ia[0]; \
82 (sp++)->ia[0] = w2.ia[1]; } while (0)
83 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
84 (sp++)->ia[0] = w2.ia[0]; \
85 (sp++)->ia[0] = w2.ia[1]; } while (0)
88 #define POPA() ((--sp)->o)
89 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
90 #define POPF() ((jfloat) (--sp)->f)
91 #if SIZEOF_VOID_P == 8
92 # define POPL() (sp -= 2, (jlong) sp->l)
93 # define POPD() (sp -= 2, (jdouble) sp->d)
95 # define POPL() ({ _Jv_word2 w2; \
96 w2.ia[1] = (--sp)->ia[0]; \
97 w2.ia[0] = (--sp)->ia[0]; w2.l; })
98 # define POPD() ({ _Jv_word2 w2; \
99 w2.ia[1] = (--sp)->ia[0]; \
100 w2.ia[0] = (--sp)->ia[0]; w2.d; })
103 #define LOADA(I) (sp++)->o = locals[I].o
104 #define LOADI(I) (sp++)->i = locals[I].i
105 #define LOADF(I) (sp++)->f = locals[I].f
106 #if SIZEOF_VOID_P == 8
107 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
108 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
110 # define LOADL(I) do { 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 #if SIZEOF_VOID_P == 8
121 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
122 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
124 # define STOREL(I) do { jint __idx = (I); \
125 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
126 locals[__idx].ia[0] = (--sp)->ia[0]; \
128 # define STORED(I) STOREL(I)
131 #define PEEKI(I) (locals+(I))->i
132 #define PEEKA(I) (locals+(I))->o
134 #define POKEI(I,V) ((locals+(I))->i = (V))
137 #define BINOPI(OP) { \
138 jint value2 = POPI(); \
139 jint value1 = POPI(); \
140 PUSHI(value1 OP value2); \
143 #define BINOPF(OP) { \
144 jfloat value2 = POPF(); \
145 jfloat value1 = POPF(); \
146 PUSHF(value1 OP value2); \
149 #define BINOPL(OP) { \
150 jlong value2 = POPL(); \
151 jlong value1 = POPL(); \
152 PUSHL(value1 OP value2); \
155 #define BINOPD(OP) { \
156 jdouble value2 = POPD(); \
157 jdouble value1 = POPD(); \
158 PUSHD(value1 OP value2); \
161 static inline jint get1s(unsigned char* loc) {
162 return *(signed char*)loc;
165 static inline jint get1u(unsigned char* loc) {
169 static inline jint get2s(unsigned char* loc) {
170 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
173 static inline jint get2u(unsigned char* loc) {
174 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
177 static jint get4(unsigned char* loc) {
178 return (((jint)(loc[0])) << 24)
179 | (((jint)(loc[1])) << 16)
180 | (((jint)(loc[2])) << 8)
181 | (((jint)(loc[3])) << 0);
188 #define NULLCHECK(X) \
189 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
193 // this method starts the actual running of the method. It is inlined
194 // in three different variants in the static methods run_normal,
195 // run_sync_object and run_sync_class (see below). Those static methods
196 // are installed directly in the stub for this method (by
197 // _Jv_InterpMethod::ncode, in resolve.cc).
200 _Jv_InterpMethod::run (ffi_cif* cif,
203 _Jv_InterpMethodInvocation *inv)
206 inv->pc = bytecode ();
207 inv->sp = inv->stack_base ();
208 _Jv_word *locals = inv->local_base ();
210 /* Go straight at it! the ffi raw format matches the internal
211 stack representation exactly. At least, that's the idea.
213 memcpy ((void*) locals, (void*) args, args_raw_size);
223 catch (java::lang::Throwable *ex2)
228 if (ex == 0) // no exception...
230 /* define sp locally, so the POP? macros will pick it up */
231 _Jv_word *sp = inv->sp;
232 int rtype = cif->rtype->type;
234 if (rtype == FFI_TYPE_POINTER)
237 *(jobject*) retp = r;
240 else if (rtype == FFI_TYPE_SINT32)
246 else if (rtype == FFI_TYPE_VOID)
259 case FFI_TYPE_DOUBLE:
267 case FFI_TYPE_UINT16:
268 case FFI_TYPE_UINT32:
270 case FFI_TYPE_SINT16:
277 case FFI_TYPE_SINT64:
285 throw_internal_error ("unknown return type");
289 /** handle an exception */
290 if ( find_exception (ex, inv) )
296 bool _Jv_InterpMethod::find_exception (jobject ex,
297 _Jv_InterpMethodInvocation *inv)
299 int logical_pc = inv->pc - bytecode ();
300 _Jv_InterpException *exc = exceptions ();
301 jclass exc_class = ex->getClass ();
303 for (int i = 0; i < exc_count; i++)
305 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
309 if (exc[i].handler_type != 0)
310 handler = (_Jv_ResolvePoolEntry (defining_class,
311 exc[i].handler_type)).clazz;
315 if (handler==NULL || handler->isAssignableFrom (exc_class))
317 inv->pc = bytecode () + exc[i].handler_pc;
318 inv->sp = inv->stack_base (); // reset stack
319 (inv->sp++)->o = ex; // push exception
327 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
332 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
334 // we do the alloca of the method invocation here, to allow the method
335 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
336 int storage_size = _this->max_stack+_this->max_locals;
337 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
338 alloca (sizeof (_Jv_InterpMethodInvocation)
339 + storage_size * sizeof (_Jv_word));
341 jobject ex = _this->run (cif, ret, args, inv);
342 if (ex != 0) _Jv_Throw (ex);
345 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
350 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
351 jobject rcv = (jobject)args[0].ptr;
353 int storage_size = _this->max_stack+_this->max_locals;
354 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
355 alloca (sizeof (_Jv_InterpMethodInvocation)
356 + storage_size * sizeof (_Jv_word));
358 _Jv_MonitorEnter (rcv);
359 jobject ex = _this->run (cif, ret, args, inv);
360 _Jv_MonitorExit (rcv);
362 if (ex != 0) _Jv_Throw (ex);
365 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
370 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
371 jclass sync = _this->defining_class;
373 int storage_size = _this->max_stack+_this->max_locals;
374 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
375 alloca (sizeof (_Jv_InterpMethodInvocation)
376 + storage_size * sizeof (_Jv_word));
378 _Jv_MonitorEnter (sync);
379 jobject ex = _this->run (cif, ret, args, inv);
380 _Jv_MonitorExit (sync);
382 if (ex != 0) _Jv_Throw (ex);
386 This proceeds execution, as designated in "inv". If an exception
387 happens, then it is simply thrown, and handled in Java. Thus, the pc
388 needs to be stored in the inv->pc at all times, so we can figure
389 out which handler (if any) to invoke.
391 One design issue, which I have not completely considered, is if it
392 should be possible to have interpreted classes linked in! Seldom used
393 (or non-critical) classes could reasonably be interpreted.
397 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
399 using namespace java::lang::reflect;
401 _Jv_word *sp = inv->sp;
402 unsigned char *pc = inv->pc;
403 _Jv_word *locals = inv->local_base ();
405 _Jv_word *pool_data = defining_class->constants.data;
407 /* these two are used in the invokeXXX instructions */
409 _Jv_ResolvedMethod* rmeth;
411 #define INSN_LABEL(op) &&insn_##op
412 #define GOTO_INSN(op) goto *(insn_target[op])
414 static const void *const insn_target[] =
417 INSN_LABEL(aconst_null),
418 INSN_LABEL(iconst_m1),
419 INSN_LABEL(iconst_0),
420 INSN_LABEL(iconst_1),
421 INSN_LABEL(iconst_2),
422 INSN_LABEL(iconst_3),
423 INSN_LABEL(iconst_4),
424 INSN_LABEL(iconst_5),
425 INSN_LABEL(lconst_0),
426 INSN_LABEL(lconst_1),
427 INSN_LABEL(fconst_0),
428 INSN_LABEL(fconst_1),
429 INSN_LABEL(fconst_2),
430 INSN_LABEL(dconst_0),
431 INSN_LABEL(dconst_1),
475 INSN_LABEL(istore_0),
476 INSN_LABEL(istore_1),
477 INSN_LABEL(istore_2),
478 INSN_LABEL(istore_3),
479 INSN_LABEL(lstore_0),
480 INSN_LABEL(lstore_1),
481 INSN_LABEL(lstore_2),
482 INSN_LABEL(lstore_3),
483 INSN_LABEL(fstore_0),
484 INSN_LABEL(fstore_1),
485 INSN_LABEL(fstore_2),
486 INSN_LABEL(fstore_3),
487 INSN_LABEL(dstore_0),
488 INSN_LABEL(dstore_1),
489 INSN_LABEL(dstore_2),
490 INSN_LABEL(dstore_3),
491 INSN_LABEL(astore_0),
492 INSN_LABEL(astore_1),
493 INSN_LABEL(astore_2),
494 INSN_LABEL(astore_3),
575 INSN_LABEL(if_icmpeq),
576 INSN_LABEL(if_icmpne),
577 INSN_LABEL(if_icmplt),
578 INSN_LABEL(if_icmpge),
579 INSN_LABEL(if_icmpgt),
580 INSN_LABEL(if_icmple),
581 INSN_LABEL(if_acmpeq),
582 INSN_LABEL(if_acmpne),
586 INSN_LABEL(tableswitch),
587 INSN_LABEL(lookupswitch),
594 INSN_LABEL(getstatic),
595 INSN_LABEL(putstatic),
596 INSN_LABEL(getfield),
597 INSN_LABEL(putfield),
598 INSN_LABEL(invokevirtual),
599 INSN_LABEL(invokespecial),
600 INSN_LABEL(invokestatic),
601 INSN_LABEL(invokeinterface),
602 0, /* op_xxxunusedxxx1, */
604 INSN_LABEL(newarray),
605 INSN_LABEL(anewarray),
606 INSN_LABEL(arraylength),
608 INSN_LABEL(checkcast),
609 INSN_LABEL(instanceof),
610 INSN_LABEL(monitorenter),
611 INSN_LABEL(monitorexit),
613 INSN_LABEL(multianewarray),
615 INSN_LABEL(ifnonnull),
620 #define SAVE_PC inv->pc = pc-1
622 /* If the macro INLINE_SWITCH is not defined, then the main loop
623 operates as one big (normal) switch statement. If it is defined,
624 then the case selection is performed `inline' in the end of the
625 code for each case. The latter saves a native branch instruction
626 for each java-instruction, but expands the code size somewhat.
628 NOTE: On i386 defining INLINE_SWITCH improves over all
629 performance approximately seven percent, but it may be different
630 for other machines. At some point, this may be made into a proper
631 configuration parameter. */
633 #define INLINE_SWITCH
637 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
643 #define NEXT_INSN goto next_insn
650 /* The first few instructions here are ordered according to their
651 frequency, in the hope that this will improve code locality a
654 insn_aload_0: // 0x2a
659 LOADI (get1u (pc++));
662 insn_iload_1: // 0x1b
666 insn_invokevirtual: // 0xb6
669 int index = get2u (pc); pc += 2;
671 /* _Jv_ResolvePoolEntry returns immediately if the value already
672 * is resolved. If we want to clutter up the code here to gain
673 * a little performance, then we can check the corresponding bit
674 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
675 * don't think it is worth it. */
677 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
679 sp -= rmeth->stack_item_count;
682 if (rmeth->vtable_index == -1)
684 // final methods do not appear in the vtable,
685 // if it does not appear in the superclass.
686 fun = (void (*)()) rmeth->method->ncode;
690 jobject rcv = sp[0].o;
691 _Jv_VTable *table = *(_Jv_VTable**)rcv;
692 fun = (void (*)()) table->method[rmeth->vtable_index];
699 /* here goes the magic again... */
700 ffi_cif *cif = &rmeth->cif;
701 ffi_raw *raw = (ffi_raw*) sp;
705 #if FFI_NATIVE_RAW_API
706 /* We assume that this is only implemented if it's correct */
707 /* to use it here. On a 64 bit machine, it never is. */
708 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
710 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
713 int rtype = cif->rtype->type;
715 /* the likelyhood of object, int, or void return is very high,
716 * so those are checked before the switch */
717 if (rtype == FFI_TYPE_POINTER)
719 PUSHA (*(jobject*)&rvalue);
721 else if (rtype == FFI_TYPE_SINT32)
723 PUSHI (*(jint*)&rvalue);
725 else if (rtype == FFI_TYPE_VOID)
733 jbyte value = (*(jint*)&rvalue) & 0xff;
738 case FFI_TYPE_SINT16:
740 jshort value = (*(jint*)&rvalue) & 0xffff;
745 case FFI_TYPE_UINT16:
747 jint value = (*(jint*)&rvalue) & 0xffff;
753 PUSHF (*(jfloat*)&rvalue);
756 case FFI_TYPE_DOUBLE:
760 case FFI_TYPE_SINT64:
761 PUSHL (*(jlong*)&rvalue);
765 throw_internal_error ("unknown return type in invokeXXX");
840 PUSHI (get2s(pc)); pc += 2;
845 int index = get1u (pc++);
846 PUSHA(pool_data[index].o);
852 int index = get2u (pc); pc += 2;
853 PUSHA(pool_data[index].o);
859 int index = get2u (pc); pc += 2;
860 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
866 LOADL (get1u (pc++));
870 LOADF (get1u (pc++));
874 LOADD (get1u (pc++));
878 LOADA (get1u (pc++));
957 jintArray arr = (jintArray) POPA();
959 if (index < 0 || index >= arr->length)
961 _Jv_ThrowBadArrayIndex (index);
963 PUSHI( elements(arr)[index] );
971 jlongArray arr = (jlongArray) POPA();
973 if (index < 0 || index >= arr->length)
975 _Jv_ThrowBadArrayIndex (index);
977 PUSHL( elements(arr)[index] );
985 jfloatArray arr = (jfloatArray) POPA();
987 if (index < 0 || index >= arr->length)
989 _Jv_ThrowBadArrayIndex (index);
991 PUSHF( elements(arr)[index] );
999 jdoubleArray arr = (jdoubleArray) POPA();
1001 if (index < 0 || index >= arr->length)
1003 _Jv_ThrowBadArrayIndex (index);
1005 PUSHD( elements(arr)[index] );
1012 jint index = POPI();
1013 jobjectArray arr = (jobjectArray) POPA();
1015 if (index < 0 || index >= arr->length)
1017 _Jv_ThrowBadArrayIndex (index);
1019 PUSHA( elements(arr)[index] );
1026 jint index = POPI();
1027 jbyteArray arr = (jbyteArray) POPA();
1029 if (index < 0 || index >= arr->length)
1031 _Jv_ThrowBadArrayIndex (index);
1033 PUSHI( elements(arr)[index] );
1040 jint index = POPI();
1041 jcharArray arr = (jcharArray) POPA();
1043 if (index < 0 || index >= arr->length)
1045 _Jv_ThrowBadArrayIndex (index);
1047 PUSHI( elements(arr)[index] );
1054 jint index = POPI();
1055 jshortArray arr = (jshortArray) POPA();
1057 if (index < 0 || index >= arr->length)
1059 _Jv_ThrowBadArrayIndex (index);
1061 PUSHI( elements(arr)[index] );
1066 STOREI (get1u (pc++));
1070 STOREL (get1u (pc++));
1074 STOREF (get1u (pc++));
1078 STORED (get1u (pc++));
1082 STOREA (get1u (pc++));
1168 jint value = POPI();
1169 jint index = POPI();
1170 jintArray arr = (jintArray) POPA();
1172 if (index < 0 || index >= arr->length)
1174 _Jv_ThrowBadArrayIndex (index);
1176 elements(arr)[index] = value;
1183 jlong value = POPL();
1184 jint index = POPI();
1185 jlongArray arr = (jlongArray) POPA();
1187 if (index < 0 || index >= arr->length)
1189 _Jv_ThrowBadArrayIndex (index);
1191 elements(arr)[index] = value;
1198 jfloat value = POPF();
1199 jint index = POPI();
1200 jfloatArray arr = (jfloatArray) POPA();
1202 if (index < 0 || index >= arr->length)
1204 _Jv_ThrowBadArrayIndex (index);
1206 elements(arr)[index] = value;
1213 jdouble value = POPD();
1214 jint index = POPI();
1215 jdoubleArray arr = (jdoubleArray) POPA();
1217 if (index < 0 || index >= arr->length)
1219 _Jv_ThrowBadArrayIndex (index);
1221 elements(arr)[index] = value;
1228 jobject value = POPA();
1229 jint index = POPI();
1230 jobjectArray arr = (jobjectArray) POPA();
1232 if (index < 0 || index >= arr->length)
1234 _Jv_ThrowBadArrayIndex (index);
1236 _Jv_CheckArrayStore (arr, value);
1237 elements(arr)[index] = value;
1244 jbyte value = (jbyte) POPI();
1245 jint index = POPI();
1246 jbyteArray arr = (jbyteArray) POPA();
1248 if (index < 0 || index >= arr->length)
1250 _Jv_ThrowBadArrayIndex (index);
1252 elements(arr)[index] = value;
1259 jchar value = (jchar) POPI();
1260 jint index = POPI();
1261 jcharArray arr = (jcharArray) POPA();
1263 if (index < 0 || index >= arr->length)
1265 _Jv_ThrowBadArrayIndex (index);
1267 elements(arr)[index] = value;
1274 jshort value = (jshort) POPI();
1275 jint index = POPI();
1276 jshortArray arr = (jshortArray) POPA();
1278 if (index < 0 || index >= arr->length)
1280 _Jv_ThrowBadArrayIndex (index);
1282 elements(arr)[index] = value;
1300 dupx (sp, 1, 1); sp+=1;
1304 dupx (sp, 1, 2); sp+=1;
1314 dupx (sp, 2, 1); sp+=2;
1318 dupx (sp, 2, 2); sp+=2;
1323 jobject tmp1 = POPA();
1324 jobject tmp2 = POPA();
1381 jint value2 = POPI();
1382 jint value1 = POPI();
1383 jint res = _Jv_divI (value1, value2);
1391 jlong value2 = POPL();
1392 jlong value1 = POPL();
1393 jlong res = _Jv_divJ (value1, value2);
1401 jfloat value2 = POPF();
1402 jfloat value1 = POPF();
1403 jfloat res = value1 / value2;
1411 jdouble value2 = POPD();
1412 jdouble value1 = POPD();
1413 jdouble res = value1 / value2;
1421 jint value2 = POPI();
1422 jint value1 = POPI();
1423 jint res = _Jv_remI (value1, value2);
1431 jlong value2 = POPL();
1432 jlong value1 = POPL();
1433 jlong res = _Jv_remJ (value1, value2);
1441 jfloat value2 = POPF();
1442 jfloat value1 = POPF();
1443 jfloat res = __ieee754_fmod (value1, value2);
1451 jdouble value2 = POPD();
1452 jdouble value1 = POPD();
1453 jdouble res = __ieee754_fmod (value1, value2);
1460 jint value = POPI();
1467 jlong value = POPL();
1474 jfloat value = POPF();
1481 jdouble value = POPD();
1488 jint shift = (POPI() & 0x1f);
1489 jint value = POPI();
1490 PUSHI (value << shift);
1496 jint shift = (POPI() & 0x3f);
1497 jlong value = POPL();
1498 PUSHL (value << shift);
1504 jint shift = (POPI() & 0x1f);
1505 jint value = POPI();
1506 PUSHI (value >> shift);
1512 jint shift = (POPI() & 0x3f);
1513 jlong value = POPL();
1514 PUSHL (value >> shift);
1520 jint shift = (POPI() & 0x1f);
1521 unsigned long value = POPI();
1522 PUSHI ((jint) (value >> shift));
1528 jint shift = (POPI() & 0x3f);
1529 UINT64 value = (UINT64) POPL();
1530 PUSHL ((value >> shift));
1560 jint index = get1u (pc++);
1561 jint amount = get1s (pc++);
1562 locals[index].i += amount;
1567 {jlong value = POPI(); PUSHL (value);}
1571 {jfloat value = POPI(); PUSHF (value);}
1575 {jdouble value = POPI(); PUSHD (value);}
1579 {jint value = POPL(); PUSHI (value);}
1583 {jfloat value = POPL(); PUSHF (value);}
1587 {jdouble value = POPL(); PUSHD (value);}
1591 { jint value = (jint)POPF (); PUSHI(value); }
1595 { jlong value = (jlong)POPF (); PUSHL(value); }
1599 { jdouble value = POPF (); PUSHD(value); }
1603 { jint value = (jint)POPD (); PUSHI(value); }
1607 { jlong value = (jlong)POPD (); PUSHL(value); }
1611 { jfloat value = POPD (); PUSHF(value); }
1615 { jbyte value = POPI (); PUSHI(value); }
1619 { jchar value = POPI (); PUSHI(value); }
1623 { jshort value = POPI (); PUSHI(value); }
1628 jlong value2 = POPL ();
1629 jlong value1 = POPL ();
1630 if (value1 > value2)
1632 else if (value1 == value2)
1642 jfloat value2 = POPF ();
1643 jfloat value1 = POPF ();
1644 if (value1 > value2)
1646 else if (value1 == value2)
1648 else if (value1 < value2)
1650 else if ((*(pc-1)) == op_fcmpg)
1660 jdouble value2 = POPD ();
1661 jdouble value1 = POPD ();
1662 if (value1 > value2)
1664 else if (value1 == value2)
1666 else if (value1 < value2)
1668 else if ((*(pc-1)) == op_dcmpg)
1677 jint offset = get2s (pc);
1687 jint offset = get2s (pc);
1697 jint offset = get2s (pc);
1707 jint offset = get2s (pc);
1717 jint offset = get2s (pc);
1727 jint offset = get2s (pc);
1737 jint offset = get2s (pc);
1738 jint value2 = POPI();
1739 jint value1 = POPI();
1740 if (value1 == value2)
1749 jint offset = get2s (pc);
1750 jint value2 = POPI();
1751 jint value1 = POPI();
1752 if (value1 != value2)
1761 jint offset = get2s (pc);
1762 jint value2 = POPI();
1763 jint value1 = POPI();
1764 if (value1 < value2)
1773 jint offset = get2s (pc);
1774 jint value2 = POPI();
1775 jint value1 = POPI();
1776 if (value1 >= value2)
1785 jint offset = get2s (pc);
1786 jint value2 = POPI();
1787 jint value1 = POPI();
1788 if (value1 > value2)
1797 jint offset = get2s (pc);
1798 jint value2 = POPI();
1799 jint value1 = POPI();
1800 if (value1 <= value2)
1809 jint offset = get2s (pc);
1810 jobject value2 = POPA();
1811 jobject value1 = POPA();
1812 if (value1 == value2)
1821 jint offset = get2s (pc);
1822 jobject value2 = POPA();
1823 jobject value1 = POPA();
1824 if (value1 != value2)
1833 jint offset = get2s (pc);
1840 unsigned char *base_pc = pc-1;
1841 jint offset = get2s (pc); pc += 2;
1842 PUSHA ((jobject)pc);
1843 pc = base_pc+offset;
1849 jint index = get1u (pc);
1850 pc = (unsigned char*) PEEKA (index);
1856 unsigned char *base_pc = pc-1;
1859 unsigned char* base = bytecode ();
1860 while ((pc-base) % 4 != 0)
1863 jint def = get4 (pc);
1864 jint low = get4 (pc+4);
1865 jint high = get4 (pc+8);
1867 if (index < low || index > high)
1870 pc = base_pc + get4 (pc+4*(index-low+3));
1876 unsigned char *base_pc = pc-1;
1879 unsigned char* base = bytecode ();
1880 while ((pc-base) % 4 != 0)
1883 jint def = get4 (pc);
1884 jint npairs = get4 (pc+4);
1889 // simple binary search...
1892 int half = (min+max)/2;
1893 int match = get4 (pc+ 4*(2 + 2*half));
1898 else if (index < match)
1905 if (index == get4 (pc+ 4*(2 + 2*min)))
1906 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1912 /* on return, just save the sp and return to caller */
1925 jint fieldref_index = get2u (pc); pc += 2;
1926 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1927 _Jv_Field *field = pool_data[fieldref_index].field;
1929 if ((field->flags & Modifier::STATIC) == 0)
1930 throw_incompatible_class_change_error
1931 (JvNewStringLatin1 ("field no longer static"));
1933 jclass type = field->type;
1935 if (type->isPrimitive ())
1937 switch (type->size_in_bytes)
1940 PUSHI (*(jbyte*) (field->u.addr));
1944 if (type == JvPrimClass (char))
1945 PUSHI(*(jchar*) (field->u.addr));
1947 PUSHI(*(jshort*) (field->u.addr));
1951 PUSHI(*(jint*) (field->u.addr));
1955 PUSHL(*(jlong*) (field->u.addr));
1961 PUSHA(*(jobject*) (field->u.addr));
1969 jint fieldref_index = get2u (pc); pc += 2;
1970 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1971 _Jv_Field *field = pool_data[fieldref_index].field;
1973 if ((field->flags & Modifier::STATIC) != 0)
1974 throw_incompatible_class_change_error
1975 (JvNewStringLatin1 ("field is static"));
1977 jclass type = field->type;
1978 jint field_offset = field->u.boffset;
1979 if (field_offset > 0xffff)
1980 JvThrow (new java::lang::VirtualMachineError);
1982 jobject obj = POPA();
1985 if (type->isPrimitive ())
1987 switch (type->size_in_bytes)
1990 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1994 if (type == JvPrimClass (char))
1995 PUSHI (*(jchar*) ((char*)obj + field_offset));
1997 PUSHI (*(jshort*) ((char*)obj + field_offset));
2001 PUSHI (*(jint*) ((char*)obj + field_offset));
2005 PUSHL(*(jlong*) ((char*)obj + field_offset));
2011 PUSHA(*(jobject*) ((char*)obj + field_offset));
2019 jint fieldref_index = get2u (pc); pc += 2;
2020 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2021 _Jv_Field *field = pool_data[fieldref_index].field;
2023 jclass type = field->type;
2025 // ResolvePoolEntry cannot check this
2026 if ((field->flags & Modifier::STATIC) == 0)
2027 throw_incompatible_class_change_error
2028 (JvNewStringLatin1 ("field no longer static"));
2030 if (type->isPrimitive ())
2032 switch (type->size_in_bytes)
2036 jint value = POPI();
2037 *(jbyte*) (field->u.addr) = value;
2043 jint value = POPI();
2044 *(jchar*) (field->u.addr) = value;
2050 jint value = POPI();
2051 *(jint*) (field->u.addr) = value;
2057 jlong value = POPL();
2058 *(jlong*) (field->u.addr) = value;
2065 jobject value = POPA();
2066 *(jobject*) (field->u.addr) = value;
2075 jint fieldref_index = get2u (pc); pc += 2;
2076 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2077 _Jv_Field *field = pool_data[fieldref_index].field;
2079 jclass type = field->type;
2081 if ((field->flags & Modifier::STATIC) != 0)
2082 throw_incompatible_class_change_error
2083 (JvNewStringLatin1 ("field is static"));
2085 jint field_offset = field->u.boffset;
2086 if (field_offset > 0xffff)
2087 JvThrow (new java::lang::VirtualMachineError);
2089 if (type->isPrimitive ())
2091 switch (type->size_in_bytes)
2095 jint value = POPI();
2096 jobject obj = POPA();
2098 *(jbyte*) ((char*)obj + field_offset) = value;
2104 jint value = POPI();
2105 jobject obj = POPA();
2107 *(jchar*) ((char*)obj + field_offset) = value;
2113 jint value = POPI();
2114 jobject obj = POPA();
2116 *(jint*) ((char*)obj + field_offset) = value;
2122 jlong value = POPL();
2123 jobject obj = POPA();
2125 *(jlong*) ((char*)obj + field_offset) = value;
2132 jobject value = POPA();
2133 jobject obj = POPA();
2135 *(jobject*) ((char*)obj + field_offset) = value;
2143 int index = get2u (pc); pc += 2;
2145 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2147 sp -= rmeth->stack_item_count;
2149 NULLCHECK (sp[0].o);
2151 fun = (void (*)()) rmeth->method->ncode;
2153 goto perform_invoke;
2158 int index = get2u (pc); pc += 2;
2160 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2162 sp -= rmeth->stack_item_count;
2164 _Jv_InitClass (rmeth->klass);
2165 fun = (void (*)()) rmeth->method->ncode;
2167 goto perform_invoke;
2169 insn_invokeinterface:
2172 int index = get2u (pc); pc += 2;
2174 // invokeinterface has two unused bytes...
2177 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2179 sp -= rmeth->stack_item_count;
2181 jobject rcv = sp[0].o;
2186 _Jv_LookupInterfaceMethod (rcv->getClass (),
2187 rmeth->method->name,
2188 rmeth->method->signature);
2190 goto perform_invoke;
2196 int index = get2u (pc); pc += 2;
2197 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2198 _Jv_InitClass (klass);
2199 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2207 int atype = get1u (pc++);
2209 jobject result = _Jv_NewArray (atype, size);
2217 int index = get2u (pc); pc += 2;
2218 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2220 _Jv_InitClass (klass);
2221 jobject result = _Jv_NewObjectArray (size, klass, 0);
2229 __JArray *arr = (__JArray*)POPA();
2230 PUSHI (arr->length);
2237 jobject value = POPA();
2245 jobject value = POPA();
2246 jint index = get2u (pc); pc += 2;
2247 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2249 if (value != NULL && ! to->isInstance (value))
2251 JvThrow (new java::lang::ClassCastException
2262 jobject value = POPA();
2263 jint index = get2u (pc); pc += 2;
2264 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2265 PUSHI (to->isInstance (value));
2272 jobject value = POPA();
2274 _Jv_MonitorEnter (value);
2281 jobject value = POPA();
2283 _Jv_MonitorExit (value);
2289 unsigned char* base_pc = pc-1;
2290 jint offset = get2s (pc); pc += 2;
2291 jobject val = POPA();
2293 pc = base_pc+offset;
2299 unsigned char* base_pc = pc-1;
2300 jint offset = get2s (pc); pc += 2;
2301 jobject val = POPA();
2303 pc = base_pc+offset;
2310 jint the_mod_op = get1u (pc++);
2311 jint wide = get2u (pc); pc += 2;
2352 pc = (unsigned char*) PEEKA (wide);
2357 jint amount = get2s (pc); pc += 2;
2358 jint value = PEEKI (wide);
2359 POKEI (wide, value+amount);
2364 throw_internal_error ("illegal bytecode modified by wide");
2369 insn_multianewarray:
2372 int kind_index = get2u (pc); pc += 2;
2373 int dim = get1u (pc); pc += 1;
2376 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2377 _Jv_InitClass (type);
2378 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2380 for (int i = dim - 1; i >= 0; i--)
2385 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2393 unsigned char* base_pc = pc-1;
2394 int offset = get4 (pc); pc += 4;
2395 pc = base_pc+offset;
2401 unsigned char* base_pc = pc-1;
2402 int offset = get4 (pc); pc += 4;
2404 pc = base_pc+offset;
2411 throw_internal_error (char *msg)
2413 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2417 throw_incompatible_class_change_error (jstring msg)
2419 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2423 static java::lang::NullPointerException *null_pointer_exc;
2425 throw_null_pointer_exception ()
2427 if (null_pointer_exc == NULL)
2428 null_pointer_exc = new java::lang::NullPointerException;
2430 JvThrow (null_pointer_exc);
2434 #endif // INTERPRETER