1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001, 2002 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 // Define this to get the direct-threaded interpreter. If undefined,
16 // we revert to a basic bytecode interpreter. The former is faster
17 // but uses more memory.
18 #define DIRECT_THREADED
20 #pragma implementation "java-interp.h"
23 #include <java-cpool.h>
24 #include <java-interp.h>
25 #include <java/lang/System.h>
26 #include <java/lang/String.h>
27 #include <java/lang/Integer.h>
28 #include <java/lang/Long.h>
29 #include <java/lang/StringBuffer.h>
30 #include <java/lang/Class.h>
31 #include <java/lang/reflect/Modifier.h>
32 #include <java/lang/ClassCastException.h>
33 #include <java/lang/VirtualMachineError.h>
34 #include <java/lang/InternalError.h>
35 #include <java/lang/NullPointerException.h>
36 #include <java/lang/ArithmeticException.h>
37 #include <java/lang/IncompatibleClassChangeError.h>
38 #include <java/lang/Thread.h>
39 #include <java-insns.h>
40 #include <java-signal.h>
48 static void throw_internal_error (char *msg)
49 __attribute__ ((__noreturn__));
50 static void throw_incompatible_class_change_error (jstring msg)
51 __attribute__ ((__noreturn__));
53 static void throw_null_pointer_exception ()
54 __attribute__ ((__noreturn__));
57 extern "C" double __ieee754_fmod (double,double);
59 // This represents a single slot in the "compiled" form of the
65 // An integer value used by an instruction.
67 // A pointer value used by an instruction.
71 // The type of the PC depends on whether we're doing direct threading
72 // or a more ordinary bytecode interpreter.
73 #ifdef DIRECT_THREADED
74 typedef insn_slot *pc_t;
76 typedef unsigned char *pc_t;
79 static inline void dupx (_Jv_word *sp, int n, int x)
81 // first "slide" n+x elements n to the right
83 for (int i = 0; i < n+x; i++)
85 sp[(top-i)] = sp[(top-i)-n];
88 // next, copy the n top elements, n+x down
89 for (int i = 0; i < n; i++)
91 sp[top-(n+x)-i] = sp[top-i];
96 // Used to convert from floating types to integral types.
97 template<typename TO, typename FROM>
99 convert (FROM val, TO min, TO max)
102 if (val >= (FROM) max)
104 else if (val <= (FROM) min)
113 #define PUSHA(V) (sp++)->o = (V)
114 #define PUSHI(V) (sp++)->i = (V)
115 #define PUSHF(V) (sp++)->f = (V)
116 #if SIZEOF_VOID_P == 8
117 # define PUSHL(V) (sp->l = (V), sp += 2)
118 # define PUSHD(V) (sp->d = (V), sp += 2)
120 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
121 (sp++)->ia[0] = w2.ia[0]; \
122 (sp++)->ia[0] = w2.ia[1]; } while (0)
123 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
124 (sp++)->ia[0] = w2.ia[0]; \
125 (sp++)->ia[0] = w2.ia[1]; } while (0)
128 #define POPA() ((--sp)->o)
129 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
130 #define POPF() ((jfloat) (--sp)->f)
131 #if SIZEOF_VOID_P == 8
132 # define POPL() (sp -= 2, (jlong) sp->l)
133 # define POPD() (sp -= 2, (jdouble) sp->d)
135 # define POPL() ({ _Jv_word2 w2; \
136 w2.ia[1] = (--sp)->ia[0]; \
137 w2.ia[0] = (--sp)->ia[0]; w2.l; })
138 # define POPD() ({ _Jv_word2 w2; \
139 w2.ia[1] = (--sp)->ia[0]; \
140 w2.ia[0] = (--sp)->ia[0]; w2.d; })
143 #define LOADA(I) (sp++)->o = locals[I].o
144 #define LOADI(I) (sp++)->i = locals[I].i
145 #define LOADF(I) (sp++)->f = locals[I].f
146 #if SIZEOF_VOID_P == 8
147 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
148 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
150 # define LOADL(I) do { jint __idx = (I); \
151 (sp++)->ia[0] = locals[__idx].ia[0]; \
152 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
154 # define LOADD(I) LOADL(I)
157 #define STOREA(I) locals[I].o = (--sp)->o
158 #define STOREI(I) locals[I].i = (--sp)->i
159 #define STOREF(I) locals[I].f = (--sp)->f
160 #if SIZEOF_VOID_P == 8
161 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
162 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
164 # define STOREL(I) do { jint __idx = (I); \
165 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
166 locals[__idx].ia[0] = (--sp)->ia[0]; \
168 # define STORED(I) STOREL(I)
171 #define PEEKI(I) (locals+(I))->i
172 #define PEEKA(I) (locals+(I))->o
174 #define POKEI(I,V) ((locals+(I))->i = (V))
177 #define BINOPI(OP) { \
178 jint value2 = POPI(); \
179 jint value1 = POPI(); \
180 PUSHI(value1 OP value2); \
183 #define BINOPF(OP) { \
184 jfloat value2 = POPF(); \
185 jfloat value1 = POPF(); \
186 PUSHF(value1 OP value2); \
189 #define BINOPL(OP) { \
190 jlong value2 = POPL(); \
191 jlong value1 = POPL(); \
192 PUSHL(value1 OP value2); \
195 #define BINOPD(OP) { \
196 jdouble value2 = POPD(); \
197 jdouble value1 = POPD(); \
198 PUSHD(value1 OP value2); \
201 static inline jint get1s(unsigned char* loc) {
202 return *(signed char*)loc;
205 static inline jint get1u(unsigned char* loc) {
209 static inline jint get2s(unsigned char* loc) {
210 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
213 static inline jint get2u(unsigned char* loc) {
214 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
217 static jint get4(unsigned char* loc) {
218 return (((jint)(loc[0])) << 24)
219 | (((jint)(loc[1])) << 16)
220 | (((jint)(loc[2])) << 8)
221 | (((jint)(loc[3])) << 0);
227 #define NULLARRAYCHECK(X)
229 #define NULLCHECK(X) \
230 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
231 #define NULLARRAYCHECK(X) \
232 do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
235 #define ARRAYBOUNDSCHECK(array, index) \
238 if (((unsigned) index) >= (unsigned) (array->length)) \
239 _Jv_ThrowBadArrayIndex (index); \
243 void _Jv_InterpMethod::run_normal (ffi_cif *,
248 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
249 _this->run (ret, args);
252 void _Jv_InterpMethod::run_synch_object (ffi_cif *,
257 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
259 jobject rcv = (jobject) args[0].ptr;
260 JvSynchronize mutex (rcv);
262 _this->run (ret, args);
265 void _Jv_InterpMethod::run_synch_class (ffi_cif *,
270 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
272 jclass sync = _this->defining_class;
273 JvSynchronize mutex (sync);
275 _this->run (ret, args);
278 #ifdef DIRECT_THREADED
279 // "Compile" a method by turning it from bytecode to direct-threaded
282 _Jv_InterpMethod::compile (const void * const *insn_targets)
284 insn_slot *insns = NULL;
286 unsigned char *codestart = bytecode ();
287 unsigned char *end = codestart + code_length;
288 _Jv_word *pool_data = defining_class->constants.data;
290 #define SET_ONE(Field, Value) \
296 insns[next++].Field = Value; \
300 #define SET_INSN(Value) SET_ONE (insn, (void *) Value)
301 #define SET_INT(Value) SET_ONE (int_val, Value)
302 #define SET_DATUM(Value) SET_ONE (datum, Value)
304 // Map from bytecode PC to slot in INSNS.
305 int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
306 for (int i = 0; i < code_length; ++i)
309 for (int i = 0; i < 2; ++i)
311 jboolean first_pass = i == 0;
315 insns = (insn_slot *) _Jv_Malloc (sizeof (insn_slot) * next);
319 unsigned char *pc = codestart;
322 int base_pc_val = pc - codestart;
324 pc_mapping[base_pc_val] = next;
326 java_opcode opcode = (java_opcode) *pc++;
328 if (opcode == op_nop)
330 SET_INSN (insn_targets[opcode]);
471 case op_monitorenter:
481 // No argument, nothing else to do.
485 SET_INT (get1s (pc));
491 int index = get1u (pc);
493 SET_DATUM (pool_data[index].o);
509 SET_INT (get1u (pc));
514 SET_INT (get1u (pc));
515 SET_INT (get1s (pc + 1));
521 int index = get2u (pc);
523 SET_DATUM (pool_data[index].o);
529 int index = get2u (pc);
531 SET_DATUM (&pool_data[index]);
536 SET_INT (get2s (pc));
548 case op_invokespecial:
549 case op_invokestatic:
550 case op_invokevirtual:
551 SET_INT (get2u (pc));
555 case op_multianewarray:
556 SET_INT (get2u (pc));
557 SET_INT (get1u (pc + 2));
580 int offset = get2s (pc);
583 int new_pc = base_pc_val + offset;
585 bool orig_was_goto = opcode == op_goto;
587 // Thread jumps. We limit the loop count; this lets
588 // us avoid infinite loops if the bytecode contains
589 // such. `10' is arbitrary.
591 while (codestart[new_pc] == op_goto && count-- > 0)
592 new_pc += get2s (&codestart[new_pc + 1]);
594 // If the jump takes us to a `return' instruction and
595 // the original branch was an unconditional goto, then
596 // we hoist the return.
597 opcode = (java_opcode) codestart[new_pc];
599 && (opcode == op_ireturn || opcode == op_lreturn
600 || opcode == op_freturn || opcode == op_dreturn
601 || opcode == op_areturn || opcode == op_return))
604 SET_INSN (insn_targets[opcode]);
607 SET_DATUM (&insns[pc_mapping[new_pc]]);
613 while ((pc - codestart) % 4 != 0)
616 jint def = get4 (pc);
617 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
623 int high = get4 (pc);
627 for (int i = low; i <= high; ++i)
629 SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
635 case op_lookupswitch:
637 while ((pc - codestart) % 4 != 0)
640 jint def = get4 (pc);
641 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
644 jint npairs = get4 (pc);
650 jint match = get4 (pc);
651 jint offset = get4 (pc + 4);
653 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
659 case op_invokeinterface:
661 jint index = get2u (pc);
663 // We ignore the next two bytes.
671 opcode = (java_opcode) get1u (pc);
673 jint val = get2u (pc);
676 // We implement narrow and wide instructions using the
677 // same code in the interpreter. So we rewrite the
678 // instruction slot here.
680 insns[next - 1].insn = (void *) insn_targets[opcode];
683 if (opcode == op_iinc)
685 SET_INT (get2s (pc));
694 jint offset = get4 (pc);
696 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
700 // Some "can't happen" cases that we include for
701 // error-checking purposes.
719 case op_getstatic_2s:
720 case op_getstatic_2u:
731 // Now update exceptions.
732 _Jv_InterpException *exc = exceptions ();
733 for (int i = 0; i < exc_count; ++i)
735 exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
736 exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
737 exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
738 jclass handler = (_Jv_ResolvePoolEntry (defining_class,
739 exc[i].handler_type.i)).clazz;
740 exc[i].handler_type.p = handler;
745 #endif /* DIRECT_THREADED */
747 // This function exists so that the stack-tracing code can find the
748 // boundaries of the interpreter.
750 _Jv_StartOfInterpreter (void)
755 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
757 using namespace java::lang::reflect;
759 // FRAME_DESC registers this particular invocation as the top-most
760 // interpreter frame. This lets the stack tracing code (for
761 // Throwable) print information about the method being interpreted
762 // rather than about the interpreter itself. FRAME_DESC has a
763 // destructor so it cleans up automatically when the interpreter
765 java::lang::Thread *thread = java::lang::Thread::currentThread();
766 _Jv_MethodChain frame_desc (this,
767 (_Jv_MethodChain **) &thread->interp_frame);
769 _Jv_word stack[max_stack];
770 _Jv_word *sp = stack;
772 _Jv_word locals[max_locals];
774 /* Go straight at it! the ffi raw format matches the internal
775 stack representation exactly. At least, that's the idea.
777 memcpy ((void*) locals, (void*) args, args_raw_size);
779 _Jv_word *pool_data = defining_class->constants.data;
781 /* These three are temporaries for common code used by several
784 _Jv_ResolvedMethod* rmeth;
787 #define INSN_LABEL(op) &&insn_##op
789 static const void *const insn_target[] =
792 INSN_LABEL(aconst_null),
793 INSN_LABEL(iconst_m1),
794 INSN_LABEL(iconst_0),
795 INSN_LABEL(iconst_1),
796 INSN_LABEL(iconst_2),
797 INSN_LABEL(iconst_3),
798 INSN_LABEL(iconst_4),
799 INSN_LABEL(iconst_5),
800 INSN_LABEL(lconst_0),
801 INSN_LABEL(lconst_1),
802 INSN_LABEL(fconst_0),
803 INSN_LABEL(fconst_1),
804 INSN_LABEL(fconst_2),
805 INSN_LABEL(dconst_0),
806 INSN_LABEL(dconst_1),
850 INSN_LABEL(istore_0),
851 INSN_LABEL(istore_1),
852 INSN_LABEL(istore_2),
853 INSN_LABEL(istore_3),
854 INSN_LABEL(lstore_0),
855 INSN_LABEL(lstore_1),
856 INSN_LABEL(lstore_2),
857 INSN_LABEL(lstore_3),
858 INSN_LABEL(fstore_0),
859 INSN_LABEL(fstore_1),
860 INSN_LABEL(fstore_2),
861 INSN_LABEL(fstore_3),
862 INSN_LABEL(dstore_0),
863 INSN_LABEL(dstore_1),
864 INSN_LABEL(dstore_2),
865 INSN_LABEL(dstore_3),
866 INSN_LABEL(astore_0),
867 INSN_LABEL(astore_1),
868 INSN_LABEL(astore_2),
869 INSN_LABEL(astore_3),
950 INSN_LABEL(if_icmpeq),
951 INSN_LABEL(if_icmpne),
952 INSN_LABEL(if_icmplt),
953 INSN_LABEL(if_icmpge),
954 INSN_LABEL(if_icmpgt),
955 INSN_LABEL(if_icmple),
956 INSN_LABEL(if_acmpeq),
957 INSN_LABEL(if_acmpne),
961 INSN_LABEL(tableswitch),
962 INSN_LABEL(lookupswitch),
969 INSN_LABEL(getstatic),
970 INSN_LABEL(putstatic),
971 INSN_LABEL(getfield),
972 INSN_LABEL(putfield),
973 INSN_LABEL(invokevirtual),
974 INSN_LABEL(invokespecial),
975 INSN_LABEL(invokestatic),
976 INSN_LABEL(invokeinterface),
979 INSN_LABEL(newarray),
980 INSN_LABEL(anewarray),
981 INSN_LABEL(arraylength),
983 INSN_LABEL(checkcast),
984 INSN_LABEL(instanceof),
985 INSN_LABEL(monitorenter),
986 INSN_LABEL(monitorexit),
987 #ifdef DIRECT_THREADED
992 INSN_LABEL(multianewarray),
994 INSN_LABEL(ifnonnull),
1002 #ifdef DIRECT_THREADED
1004 #define NEXT_INSN goto *((pc++)->insn)
1005 #define INTVAL() ((pc++)->int_val)
1006 #define AVAL() ((pc++)->datum)
1008 #define GET1S() INTVAL ()
1009 #define GET2S() INTVAL ()
1010 #define GET1U() INTVAL ()
1011 #define GET2U() INTVAL ()
1012 #define AVAL1U() AVAL ()
1013 #define AVAL2U() AVAL ()
1014 #define AVAL2UP() AVAL ()
1015 #define SKIP_GOTO ++pc
1016 #define GOTO_VAL() (insn_slot *) pc->datum
1017 #define PCVAL(unionval) unionval.p
1018 #define AMPAMP(label) &&label
1020 // Compile if we must.
1021 if (prepared == NULL)
1022 compile (insn_target);
1023 pc = (insn_slot *) prepared;
1027 #define NEXT_INSN goto *(insn_target[*pc++])
1029 #define GET1S() get1s (pc++)
1030 #define GET2S() (pc += 2, get2s (pc- 2))
1031 #define GET1U() get1u (pc++)
1032 #define GET2U() (pc += 2, get2u (pc - 2))
1033 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1034 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1035 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1036 #define SKIP_GOTO pc += 2
1037 #define GOTO_VAL() pc - 1 + get2s (pc)
1038 #define PCVAL(unionval) unionval.i
1039 #define AMPAMP(label) NULL
1043 #endif /* DIRECT_THREADED */
1045 #define TAKE_GOTO pc = GOTO_VAL ()
1049 // We keep nop around. It is used if we're interpreting the
1050 // bytecodes and not doing direct threading.
1054 /* The first few instructions here are ordered according to their
1055 frequency, in the hope that this will improve code locality a
1058 insn_aload_0: // 0x2a
1066 insn_iload_1: // 0x1b
1070 insn_invokevirtual: // 0xb6
1072 int index = GET2U ();
1074 /* _Jv_ResolvePoolEntry returns immediately if the value already
1075 * is resolved. If we want to clutter up the code here to gain
1076 * a little performance, then we can check the corresponding bit
1077 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
1078 * don't think it is worth it. */
1080 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
1082 sp -= rmeth->stack_item_count;
1083 // We don't use NULLCHECK here because we can't rely on that
1084 // working if the method is final. So instead we do an
1087 throw new java::lang::NullPointerException;
1089 if (rmeth->vtable_index == -1)
1091 // final methods do not appear in the vtable,
1092 // if it does not appear in the superclass.
1093 fun = (void (*)()) rmeth->method->ncode;
1097 jobject rcv = sp[0].o;
1098 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1099 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1102 #ifdef DIRECT_THREADED
1103 // Rewrite instruction so that we use a faster pre-resolved
1105 pc[-2].insn = &&invokevirtual_resolved;
1106 pc[-1].datum = rmeth;
1107 #endif /* DIRECT_THREADED */
1109 goto perform_invoke;
1111 #ifdef DIRECT_THREADED
1112 invokevirtual_resolved:
1114 rmeth = (_Jv_ResolvedMethod *) AVAL ();
1115 sp -= rmeth->stack_item_count;
1116 // We don't use NULLCHECK here because we can't rely on that
1117 // working if the method is final. So instead we do an
1120 throw new java::lang::NullPointerException;
1122 if (rmeth->vtable_index == -1)
1124 // final methods do not appear in the vtable,
1125 // if it does not appear in the superclass.
1126 fun = (void (*)()) rmeth->method->ncode;
1130 jobject rcv = sp[0].o;
1131 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1132 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1135 goto perform_invoke;
1136 #endif /* DIRECT_THREADED */
1140 /* here goes the magic again... */
1141 ffi_cif *cif = &rmeth->cif;
1142 ffi_raw *raw = (ffi_raw*) sp;
1146 #if FFI_NATIVE_RAW_API
1147 /* We assume that this is only implemented if it's correct */
1148 /* to use it here. On a 64 bit machine, it never is. */
1149 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
1151 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
1154 int rtype = cif->rtype->type;
1156 /* the likelyhood of object, int, or void return is very high,
1157 * so those are checked before the switch */
1158 if (rtype == FFI_TYPE_POINTER)
1160 PUSHA (*(jobject*)&rvalue);
1162 else if (rtype == FFI_TYPE_SINT32)
1164 PUSHI (*(jint*)&rvalue);
1166 else if (rtype == FFI_TYPE_VOID)
1174 case FFI_TYPE_SINT8:
1176 jbyte value = (*(jint*)&rvalue) & 0xff;
1181 case FFI_TYPE_SINT16:
1183 jshort value = (*(jint*)&rvalue) & 0xffff;
1188 case FFI_TYPE_UINT16:
1190 jint value = (*(jint*)&rvalue) & 0xffff;
1195 case FFI_TYPE_FLOAT:
1196 PUSHF (*(jfloat*)&rvalue);
1199 case FFI_TYPE_DOUBLE:
1203 case FFI_TYPE_SINT64:
1204 PUSHL (*(jlong*)&rvalue);
1208 throw_internal_error ("unknown return type in invokeXXX");
1275 // For direct threaded, bipush and sipush are the same.
1276 #ifndef DIRECT_THREADED
1279 #endif /* DIRECT_THREADED */
1285 // For direct threaded, ldc and ldc_w are the same.
1286 #ifndef DIRECT_THREADED
1287 PUSHA ((jobject) AVAL1U ());
1289 #endif /* DIRECT_THREADED */
1291 PUSHA ((jobject) AVAL2U ());
1296 void *where = AVAL2UP ();
1297 memcpy (sp, where, 2*sizeof (_Jv_word));
1392 jint index = POPI();
1393 jintArray arr = (jintArray) POPA();
1394 NULLARRAYCHECK (arr);
1395 ARRAYBOUNDSCHECK (arr, index);
1396 PUSHI( elements(arr)[index] );
1402 jint index = POPI();
1403 jlongArray arr = (jlongArray) POPA();
1404 NULLARRAYCHECK (arr);
1405 ARRAYBOUNDSCHECK (arr, index);
1406 PUSHL( elements(arr)[index] );
1412 jint index = POPI();
1413 jfloatArray arr = (jfloatArray) POPA();
1414 NULLARRAYCHECK (arr);
1415 ARRAYBOUNDSCHECK (arr, index);
1416 PUSHF( elements(arr)[index] );
1422 jint index = POPI();
1423 jdoubleArray arr = (jdoubleArray) POPA();
1424 NULLARRAYCHECK (arr);
1425 ARRAYBOUNDSCHECK (arr, index);
1426 PUSHD( elements(arr)[index] );
1432 jint index = POPI();
1433 jobjectArray arr = (jobjectArray) POPA();
1434 NULLARRAYCHECK (arr);
1435 ARRAYBOUNDSCHECK (arr, index);
1436 PUSHA( elements(arr)[index] );
1442 jint index = POPI();
1443 jbyteArray arr = (jbyteArray) POPA();
1444 NULLARRAYCHECK (arr);
1445 ARRAYBOUNDSCHECK (arr, index);
1446 PUSHI( elements(arr)[index] );
1452 jint index = POPI();
1453 jcharArray arr = (jcharArray) POPA();
1454 NULLARRAYCHECK (arr);
1455 ARRAYBOUNDSCHECK (arr, index);
1456 PUSHI( elements(arr)[index] );
1462 jint index = POPI();
1463 jshortArray arr = (jshortArray) POPA();
1464 NULLARRAYCHECK (arr);
1465 ARRAYBOUNDSCHECK (arr, index);
1466 PUSHI( elements(arr)[index] );
1572 jint value = POPI();
1573 jint index = POPI();
1574 jintArray arr = (jintArray) POPA();
1575 NULLARRAYCHECK (arr);
1576 ARRAYBOUNDSCHECK (arr, index);
1577 elements(arr)[index] = value;
1583 jlong value = POPL();
1584 jint index = POPI();
1585 jlongArray arr = (jlongArray) POPA();
1586 NULLARRAYCHECK (arr);
1587 ARRAYBOUNDSCHECK (arr, index);
1588 elements(arr)[index] = value;
1594 jfloat value = POPF();
1595 jint index = POPI();
1596 jfloatArray arr = (jfloatArray) POPA();
1597 NULLARRAYCHECK (arr);
1598 ARRAYBOUNDSCHECK (arr, index);
1599 elements(arr)[index] = value;
1605 jdouble value = POPD();
1606 jint index = POPI();
1607 jdoubleArray arr = (jdoubleArray) POPA();
1608 NULLARRAYCHECK (arr);
1609 ARRAYBOUNDSCHECK (arr, index);
1610 elements(arr)[index] = value;
1616 jobject value = POPA();
1617 jint index = POPI();
1618 jobjectArray arr = (jobjectArray) POPA();
1619 NULLARRAYCHECK (arr);
1620 ARRAYBOUNDSCHECK (arr, index);
1621 _Jv_CheckArrayStore (arr, value);
1622 elements(arr)[index] = value;
1628 jbyte value = (jbyte) POPI();
1629 jint index = POPI();
1630 jbyteArray arr = (jbyteArray) POPA();
1631 NULLARRAYCHECK (arr);
1632 ARRAYBOUNDSCHECK (arr, index);
1633 elements(arr)[index] = value;
1639 jchar value = (jchar) POPI();
1640 jint index = POPI();
1641 jcharArray arr = (jcharArray) POPA();
1642 NULLARRAYCHECK (arr);
1643 ARRAYBOUNDSCHECK (arr, index);
1644 elements(arr)[index] = value;
1650 jshort value = (jshort) POPI();
1651 jint index = POPI();
1652 jshortArray arr = (jshortArray) POPA();
1653 NULLARRAYCHECK (arr);
1654 ARRAYBOUNDSCHECK (arr, index);
1655 elements(arr)[index] = value;
1673 dupx (sp, 1, 1); sp+=1;
1677 dupx (sp, 1, 2); sp+=1;
1687 dupx (sp, 2, 1); sp+=2;
1691 dupx (sp, 2, 2); sp+=2;
1696 jobject tmp1 = POPA();
1697 jobject tmp2 = POPA();
1753 jint value2 = POPI();
1754 jint value1 = POPI();
1755 jint res = _Jv_divI (value1, value2);
1762 jlong value2 = POPL();
1763 jlong value1 = POPL();
1764 jlong res = _Jv_divJ (value1, value2);
1771 jfloat value2 = POPF();
1772 jfloat value1 = POPF();
1773 jfloat res = value1 / value2;
1780 jdouble value2 = POPD();
1781 jdouble value1 = POPD();
1782 jdouble res = value1 / value2;
1789 jint value2 = POPI();
1790 jint value1 = POPI();
1791 jint res = _Jv_remI (value1, value2);
1798 jlong value2 = POPL();
1799 jlong value1 = POPL();
1800 jlong res = _Jv_remJ (value1, value2);
1807 jfloat value2 = POPF();
1808 jfloat value1 = POPF();
1809 jfloat res = __ieee754_fmod (value1, value2);
1816 jdouble value2 = POPD();
1817 jdouble value1 = POPD();
1818 jdouble res = __ieee754_fmod (value1, value2);
1825 jint value = POPI();
1832 jlong value = POPL();
1839 jfloat value = POPF();
1846 jdouble value = POPD();
1853 jint shift = (POPI() & 0x1f);
1854 jint value = POPI();
1855 PUSHI (value << shift);
1861 jint shift = (POPI() & 0x3f);
1862 jlong value = POPL();
1863 PUSHL (value << shift);
1869 jint shift = (POPI() & 0x1f);
1870 jint value = POPI();
1871 PUSHI (value >> shift);
1877 jint shift = (POPI() & 0x3f);
1878 jlong value = POPL();
1879 PUSHL (value >> shift);
1885 jint shift = (POPI() & 0x1f);
1886 unsigned long value = POPI();
1887 PUSHI ((jint) (value >> shift));
1893 jint shift = (POPI() & 0x3f);
1894 UINT64 value = (UINT64) POPL();
1895 PUSHL ((value >> shift));
1925 jint index = GET1U ();
1926 jint amount = GET1S ();
1927 locals[index].i += amount;
1932 {jlong value = POPI(); PUSHL (value);}
1936 {jfloat value = POPI(); PUSHF (value);}
1940 {jdouble value = POPI(); PUSHD (value);}
1944 {jint value = POPL(); PUSHI (value);}
1948 {jfloat value = POPL(); PUSHF (value);}
1952 {jdouble value = POPL(); PUSHD (value);}
1957 using namespace java::lang;
1958 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1965 using namespace java::lang;
1966 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1972 { jdouble value = POPF (); PUSHD(value); }
1977 using namespace java::lang;
1978 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1985 using namespace java::lang;
1986 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1992 { jfloat value = POPD (); PUSHF(value); }
1996 { jbyte value = POPI (); PUSHI(value); }
2000 { jchar value = POPI (); PUSHI(value); }
2004 { jshort value = POPI (); PUSHI(value); }
2009 jlong value2 = POPL ();
2010 jlong value1 = POPL ();
2011 if (value1 > value2)
2013 else if (value1 == value2)
2029 jfloat value2 = POPF ();
2030 jfloat value1 = POPF ();
2031 if (value1 > value2)
2033 else if (value1 == value2)
2035 else if (value1 < value2)
2051 jdouble value2 = POPD ();
2052 jdouble value1 = POPD ();
2053 if (value1 > value2)
2055 else if (value1 == value2)
2057 else if (value1 < value2)
2120 jint value2 = POPI();
2121 jint value1 = POPI();
2122 if (value1 == value2)
2131 jint value2 = POPI();
2132 jint value1 = POPI();
2133 if (value1 != value2)
2142 jint value2 = POPI();
2143 jint value1 = POPI();
2144 if (value1 < value2)
2153 jint value2 = POPI();
2154 jint value1 = POPI();
2155 if (value1 >= value2)
2164 jint value2 = POPI();
2165 jint value1 = POPI();
2166 if (value1 > value2)
2175 jint value2 = POPI();
2176 jint value1 = POPI();
2177 if (value1 <= value2)
2186 jobject value2 = POPA();
2187 jobject value1 = POPA();
2188 if (value1 == value2)
2197 jobject value2 = POPA();
2198 jobject value1 = POPA();
2199 if (value1 != value2)
2207 #ifndef DIRECT_THREADED
2208 // For direct threaded, goto and goto_w are the same.
2209 pc = pc - 1 + get4 (pc);
2211 #endif /* DIRECT_THREADED */
2217 #ifndef DIRECT_THREADED
2218 // For direct threaded, jsr and jsr_w are the same.
2220 pc_t next = pc - 1 + get4 (pc);
2222 PUSHA ((jobject) pc);
2226 #endif /* DIRECT_THREADED */
2229 pc_t next = GOTO_VAL();
2231 PUSHA ((jobject) pc);
2238 jint index = GET1U ();
2239 pc = (pc_t) PEEKA (index);
2245 #ifdef DIRECT_THREADED
2246 void *def = (pc++)->datum;
2250 jint low = INTVAL ();
2251 jint high = INTVAL ();
2253 if (index < low || index > high)
2254 pc = (insn_slot *) def;
2256 pc = (insn_slot *) ((pc + index - low)->datum);
2258 pc_t base_pc = pc - 1;
2259 int index = POPI ();
2261 pc_t base = (pc_t) bytecode ();
2262 while ((pc - base) % 4 != 0)
2265 jint def = get4 (pc);
2266 jint low = get4 (pc + 4);
2267 jint high = get4 (pc + 8);
2268 if (index < low || index > high)
2271 pc = base_pc + get4 (pc + 4 * (index - low + 3));
2272 #endif /* DIRECT_THREADED */
2278 #ifdef DIRECT_THREADED
2279 void *def = (pc++)->insn;
2283 jint npairs = INTVAL ();
2285 int max = npairs - 1;
2288 // Simple binary search...
2291 int half = (min + max) / 2;
2292 int match = pc[2 * half].int_val;
2297 pc = (insn_slot *) pc[2 * half + 1].datum;
2300 else if (index < match)
2301 // We can use HALF - 1 here because we check again on
2305 // We can use HALF + 1 here because we check again on
2309 if (index == pc[2 * min].int_val)
2310 pc = (insn_slot *) pc[2 * min + 1].datum;
2312 pc = (insn_slot *) def;
2314 unsigned char *base_pc = pc-1;
2317 unsigned char* base = bytecode ();
2318 while ((pc-base) % 4 != 0)
2321 jint def = get4 (pc);
2322 jint npairs = get4 (pc+4);
2327 // Simple binary search...
2330 int half = (min+max)/2;
2331 int match = get4 (pc+ 4*(2 + 2*half));
2335 else if (index < match)
2336 // We can use HALF - 1 here because we check again on
2340 // We can use HALF + 1 here because we check again on
2345 if (index == get4 (pc+ 4*(2 + 2*min)))
2346 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
2349 #endif /* DIRECT_THREADED */
2354 *(jobject *) retp = POPA ();
2358 *(jlong *) retp = POPL ();
2362 *(jfloat *) retp = POPF ();
2366 *(jdouble *) retp = POPD ();
2370 *(jint *) retp = POPI ();
2378 jint fieldref_index = GET2U ();
2379 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2380 _Jv_Field *field = pool_data[fieldref_index].field;
2382 if ((field->flags & Modifier::STATIC) == 0)
2383 throw_incompatible_class_change_error
2384 (JvNewStringLatin1 ("field no longer static"));
2386 jclass type = field->type;
2388 // We rewrite the instruction once we discover what it refers
2390 void *newinsn = NULL;
2391 if (type->isPrimitive ())
2393 switch (type->size_in_bytes)
2396 PUSHI (*(jbyte*) (field->u.addr));
2397 newinsn = AMPAMP (getstatic_resolved_1);
2401 if (type == JvPrimClass (char))
2403 PUSHI(*(jchar*) (field->u.addr));
2404 newinsn = AMPAMP (getstatic_resolved_char);
2408 PUSHI(*(jshort*) (field->u.addr));
2409 newinsn = AMPAMP (getstatic_resolved_short);
2414 PUSHI(*(jint*) (field->u.addr));
2415 newinsn = AMPAMP (getstatic_resolved_4);
2419 PUSHL(*(jlong*) (field->u.addr));
2420 newinsn = AMPAMP (getstatic_resolved_8);
2426 PUSHA(*(jobject*) (field->u.addr));
2427 newinsn = AMPAMP (getstatic_resolved_obj);
2430 #ifdef DIRECT_THREADED
2431 pc[-2].insn = newinsn;
2432 pc[-1].datum = field->u.addr;
2433 #endif /* DIRECT_THREADED */
2437 #ifdef DIRECT_THREADED
2438 getstatic_resolved_1:
2439 PUSHI (*(jbyte *) AVAL ());
2442 getstatic_resolved_char:
2443 PUSHI (*(jchar *) AVAL ());
2446 getstatic_resolved_short:
2447 PUSHI (*(jshort *) AVAL ());
2450 getstatic_resolved_4:
2451 PUSHI (*(jint *) AVAL ());
2454 getstatic_resolved_8:
2455 PUSHL (*(jlong *) AVAL ());
2458 getstatic_resolved_obj:
2459 PUSHA (*(jobject *) AVAL ());
2461 #endif /* DIRECT_THREADED */
2465 jint fieldref_index = GET2U ();
2466 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2467 _Jv_Field *field = pool_data[fieldref_index].field;
2469 if ((field->flags & Modifier::STATIC) != 0)
2470 throw_incompatible_class_change_error
2471 (JvNewStringLatin1 ("field is static"));
2473 jclass type = field->type;
2474 jint field_offset = field->u.boffset;
2475 if (field_offset > 0xffff)
2476 throw new java::lang::VirtualMachineError;
2478 jobject obj = POPA();
2481 void *newinsn = NULL;
2482 if (type->isPrimitive ())
2484 switch (type->size_in_bytes)
2487 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2488 newinsn = AMPAMP (getfield_resolved_1);
2492 if (type == JvPrimClass (char))
2494 PUSHI (*(jchar*) ((char*)obj + field_offset));
2495 newinsn = AMPAMP (getfield_resolved_char);
2499 PUSHI (*(jshort*) ((char*)obj + field_offset));
2500 newinsn = AMPAMP (getfield_resolved_short);
2505 PUSHI (*(jint*) ((char*)obj + field_offset));
2506 newinsn = AMPAMP (getfield_resolved_4);
2510 PUSHL(*(jlong*) ((char*)obj + field_offset));
2511 newinsn = AMPAMP (getfield_resolved_8);
2517 PUSHA(*(jobject*) ((char*)obj + field_offset));
2518 newinsn = AMPAMP (getfield_resolved_obj);
2521 #ifdef DIRECT_THREADED
2522 pc[-2].insn = newinsn;
2523 pc[-1].int_val = field_offset;
2524 #endif /* DIRECT_THREADED */
2528 #ifdef DIRECT_THREADED
2529 getfield_resolved_1:
2531 char *obj = (char *) POPA ();
2533 PUSHI (*(jbyte *) (obj + INTVAL ()));
2537 getfield_resolved_char:
2539 char *obj = (char *) POPA ();
2541 PUSHI (*(jchar *) (obj + INTVAL ()));
2545 getfield_resolved_short:
2547 char *obj = (char *) POPA ();
2549 PUSHI (*(jshort *) (obj + INTVAL ()));
2553 getfield_resolved_4:
2555 char *obj = (char *) POPA ();
2557 PUSHI (*(jint *) (obj + INTVAL ()));
2561 getfield_resolved_8:
2563 char *obj = (char *) POPA ();
2565 PUSHL (*(jlong *) (obj + INTVAL ()));
2569 getfield_resolved_obj:
2571 char *obj = (char *) POPA ();
2573 PUSHA (*(jobject *) (obj + INTVAL ()));
2576 #endif /* DIRECT_THREADED */
2580 jint fieldref_index = GET2U ();
2581 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2582 _Jv_Field *field = pool_data[fieldref_index].field;
2584 jclass type = field->type;
2586 // ResolvePoolEntry cannot check this
2587 if ((field->flags & Modifier::STATIC) == 0)
2588 throw_incompatible_class_change_error
2589 (JvNewStringLatin1 ("field no longer static"));
2591 void *newinsn = NULL;
2592 if (type->isPrimitive ())
2594 switch (type->size_in_bytes)
2598 jint value = POPI();
2599 *(jbyte*) (field->u.addr) = value;
2600 newinsn = AMPAMP (putstatic_resolved_1);
2606 jint value = POPI();
2607 *(jchar*) (field->u.addr) = value;
2608 newinsn = AMPAMP (putstatic_resolved_2);
2614 jint value = POPI();
2615 *(jint*) (field->u.addr) = value;
2616 newinsn = AMPAMP (putstatic_resolved_4);
2622 jlong value = POPL();
2623 *(jlong*) (field->u.addr) = value;
2624 newinsn = AMPAMP (putstatic_resolved_8);
2631 jobject value = POPA();
2632 *(jobject*) (field->u.addr) = value;
2633 newinsn = AMPAMP (putstatic_resolved_obj);
2636 #ifdef DIRECT_THREADED
2637 pc[-2].insn = newinsn;
2638 pc[-1].datum = field->u.addr;
2639 #endif /* DIRECT_THREADED */
2643 #ifdef DIRECT_THREADED
2644 putstatic_resolved_1:
2645 *(jbyte *) AVAL () = POPI ();
2648 putstatic_resolved_2:
2649 *(jchar *) AVAL () = POPI ();
2652 putstatic_resolved_4:
2653 *(jint *) AVAL () = POPI ();
2656 putstatic_resolved_8:
2657 *(jlong *) AVAL () = POPL ();
2660 putstatic_resolved_obj:
2661 *(jobject *) AVAL () = POPA ();
2663 #endif /* DIRECT_THREADED */
2667 jint fieldref_index = GET2U ();
2668 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2669 _Jv_Field *field = pool_data[fieldref_index].field;
2671 jclass type = field->type;
2673 if ((field->flags & Modifier::STATIC) != 0)
2674 throw_incompatible_class_change_error
2675 (JvNewStringLatin1 ("field is static"));
2677 jint field_offset = field->u.boffset;
2678 if (field_offset > 0xffff)
2679 throw new java::lang::VirtualMachineError;
2681 void *newinsn = NULL;
2682 if (type->isPrimitive ())
2684 switch (type->size_in_bytes)
2688 jint value = POPI();
2689 jobject obj = POPA();
2691 *(jbyte*) ((char*)obj + field_offset) = value;
2692 newinsn = AMPAMP (putfield_resolved_1);
2698 jint value = POPI();
2699 jobject obj = POPA();
2701 *(jchar*) ((char*)obj + field_offset) = value;
2702 newinsn = AMPAMP (putfield_resolved_2);
2708 jint value = POPI();
2709 jobject obj = POPA();
2711 *(jint*) ((char*)obj + field_offset) = value;
2712 newinsn = AMPAMP (putfield_resolved_4);
2718 jlong value = POPL();
2719 jobject obj = POPA();
2721 *(jlong*) ((char*)obj + field_offset) = value;
2722 newinsn = AMPAMP (putfield_resolved_8);
2729 jobject value = POPA();
2730 jobject obj = POPA();
2732 *(jobject*) ((char*)obj + field_offset) = value;
2733 newinsn = AMPAMP (putfield_resolved_obj);
2736 #ifdef DIRECT_THREADED
2737 pc[-2].insn = newinsn;
2738 pc[-1].int_val = field_offset;
2739 #endif /* DIRECT_THREADED */
2743 #ifdef DIRECT_THREADED
2744 putfield_resolved_1:
2747 char *obj = (char *) POPA ();
2749 *(jbyte *) (obj + INTVAL ()) = val;
2753 putfield_resolved_2:
2756 char *obj = (char *) POPA ();
2758 *(jchar *) (obj + INTVAL ()) = val;
2762 putfield_resolved_4:
2765 char *obj = (char *) POPA ();
2767 *(jint *) (obj + INTVAL ()) = val;
2771 putfield_resolved_8:
2773 jlong val = POPL ();
2774 char *obj = (char *) POPA ();
2776 *(jlong *) (obj + INTVAL ()) = val;
2780 putfield_resolved_obj:
2782 jobject val = POPA ();
2783 char *obj = (char *) POPA ();
2785 *(jobject *) (obj + INTVAL ()) = val;
2788 #endif /* DIRECT_THREADED */
2792 int index = GET2U ();
2794 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2796 sp -= rmeth->stack_item_count;
2798 NULLCHECK (sp[0].o);
2800 fun = (void (*)()) rmeth->method->ncode;
2802 #ifdef DIRECT_THREADED
2803 // Rewrite instruction so that we use a faster pre-resolved
2805 pc[-2].insn = &&invokespecial_resolved;
2806 pc[-1].datum = rmeth;
2807 #endif /* DIRECT_THREADED */
2809 goto perform_invoke;
2811 #ifdef DIRECT_THREADED
2812 invokespecial_resolved:
2814 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2815 sp -= rmeth->stack_item_count;
2816 NULLCHECK (sp[0].o);
2817 fun = (void (*)()) rmeth->method->ncode;
2819 goto perform_invoke;
2820 #endif /* DIRECT_THREADED */
2824 int index = GET2U ();
2826 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2828 sp -= rmeth->stack_item_count;
2830 _Jv_InitClass (rmeth->klass);
2831 fun = (void (*)()) rmeth->method->ncode;
2833 #ifdef DIRECT_THREADED
2834 // Rewrite instruction so that we use a faster pre-resolved
2836 pc[-2].insn = &&invokestatic_resolved;
2837 pc[-1].datum = rmeth;
2838 #endif /* DIRECT_THREADED */
2840 goto perform_invoke;
2842 #ifdef DIRECT_THREADED
2843 invokestatic_resolved:
2845 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2846 sp -= rmeth->stack_item_count;
2847 fun = (void (*)()) rmeth->method->ncode;
2849 goto perform_invoke;
2850 #endif /* DIRECT_THREADED */
2852 insn_invokeinterface:
2854 int index = GET2U ();
2856 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2858 sp -= rmeth->stack_item_count;
2860 jobject rcv = sp[0].o;
2865 _Jv_LookupInterfaceMethod (rcv->getClass (),
2866 rmeth->method->name,
2867 rmeth->method->signature);
2869 #ifdef DIRECT_THREADED
2870 // Rewrite instruction so that we use a faster pre-resolved
2872 pc[-2].insn = &&invokeinterface_resolved;
2873 pc[-1].datum = rmeth;
2875 // Skip dummy bytes.
2877 #endif /* DIRECT_THREADED */
2879 goto perform_invoke;
2881 #ifdef DIRECT_THREADED
2882 invokeinterface_resolved:
2884 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2885 sp -= rmeth->stack_item_count;
2886 jobject rcv = sp[0].o;
2889 _Jv_LookupInterfaceMethod (rcv->getClass (),
2890 rmeth->method->name,
2891 rmeth->method->signature);
2893 goto perform_invoke;
2894 #endif /* DIRECT_THREADED */
2898 int index = GET2U ();
2899 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2900 _Jv_InitClass (klass);
2901 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2904 #ifdef DIRECT_THREADED
2905 pc[-2].insn = &&new_resolved;
2906 pc[-1].datum = klass;
2907 #endif /* DIRECT_THREADED */
2911 #ifdef DIRECT_THREADED
2914 jclass klass = (jclass) AVAL ();
2915 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2919 #endif /* DIRECT_THREADED */
2923 int atype = GET1U ();
2925 jobject result = _Jv_NewArray (atype, size);
2932 int index = GET2U ();
2933 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2935 _Jv_InitClass (klass);
2936 jobject result = _Jv_NewObjectArray (size, klass, 0);
2939 #ifdef DIRECT_THREADED
2940 pc[-2].insn = &&anewarray_resolved;
2941 pc[-1].datum = klass;
2942 #endif /* DIRECT_THREADED */
2946 #ifdef DIRECT_THREADED
2949 jclass klass = (jclass) AVAL ();
2951 jobject result = _Jv_NewObjectArray (size, klass, 0);
2955 #endif /* DIRECT_THREADED */
2959 __JArray *arr = (__JArray*)POPA();
2960 NULLARRAYCHECK (arr);
2961 PUSHI (arr->length);
2967 jobject value = POPA();
2968 throw static_cast<jthrowable>(value);
2974 jobject value = POPA();
2975 jint index = GET2U ();
2976 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2978 if (value != NULL && ! to->isInstance (value))
2979 throw new java::lang::ClassCastException (to->getName());
2983 #ifdef DIRECT_THREADED
2984 pc[-2].insn = &&checkcast_resolved;
2986 #endif /* DIRECT_THREADED */
2990 #ifdef DIRECT_THREADED
2993 jobject value = POPA ();
2994 jclass to = (jclass) AVAL ();
2995 if (value != NULL && ! to->isInstance (value))
2996 throw new java::lang::ClassCastException (to->getName());
3000 #endif /* DIRECT_THREADED */
3004 jobject value = POPA();
3005 jint index = GET2U ();
3006 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3007 PUSHI (to->isInstance (value));
3009 #ifdef DIRECT_THREADED
3010 pc[-2].insn = &&instanceof_resolved;
3012 #endif /* DIRECT_THREADED */
3016 #ifdef DIRECT_THREADED
3017 instanceof_resolved:
3019 jobject value = POPA ();
3020 jclass to = (jclass) AVAL ();
3021 PUSHI (to->isInstance (value));
3024 #endif /* DIRECT_THREADED */
3028 jobject value = POPA();
3030 _Jv_MonitorEnter (value);
3036 jobject value = POPA();
3038 _Jv_MonitorExit (value);
3044 jobject val = POPA();
3054 jobject val = POPA();
3062 insn_multianewarray:
3064 int kind_index = GET2U ();
3068 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
3069 _Jv_InitClass (type);
3070 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
3072 for (int i = dim - 1; i >= 0; i--)
3077 jobject res = _Jv_NewMultiArray (type,dim, sizes);
3083 #ifndef DIRECT_THREADED
3086 jint the_mod_op = get1u (pc++);
3087 jint wide = get2u (pc); pc += 2;
3128 pc = (unsigned char*) PEEKA (wide);
3133 jint amount = get2s (pc); pc += 2;
3134 jint value = PEEKI (wide);
3135 POKEI (wide, value+amount);
3140 throw_internal_error ("illegal bytecode modified by wide");
3144 #endif /* DIRECT_THREADED */
3146 catch (java::lang::Throwable *ex)
3148 #ifdef DIRECT_THREADED
3149 void *logical_pc = (void *) ((insn_slot *) pc - 1);
3151 int logical_pc = pc - 1 - bytecode ();
3153 _Jv_InterpException *exc = exceptions ();
3154 jclass exc_class = ex->getClass ();
3156 for (int i = 0; i < exc_count; i++)
3158 if (PCVAL (exc[i].start_pc) <= logical_pc
3159 && logical_pc < PCVAL (exc[i].end_pc))
3161 #ifdef DIRECT_THREADED
3162 jclass handler = (jclass) exc[i].handler_type.p;
3164 jclass handler = NULL;
3165 if (exc[i].handler_type.i != 0)
3166 handler = (_Jv_ResolvePoolEntry (defining_class,
3167 exc[i].handler_type.i)).clazz;
3168 #endif /* DIRECT_THREADED */
3170 if (handler == NULL || handler->isAssignableFrom (exc_class))
3172 #ifdef DIRECT_THREADED
3173 pc = (insn_slot *) exc[i].handler_pc.p;
3175 pc = bytecode () + exc[i].handler_pc.i;
3176 #endif /* DIRECT_THREADED */
3178 sp++->o = ex; // Push exception.
3184 // No handler, so re-throw.
3189 // This function exists so that the stack-tracing code can find the
3190 // boundaries of the interpreter.
3192 _Jv_EndOfInterpreter (void)
3197 throw_internal_error (char *msg)
3199 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
3203 throw_incompatible_class_change_error (jstring msg)
3205 throw new java::lang::IncompatibleClassChangeError (msg);
3209 static java::lang::NullPointerException *null_pointer_exc;
3211 throw_null_pointer_exception ()
3213 if (null_pointer_exc == NULL)
3214 null_pointer_exc = new java::lang::NullPointerException;
3216 throw null_pointer_exc;
3220 #endif // INTERPRETER