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>
40 #define ClassError _CL_Q34java4lang5Error
41 extern java::lang::Class ClassError;
43 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
45 static void throw_internal_error (char *msg)
46 __attribute__ ((__noreturn__));
47 static void throw_incompatible_class_change_error (jstring msg)
48 __attribute__ ((__noreturn__));
50 static void throw_null_pointer_exception ()
51 __attribute__ ((__noreturn__));
54 extern "C" double __ieee754_fmod __P((double,double));
56 static inline void dupx (_Jv_word *sp, int n, int x)
58 // first "slide" n+x elements n to the right
60 for (int i = 0; i < n+x; i++)
62 sp[(top-i)] = sp[(top-i)-n];
65 // next, copy the n top elements, n+x down
66 for (int i = 0; i < n; i++)
68 sp[top-(n+x)-i] = sp[top-i];
74 #define PUSHA(V) (sp++)->o = (V)
75 #define PUSHI(V) (sp++)->i = (V)
76 #define PUSHF(V) (sp++)->f = (V)
77 #if SIZEOF_VOID_P == 8
78 # define PUSHL(V) (sp->l = (V), sp += 2)
79 # define PUSHD(V) (sp->d = (V), sp += 2)
81 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
82 (sp++)->ia[0] = w2.ia[0]; \
83 (sp++)->ia[0] = w2.ia[1]; } while (0)
84 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
85 (sp++)->ia[0] = w2.ia[0]; \
86 (sp++)->ia[0] = w2.ia[1]; } while (0)
89 #define POPA() ((--sp)->o)
90 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
91 #define POPF() ((jfloat) (--sp)->f)
92 #if SIZEOF_VOID_P == 8
93 # define POPL() (sp -= 2, (jlong) sp->l)
94 # define POPD() (sp -= 2, (jdouble) sp->d)
96 # define POPL() ({ _Jv_word2 w2; \
97 w2.ia[1] = (--sp)->ia[0]; \
98 w2.ia[0] = (--sp)->ia[0]; w2.l; })
99 # define POPD() ({ _Jv_word2 w2; \
100 w2.ia[1] = (--sp)->ia[0]; \
101 w2.ia[0] = (--sp)->ia[0]; w2.d; })
104 #define LOADA(I) (sp++)->o = locals[I].o
105 #define LOADI(I) (sp++)->i = locals[I].i
106 #define LOADF(I) (sp++)->f = locals[I].f
107 #if SIZEOF_VOID_P == 8
108 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
109 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
111 # define LOADL(I) do { jint __idx = (I); \
112 (sp++)->ia[0] = locals[__idx].ia[0]; \
113 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
115 # define LOADD(I) LOADL(I)
118 #define STOREA(I) locals[I].o = (--sp)->o
119 #define STOREI(I) locals[I].i = (--sp)->i
120 #define STOREF(I) locals[I].f = (--sp)->f
121 #if SIZEOF_VOID_P == 8
122 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
123 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
125 # define STOREL(I) do { jint __idx = (I); \
126 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
127 locals[__idx].ia[0] = (--sp)->ia[0]; \
129 # define STORED(I) STOREL(I)
132 #define PEEKI(I) (locals+(I))->i
133 #define PEEKA(I) (locals+(I))->o
135 #define POKEI(I,V) ((locals+(I))->i = (V))
138 #define BINOPI(OP) { \
139 jint value2 = POPI(); \
140 jint value1 = POPI(); \
141 PUSHI(value1 OP value2); \
144 #define BINOPF(OP) { \
145 jfloat value2 = POPF(); \
146 jfloat value1 = POPF(); \
147 PUSHF(value1 OP value2); \
150 #define BINOPL(OP) { \
151 jlong value2 = POPL(); \
152 jlong value1 = POPL(); \
153 PUSHL(value1 OP value2); \
156 #define BINOPD(OP) { \
157 jdouble value2 = POPD(); \
158 jdouble value1 = POPD(); \
159 PUSHD(value1 OP value2); \
162 static inline jint get1s(unsigned char* loc) {
163 return *(signed char*)loc;
166 static inline jint get1u(unsigned char* loc) {
170 static inline jint get2s(unsigned char* loc) {
171 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
174 static inline jint get2u(unsigned char* loc) {
175 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
178 static jint get4(unsigned char* loc) {
179 return (((jint)(loc[0])) << 24)
180 | (((jint)(loc[1])) << 16)
181 | (((jint)(loc[2])) << 8)
182 | (((jint)(loc[3])) << 0);
189 #define NULLCHECK(X) \
190 do { if ((X)==NULL) throw_null_pointer_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 least, that's the idea.
214 memcpy ((void*) locals, (void*) args, args_raw_size);
224 catch (java::lang::Throwable *ex2)
229 if (ex == 0) // no exception...
231 /* define sp locally, so the POP? macros will pick it up */
232 _Jv_word *sp = inv->sp;
233 int rtype = cif->rtype->type;
235 if (rtype == FFI_TYPE_POINTER)
238 *(jobject*) retp = r;
241 else if (rtype == FFI_TYPE_SINT32)
247 else if (rtype == FFI_TYPE_VOID)
260 case FFI_TYPE_DOUBLE:
268 case FFI_TYPE_UINT16:
269 case FFI_TYPE_UINT32:
271 case FFI_TYPE_SINT16:
278 case FFI_TYPE_SINT64:
286 throw_internal_error ("unknown return type");
290 /** handle an exception */
291 if ( find_exception (ex, inv) )
297 bool _Jv_InterpMethod::find_exception (jobject ex,
298 _Jv_InterpMethodInvocation *inv)
300 int logical_pc = inv->pc - bytecode ();
301 _Jv_InterpException *exc = exceptions ();
302 jclass exc_class = ex->getClass ();
304 for (int i = 0; i < exc_count; i++)
306 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
310 if (exc[i].handler_type != 0)
311 handler = (_Jv_ResolvePoolEntry (defining_class,
312 exc[i].handler_type)).clazz;
316 if (handler==NULL || handler->isAssignableFrom (exc_class))
318 inv->pc = bytecode () + exc[i].handler_pc;
319 inv->sp = inv->stack_base (); // reset stack
320 (inv->sp++)->o = ex; // push exception
328 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
333 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
335 // we do the alloca of the method invocation here, to allow the method
336 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
337 int storage_size = _this->max_stack+_this->max_locals;
338 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
339 alloca (sizeof (_Jv_InterpMethodInvocation)
340 + storage_size * sizeof (_Jv_word));
342 jobject ex = _this->run (cif, ret, args, inv);
343 if (ex != 0) _Jv_Throw (ex);
346 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
351 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
352 jobject rcv = (jobject)args[0].ptr;
354 int storage_size = _this->max_stack+_this->max_locals;
355 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
356 alloca (sizeof (_Jv_InterpMethodInvocation)
357 + storage_size * sizeof (_Jv_word));
359 _Jv_MonitorEnter (rcv);
360 jobject ex = _this->run (cif, ret, args, inv);
361 _Jv_MonitorExit (rcv);
363 if (ex != 0) _Jv_Throw (ex);
366 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
371 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
372 jclass sync = _this->defining_class;
374 int storage_size = _this->max_stack+_this->max_locals;
375 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
376 alloca (sizeof (_Jv_InterpMethodInvocation)
377 + storage_size * sizeof (_Jv_word));
379 _Jv_MonitorEnter (sync);
380 jobject ex = _this->run (cif, ret, args, inv);
381 _Jv_MonitorExit (sync);
383 if (ex != 0) _Jv_Throw (ex);
387 This proceeds execution, as designated in "inv". If an exception
388 happens, then it is simply thrown, and handled in Java. Thus, the pc
389 needs to be stored in the inv->pc at all times, so we can figure
390 out which handler (if any) to invoke.
392 One design issue, which I have not completely considered, is if it
393 should be possible to have interpreted classes linked in! Seldom used
394 (or non-critical) classes could reasonably be interpreted.
398 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
400 using namespace java::lang::reflect;
402 _Jv_word *sp = inv->sp;
403 unsigned char *pc = inv->pc;
404 _Jv_word *locals = inv->local_base ();
406 _Jv_word *pool_data = defining_class->constants.data;
408 /* these two are used in the invokeXXX instructions */
410 _Jv_ResolvedMethod* rmeth;
412 #define INSN_LABEL(op) &&insn_##op
413 #define GOTO_INSN(op) goto *(insn_target[op])
415 static const void *const insn_target[] =
418 INSN_LABEL(aconst_null),
419 INSN_LABEL(iconst_m1),
420 INSN_LABEL(iconst_0),
421 INSN_LABEL(iconst_1),
422 INSN_LABEL(iconst_2),
423 INSN_LABEL(iconst_3),
424 INSN_LABEL(iconst_4),
425 INSN_LABEL(iconst_5),
426 INSN_LABEL(lconst_0),
427 INSN_LABEL(lconst_1),
428 INSN_LABEL(fconst_0),
429 INSN_LABEL(fconst_1),
430 INSN_LABEL(fconst_2),
431 INSN_LABEL(dconst_0),
432 INSN_LABEL(dconst_1),
476 INSN_LABEL(istore_0),
477 INSN_LABEL(istore_1),
478 INSN_LABEL(istore_2),
479 INSN_LABEL(istore_3),
480 INSN_LABEL(lstore_0),
481 INSN_LABEL(lstore_1),
482 INSN_LABEL(lstore_2),
483 INSN_LABEL(lstore_3),
484 INSN_LABEL(fstore_0),
485 INSN_LABEL(fstore_1),
486 INSN_LABEL(fstore_2),
487 INSN_LABEL(fstore_3),
488 INSN_LABEL(dstore_0),
489 INSN_LABEL(dstore_1),
490 INSN_LABEL(dstore_2),
491 INSN_LABEL(dstore_3),
492 INSN_LABEL(astore_0),
493 INSN_LABEL(astore_1),
494 INSN_LABEL(astore_2),
495 INSN_LABEL(astore_3),
576 INSN_LABEL(if_icmpeq),
577 INSN_LABEL(if_icmpne),
578 INSN_LABEL(if_icmplt),
579 INSN_LABEL(if_icmpge),
580 INSN_LABEL(if_icmpgt),
581 INSN_LABEL(if_icmple),
582 INSN_LABEL(if_acmpeq),
583 INSN_LABEL(if_acmpne),
587 INSN_LABEL(tableswitch),
588 INSN_LABEL(lookupswitch),
595 INSN_LABEL(getstatic),
596 INSN_LABEL(putstatic),
597 INSN_LABEL(getfield),
598 INSN_LABEL(putfield),
599 INSN_LABEL(invokevirtual),
600 INSN_LABEL(invokespecial),
601 INSN_LABEL(invokestatic),
602 INSN_LABEL(invokeinterface),
603 0, /* op_xxxunusedxxx1, */
605 INSN_LABEL(newarray),
606 INSN_LABEL(anewarray),
607 INSN_LABEL(arraylength),
609 INSN_LABEL(checkcast),
610 INSN_LABEL(instanceof),
611 INSN_LABEL(monitorenter),
612 INSN_LABEL(monitorexit),
614 INSN_LABEL(multianewarray),
616 INSN_LABEL(ifnonnull),
621 #define SAVE_PC inv->pc = pc-1
623 /* If the macro INLINE_SWITCH is not defined, then the main loop
624 operates as one big (normal) switch statement. If it is defined,
625 then the case selection is performed `inline' in the end of the
626 code for each case. The latter saves a native branch instruction
627 for each java-instruction, but expands the code size somewhat.
629 NOTE: On i386 defining INLINE_SWITCH improves over all
630 performance approximately seven percent, but it may be different
631 for other machines. At some point, this may be made into a proper
632 configuration parameter. */
634 #define INLINE_SWITCH
638 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
644 #define NEXT_INSN goto next_insn
651 /* The first few instructions here are ordered according to their
652 frequency, in the hope that this will improve code locality a
655 insn_aload_0: // 0x2a
660 LOADI (get1u (pc++));
663 insn_iload_1: // 0x1b
667 insn_invokevirtual: // 0xb6
670 int index = get2u (pc); pc += 2;
672 /* _Jv_ResolvePoolEntry returns immediately if the value already
673 * is resolved. If we want to clutter up the code here to gain
674 * a little performance, then we can check the corresponding bit
675 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
676 * don't think it is worth it. */
678 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
680 sp -= rmeth->stack_item_count;
683 if (rmeth->vtable_index == -1)
685 // final methods do not appear in the vtable,
686 // if it does not appear in the superclass.
687 fun = (void (*) (...)) rmeth->method->ncode;
691 jobject rcv = sp[0].o;
692 _Jv_VTable *table = *(_Jv_VTable**)rcv;
693 fun = (void (*) (...))table->method[rmeth->vtable_index];
700 /* here goes the magic again... */
701 ffi_cif *cif = &rmeth->cif;
702 ffi_raw *raw = (ffi_raw*) sp;
706 #if FFI_NATIVE_RAW_API
707 /* We assume that this is only implemented if it's correct */
708 /* to use it here. On a 64 bit machine, it never is. */
709 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
711 ffi_java_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 STOREA (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();
1384 jint res = _Jv_divI (value1, value2);
1392 jlong value2 = POPL();
1393 jlong value1 = POPL();
1394 jlong res = _Jv_divJ (value1, value2);
1402 jfloat value2 = POPF();
1403 jfloat value1 = POPF();
1404 jfloat res = value1 / value2;
1412 jdouble value2 = POPD();
1413 jdouble value1 = POPD();
1414 jdouble res = value1 / value2;
1422 jint value2 = POPI();
1423 jint value1 = POPI();
1424 jint res = _Jv_remI (value1, value2);
1432 jlong value2 = POPL();
1433 jlong value1 = POPL();
1434 jlong res = _Jv_remJ (value1, value2);
1442 jfloat value2 = POPF();
1443 jfloat value1 = POPF();
1444 jfloat res = __ieee754_fmod (value1, value2);
1452 jdouble value2 = POPD();
1453 jdouble value1 = POPD();
1454 jdouble res = __ieee754_fmod (value1, value2);
1461 jint value = POPI();
1468 jlong value = POPL();
1475 jfloat value = POPF();
1482 jdouble value = POPD();
1489 jint shift = (POPI() & 0x1f);
1490 jint value = POPI();
1491 PUSHI (value << shift);
1497 jint shift = (POPI() & 0x3f);
1498 jlong value = POPL();
1499 PUSHL (value << shift);
1505 jint shift = (POPI() & 0x1f);
1506 jint value = POPI();
1507 PUSHI (value >> shift);
1513 jint shift = (POPI() & 0x3f);
1514 jlong value = POPL();
1515 PUSHL (value >> shift);
1521 jint shift = (POPI() & 0x1f);
1522 unsigned long value = POPI();
1523 PUSHI ((jint) (value >> shift));
1529 jint shift = (POPI() & 0x3f);
1530 UINT64 value = (UINT64) POPL();
1531 PUSHL ((value >> shift));
1561 jint index = get1u (pc++);
1562 jint amount = get1s (pc++);
1563 locals[index].i += amount;
1568 {jlong value = POPI(); PUSHL (value);}
1572 {jfloat value = POPI(); PUSHF (value);}
1576 {jdouble value = POPI(); PUSHD (value);}
1580 {jint value = POPL(); PUSHI (value);}
1584 {jfloat value = POPL(); PUSHF (value);}
1588 {jdouble value = POPL(); PUSHD (value);}
1592 { jint value = (jint)POPF (); PUSHI(value); }
1596 { jlong value = (jlong)POPF (); PUSHL(value); }
1600 { jdouble value = POPF (); PUSHD(value); }
1604 { jint value = (jint)POPD (); PUSHI(value); }
1608 { jlong value = (jlong)POPD (); PUSHL(value); }
1612 { jfloat value = POPD (); PUSHF(value); }
1616 { jbyte value = POPI (); PUSHI(value); }
1620 { jchar value = POPI (); PUSHI(value); }
1624 { jshort value = POPI (); PUSHI(value); }
1629 jlong value2 = POPL ();
1630 jlong value1 = POPL ();
1631 if (value1 > value2)
1633 else if (value1 == value2)
1643 jfloat value2 = POPF ();
1644 jfloat value1 = POPF ();
1645 if (value1 > value2)
1647 else if (value1 == value2)
1649 else if (value1 < value2)
1651 else if ((*(pc-1)) == op_fcmpg)
1661 jdouble value2 = POPD ();
1662 jdouble value1 = POPD ();
1663 if (value1 > value2)
1665 else if (value1 == value2)
1667 else if (value1 < value2)
1669 else if ((*(pc-1)) == op_dcmpg)
1678 jint offset = get2s (pc);
1688 jint offset = get2s (pc);
1698 jint offset = get2s (pc);
1708 jint offset = get2s (pc);
1718 jint offset = get2s (pc);
1728 jint offset = get2s (pc);
1738 jint offset = get2s (pc);
1739 jint value2 = POPI();
1740 jint value1 = POPI();
1741 if (value1 == value2)
1750 jint offset = get2s (pc);
1751 jint value2 = POPI();
1752 jint value1 = POPI();
1753 if (value1 != value2)
1762 jint offset = get2s (pc);
1763 jint value2 = POPI();
1764 jint value1 = POPI();
1765 if (value1 < value2)
1774 jint offset = get2s (pc);
1775 jint value2 = POPI();
1776 jint value1 = POPI();
1777 if (value1 >= value2)
1786 jint offset = get2s (pc);
1787 jint value2 = POPI();
1788 jint value1 = POPI();
1789 if (value1 > value2)
1798 jint offset = get2s (pc);
1799 jint value2 = POPI();
1800 jint value1 = POPI();
1801 if (value1 <= value2)
1810 jint offset = get2s (pc);
1811 jobject value2 = POPA();
1812 jobject value1 = POPA();
1813 if (value1 == value2)
1822 jint offset = get2s (pc);
1823 jobject value2 = POPA();
1824 jobject value1 = POPA();
1825 if (value1 != value2)
1834 jint offset = get2s (pc);
1841 unsigned char *base_pc = pc-1;
1842 jint offset = get2s (pc); pc += 2;
1843 PUSHA ((jobject)pc);
1844 pc = base_pc+offset;
1850 jint index = get1u (pc);
1851 pc = (unsigned char*) PEEKA (index);
1857 unsigned char *base_pc = pc-1;
1860 unsigned char* base = bytecode ();
1861 while ((pc-base) % 4 != 0)
1864 jint def = get4 (pc);
1865 jint low = get4 (pc+4);
1866 jint high = get4 (pc+8);
1868 if (index < low || index > high)
1871 pc = base_pc + get4 (pc+4*(index-low+3));
1877 unsigned char *base_pc = pc-1;
1880 unsigned char* base = bytecode ();
1881 while ((pc-base) % 4 != 0)
1884 jint def = get4 (pc);
1885 jint npairs = get4 (pc+4);
1890 // simple binary search...
1893 int half = (min+max)/2;
1894 int match = get4 (pc+ 4*(2 + 2*half));
1899 else if (index < match)
1906 if (index == get4 (pc+ 4*(2 + 2*min)))
1907 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1913 /* on return, just save the sp and return to caller */
1926 jint fieldref_index = get2u (pc); pc += 2;
1927 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1928 _Jv_Field *field = pool_data[fieldref_index].field;
1930 if ((field->flags & Modifier::STATIC) == 0)
1931 throw_incompatible_class_change_error
1932 (JvNewStringLatin1 ("field no longer static"));
1934 jclass type = field->type;
1936 if (type->isPrimitive ())
1938 switch (type->size_in_bytes)
1941 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;
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;
2182 jobject rcv = sp[0].o;
2184 fun = (void (*) (...))
2185 _Jv_LookupInterfaceMethod (rcv->getClass (),
2186 rmeth->method->name,
2187 rmeth->method->signature);
2189 goto perform_invoke;
2195 int index = get2u (pc); pc += 2;
2196 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2197 _Jv_InitClass (klass);
2198 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2206 int atype = get1u (pc++);
2208 jobject result = _Jv_NewArray (atype, size);
2216 int index = get2u (pc); pc += 2;
2217 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2219 _Jv_InitClass (klass);
2220 jobject result = _Jv_NewObjectArray (size, klass, 0);
2228 __JArray *arr = (__JArray*)POPA();
2229 PUSHI (arr->length);
2236 jobject value = POPA();
2244 jobject value = POPA();
2245 jint index = get2u (pc); pc += 2;
2246 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2248 if (value != NULL && ! to->isInstance (value))
2250 JvThrow (new java::lang::ClassCastException
2261 jobject value = POPA();
2262 jint index = get2u (pc); pc += 2;
2263 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2264 PUSHI (to->isInstance (value));
2271 jobject value = POPA();
2273 _Jv_MonitorEnter (value);
2280 jobject value = POPA();
2282 _Jv_MonitorExit (value);
2288 unsigned char* base_pc = pc-1;
2289 jint offset = get2s (pc); pc += 2;
2290 jobject val = POPA();
2292 pc = base_pc+offset;
2298 unsigned char* base_pc = pc-1;
2299 jint offset = get2s (pc); pc += 2;
2300 jobject val = POPA();
2302 pc = base_pc+offset;
2309 jint the_mod_op = get1u (pc++);
2310 jint wide = get2u (pc); pc += 2;
2351 pc = (unsigned char*) PEEKA (wide);
2356 jint amount = get2s (pc); pc += 2;
2357 jint value = PEEKI (wide);
2358 POKEI (wide, value+amount);
2363 throw_internal_error ("illegal bytecode modified by wide");
2368 insn_multianewarray:
2371 int kind_index = get2u (pc); pc += 2;
2372 int dim = get1u (pc); pc += 1;
2375 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2376 _Jv_InitClass (type);
2377 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2379 for (int i = dim - 1; i >= 0; i--)
2384 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2392 unsigned char* base_pc = pc-1;
2393 int offset = get4 (pc); pc += 4;
2394 pc = base_pc+offset;
2400 unsigned char* base_pc = pc-1;
2401 int offset = get4 (pc); pc += 4;
2403 pc = base_pc+offset;
2410 throw_internal_error (char *msg)
2412 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2416 throw_incompatible_class_change_error (jstring msg)
2418 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2422 static java::lang::NullPointerException *null_pointer_exc;
2424 throw_null_pointer_exception ()
2426 if (null_pointer_exc == NULL)
2427 null_pointer_exc = new java::lang::NullPointerException;
2429 JvThrow (null_pointer_exc);
2433 #endif // INTERPRETER