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>
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 (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
));
1945 if (type
== JvPrimClass (char))
1946 PUSHI(*(jchar
*) (field
->u
.addr
));
1948 PUSHI(*(jshort
*) (field
->u
.addr
));
1952 PUSHI(*(jint
*) (field
->u
.addr
));
1956 PUSHL(*(jlong
*) (field
->u
.addr
));
1962 PUSHA(*(jobject
*) (field
->u
.addr
));
1970 jint fieldref_index
= get2u (pc
); pc
+= 2;
1971 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1972 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1974 if ((field
->flags
& Modifier::STATIC
) != 0)
1975 throw_incompatible_class_change_error
1976 (JvNewStringLatin1 ("field is static"));
1978 jclass type
= field
->type
;
1979 jint field_offset
= field
->u
.boffset
;
1980 if (field_offset
> 0xffff)
1981 JvThrow (new java::lang::VirtualMachineError
);
1983 jobject obj
= POPA();
1986 if (type
->isPrimitive ())
1988 switch (type
->size_in_bytes
)
1991 PUSHI (*(jbyte
*) ((char*)obj
+ field_offset
));
1995 if (type
== JvPrimClass (char))
1996 PUSHI (*(jchar
*) ((char*)obj
+ field_offset
));
1998 PUSHI (*(jshort
*) ((char*)obj
+ field_offset
));
2002 PUSHI (*(jint
*) ((char*)obj
+ field_offset
));
2006 PUSHL(*(jlong
*) ((char*)obj
+ field_offset
));
2012 PUSHA(*(jobject
*) ((char*)obj
+ field_offset
));
2020 jint fieldref_index
= get2u (pc
); pc
+= 2;
2021 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2022 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2024 jclass type
= field
->type
;
2026 // ResolvePoolEntry cannot check this
2027 if ((field
->flags
& Modifier::STATIC
) == 0)
2028 throw_incompatible_class_change_error
2029 (JvNewStringLatin1 ("field no longer static"));
2031 if (type
->isPrimitive ())
2033 switch (type
->size_in_bytes
)
2037 jint value
= POPI();
2038 *(jbyte
*) (field
->u
.addr
) = value
;
2044 jint value
= POPI();
2045 *(jchar
*) (field
->u
.addr
) = value
;
2051 jint value
= POPI();
2052 *(jint
*) (field
->u
.addr
) = value
;
2058 jlong value
= POPL();
2059 *(jlong
*) (field
->u
.addr
) = value
;
2066 jobject value
= POPA();
2067 *(jobject
*) (field
->u
.addr
) = value
;
2076 jint fieldref_index
= get2u (pc
); pc
+= 2;
2077 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2078 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2080 jclass type
= field
->type
;
2082 if ((field
->flags
& Modifier::STATIC
) != 0)
2083 throw_incompatible_class_change_error
2084 (JvNewStringLatin1 ("field is static"));
2086 jint field_offset
= field
->u
.boffset
;
2087 if (field_offset
> 0xffff)
2088 JvThrow (new java::lang::VirtualMachineError
);
2090 if (type
->isPrimitive ())
2092 switch (type
->size_in_bytes
)
2096 jint value
= POPI();
2097 jobject obj
= POPA();
2099 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2105 jint value
= POPI();
2106 jobject obj
= POPA();
2108 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2114 jint value
= POPI();
2115 jobject obj
= POPA();
2117 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2123 jlong value
= POPL();
2124 jobject obj
= POPA();
2126 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2133 jobject value
= POPA();
2134 jobject obj
= POPA();
2136 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2144 int index
= get2u (pc
); pc
+= 2;
2146 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2148 sp
-= rmeth
->stack_item_count
;
2150 NULLCHECK (sp
[0].o
);
2152 fun
= (void (*)()) rmeth
->method
->ncode
;
2154 goto perform_invoke
;
2159 int index
= get2u (pc
); pc
+= 2;
2161 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2163 sp
-= rmeth
->stack_item_count
;
2165 _Jv_InitClass (rmeth
->klass
);
2166 fun
= (void (*)()) rmeth
->method
->ncode
;
2168 goto perform_invoke
;
2170 insn_invokeinterface
:
2173 int index
= get2u (pc
); pc
+= 2;
2175 // invokeinterface has two unused bytes...
2178 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2180 sp
-= rmeth
->stack_item_count
;
2182 jobject rcv
= sp
[0].o
;
2187 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2188 rmeth
->method
->name
,
2189 rmeth
->method
->signature
);
2191 goto perform_invoke
;
2197 int index
= get2u (pc
); pc
+= 2;
2198 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2199 _Jv_InitClass (klass
);
2200 jobject res
= _Jv_AllocObject (klass
, klass
->size_in_bytes
);
2208 int atype
= get1u (pc
++);
2210 jobject result
= _Jv_NewArray (atype
, size
);
2218 int index
= get2u (pc
); pc
+= 2;
2219 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2221 _Jv_InitClass (klass
);
2222 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2230 __JArray
*arr
= (__JArray
*)POPA();
2231 PUSHI (arr
->length
);
2238 jobject value
= POPA();
2246 jobject value
= POPA();
2247 jint index
= get2u (pc
); pc
+= 2;
2248 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2250 if (value
!= NULL
&& ! to
->isInstance (value
))
2252 JvThrow (new java::lang::ClassCastException
2263 jobject value
= POPA();
2264 jint index
= get2u (pc
); pc
+= 2;
2265 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2266 PUSHI (to
->isInstance (value
));
2273 jobject value
= POPA();
2275 _Jv_MonitorEnter (value
);
2282 jobject value
= POPA();
2284 _Jv_MonitorExit (value
);
2290 unsigned char* base_pc
= pc
-1;
2291 jint offset
= get2s (pc
); pc
+= 2;
2292 jobject val
= POPA();
2294 pc
= base_pc
+offset
;
2300 unsigned char* base_pc
= pc
-1;
2301 jint offset
= get2s (pc
); pc
+= 2;
2302 jobject val
= POPA();
2304 pc
= base_pc
+offset
;
2311 jint the_mod_op
= get1u (pc
++);
2312 jint wide
= get2u (pc
); pc
+= 2;
2353 pc
= (unsigned char*) PEEKA (wide
);
2358 jint amount
= get2s (pc
); pc
+= 2;
2359 jint value
= PEEKI (wide
);
2360 POKEI (wide
, value
+amount
);
2365 throw_internal_error ("illegal bytecode modified by wide");
2370 insn_multianewarray
:
2373 int kind_index
= get2u (pc
); pc
+= 2;
2374 int dim
= get1u (pc
); pc
+= 1;
2377 = (_Jv_ResolvePoolEntry (defining_class
, kind_index
)).clazz
;
2378 _Jv_InitClass (type
);
2379 jint
*sizes
= (jint
*) alloca (sizeof (jint
)*dim
);
2381 for (int i
= dim
- 1; i
>= 0; i
--)
2386 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2394 unsigned char* base_pc
= pc
-1;
2395 int offset
= get4 (pc
); pc
+= 4;
2396 pc
= base_pc
+offset
;
2402 unsigned char* base_pc
= pc
-1;
2403 int offset
= get4 (pc
); pc
+= 4;
2405 pc
= base_pc
+offset
;
2412 throw_internal_error (char *msg
)
2414 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg
)));
2418 throw_incompatible_class_change_error (jstring msg
)
2420 JvThrow (new java::lang::IncompatibleClassChangeError (msg
));
2424 static java::lang::NullPointerException
*null_pointer_exc
;
2426 throw_null_pointer_exception ()
2428 if (null_pointer_exc
== NULL
)
2429 null_pointer_exc
= new java::lang::NullPointerException
;
2431 JvThrow (null_pointer_exc
);
2435 #endif // INTERPRETER