1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999 Cygnus Solutions
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> */
13 /* define this to get instruction timings. */
14 /* #define TIME_MAINLOOP */
18 #pragma implementation "java-interp.h"
22 #include <java-field.h>
23 #include <java-cpool.h>
24 #include <java-interp.h>
25 #include <java/lang/fdlibm.h>
26 #include <java/lang/System.h>
27 #include <java/lang/String.h>
28 #include <java/lang/Integer.h>
29 #include <java/lang/StringBuffer.h>
30 #include <java/io/PrintStream.h>
31 #include <java/lang/Class.h>
32 #include <java/lang/reflect/Modifier.h>
33 #include <java/lang/ClassCastException.h>
34 #include <java/lang/VirtualMachineError.h>
35 #include <java/lang/InternalError.h>
36 #include <java/lang/NullPointerException.h>
37 #include <java/lang/ArithmeticException.h>
38 #include <java/lang/IncompatibleClassChangeError.h>
39 #include <java-insns.h>
40 #include <java-signal.h>
48 #include <gnu/gcj/runtime/MethodInvocation.h>
50 /* This should never happen. */
52 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
55 JvFail ("no interpreter");
60 #define ClassError _CL_Q34java4lang5Error
61 extern java::lang::Class ClassError;
63 static const int PUBLIC = 0x001;
64 static const int PRIVATE = 0x002;
65 static const int PROTECTED = 0x004;
66 static const int STATIC = 0x008;
67 static const int FINAL = 0x010;
68 static const int SYNCHRONIZED = 0x020;
69 static const int VOLATILE = 0x040;
70 static const int TRANSIENT = 0x080;
71 static const int NATIVE = 0x100;
72 static const int INTERFACE = 0x200;
73 static const int ABSTRACT = 0x400;
74 static const int ALL_FLAGS = 0x7FF;
76 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
78 static void throw_internal_error (char *msg)
79 __attribute__ ((__noreturn__));
80 static void throw_incompatible_class_change_error (jstring msg)
81 __attribute__ ((__noreturn__));
83 static void throw_null_pointer_exception ()
84 __attribute__ ((__noreturn__));
87 static void throw_arithmetic_exception ()
88 __attribute__ ((__noreturn__));
92 static inline void dupx (_Jv_word *&sp, int n, int x)
94 // first "slide" n+x elements n to the right
96 for (int i = 0; i < n+x; i++)
98 sp[(top-i)] = sp[(top-i)-n];
101 // next, copy the n top elements, n+x down
102 for (int i = 0; i < n; i++)
104 sp[top-(n+x)-i] = sp[top-i];
112 #define PUSHA(V) (sp++)->o = (V)
113 #define PUSHI(V) (sp++)->i = (V)
114 #define PUSHF(V) (sp++)->f = (V)
115 #define PUSHL(V) ({ _Jv_word2 w2; w2.l=(V); \
116 (sp++)->ia[0] = w2.ia[0]; \
117 (sp++)->ia[0] = w2.ia[1]; })
118 #define PUSHD(V) ({ _Jv_word2 w2; w2.d=(V); \
119 (sp++)->ia[0] = w2.ia[0]; \
120 (sp++)->ia[0] = w2.ia[1]; })
122 #define POPA() ((--sp)->o)
123 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
124 #define POPF() ((jfloat) (--sp)->f)
125 #define POPL() ({ _Jv_word2 w2; \
126 w2.ia[1] = (--sp)->ia[0]; \
127 w2.ia[0] = (--sp)->ia[0]; w2.l; })
128 #define POPD() ({ _Jv_word2 w2; \
129 w2.ia[1] = (--sp)->ia[0]; \
130 w2.ia[0] = (--sp)->ia[0]; w2.d; })
132 #define LOADA(I) (sp++)->o = locals[I].o
133 #define LOADI(I) (sp++)->i = locals[I].i
134 #define LOADF(I) (sp++)->f = locals[I].f
135 #define LOADL(I) ({ jint __idx = (I); \
136 (sp++)->ia[0] = locals[__idx].ia[0]; \
137 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
139 #define LOADD(I) LOADL(I)
142 #define STOREA(I) locals[I].o = (--sp)->o
143 #define STOREI(I) locals[I].i = (--sp)->i
144 #define STOREF(I) locals[I].f = (--sp)->f
145 #define STOREL(I) ({ jint __idx = (I); \
146 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
147 locals[__idx].ia[0] = (--sp)->ia[0]; \
149 #define STORED(I) STOREL(I)
151 #define PEEKI(I) (locals+(I))->i
152 #define PEEKA(I) (locals+(I))->o
154 #define POKEI(I,V) (*(jint*) (locals+(I)) = (V))
157 #define BINOPI(OP) { \
158 jint value2 = POPI(); \
159 jint value1 = POPI(); \
160 PUSHI(value1 OP value2); \
163 #define BINOPF(OP) { \
164 jfloat value2 = POPF(); \
165 jfloat value1 = POPF(); \
166 PUSHF(value1 OP value2); \
169 #define BINOPL(OP) { \
170 jlong value2 = POPL(); \
171 jlong value1 = POPL(); \
172 PUSHL(value1 OP value2); \
175 #define BINOPD(OP) { \
176 jdouble value2 = POPD(); \
177 jdouble value1 = POPD(); \
178 PUSHD(value1 OP value2); \
181 static inline jint get1s(unsigned char* loc) {
182 return *(signed char*)loc;
185 static inline jint get1u(unsigned char* loc) {
189 static inline jint get2s(unsigned char* loc) {
190 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
193 static inline jint get2u(unsigned char* loc) {
194 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
197 static jint get4(unsigned char* loc) {
198 return (((jint)(loc[0])) << 24)
199 | (((jint)(loc[1])) << 16)
200 | (((jint)(loc[2])) << 8)
201 | (((jint)(loc[3])) << 0);
208 #define NULLCHECK(X) \
209 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
215 #define ZEROCHECK(X) \
216 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
219 // this method starts the actual running of the method. It is inlined
220 // in three different variants in the static methods run_normal,
221 // run_sync_object and run_sync_class (see below). Those static methods
222 // are installed directly in the stub for this method (by
223 // _Jv_InterpMethod::ncode, in resolve.cc).
226 _Jv_InterpMethod::run (ffi_cif* cif,
229 _Jv_InterpMethodInvocation *inv)
232 inv->pc = bytecode ();
233 inv->sp = inv->stack_base ();
234 _Jv_word *locals = inv->local_base ();
236 /* Go straight at it! the ffi raw format matches the internal
237 stack representation exactly. At leat, that's the idea.
239 memcpy ((void*) locals, (void*) args, args_raw_size);
242 /* this will call the method _Jv_InterpMethod::continue0, see below */
244 gnu::gcj::runtime::MethodInvocation::continue0
245 ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
247 if (ex == 0) // no exception...
249 /* define sp locally, so the POP? macros will pick it up */
250 _Jv_word *sp = inv->sp;
251 int rtype = cif->rtype->type;
253 if (rtype == FFI_TYPE_POINTER)
256 *(jobject*) retp = r;
259 else if (rtype == FFI_TYPE_SINT32)
265 else if (rtype == FFI_TYPE_VOID)
278 case FFI_TYPE_DOUBLE:
286 case FFI_TYPE_UINT16:
287 case FFI_TYPE_UINT32:
289 case FFI_TYPE_SINT16:
296 case FFI_TYPE_SINT64:
304 throw_internal_error ("unknown return type");
309 /** handle an exception */
310 if ( find_exception (ex, inv) )
313 java::lang::System::out->println
314 (_Jv_NewStringUTF (self->name->data));
319 bool _Jv_InterpMethod::find_exception (jobject ex,
320 _Jv_InterpMethodInvocation *inv)
322 int logical_pc = inv->pc - bytecode ();
323 _Jv_InterpException *exc = exceptions ();
324 jclass exc_class = ex->getClass ();
326 for (int i = 0; i < exc_count; i++)
328 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
332 if (exc[i].handler_type != 0)
333 handler = (_Jv_ResolvePoolEntry (defining_class,
334 exc[i].handler_type)).clazz;
338 if (handler==NULL || handler->isAssignableFrom (exc_class))
340 inv->pc = bytecode () + exc[i].handler_pc;
341 inv->sp = inv->stack_base (); // reset stack
342 (inv->sp++)->o = ex; // push exception
350 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
355 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
357 // we do the alloca of the method invocation here, to allow the method
358 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
359 int storage_size = _this->max_stack+_this->max_locals;
360 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
361 alloca (sizeof (_Jv_InterpMethodInvocation)
362 + storage_size * sizeof (_Jv_word));
364 jobject ex = _this->run (cif, ret, args, inv);
365 if (ex != 0) _Jv_Throw (ex);
368 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
373 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
374 jobject rcv = (jobject)args[0].ptr;
376 int storage_size = _this->max_stack+_this->max_locals;
377 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
378 alloca (sizeof (_Jv_InterpMethodInvocation)
379 + storage_size * sizeof (_Jv_word));
381 _Jv_MonitorEnter (rcv);
382 jobject ex = _this->run (cif, ret, args, inv);
383 _Jv_MonitorExit (rcv);
385 if (ex != 0) _Jv_Throw (ex);
388 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
393 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
394 jclass sync = _this->defining_class;
396 int storage_size = _this->max_stack+_this->max_locals;
397 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
398 alloca (sizeof (_Jv_InterpMethodInvocation)
399 + storage_size * sizeof (_Jv_word));
401 _Jv_MonitorEnter (sync);
402 jobject ex = _this->run (cif, ret, args, inv);
403 _Jv_MonitorExit (sync);
405 if (ex != 0) _Jv_Throw (ex);
408 /* this is the exception handler hack, for the interpreter */
410 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
411 gnu::gcj::RawData *inv)
413 _Jv_InterpMethod *meth0 = (_Jv_InterpMethod*)meth;
414 _Jv_InterpMethodInvocation *inv0 = (_Jv_InterpMethodInvocation*)inv;
415 meth0->continue1 (inv0);
419 This proceeds execution, as designated in "inv". If an exception
420 happens, then it is simply thrown, and handled in Java. Thus, the pc
421 needs to be stored in the invocation at all times, so we can figure
422 out which handler (if any) to invoke.
424 One design issue, which I have not completely considered, is if it
425 should be possible to have interpreted classes linked in! Seldom used
426 (or non-critical) classes could reasonably be interpreted.
431 static jlong insn_time [256] = { 0 };
432 static jlong insn_count[256] = { 0 };
437 double total_all = 0;
438 for (int i = 0; i < 256; i++)
440 total_all += insn_time[i];
443 for (int i = 0; i < 256; i++)
445 jlong total = insn_time[i];
446 jlong count = insn_count[i];
448 if (count == 0) continue;
450 jlong amount = total/count;
452 printf ("in 0x%02x: %7Li %7Li %7Li %2.1f%%\n", i,
453 (long long)count, (long long)total, (long long)amount,
454 (float) (100.0*(double)total/total_all)
460 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
462 _Jv_word *sp = inv->sp;
463 unsigned char *pc = inv->pc;
464 _Jv_word *locals = inv->local_base ();
467 jclass defining_class = this->defining_class;
468 _Jv_word *pool_data = defining_class->constants.data;
470 /* these two are used in the invokeXXX instructions */
472 _Jv_ResolvedMethod* rmeth;
478 static jlong time_warp = 0;
481 ((jlong) (TV).tv_sec * 1000000LL + (jlong)(TV).tv_usec)
488 gettimeofday (&tv, 0);
489 for (int i = 0; i < 100; i++)
490 gettimeofday (&tv2, 0);
492 jlong then = USEC(tv);
493 jlong now = USEC(tv2);
494 time_warp = (now - then) / 100;
500 #define TIME_SUSPEND do { \
501 gettimeofday (&tv, 0); \
502 jlong now = USEC(tv); \
503 insn_time[last_opcode] += (now - last_time) - time_warp; \
506 #define TIME_RESUME do { \
507 gettimeofday (&tv, 0); \
508 last_time = USEC(tv); \
512 gettimeofday (&tv, 0);
513 last_time = (jlong)tv.tv_sec * 1000000LL + (jlong)tv.tv_usec;
527 gettimeofday (&tv, 0);
528 jlong now = USEC(tv);
529 insn_time[last_opcode] += (now - last_time) - time_warp;
532 insn_count[last_opcode] += 1;
539 case op_aload_0: // 0x2a
543 case op_iload: // 0x15
544 LOADI (get1u (pc++));
547 case op_getfield_4: // 0xd8
549 jobject obj = POPA();
551 jint field_offset = get2u (pc); pc += 2;
552 PUSHI (*(jint*) ((char*)obj + field_offset));
556 case op_iload_1: // 0x1b
560 case op_getfield_a: // 0xda
562 jobject obj = POPA();
564 jint field_offset = get2u (pc); pc += 2;
565 PUSHA(*(jobject*) ((char*)obj + field_offset));
569 case op_invokevirtual: // 0xb6
571 int index = get2u (pc); pc += 2;
573 /* _Jv_ResolvePoolEntry returns immediately if the value already
574 * is resolved. If we want to clutter up the code here to gain
575 * a little performance, then we can check the corresponding bit
576 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
577 * don't think it is worth it. */
579 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
581 sp -= rmeth->stack_item_count;
584 if (rmeth->vtable_index == -1)
586 // final methods do not appear in the vtable,
587 // if it does not appear in the superclass.
588 fun = (void (*) (...)) rmeth->method->ncode;
592 jobject rcv = sp[0].o;
593 _Jv_VTable *table = *(_Jv_VTable**)rcv;
594 fun = (void (*) (...))table->method[rmeth->vtable_index];
601 /* here goes the magic again... */
602 ffi_cif *cif = &rmeth->cif;
603 ffi_raw *raw = (ffi_raw*) sp;
608 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
611 int rtype = cif->rtype->type;
613 /* the likelyhood of object, int, or void return is very high,
614 * so those are checked before the switch */
615 if (rtype == FFI_TYPE_POINTER)
617 PUSHA (*(jobject*)&rvalue);
619 else if (rtype == FFI_TYPE_SINT32)
621 PUSHI (*(jint*)&rvalue);
623 else if (rtype == FFI_TYPE_VOID)
631 jbyte value = (*(jint*)&rvalue) & 0xff;
636 case FFI_TYPE_SINT16:
638 jshort value = (*(jint*)&rvalue) & 0xffff;
643 case FFI_TYPE_UINT16:
645 jint value = (*(jint*)&rvalue) & 0xffff;
651 PUSHF (*(jfloat*)&rvalue);
654 case FFI_TYPE_DOUBLE:
658 case FFI_TYPE_SINT64:
659 PUSHL (*(jlong*)&rvalue);
663 throw_internal_error ("unknown return type in invokeXXX");
684 PUSHI (opcode-op_iconst_0);
689 PUSHL ((jlong) (opcode-op_lconst_0));
695 PUSHF ((jfloat) (opcode-op_fconst_0));
700 PUSHD ((jdouble) (opcode-op_dconst_0));
708 PUSHI (get2s(pc)); pc += 2;
713 int index = get1u (pc++);
714 PUSHA(pool_data[index].o);
720 int index = get2u (pc); pc += 2;
721 PUSHA(pool_data[index].o);
727 int index = get2u (pc); pc += 2;
728 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
734 LOADL (get1u (pc++));
738 LOADF (get1u (pc++));
742 LOADD (get1u (pc++));
746 LOADA (get1u (pc++));
765 LOADL (opcode-op_lload_0);
772 LOADF (opcode-op_fload_0);
779 LOADD (opcode-op_dload_0);
797 jintArray arr = (jintArray) POPA();
799 if (index < 0 || index >= arr->length)
802 _Jv_ThrowBadArrayIndex (index);
804 PUSHI( elements(arr)[index] );
811 jlongArray arr = (jlongArray) POPA();
813 if (index < 0 || index >= arr->length)
816 _Jv_ThrowBadArrayIndex (index);
818 PUSHL( elements(arr)[index] );
825 jfloatArray arr = (jfloatArray) POPA();
827 if (index < 0 || index >= arr->length)
830 _Jv_ThrowBadArrayIndex (index);
832 PUSHF( elements(arr)[index] );
839 jdoubleArray arr = (jdoubleArray) POPA();
841 if (index < 0 || index >= arr->length)
844 _Jv_ThrowBadArrayIndex (index);
846 PUSHD( elements(arr)[index] );
853 jobjectArray arr = (jobjectArray) POPA();
855 if (index < 0 || index >= arr->length)
858 _Jv_ThrowBadArrayIndex (index);
860 PUSHA( elements(arr)[index] );
867 jbyteArray arr = (jbyteArray) POPA();
869 if (index < 0 || index >= arr->length)
872 _Jv_ThrowBadArrayIndex (index);
874 PUSHI( elements(arr)[index] );
881 jcharArray arr = (jcharArray) POPA();
883 if (index < 0 || index >= arr->length)
886 _Jv_ThrowBadArrayIndex (index);
888 PUSHI( elements(arr)[index] );
895 jshortArray arr = (jshortArray) POPA();
897 if (index < 0 || index >= arr->length)
900 _Jv_ThrowBadArrayIndex (index);
902 PUSHI( elements(arr)[index] );
907 STOREI (get1u (pc++));
911 STOREL (get1u (pc++));
915 STOREF (get1u (pc++));
919 STORED (get1u (pc++));
923 STOREI (get1u (pc++));
930 STOREI (opcode-op_istore_0);
937 STOREL (opcode-op_lstore_0);
944 STOREF (opcode-op_fstore_0);
951 STORED (opcode-op_dstore_0);
958 STOREA (opcode-op_astore_0);
965 jintArray arr = (jintArray) POPA();
967 if (index < 0 || index >= arr->length)
970 _Jv_ThrowBadArrayIndex (index);
972 elements(arr)[index] = value;
978 jlong value = POPL();
980 jlongArray arr = (jlongArray) POPA();
982 if (index < 0 || index >= arr->length)
985 _Jv_ThrowBadArrayIndex (index);
987 elements(arr)[index] = value;
993 jfloat value = POPF();
995 jfloatArray arr = (jfloatArray) POPA();
997 if (index < 0 || index >= arr->length)
1000 _Jv_ThrowBadArrayIndex (index);
1002 elements(arr)[index] = value;
1008 jdouble value = POPD();
1009 jint index = POPI();
1010 jdoubleArray arr = (jdoubleArray) POPA();
1012 if (index < 0 || index >= arr->length)
1015 _Jv_ThrowBadArrayIndex (index);
1017 elements(arr)[index] = value;
1023 jobject value = POPA();
1024 jint index = POPI();
1025 jobjectArray arr = (jobjectArray) POPA();
1027 if (index < 0 || index >= arr->length)
1030 _Jv_ThrowBadArrayIndex (index);
1032 _Jv_CheckArrayStore (arr, value);
1033 elements(arr)[index] = value;
1039 jbyte value = (jbyte) POPI();
1040 jint index = POPI();
1041 jbyteArray arr = (jbyteArray) POPA();
1043 if (index < 0 || index >= arr->length)
1046 _Jv_ThrowBadArrayIndex (index);
1048 elements(arr)[index] = value;
1054 jchar value = (jchar) POPI();
1055 jint index = POPI();
1056 jcharArray arr = (jcharArray) POPA();
1058 if (index < 0 || index >= arr->length)
1061 _Jv_ThrowBadArrayIndex (index);
1063 elements(arr)[index] = value;
1069 jshort value = (jshort) POPI();
1070 jint index = POPI();
1071 jshortArray arr = (jshortArray) POPA();
1073 if (index < 0 || index >= arr->length)
1076 _Jv_ThrowBadArrayIndex (index);
1078 elements(arr)[index] = value;
1119 jobject tmp1 = POPA();
1120 jobject tmp2 = POPA();
1176 jint value2 = POPI();
1177 jint value1 = POPI();
1179 jint res = value1 / value2;
1186 jlong value2 = POPL();
1187 jlong value1 = POPL();
1189 jlong res = value1 / value2;
1196 jfloat value2 = POPF();
1197 jfloat value1 = POPF();
1199 jfloat res = value1 / value2;
1206 jdouble value2 = POPD();
1207 jdouble value1 = POPD();
1209 jdouble res = value1 / value2;
1216 jint value2 = POPI();
1217 jint value1 = POPI();
1219 jint res = value1 % value2;
1226 jlong value2 = POPL();
1227 jlong value1 = POPL();
1229 jlong res = value1 % value2;
1236 jfloat value2 = POPF();
1237 jfloat value1 = POPF();
1239 jfloat res = __ieee754_fmod (value1, value2);
1246 jdouble value2 = POPD();
1247 jdouble value1 = POPD();
1249 jdouble res = __ieee754_fmod (value1, value2);
1255 *(jint*) (sp-1) *= -1;
1259 *(jlong*) (sp-1) *= -1;
1263 *(jfloat*) (sp-1) *= -1;
1267 *(jdouble*) (sp-1) *= -1;
1272 jint shift = (POPI() & 0x1f);
1273 jint value = POPI();
1274 PUSHI (value << shift);
1280 jint shift = (POPI() & 0x3f);
1281 jlong value = POPL();
1282 PUSHL (value << shift);
1288 jint shift = (POPI() & 0x1f);
1289 jint value = POPI();
1290 PUSHI (value >> shift);
1296 jint shift = (POPI() & 0x3f);
1297 jlong value = POPL();
1298 PUSHL (value >> shift);
1304 jint shift = (POPI() & 0x1f);
1305 unsigned long value = POPI();
1306 PUSHI ((jint) (value >> shift));
1312 jint shift = (POPI() & 0x3f);
1313 UINT64 value = (UINT64) POPL();
1314 PUSHL ((value >> shift));
1344 jint index = get1u (pc++);
1345 jint amount = get1s (pc++);
1346 *(jint*) (locals + index) += amount;
1351 {jlong value = POPI(); PUSHL (value);}
1355 {jfloat value = POPI(); PUSHF (value);}
1359 {jdouble value = POPI(); PUSHD (value);}
1363 {jint value = POPL(); PUSHI (value);}
1367 {jfloat value = POPL(); PUSHF (value);}
1371 {jdouble value = POPL(); PUSHD (value);}
1375 { jint value = (jint)POPF (); PUSHI(value); }
1379 { jlong value = (jlong)POPF (); PUSHL(value); }
1383 { jdouble value = POPF (); PUSHD(value); }
1387 { jint value = (jint)POPD (); PUSHI(value); }
1391 { jlong value = (jlong)POPD (); PUSHL(value); }
1395 { jfloat value = POPD (); PUSHF(value); }
1399 { jbyte value = POPI (); PUSHI(value); }
1403 { jchar value = POPI (); PUSHI(value); }
1407 { jshort value = POPI (); PUSHI(value); }
1412 jlong value2 = POPL ();
1413 jlong value1 = POPL ();
1414 if (value1 > value2)
1416 else if (value1 == value2)
1426 jfloat value2 = POPF ();
1427 jfloat value1 = POPF ();
1428 if (value1 > value2)
1430 else if (value1 == value2)
1432 else if (value1 < value2)
1434 else if (opcode == op_fcmpg)
1444 jdouble value2 = POPD ();
1445 jdouble value1 = POPD ();
1446 if (value1 > value2)
1448 else if (value1 == value2)
1450 else if (value1 < value2)
1452 else if (opcode == op_dcmpg)
1461 jint offset = get2s (pc);
1471 jint offset = get2s (pc);
1481 jint offset = get2s (pc);
1491 jint offset = get2s (pc);
1501 jint offset = get2s (pc);
1511 jint offset = get2s (pc);
1521 jint offset = get2s (pc);
1522 jint value2 = POPI();
1523 jint value1 = POPI();
1524 if (value1 == value2)
1533 jint offset = get2s (pc);
1534 jint value2 = POPI();
1535 jint value1 = POPI();
1536 if (value1 != value2)
1545 jint offset = get2s (pc);
1546 jint value2 = POPI();
1547 jint value1 = POPI();
1548 if (value1 < value2)
1557 jint offset = get2s (pc);
1558 jint value2 = POPI();
1559 jint value1 = POPI();
1560 if (value1 >= value2)
1569 jint offset = get2s (pc);
1570 jint value2 = POPI();
1571 jint value1 = POPI();
1572 if (value1 > value2)
1581 jint offset = get2s (pc);
1582 jint value2 = POPI();
1583 jint value1 = POPI();
1584 if (value1 <= value2)
1593 jint offset = get2s (pc);
1594 jobject value2 = POPA();
1595 jobject value1 = POPA();
1596 if (value1 == value2)
1605 jint offset = get2s (pc);
1606 jobject value2 = POPA();
1607 jobject value1 = POPA();
1608 if (value1 != value2)
1617 jint offset = get2s (pc);
1624 unsigned char *base_pc = pc-1;
1625 jint offset = get2s (pc); pc += 2;
1626 PUSHA ((jobject)pc);
1627 pc = base_pc+offset;
1633 jint index = get1u (pc);
1634 pc = (unsigned char*) PEEKA (index);
1638 case op_tableswitch:
1640 unsigned char *base_pc = pc-1;
1643 unsigned char* base = bytecode ();
1644 while ((pc-base) % 4 != 0)
1647 jint def = get4 (pc);
1648 jint low = get4 (pc+4);
1649 jint high = get4 (pc+8);
1651 if (index < low || index > high)
1654 pc = base_pc + get4 (pc+4*(index-low+3));
1658 case op_lookupswitch:
1660 unsigned char *base_pc = pc-1;
1663 unsigned char* base = bytecode ();
1664 while ((pc-base) % 4 != 0)
1667 jint def = get4 (pc);
1668 jint npairs = get4 (pc+4);
1673 // simple binary search...
1676 int half = (min+max)/2;
1677 int match = get4 (pc+ 4*(2 + 2*half));
1682 else if (index < match)
1689 if (index == get4 (pc+ 4*(2 + 2*min)))
1690 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1696 /* on return, just save the sp and return to caller */
1709 unsigned char *base_pc = pc-1;
1710 jint fieldref_index = get2u (pc); pc += 2;
1711 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1712 _Jv_Field *field = pool_data[fieldref_index].field;
1714 if ((field->flags & STATIC) == 0)
1715 throw_incompatible_class_change_error
1716 (JvNewStringLatin1 ("field no longer static"));
1718 jclass type = field->type;
1720 if (type->isPrimitive ())
1722 switch (type->size_in_bytes)
1725 *base_pc = op_getstatic_1;
1729 if (type == JvPrimClass (char))
1730 *base_pc = op_getstatic_2u;
1732 *base_pc = op_getstatic_2s;
1736 *base_pc = op_getstatic_4;
1740 *base_pc = op_getstatic_8;
1746 *base_pc = op_getstatic_a;
1755 unsigned char *base_pc = pc-1;
1756 jint fieldref_index = get2u (pc); pc += 2;
1757 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1758 _Jv_Field *field = pool_data[fieldref_index].field;
1760 if ((field->flags & STATIC) != 0)
1761 throw_incompatible_class_change_error
1762 (JvNewStringLatin1 ("field is static"));
1764 jclass type = field->type;
1766 if (type->isPrimitive ())
1768 switch (type->size_in_bytes)
1771 *base_pc = op_getfield_1;
1775 if (type == JvPrimClass (char))
1776 *base_pc = op_getfield_2u;
1778 *base_pc = op_getfield_2s;
1782 *base_pc = op_getfield_4;
1786 *base_pc = op_getfield_8;
1792 *base_pc = op_getfield_a;
1795 if (field->u.boffset > 0xffff)
1796 JvThrow (new java::lang::VirtualMachineError);
1798 base_pc[1] = (field->u.boffset>>8) & 0xff;
1799 base_pc[2] = field->u.boffset & 0xff;
1807 unsigned char* base_pc = pc-1;
1808 jint fieldref_index = get2u (pc); pc += 2;
1809 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1810 _Jv_Field *field = pool_data[fieldref_index].field;
1812 jclass type = field->type;
1814 // ResolvePoolEntry cannot check this
1815 if ((field->flags & STATIC) == 0)
1816 throw_incompatible_class_change_error
1817 (JvNewStringLatin1 ("field no longer static"));
1819 /* if this is patented, then maybe we could install
1820 a function in the constant pool, to do the right thing */
1822 if (type->isPrimitive ())
1824 switch (type->size_in_bytes)
1827 *base_pc = op_putstatic_1;
1831 *base_pc = op_putstatic_2;
1835 *base_pc = op_putstatic_4;
1839 *base_pc = op_putstatic_8;
1845 *base_pc = op_putstatic_a;
1848 // do the instruction again!
1856 unsigned char* base_pc = pc-1;
1857 jint fieldref_index = get2u (pc); pc += 2;
1858 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1859 _Jv_Field *field = pool_data[fieldref_index].field;
1861 jclass type = field->type;
1863 if ((field->flags & STATIC) != 0)
1864 throw_incompatible_class_change_error
1865 (JvNewStringLatin1 ("field is static"));
1867 if (type->isPrimitive ())
1869 switch (type->size_in_bytes)
1872 *base_pc = op_putfield_1;
1876 *base_pc = op_putfield_2;
1880 *base_pc = op_putfield_4;
1884 *base_pc = op_putfield_8;
1890 *base_pc = op_putfield_a;
1893 if (field->u.boffset > 0xffff)
1894 JvThrow (new java::lang::VirtualMachineError);
1896 base_pc[1] = (field->u.boffset>>8) & 0xff;
1897 base_pc[2] = field->u.boffset & 0xff;
1899 // do the instruction again!
1907 jobject obj = POPA();
1909 jint field_offset = get2u (pc); pc += 2;
1910 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1914 case op_getfield_2s:
1916 jobject obj = POPA();
1918 jint field_offset = get2u (pc); pc += 2;
1919 PUSHI (*(jshort*) ((char*)obj + field_offset));
1923 case op_getfield_2u:
1925 jobject obj = POPA();
1927 jint field_offset = get2u (pc); pc += 2;
1928 PUSHI (*(jchar*) ((char*)obj + field_offset));
1934 jobject obj = POPA();
1936 jint field_offset = get2u (pc); pc += 2;
1937 PUSHL(*(jlong*) ((char*)obj + field_offset));
1941 case op_getstatic_1:
1943 jint fieldref_index = get2u (pc); pc += 2;
1944 _Jv_Field *field = pool_data[fieldref_index].field;
1945 PUSHI (*(jbyte*) (field->u.addr));
1949 case op_getstatic_2s:
1951 jint fieldref_index = get2u (pc); pc += 2;
1952 _Jv_Field *field = pool_data[fieldref_index].field;
1953 PUSHI(*(jshort*) (field->u.addr));
1957 case op_getstatic_2u:
1959 jint fieldref_index = get2u (pc); pc += 2;
1960 _Jv_Field *field = pool_data[fieldref_index].field;
1961 PUSHI(*(jchar*) (field->u.addr));
1965 case op_getstatic_4:
1967 jint fieldref_index = get2u (pc); pc += 2;
1968 _Jv_Field *field = pool_data[fieldref_index].field;
1969 PUSHI(*(jint*) (field->u.addr));
1973 case op_getstatic_8:
1975 jint fieldref_index = get2u (pc); pc += 2;
1976 _Jv_Field *field = pool_data[fieldref_index].field;
1977 PUSHL(*(jlong*) (field->u.addr));
1981 case op_getstatic_a:
1983 jint fieldref_index = get2u (pc); pc += 2;
1984 _Jv_Field *field = pool_data[fieldref_index].field;
1985 PUSHA(*(jobject*) (field->u.addr));
1991 jint value = POPI();
1992 jobject obj = POPA();
1994 jint field_offset = get2u (pc); pc += 2;
1995 *(jbyte*) ((char*)obj + field_offset) = value;
2001 jint value = POPI();
2002 jobject obj = POPA();
2004 jint field_offset = get2u (pc); pc += 2;
2005 *(jchar*) ((char*)obj + field_offset) = value;
2011 jint value = POPI();
2012 jobject obj = POPA();
2014 jint field_offset = get2u (pc); pc += 2;
2015 *(jint*) ((char*)obj + field_offset) = value;
2021 jlong value = POPL();
2022 jobject obj = POPA();
2024 jint field_offset = get2u (pc); pc += 2;
2025 *(jlong*) ((char*)obj + field_offset) = value;
2031 jobject value = POPA();
2032 jobject obj = POPA();
2034 jint field_offset = get2u (pc); pc += 2;
2035 *(jobject*) ((char*)obj + field_offset) = value;
2039 case op_putstatic_1:
2041 jint value = POPI();
2042 jint fieldref_index = get2u (pc); pc += 2;
2043 _Jv_Field *field = pool_data[fieldref_index].field;
2044 *(jbyte*) (field->u.addr) = value;
2048 case op_putstatic_2:
2050 jint value = POPI();
2051 jint fieldref_index = get2u (pc); pc += 2;
2052 _Jv_Field *field = pool_data[fieldref_index].field;
2053 *(jchar*) (field->u.addr) = value;
2057 case op_putstatic_4:
2059 jint value = POPI();
2060 jint fieldref_index = get2u (pc); pc += 2;
2061 _Jv_Field *field = pool_data[fieldref_index].field;
2062 *(jint*) (field->u.addr) = value;
2066 case op_putstatic_8:
2068 jlong value = POPL();
2069 jint fieldref_index = get2u (pc); pc += 2;
2070 _Jv_Field *field = pool_data[fieldref_index].field;
2071 *(jlong*) (field->u.addr) = value;
2075 case op_putstatic_a:
2077 jobject value = POPA();
2078 jint fieldref_index = get2u (pc); pc += 2;
2079 _Jv_Field *field = pool_data[fieldref_index].field;
2080 *(jobject*) (field->u.addr) = value;
2084 case op_invokespecial:
2086 int index = get2u (pc); pc += 2;
2088 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2090 sp -= rmeth->stack_item_count;
2094 fun = (void (*) (...))rmeth->method->ncode;
2096 goto perform_invoke;
2098 case op_invokestatic:
2100 int index = get2u (pc); pc += 2;
2102 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2104 sp -= rmeth->stack_item_count;
2106 _Jv_InitClass (rmeth->klass);
2107 fun = (void (*) (...))rmeth->method->ncode;
2109 goto perform_invoke;
2111 case op_invokeinterface:
2113 int index = get2u (pc); pc += 2;
2115 // invokeinterface has two unused bytes...
2118 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2120 sp -= rmeth->stack_item_count;
2123 jobject rcv = sp[0].o;
2125 fun = (void (*) (...))
2126 _Jv_LookupInterfaceMethod (rcv->getClass (),
2127 rmeth->method->name,
2128 rmeth->method->signature);
2130 goto perform_invoke;
2135 int index = get2u (pc); pc += 2;
2136 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2137 _Jv_InitClass (klass);
2138 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2145 int atype = get1u (pc++);
2147 jobject result = _Jv_NewArray (atype, size);
2154 int index = get2u (pc); pc += 2;
2155 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2157 _Jv_InitClass (klass);
2158 jobject result = _Jv_NewObjectArray (size, klass, 0);
2163 case op_arraylength:
2165 __JArray *arr = (__JArray*)POPA();
2166 PUSHI (arr->length);
2172 jobject value = POPA();
2180 jobject value = POPA();
2181 jint index = get2u (pc); pc += 2;
2182 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2184 if (value != NULL && ! to->isInstance (value))
2187 JvThrow (new java::lang::ClassCastException
2197 jobject value = POPA();
2198 jint index = get2u (pc); pc += 2;
2199 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2200 PUSHI (to->isInstance (value));
2204 case op_monitorenter:
2206 jobject value = POPA();
2208 _Jv_MonitorEnter (value);
2212 case op_monitorexit:
2214 jobject value = POPA();
2216 _Jv_MonitorExit (value);
2222 unsigned char* base_pc = pc-1;
2223 jint offset = get2s (pc); pc += 2;
2224 jobject val = POPA();
2226 pc = base_pc+offset;
2232 unsigned char* base_pc = pc-1;
2233 jint offset = get2s (pc); pc += 2;
2234 jobject val = POPA();
2236 pc = base_pc+offset;
2242 jint the_mod_op = get1u (pc++);
2243 jint wide = get2u (pc); pc += 2;
2284 pc = (unsigned char*) PEEKA (wide);
2289 jint amount = get2s (pc); pc += 2;
2290 jint value = PEEKI (wide);
2291 POKEI (wide, value+amount);
2296 throw_internal_error ("illegal bytecode modified by wide");
2301 case op_multianewarray:
2303 int kind_index = get2u (pc); pc += 2;
2304 int dim = get1u (pc); pc += 1;
2307 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2308 _Jv_InitClass (type);
2309 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2311 for (int i = dim - 1; i >= 0; i--)
2316 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2324 unsigned char* base_pc = pc-1;
2325 int offset = get4 (pc); pc += 4;
2326 pc = base_pc+offset;
2332 unsigned char* base_pc = pc-1;
2333 int offset = get4 (pc); pc += 4;
2335 pc = base_pc+offset;
2340 throw_internal_error ("opcode not implemented");
2348 throw_internal_error (char *msg)
2350 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2354 throw_incompatible_class_change_error (jstring msg)
2356 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2360 static java::lang::NullPointerException *null_pointer_exc;
2362 throw_null_pointer_exception ()
2364 if (null_pointer_exc == NULL)
2365 null_pointer_exc = new java::lang::NullPointerException;
2367 JvThrow (null_pointer_exc);
2372 static java::lang::ArithmeticException *arithmetic_exc;
2374 throw_arithmetic_exception ()
2376 if (arithmetic_exc == NULL)
2377 arithmetic_exc = new java::lang::ArithmeticException
2378 (JvNewStringLatin1 ("/ by zero"));
2380 JvThrow (arithmetic_exc);
2387 _Jv_InterpMethod::dump_object(o);
2390 /* FIXME: This is not finished! */
2392 _Jv_InterpMethod::dump_object(jobject o)
2394 java::io::PrintStream *out = java::lang::System::out;
2398 out->println (JvNewStringLatin1 ("<null>"));
2402 jclass klass = o->getClass ();
2404 out->print (klass->getName ());
2405 out->print (JvNewStringLatin1 ("@0x"));
2406 out->print (java::lang::Integer::toHexString ((jint)o));
2407 out->print (JvNewStringLatin1 ("{"));
2409 while (klass && klass != &ObjectClass)
2411 _Jv_Field *fields = klass->fields;
2412 int max = klass->field_count;
2414 for (int i = 0; i < max; ++i)
2416 out->print (_Jv_NewStringUTF (field->name->data));
2417 out->print (JvNewStringLatin1 ("="));
2419 if (JvFieldIsRef (field))
2421 if (field->flags & STATIC)
2422 out->print (JvGetSt)
2424 field = field->getNextInstanceField ();
2426 if (i+1 < max && klass->getSuperclass () != null)
2427 out->print (JvNewStringLatin1 ("; "));
2430 klass = klass->getSuperclass();
2433 out->print (JvNewStringLatin1 ("}\n"));
2437 #endif // INTERPRETER