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>
38 #define ClassError _CL_Q34java4lang5Error
39 extern java::lang::Class ClassError
;
41 static _Jv_Utf8Const
*init_name
= _Jv_makeUtf8Const ("<init>", 6);
43 static void throw_internal_error (char *msg
)
44 __attribute__ ((__noreturn__
));
45 static void throw_incompatible_class_change_error (jstring msg
)
46 __attribute__ ((__noreturn__
));
48 static void throw_null_pointer_exception ()
49 __attribute__ ((__noreturn__
));
52 static void throw_arithmetic_exception ()
53 __attribute__ ((__noreturn__
));
57 extern "C" double __ieee754_fmod
__P((double,double));
59 static inline void dupx (_Jv_word
*sp
, int n
, int x
)
61 // first "slide" n+x elements n to the right
63 for (int i
= 0; i
< n
+x
; i
++)
65 sp
[(top
-i
)] = sp
[(top
-i
)-n
];
68 // next, copy the n top elements, n+x down
69 for (int i
= 0; i
< n
; i
++)
71 sp
[top
-(n
+x
)-i
] = sp
[top
-i
];
77 #define PUSHA(V) (sp++)->o = (V)
78 #define PUSHI(V) (sp++)->i = (V)
79 #define PUSHF(V) (sp++)->f = (V)
80 #if SIZEOF_VOID_P == 8
81 # define PUSHL(V) (sp->l = (V), sp += 2)
82 # define PUSHD(V) (sp->d = (V), sp += 2)
84 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
85 (sp++)->ia[0] = w2.ia[0]; \
86 (sp++)->ia[0] = w2.ia[1]; } while (0)
87 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
88 (sp++)->ia[0] = w2.ia[0]; \
89 (sp++)->ia[0] = w2.ia[1]; } while (0)
92 #define POPA() ((--sp)->o)
93 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
94 #define POPF() ((jfloat) (--sp)->f)
95 #if SIZEOF_VOID_P == 8
96 # define POPL() (sp -= 2, (jlong) sp->l)
97 # define POPD() (sp -= 2, (jdouble) sp->d)
99 # define POPL() ({ _Jv_word2 w2; \
100 w2.ia[1] = (--sp)->ia[0]; \
101 w2.ia[0] = (--sp)->ia[0]; w2.l; })
102 # define POPD() ({ _Jv_word2 w2; \
103 w2.ia[1] = (--sp)->ia[0]; \
104 w2.ia[0] = (--sp)->ia[0]; w2.d; })
107 #define LOADA(I) (sp++)->o = locals[I].o
108 #define LOADI(I) (sp++)->i = locals[I].i
109 #define LOADF(I) (sp++)->f = locals[I].f
110 #if SIZEOF_VOID_P == 8
111 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
112 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
114 # define LOADL(I) do { jint __idx = (I); \
115 (sp++)->ia[0] = locals[__idx].ia[0]; \
116 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
118 # define LOADD(I) LOADL(I)
121 #define STOREA(I) locals[I].o = (--sp)->o
122 #define STOREI(I) locals[I].i = (--sp)->i
123 #define STOREF(I) locals[I].f = (--sp)->f
124 #if SIZEOF_VOID_P == 8
125 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
126 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
128 # define STOREL(I) do { jint __idx = (I); \
129 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
130 locals[__idx].ia[0] = (--sp)->ia[0]; \
132 # define STORED(I) STOREL(I)
135 #define PEEKI(I) (locals+(I))->i
136 #define PEEKA(I) (locals+(I))->o
138 #define POKEI(I,V) ((locals+(I))->i = (V))
141 #define BINOPI(OP) { \
142 jint value2 = POPI(); \
143 jint value1 = POPI(); \
144 PUSHI(value1 OP value2); \
147 #define BINOPF(OP) { \
148 jfloat value2 = POPF(); \
149 jfloat value1 = POPF(); \
150 PUSHF(value1 OP value2); \
153 #define BINOPL(OP) { \
154 jlong value2 = POPL(); \
155 jlong value1 = POPL(); \
156 PUSHL(value1 OP value2); \
159 #define BINOPD(OP) { \
160 jdouble value2 = POPD(); \
161 jdouble value1 = POPD(); \
162 PUSHD(value1 OP value2); \
165 static inline jint
get1s(unsigned char* loc
) {
166 return *(signed char*)loc
;
169 static inline jint
get1u(unsigned char* loc
) {
173 static inline jint
get2s(unsigned char* loc
) {
174 return (((jint
)*(signed char*)loc
) << 8) | ((jint
)*(loc
+1));
177 static inline jint
get2u(unsigned char* loc
) {
178 return (((jint
)(*loc
)) << 8) | ((jint
)*(loc
+1));
181 static jint
get4(unsigned char* loc
) {
182 return (((jint
)(loc
[0])) << 24)
183 | (((jint
)(loc
[1])) << 16)
184 | (((jint
)(loc
[2])) << 8)
185 | (((jint
)(loc
[3])) << 0);
192 #define NULLCHECK(X) \
193 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
199 #define ZEROCHECK(X) \
200 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
203 // this method starts the actual running of the method. It is inlined
204 // in three different variants in the static methods run_normal,
205 // run_sync_object and run_sync_class (see below). Those static methods
206 // are installed directly in the stub for this method (by
207 // _Jv_InterpMethod::ncode, in resolve.cc).
210 _Jv_InterpMethod::run (ffi_cif
* cif
,
213 _Jv_InterpMethodInvocation
*inv
)
216 inv
->pc
= bytecode ();
217 inv
->sp
= inv
->stack_base ();
218 _Jv_word
*locals
= inv
->local_base ();
220 /* Go straight at it! the ffi raw format matches the internal
221 stack representation exactly. At least, that's the idea.
223 memcpy ((void*) locals
, (void*) args
, args_raw_size
);
233 catch (java::lang::Throwable
*ex2
)
238 if (ex
== 0) // no exception...
240 /* define sp locally, so the POP? macros will pick it up */
241 _Jv_word
*sp
= inv
->sp
;
242 int rtype
= cif
->rtype
->type
;
244 if (rtype
== FFI_TYPE_POINTER
)
247 *(jobject
*) retp
= r
;
250 else if (rtype
== FFI_TYPE_SINT32
)
256 else if (rtype
== FFI_TYPE_VOID
)
269 case FFI_TYPE_DOUBLE
:
277 case FFI_TYPE_UINT16
:
278 case FFI_TYPE_UINT32
:
280 case FFI_TYPE_SINT16
:
287 case FFI_TYPE_SINT64
:
295 throw_internal_error ("unknown return type");
299 /** handle an exception */
300 if ( find_exception (ex
, inv
) )
306 bool _Jv_InterpMethod::find_exception (jobject ex
,
307 _Jv_InterpMethodInvocation
*inv
)
309 int logical_pc
= inv
->pc
- bytecode ();
310 _Jv_InterpException
*exc
= exceptions ();
311 jclass exc_class
= ex
->getClass ();
313 for (int i
= 0; i
< exc_count
; i
++)
315 if (exc
[i
].start_pc
<= logical_pc
&& logical_pc
< exc
[i
].end_pc
)
319 if (exc
[i
].handler_type
!= 0)
320 handler
= (_Jv_ResolvePoolEntry (defining_class
,
321 exc
[i
].handler_type
)).clazz
;
325 if (handler
==NULL
|| handler
->isAssignableFrom (exc_class
))
327 inv
->pc
= bytecode () + exc
[i
].handler_pc
;
328 inv
->sp
= inv
->stack_base (); // reset stack
329 (inv
->sp
++)->o
= ex
; // push exception
337 void _Jv_InterpMethod::run_normal (ffi_cif
* cif
,
342 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
344 // we do the alloca of the method invocation here, to allow the method
345 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
346 int storage_size
= _this
->max_stack
+_this
->max_locals
;
347 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
348 alloca (sizeof (_Jv_InterpMethodInvocation
)
349 + storage_size
* sizeof (_Jv_word
));
351 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
352 if (ex
!= 0) _Jv_Throw (ex
);
355 void _Jv_InterpMethod::run_synch_object (ffi_cif
* cif
,
360 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
361 jobject rcv
= (jobject
)args
[0].ptr
;
363 int storage_size
= _this
->max_stack
+_this
->max_locals
;
364 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
365 alloca (sizeof (_Jv_InterpMethodInvocation
)
366 + storage_size
* sizeof (_Jv_word
));
368 _Jv_MonitorEnter (rcv
);
369 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
370 _Jv_MonitorExit (rcv
);
372 if (ex
!= 0) _Jv_Throw (ex
);
375 void _Jv_InterpMethod::run_synch_class (ffi_cif
* cif
,
380 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
381 jclass sync
= _this
->defining_class
;
383 int storage_size
= _this
->max_stack
+_this
->max_locals
;
384 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
385 alloca (sizeof (_Jv_InterpMethodInvocation
)
386 + storage_size
* sizeof (_Jv_word
));
388 _Jv_MonitorEnter (sync
);
389 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
390 _Jv_MonitorExit (sync
);
392 if (ex
!= 0) _Jv_Throw (ex
);
396 This proceeds execution, as designated in "inv". If an exception
397 happens, then it is simply thrown, and handled in Java. Thus, the pc
398 needs to be stored in the inv->pc at all times, so we can figure
399 out which handler (if any) to invoke.
401 One design issue, which I have not completely considered, is if it
402 should be possible to have interpreted classes linked in! Seldom used
403 (or non-critical) classes could reasonably be interpreted.
407 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation
*inv
)
409 using namespace java::lang::reflect
;
411 register _Jv_word
*sp
= inv
->sp
;
412 register unsigned char *pc
= inv
->pc
;
413 _Jv_word
*locals
= inv
->local_base ();
415 _Jv_word
*pool_data
= defining_class
->constants
.data
;
417 /* these two are used in the invokeXXX instructions */
419 _Jv_ResolvedMethod
* rmeth
;
421 #define INSN_LABEL(op) &&insn_##op
422 #define GOTO_INSN(op) goto *(insn_target[op])
424 static const void *const insn_target
[] =
427 INSN_LABEL(aconst_null
),
428 INSN_LABEL(iconst_m1
),
429 INSN_LABEL(iconst_0
),
430 INSN_LABEL(iconst_1
),
431 INSN_LABEL(iconst_2
),
432 INSN_LABEL(iconst_3
),
433 INSN_LABEL(iconst_4
),
434 INSN_LABEL(iconst_5
),
435 INSN_LABEL(lconst_0
),
436 INSN_LABEL(lconst_1
),
437 INSN_LABEL(fconst_0
),
438 INSN_LABEL(fconst_1
),
439 INSN_LABEL(fconst_2
),
440 INSN_LABEL(dconst_0
),
441 INSN_LABEL(dconst_1
),
485 INSN_LABEL(istore_0
),
486 INSN_LABEL(istore_1
),
487 INSN_LABEL(istore_2
),
488 INSN_LABEL(istore_3
),
489 INSN_LABEL(lstore_0
),
490 INSN_LABEL(lstore_1
),
491 INSN_LABEL(lstore_2
),
492 INSN_LABEL(lstore_3
),
493 INSN_LABEL(fstore_0
),
494 INSN_LABEL(fstore_1
),
495 INSN_LABEL(fstore_2
),
496 INSN_LABEL(fstore_3
),
497 INSN_LABEL(dstore_0
),
498 INSN_LABEL(dstore_1
),
499 INSN_LABEL(dstore_2
),
500 INSN_LABEL(dstore_3
),
501 INSN_LABEL(astore_0
),
502 INSN_LABEL(astore_1
),
503 INSN_LABEL(astore_2
),
504 INSN_LABEL(astore_3
),
585 INSN_LABEL(if_icmpeq
),
586 INSN_LABEL(if_icmpne
),
587 INSN_LABEL(if_icmplt
),
588 INSN_LABEL(if_icmpge
),
589 INSN_LABEL(if_icmpgt
),
590 INSN_LABEL(if_icmple
),
591 INSN_LABEL(if_acmpeq
),
592 INSN_LABEL(if_acmpne
),
596 INSN_LABEL(tableswitch
),
597 INSN_LABEL(lookupswitch
),
604 INSN_LABEL(getstatic
),
605 INSN_LABEL(putstatic
),
606 INSN_LABEL(getfield
),
607 INSN_LABEL(putfield
),
608 INSN_LABEL(invokevirtual
),
609 INSN_LABEL(invokespecial
),
610 INSN_LABEL(invokestatic
),
611 INSN_LABEL(invokeinterface
),
612 0, /* op_xxxunusedxxx1, */
614 INSN_LABEL(newarray
),
615 INSN_LABEL(anewarray
),
616 INSN_LABEL(arraylength
),
618 INSN_LABEL(checkcast
),
619 INSN_LABEL(instanceof
),
620 INSN_LABEL(monitorenter
),
621 INSN_LABEL(monitorexit
),
623 INSN_LABEL(multianewarray
),
625 INSN_LABEL(ifnonnull
),
630 #define SAVE_PC inv->pc = pc-1
632 /* If the macro INLINE_SWITCH is not defined, then the main loop
633 operates as one big (normal) switch statement. If it is defined,
634 then the case selection is performed `inline' in the end of the
635 code for each case. The latter saves a native branch instruction
636 for each java-instruction, but expands the code size somewhat.
638 NOTE: On i386 defining INLINE_SWITCH improves over all
639 performance approximately seven percent, but it may be different
640 for other machines. At some point, this may be made into a proper
641 configuration parameter. */
643 #define INLINE_SWITCH
647 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
653 #define NEXT_INSN goto next_insn
660 /* The first few instructions here are ordered according to their
661 frequency, in the hope that this will improve code locality a
664 insn_aload_0
: // 0x2a
669 LOADI (get1u (pc
++));
672 insn_iload_1
: // 0x1b
676 insn_invokevirtual
: // 0xb6
679 int index
= get2u (pc
); pc
+= 2;
681 /* _Jv_ResolvePoolEntry returns immediately if the value already
682 * is resolved. If we want to clutter up the code here to gain
683 * a little performance, then we can check the corresponding bit
684 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
685 * don't think it is worth it. */
687 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
689 sp
-= rmeth
->stack_item_count
;
692 if (rmeth
->vtable_index
== -1)
694 // final methods do not appear in the vtable,
695 // if it does not appear in the superclass.
696 fun
= (void (*) (...)) rmeth
->method
->ncode
;
700 jobject rcv
= sp
[0].o
;
701 _Jv_VTable
*table
= *(_Jv_VTable
**)rcv
;
702 fun
= (void (*) (...))table
->method
[rmeth
->vtable_index
];
709 /* here goes the magic again... */
710 ffi_cif
*cif
= &rmeth
->cif
;
711 ffi_raw
*raw
= (ffi_raw
*) sp
;
715 #if FFI_NATIVE_RAW_API
716 /* We assume that this is only implemented if it's correct */
717 /* to use it here. On a 64 bit machine, it never is. */
718 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
720 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
723 int rtype
= cif
->rtype
->type
;
725 /* the likelyhood of object, int, or void return is very high,
726 * so those are checked before the switch */
727 if (rtype
== FFI_TYPE_POINTER
)
729 PUSHA (*(jobject
*)&rvalue
);
731 else if (rtype
== FFI_TYPE_SINT32
)
733 PUSHI (*(jint
*)&rvalue
);
735 else if (rtype
== FFI_TYPE_VOID
)
743 jbyte value
= (*(jint
*)&rvalue
) & 0xff;
748 case FFI_TYPE_SINT16
:
750 jshort value
= (*(jint
*)&rvalue
) & 0xffff;
755 case FFI_TYPE_UINT16
:
757 jint value
= (*(jint
*)&rvalue
) & 0xffff;
763 PUSHF (*(jfloat
*)&rvalue
);
766 case FFI_TYPE_DOUBLE
:
770 case FFI_TYPE_SINT64
:
771 PUSHL (*(jlong
*)&rvalue
);
775 throw_internal_error ("unknown return type in invokeXXX");
850 PUSHI (get2s(pc
)); pc
+= 2;
855 int index
= get1u (pc
++);
856 PUSHA(pool_data
[index
].o
);
862 int index
= get2u (pc
); pc
+= 2;
863 PUSHA(pool_data
[index
].o
);
869 int index
= get2u (pc
); pc
+= 2;
870 memcpy (sp
, &pool_data
[index
], 2*sizeof (_Jv_word
));
876 LOADL (get1u (pc
++));
880 LOADF (get1u (pc
++));
884 LOADD (get1u (pc
++));
888 LOADA (get1u (pc
++));
967 jintArray arr
= (jintArray
) POPA();
969 if (index
< 0 || index
>= arr
->length
)
971 _Jv_ThrowBadArrayIndex (index
);
973 PUSHI( elements(arr
)[index
] );
981 jlongArray arr
= (jlongArray
) POPA();
983 if (index
< 0 || index
>= arr
->length
)
985 _Jv_ThrowBadArrayIndex (index
);
987 PUSHL( elements(arr
)[index
] );
995 jfloatArray arr
= (jfloatArray
) POPA();
997 if (index
< 0 || index
>= arr
->length
)
999 _Jv_ThrowBadArrayIndex (index
);
1001 PUSHF( elements(arr
)[index
] );
1008 jint index
= POPI();
1009 jdoubleArray arr
= (jdoubleArray
) POPA();
1011 if (index
< 0 || index
>= arr
->length
)
1013 _Jv_ThrowBadArrayIndex (index
);
1015 PUSHD( elements(arr
)[index
] );
1022 jint index
= POPI();
1023 jobjectArray arr
= (jobjectArray
) POPA();
1025 if (index
< 0 || index
>= arr
->length
)
1027 _Jv_ThrowBadArrayIndex (index
);
1029 PUSHA( elements(arr
)[index
] );
1036 jint index
= POPI();
1037 jbyteArray arr
= (jbyteArray
) POPA();
1039 if (index
< 0 || index
>= arr
->length
)
1041 _Jv_ThrowBadArrayIndex (index
);
1043 PUSHI( elements(arr
)[index
] );
1050 jint index
= POPI();
1051 jcharArray arr
= (jcharArray
) POPA();
1053 if (index
< 0 || index
>= arr
->length
)
1055 _Jv_ThrowBadArrayIndex (index
);
1057 PUSHI( elements(arr
)[index
] );
1064 jint index
= POPI();
1065 jshortArray arr
= (jshortArray
) POPA();
1067 if (index
< 0 || index
>= arr
->length
)
1069 _Jv_ThrowBadArrayIndex (index
);
1071 PUSHI( elements(arr
)[index
] );
1076 STOREI (get1u (pc
++));
1080 STOREL (get1u (pc
++));
1084 STOREF (get1u (pc
++));
1088 STORED (get1u (pc
++));
1092 STOREA (get1u (pc
++));
1178 jint value
= POPI();
1179 jint index
= POPI();
1180 jintArray arr
= (jintArray
) POPA();
1182 if (index
< 0 || index
>= arr
->length
)
1184 _Jv_ThrowBadArrayIndex (index
);
1186 elements(arr
)[index
] = value
;
1193 jlong value
= POPL();
1194 jint index
= POPI();
1195 jlongArray arr
= (jlongArray
) POPA();
1197 if (index
< 0 || index
>= arr
->length
)
1199 _Jv_ThrowBadArrayIndex (index
);
1201 elements(arr
)[index
] = value
;
1208 jfloat value
= POPF();
1209 jint index
= POPI();
1210 jfloatArray arr
= (jfloatArray
) POPA();
1212 if (index
< 0 || index
>= arr
->length
)
1214 _Jv_ThrowBadArrayIndex (index
);
1216 elements(arr
)[index
] = value
;
1223 jdouble value
= POPD();
1224 jint index
= POPI();
1225 jdoubleArray arr
= (jdoubleArray
) POPA();
1227 if (index
< 0 || index
>= arr
->length
)
1229 _Jv_ThrowBadArrayIndex (index
);
1231 elements(arr
)[index
] = value
;
1238 jobject value
= POPA();
1239 jint index
= POPI();
1240 jobjectArray arr
= (jobjectArray
) POPA();
1242 if (index
< 0 || index
>= arr
->length
)
1244 _Jv_ThrowBadArrayIndex (index
);
1246 _Jv_CheckArrayStore (arr
, value
);
1247 elements(arr
)[index
] = value
;
1254 jbyte value
= (jbyte
) POPI();
1255 jint index
= POPI();
1256 jbyteArray arr
= (jbyteArray
) POPA();
1258 if (index
< 0 || index
>= arr
->length
)
1260 _Jv_ThrowBadArrayIndex (index
);
1262 elements(arr
)[index
] = value
;
1269 jchar value
= (jchar
) POPI();
1270 jint index
= POPI();
1271 jcharArray arr
= (jcharArray
) POPA();
1273 if (index
< 0 || index
>= arr
->length
)
1275 _Jv_ThrowBadArrayIndex (index
);
1277 elements(arr
)[index
] = value
;
1284 jshort value
= (jshort
) POPI();
1285 jint index
= POPI();
1286 jshortArray arr
= (jshortArray
) POPA();
1288 if (index
< 0 || index
>= arr
->length
)
1290 _Jv_ThrowBadArrayIndex (index
);
1292 elements(arr
)[index
] = value
;
1310 dupx (sp
, 1, 1); sp
+=1;
1314 dupx (sp
, 1, 2); sp
+=1;
1324 dupx (sp
, 2, 1); sp
+=2;
1328 dupx (sp
, 2, 2); sp
+=2;
1333 jobject tmp1
= POPA();
1334 jobject tmp2
= POPA();
1391 jint value2
= POPI();
1392 jint value1
= POPI();
1394 jint res
= value1
/ value2
;
1402 jlong value2
= POPL();
1403 jlong value1
= POPL();
1405 jlong res
= value1
/ value2
;
1413 jfloat value2
= POPF();
1414 jfloat value1
= POPF();
1416 jfloat res
= value1
/ value2
;
1424 jdouble value2
= POPD();
1425 jdouble value1
= POPD();
1427 jdouble res
= value1
/ value2
;
1435 jint value2
= POPI();
1436 jint value1
= POPI();
1438 jint res
= value1
% value2
;
1446 jlong value2
= POPL();
1447 jlong value1
= POPL();
1449 jlong res
= value1
% value2
;
1457 jfloat value2
= POPF();
1458 jfloat value1
= POPF();
1460 jfloat res
= __ieee754_fmod (value1
, value2
);
1468 jdouble value2
= POPD();
1469 jdouble value1
= POPD();
1471 jdouble res
= __ieee754_fmod (value1
, value2
);
1478 jint value
= POPI();
1485 jlong value
= POPL();
1492 jfloat value
= POPF();
1499 jdouble value
= POPD();
1506 jint shift
= (POPI() & 0x1f);
1507 jint value
= POPI();
1508 PUSHI (value
<< shift
);
1514 jint shift
= (POPI() & 0x3f);
1515 jlong value
= POPL();
1516 PUSHL (value
<< shift
);
1522 jint shift
= (POPI() & 0x1f);
1523 jint value
= POPI();
1524 PUSHI (value
>> shift
);
1530 jint shift
= (POPI() & 0x3f);
1531 jlong value
= POPL();
1532 PUSHL (value
>> shift
);
1538 jint shift
= (POPI() & 0x1f);
1539 unsigned long value
= POPI();
1540 PUSHI ((jint
) (value
>> shift
));
1546 jint shift
= (POPI() & 0x3f);
1547 UINT64 value
= (UINT64
) POPL();
1548 PUSHL ((value
>> shift
));
1578 jint index
= get1u (pc
++);
1579 jint amount
= get1s (pc
++);
1580 locals
[index
].i
+= amount
;
1585 {jlong value
= POPI(); PUSHL (value
);}
1589 {jfloat value
= POPI(); PUSHF (value
);}
1593 {jdouble value
= POPI(); PUSHD (value
);}
1597 {jint value
= POPL(); PUSHI (value
);}
1601 {jfloat value
= POPL(); PUSHF (value
);}
1605 {jdouble value
= POPL(); PUSHD (value
);}
1609 { jint value
= (jint
)POPF (); PUSHI(value
); }
1613 { jlong value
= (jlong
)POPF (); PUSHL(value
); }
1617 { jdouble value
= POPF (); PUSHD(value
); }
1621 { jint value
= (jint
)POPD (); PUSHI(value
); }
1625 { jlong value
= (jlong
)POPD (); PUSHL(value
); }
1629 { jfloat value
= POPD (); PUSHF(value
); }
1633 { jbyte value
= POPI (); PUSHI(value
); }
1637 { jchar value
= POPI (); PUSHI(value
); }
1641 { jshort value
= POPI (); PUSHI(value
); }
1646 jlong value2
= POPL ();
1647 jlong value1
= POPL ();
1648 if (value1
> value2
)
1650 else if (value1
== value2
)
1660 jfloat value2
= POPF ();
1661 jfloat value1
= POPF ();
1662 if (value1
> value2
)
1664 else if (value1
== value2
)
1666 else if (value1
< value2
)
1668 else if ((*(pc
-1)) == op_fcmpg
)
1678 jdouble value2
= POPD ();
1679 jdouble value1
= POPD ();
1680 if (value1
> value2
)
1682 else if (value1
== value2
)
1684 else if (value1
< value2
)
1686 else if ((*(pc
-1)) == op_dcmpg
)
1695 jint offset
= get2s (pc
);
1705 jint offset
= get2s (pc
);
1715 jint offset
= get2s (pc
);
1725 jint offset
= get2s (pc
);
1735 jint offset
= get2s (pc
);
1745 jint offset
= get2s (pc
);
1755 jint offset
= get2s (pc
);
1756 jint value2
= POPI();
1757 jint value1
= POPI();
1758 if (value1
== value2
)
1767 jint offset
= get2s (pc
);
1768 jint value2
= POPI();
1769 jint value1
= POPI();
1770 if (value1
!= value2
)
1779 jint offset
= get2s (pc
);
1780 jint value2
= POPI();
1781 jint value1
= POPI();
1782 if (value1
< value2
)
1791 jint offset
= get2s (pc
);
1792 jint value2
= POPI();
1793 jint value1
= POPI();
1794 if (value1
>= value2
)
1803 jint offset
= get2s (pc
);
1804 jint value2
= POPI();
1805 jint value1
= POPI();
1806 if (value1
> value2
)
1815 jint offset
= get2s (pc
);
1816 jint value2
= POPI();
1817 jint value1
= POPI();
1818 if (value1
<= value2
)
1827 jint offset
= get2s (pc
);
1828 jobject value2
= POPA();
1829 jobject value1
= POPA();
1830 if (value1
== value2
)
1839 jint offset
= get2s (pc
);
1840 jobject value2
= POPA();
1841 jobject value1
= POPA();
1842 if (value1
!= value2
)
1851 jint offset
= get2s (pc
);
1858 unsigned char *base_pc
= pc
-1;
1859 jint offset
= get2s (pc
); pc
+= 2;
1860 PUSHA ((jobject
)pc
);
1861 pc
= base_pc
+offset
;
1867 jint index
= get1u (pc
);
1868 pc
= (unsigned char*) PEEKA (index
);
1874 unsigned char *base_pc
= pc
-1;
1877 unsigned char* base
= bytecode ();
1878 while ((pc
-base
) % 4 != 0)
1881 jint def
= get4 (pc
);
1882 jint low
= get4 (pc
+4);
1883 jint high
= get4 (pc
+8);
1885 if (index
< low
|| index
> high
)
1888 pc
= base_pc
+ get4 (pc
+4*(index
-low
+3));
1894 unsigned char *base_pc
= pc
-1;
1897 unsigned char* base
= bytecode ();
1898 while ((pc
-base
) % 4 != 0)
1901 jint def
= get4 (pc
);
1902 jint npairs
= get4 (pc
+4);
1907 // simple binary search...
1910 int half
= (min
+max
)/2;
1911 int match
= get4 (pc
+ 4*(2 + 2*half
));
1916 else if (index
< match
)
1923 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1924 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1930 /* on return, just save the sp and return to caller */
1943 jint fieldref_index
= get2u (pc
); pc
+= 2;
1944 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1945 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1947 if ((field
->flags
& Modifier::STATIC
) == 0)
1948 throw_incompatible_class_change_error
1949 (JvNewStringLatin1 ("field no longer static"));
1951 jclass type
= field
->type
;
1953 if (type
->isPrimitive ())
1955 switch (type
->size_in_bytes
)
1958 PUSHI (*(jbyte
*) (field
->u
.addr
));
1961 if (type
== JvPrimClass (char))
1962 PUSHI(*(jchar
*) (field
->u
.addr
));
1964 PUSHI(*(jshort
*) (field
->u
.addr
));
1968 PUSHI(*(jint
*) (field
->u
.addr
));
1972 PUSHL(*(jlong
*) (field
->u
.addr
));
1978 PUSHA(*(jobject
*) (field
->u
.addr
));
1986 jint fieldref_index
= get2u (pc
); pc
+= 2;
1987 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1988 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1990 if ((field
->flags
& Modifier::STATIC
) != 0)
1991 throw_incompatible_class_change_error
1992 (JvNewStringLatin1 ("field is static"));
1994 jclass type
= field
->type
;
1995 jint field_offset
= field
->u
.boffset
;
1996 if (field_offset
> 0xffff)
1997 JvThrow (new java::lang::VirtualMachineError
);
1999 jobject obj
= POPA();
2002 if (type
->isPrimitive ())
2004 switch (type
->size_in_bytes
)
2007 PUSHI (*(jbyte
*) ((char*)obj
+ field_offset
));
2011 if (type
== JvPrimClass (char))
2012 PUSHI (*(jchar
*) ((char*)obj
+ field_offset
));
2014 PUSHI (*(jshort
*) ((char*)obj
+ field_offset
));
2018 PUSHI (*(jint
*) ((char*)obj
+ field_offset
));
2022 PUSHL(*(jlong
*) ((char*)obj
+ field_offset
));
2028 PUSHA(*(jobject
*) ((char*)obj
+ field_offset
));
2036 jint fieldref_index
= get2u (pc
); pc
+= 2;
2037 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2038 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2040 jclass type
= field
->type
;
2042 // ResolvePoolEntry cannot check this
2043 if ((field
->flags
& Modifier::STATIC
) == 0)
2044 throw_incompatible_class_change_error
2045 (JvNewStringLatin1 ("field no longer static"));
2047 if (type
->isPrimitive ())
2049 switch (type
->size_in_bytes
)
2053 jint value
= POPI();
2054 *(jbyte
*) (field
->u
.addr
) = value
;
2060 jint value
= POPI();
2061 *(jchar
*) (field
->u
.addr
) = value
;
2067 jint value
= POPI();
2068 *(jint
*) (field
->u
.addr
) = value
;
2074 jlong value
= POPL();
2075 *(jlong
*) (field
->u
.addr
) = value
;
2082 jobject value
= POPA();
2083 *(jobject
*) (field
->u
.addr
) = value
;
2092 jint fieldref_index
= get2u (pc
); pc
+= 2;
2093 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2094 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2096 jclass type
= field
->type
;
2098 if ((field
->flags
& Modifier::STATIC
) != 0)
2099 throw_incompatible_class_change_error
2100 (JvNewStringLatin1 ("field is static"));
2102 jint field_offset
= field
->u
.boffset
;
2103 if (field_offset
> 0xffff)
2104 JvThrow (new java::lang::VirtualMachineError
);
2106 if (type
->isPrimitive ())
2108 switch (type
->size_in_bytes
)
2112 jint value
= POPI();
2113 jobject obj
= POPA();
2115 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2121 jint value
= POPI();
2122 jobject obj
= POPA();
2124 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2130 jint value
= POPI();
2131 jobject obj
= POPA();
2133 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2139 jlong value
= POPL();
2140 jobject obj
= POPA();
2142 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2149 jobject value
= POPA();
2150 jobject obj
= POPA();
2152 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2160 int index
= get2u (pc
); pc
+= 2;
2162 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2164 sp
-= rmeth
->stack_item_count
;
2168 fun
= (void (*) (...))rmeth
->method
->ncode
;
2170 goto perform_invoke
;
2175 int index
= get2u (pc
); pc
+= 2;
2177 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2179 sp
-= rmeth
->stack_item_count
;
2181 _Jv_InitClass (rmeth
->klass
);
2182 fun
= (void (*) (...))rmeth
->method
->ncode
;
2184 goto perform_invoke
;
2186 insn_invokeinterface
:
2189 int index
= get2u (pc
); pc
+= 2;
2191 // invokeinterface has two unused bytes...
2194 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2196 sp
-= rmeth
->stack_item_count
;
2199 jobject rcv
= sp
[0].o
;
2201 fun
= (void (*) (...))
2202 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2203 rmeth
->method
->name
,
2204 rmeth
->method
->signature
);
2206 goto perform_invoke
;
2212 int index
= get2u (pc
); pc
+= 2;
2213 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2214 _Jv_InitClass (klass
);
2215 jobject res
= _Jv_AllocObject (klass
, klass
->size_in_bytes
);
2223 int atype
= get1u (pc
++);
2225 jobject result
= _Jv_NewArray (atype
, size
);
2233 int index
= get2u (pc
); pc
+= 2;
2234 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2236 _Jv_InitClass (klass
);
2237 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2245 __JArray
*arr
= (__JArray
*)POPA();
2246 PUSHI (arr
->length
);
2253 jobject value
= POPA();
2261 jobject value
= POPA();
2262 jint index
= get2u (pc
); pc
+= 2;
2263 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2265 if (value
!= NULL
&& ! to
->isInstance (value
))
2267 JvThrow (new java::lang::ClassCastException
2278 jobject value
= POPA();
2279 jint index
= get2u (pc
); pc
+= 2;
2280 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2281 PUSHI (to
->isInstance (value
));
2288 jobject value
= POPA();
2290 _Jv_MonitorEnter (value
);
2297 jobject value
= POPA();
2299 _Jv_MonitorExit (value
);
2305 unsigned char* base_pc
= pc
-1;
2306 jint offset
= get2s (pc
); pc
+= 2;
2307 jobject val
= POPA();
2309 pc
= base_pc
+offset
;
2315 unsigned char* base_pc
= pc
-1;
2316 jint offset
= get2s (pc
); pc
+= 2;
2317 jobject val
= POPA();
2319 pc
= base_pc
+offset
;
2326 jint the_mod_op
= get1u (pc
++);
2327 jint wide
= get2u (pc
); pc
+= 2;
2368 pc
= (unsigned char*) PEEKA (wide
);
2373 jint amount
= get2s (pc
); pc
+= 2;
2374 jint value
= PEEKI (wide
);
2375 POKEI (wide
, value
+amount
);
2380 throw_internal_error ("illegal bytecode modified by wide");
2385 insn_multianewarray
:
2388 int kind_index
= get2u (pc
); pc
+= 2;
2389 int dim
= get1u (pc
); pc
+= 1;
2392 = (_Jv_ResolvePoolEntry (defining_class
, kind_index
)).clazz
;
2393 _Jv_InitClass (type
);
2394 jint
*sizes
= (jint
*) alloca (sizeof (jint
)*dim
);
2396 for (int i
= dim
- 1; i
>= 0; i
--)
2401 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2409 unsigned char* base_pc
= pc
-1;
2410 int offset
= get4 (pc
); pc
+= 4;
2411 pc
= base_pc
+offset
;
2417 unsigned char* base_pc
= pc
-1;
2418 int offset
= get4 (pc
); pc
+= 4;
2420 pc
= base_pc
+offset
;
2427 throw_internal_error (char *msg
)
2429 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg
)));
2433 throw_incompatible_class_change_error (jstring msg
)
2435 JvThrow (new java::lang::IncompatibleClassChangeError (msg
));
2439 static java::lang::NullPointerException
*null_pointer_exc
;
2441 throw_null_pointer_exception ()
2443 if (null_pointer_exc
== NULL
)
2444 null_pointer_exc
= new java::lang::NullPointerException
;
2446 JvThrow (null_pointer_exc
);
2451 static java::lang::ArithmeticException
*arithmetic_exc
;
2453 throw_arithmetic_exception ()
2455 if (arithmetic_exc
== NULL
)
2456 arithmetic_exc
= new java::lang::ArithmeticException
2457 (JvNewStringLatin1 ("/ by zero"));
2459 JvThrow (arithmetic_exc
);
2464 #endif // INTERPRETER