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 extern "C" double __ieee754_fmod
__P((double,double));
54 static inline void dupx (_Jv_word
*sp
, int n
, int x
)
56 // first "slide" n+x elements n to the right
58 for (int i
= 0; i
< n
+x
; i
++)
60 sp
[(top
-i
)] = sp
[(top
-i
)-n
];
63 // next, copy the n top elements, n+x down
64 for (int i
= 0; i
< n
; i
++)
66 sp
[top
-(n
+x
)-i
] = sp
[top
-i
];
72 #define PUSHA(V) (sp++)->o = (V)
73 #define PUSHI(V) (sp++)->i = (V)
74 #define PUSHF(V) (sp++)->f = (V)
75 #if SIZEOF_VOID_P == 8
76 # define PUSHL(V) (sp->l = (V), sp += 2)
77 # define PUSHD(V) (sp->d = (V), sp += 2)
79 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
80 (sp++)->ia[0] = w2.ia[0]; \
81 (sp++)->ia[0] = w2.ia[1]; } while (0)
82 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
83 (sp++)->ia[0] = w2.ia[0]; \
84 (sp++)->ia[0] = w2.ia[1]; } while (0)
87 #define POPA() ((--sp)->o)
88 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
89 #define POPF() ((jfloat) (--sp)->f)
90 #if SIZEOF_VOID_P == 8
91 # define POPL() (sp -= 2, (jlong) sp->l)
92 # define POPD() (sp -= 2, (jdouble) sp->d)
94 # define POPL() ({ _Jv_word2 w2; \
95 w2.ia[1] = (--sp)->ia[0]; \
96 w2.ia[0] = (--sp)->ia[0]; w2.l; })
97 # define POPD() ({ _Jv_word2 w2; \
98 w2.ia[1] = (--sp)->ia[0]; \
99 w2.ia[0] = (--sp)->ia[0]; w2.d; })
102 #define LOADA(I) (sp++)->o = locals[I].o
103 #define LOADI(I) (sp++)->i = locals[I].i
104 #define LOADF(I) (sp++)->f = locals[I].f
105 #if SIZEOF_VOID_P == 8
106 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
107 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
109 # define LOADL(I) do { jint __idx = (I); \
110 (sp++)->ia[0] = locals[__idx].ia[0]; \
111 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
113 # define LOADD(I) LOADL(I)
116 #define STOREA(I) locals[I].o = (--sp)->o
117 #define STOREI(I) locals[I].i = (--sp)->i
118 #define STOREF(I) locals[I].f = (--sp)->f
119 #if SIZEOF_VOID_P == 8
120 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
121 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
123 # define STOREL(I) do { jint __idx = (I); \
124 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
125 locals[__idx].ia[0] = (--sp)->ia[0]; \
127 # define STORED(I) STOREL(I)
130 #define PEEKI(I) (locals+(I))->i
131 #define PEEKA(I) (locals+(I))->o
133 #define POKEI(I,V) ((locals+(I))->i = (V))
136 #define BINOPI(OP) { \
137 jint value2 = POPI(); \
138 jint value1 = POPI(); \
139 PUSHI(value1 OP value2); \
142 #define BINOPF(OP) { \
143 jfloat value2 = POPF(); \
144 jfloat value1 = POPF(); \
145 PUSHF(value1 OP value2); \
148 #define BINOPL(OP) { \
149 jlong value2 = POPL(); \
150 jlong value1 = POPL(); \
151 PUSHL(value1 OP value2); \
154 #define BINOPD(OP) { \
155 jdouble value2 = POPD(); \
156 jdouble value1 = POPD(); \
157 PUSHD(value1 OP value2); \
160 static inline jint
get1s(unsigned char* loc
) {
161 return *(signed char*)loc
;
164 static inline jint
get1u(unsigned char* loc
) {
168 static inline jint
get2s(unsigned char* loc
) {
169 return (((jint
)*(signed char*)loc
) << 8) | ((jint
)*(loc
+1));
172 static inline jint
get2u(unsigned char* loc
) {
173 return (((jint
)(*loc
)) << 8) | ((jint
)*(loc
+1));
176 static jint
get4(unsigned char* loc
) {
177 return (((jint
)(loc
[0])) << 24)
178 | (((jint
)(loc
[1])) << 16)
179 | (((jint
)(loc
[2])) << 8)
180 | (((jint
)(loc
[3])) << 0);
187 #define NULLCHECK(X) \
188 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
192 // this method starts the actual running of the method. It is inlined
193 // in three different variants in the static methods run_normal,
194 // run_sync_object and run_sync_class (see below). Those static methods
195 // are installed directly in the stub for this method (by
196 // _Jv_InterpMethod::ncode, in resolve.cc).
199 _Jv_InterpMethod::run (ffi_cif
* cif
,
202 _Jv_InterpMethodInvocation
*inv
)
205 inv
->pc
= bytecode ();
206 inv
->sp
= inv
->stack_base ();
207 _Jv_word
*locals
= inv
->local_base ();
209 /* Go straight at it! the ffi raw format matches the internal
210 stack representation exactly. At least, that's the idea.
212 memcpy ((void*) locals
, (void*) args
, args_raw_size
);
222 catch (java::lang::Throwable
*ex2
)
227 if (ex
== 0) // no exception...
229 /* define sp locally, so the POP? macros will pick it up */
230 _Jv_word
*sp
= inv
->sp
;
231 int rtype
= cif
->rtype
->type
;
233 if (rtype
== FFI_TYPE_POINTER
)
236 *(jobject
*) retp
= r
;
239 else if (rtype
== FFI_TYPE_SINT32
)
245 else if (rtype
== FFI_TYPE_VOID
)
258 case FFI_TYPE_DOUBLE
:
266 case FFI_TYPE_UINT16
:
267 case FFI_TYPE_UINT32
:
269 case FFI_TYPE_SINT16
:
276 case FFI_TYPE_SINT64
:
284 throw_internal_error ("unknown return type");
288 /** handle an exception */
289 if ( find_exception (ex
, inv
) )
295 bool _Jv_InterpMethod::find_exception (jobject ex
,
296 _Jv_InterpMethodInvocation
*inv
)
298 int logical_pc
= inv
->pc
- bytecode ();
299 _Jv_InterpException
*exc
= exceptions ();
300 jclass exc_class
= ex
->getClass ();
302 for (int i
= 0; i
< exc_count
; i
++)
304 if (exc
[i
].start_pc
<= logical_pc
&& logical_pc
< exc
[i
].end_pc
)
308 if (exc
[i
].handler_type
!= 0)
309 handler
= (_Jv_ResolvePoolEntry (defining_class
,
310 exc
[i
].handler_type
)).clazz
;
314 if (handler
==NULL
|| handler
->isAssignableFrom (exc_class
))
316 inv
->pc
= bytecode () + exc
[i
].handler_pc
;
317 inv
->sp
= inv
->stack_base (); // reset stack
318 (inv
->sp
++)->o
= ex
; // push exception
326 void _Jv_InterpMethod::run_normal (ffi_cif
* cif
,
331 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
333 // we do the alloca of the method invocation here, to allow the method
334 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
335 int storage_size
= _this
->max_stack
+_this
->max_locals
;
336 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
337 alloca (sizeof (_Jv_InterpMethodInvocation
)
338 + storage_size
* sizeof (_Jv_word
));
340 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
341 if (ex
!= 0) _Jv_Throw (ex
);
344 void _Jv_InterpMethod::run_synch_object (ffi_cif
* cif
,
349 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
350 jobject rcv
= (jobject
)args
[0].ptr
;
352 int storage_size
= _this
->max_stack
+_this
->max_locals
;
353 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
354 alloca (sizeof (_Jv_InterpMethodInvocation
)
355 + storage_size
* sizeof (_Jv_word
));
357 _Jv_MonitorEnter (rcv
);
358 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
359 _Jv_MonitorExit (rcv
);
361 if (ex
!= 0) _Jv_Throw (ex
);
364 void _Jv_InterpMethod::run_synch_class (ffi_cif
* cif
,
369 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
370 jclass sync
= _this
->defining_class
;
372 int storage_size
= _this
->max_stack
+_this
->max_locals
;
373 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
374 alloca (sizeof (_Jv_InterpMethodInvocation
)
375 + storage_size
* sizeof (_Jv_word
));
377 _Jv_MonitorEnter (sync
);
378 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
379 _Jv_MonitorExit (sync
);
381 if (ex
!= 0) _Jv_Throw (ex
);
385 This proceeds execution, as designated in "inv". If an exception
386 happens, then it is simply thrown, and handled in Java. Thus, the pc
387 needs to be stored in the inv->pc at all times, so we can figure
388 out which handler (if any) to invoke.
390 One design issue, which I have not completely considered, is if it
391 should be possible to have interpreted classes linked in! Seldom used
392 (or non-critical) classes could reasonably be interpreted.
396 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation
*inv
)
398 using namespace java::lang::reflect
;
400 _Jv_word
*sp
= inv
->sp
;
401 unsigned char *pc
= inv
->pc
;
402 _Jv_word
*locals
= inv
->local_base ();
404 _Jv_word
*pool_data
= defining_class
->constants
.data
;
406 /* these two are used in the invokeXXX instructions */
408 _Jv_ResolvedMethod
* rmeth
;
410 #define INSN_LABEL(op) &&insn_##op
411 #define GOTO_INSN(op) goto *(insn_target[op])
413 static const void *const insn_target
[] =
416 INSN_LABEL(aconst_null
),
417 INSN_LABEL(iconst_m1
),
418 INSN_LABEL(iconst_0
),
419 INSN_LABEL(iconst_1
),
420 INSN_LABEL(iconst_2
),
421 INSN_LABEL(iconst_3
),
422 INSN_LABEL(iconst_4
),
423 INSN_LABEL(iconst_5
),
424 INSN_LABEL(lconst_0
),
425 INSN_LABEL(lconst_1
),
426 INSN_LABEL(fconst_0
),
427 INSN_LABEL(fconst_1
),
428 INSN_LABEL(fconst_2
),
429 INSN_LABEL(dconst_0
),
430 INSN_LABEL(dconst_1
),
474 INSN_LABEL(istore_0
),
475 INSN_LABEL(istore_1
),
476 INSN_LABEL(istore_2
),
477 INSN_LABEL(istore_3
),
478 INSN_LABEL(lstore_0
),
479 INSN_LABEL(lstore_1
),
480 INSN_LABEL(lstore_2
),
481 INSN_LABEL(lstore_3
),
482 INSN_LABEL(fstore_0
),
483 INSN_LABEL(fstore_1
),
484 INSN_LABEL(fstore_2
),
485 INSN_LABEL(fstore_3
),
486 INSN_LABEL(dstore_0
),
487 INSN_LABEL(dstore_1
),
488 INSN_LABEL(dstore_2
),
489 INSN_LABEL(dstore_3
),
490 INSN_LABEL(astore_0
),
491 INSN_LABEL(astore_1
),
492 INSN_LABEL(astore_2
),
493 INSN_LABEL(astore_3
),
574 INSN_LABEL(if_icmpeq
),
575 INSN_LABEL(if_icmpne
),
576 INSN_LABEL(if_icmplt
),
577 INSN_LABEL(if_icmpge
),
578 INSN_LABEL(if_icmpgt
),
579 INSN_LABEL(if_icmple
),
580 INSN_LABEL(if_acmpeq
),
581 INSN_LABEL(if_acmpne
),
585 INSN_LABEL(tableswitch
),
586 INSN_LABEL(lookupswitch
),
593 INSN_LABEL(getstatic
),
594 INSN_LABEL(putstatic
),
595 INSN_LABEL(getfield
),
596 INSN_LABEL(putfield
),
597 INSN_LABEL(invokevirtual
),
598 INSN_LABEL(invokespecial
),
599 INSN_LABEL(invokestatic
),
600 INSN_LABEL(invokeinterface
),
601 0, /* op_xxxunusedxxx1, */
603 INSN_LABEL(newarray
),
604 INSN_LABEL(anewarray
),
605 INSN_LABEL(arraylength
),
607 INSN_LABEL(checkcast
),
608 INSN_LABEL(instanceof
),
609 INSN_LABEL(monitorenter
),
610 INSN_LABEL(monitorexit
),
612 INSN_LABEL(multianewarray
),
614 INSN_LABEL(ifnonnull
),
619 #define SAVE_PC inv->pc = pc-1
621 /* If the macro INLINE_SWITCH is not defined, then the main loop
622 operates as one big (normal) switch statement. If it is defined,
623 then the case selection is performed `inline' in the end of the
624 code for each case. The latter saves a native branch instruction
625 for each java-instruction, but expands the code size somewhat.
627 NOTE: On i386 defining INLINE_SWITCH improves over all
628 performance approximately seven percent, but it may be different
629 for other machines. At some point, this may be made into a proper
630 configuration parameter. */
632 #define INLINE_SWITCH
636 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
642 #define NEXT_INSN goto next_insn
649 /* The first few instructions here are ordered according to their
650 frequency, in the hope that this will improve code locality a
653 insn_aload_0
: // 0x2a
658 LOADI (get1u (pc
++));
661 insn_iload_1
: // 0x1b
665 insn_invokevirtual
: // 0xb6
668 int index
= get2u (pc
); pc
+= 2;
670 /* _Jv_ResolvePoolEntry returns immediately if the value already
671 * is resolved. If we want to clutter up the code here to gain
672 * a little performance, then we can check the corresponding bit
673 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
674 * don't think it is worth it. */
676 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
678 sp
-= rmeth
->stack_item_count
;
681 if (rmeth
->vtable_index
== -1)
683 // final methods do not appear in the vtable,
684 // if it does not appear in the superclass.
685 fun
= (void (*) (...)) rmeth
->method
->ncode
;
689 jobject rcv
= sp
[0].o
;
690 _Jv_VTable
*table
= *(_Jv_VTable
**)rcv
;
691 fun
= (void (*) (...))table
->method
[rmeth
->vtable_index
];
698 /* here goes the magic again... */
699 ffi_cif
*cif
= &rmeth
->cif
;
700 ffi_raw
*raw
= (ffi_raw
*) sp
;
704 #if FFI_NATIVE_RAW_API
705 /* We assume that this is only implemented if it's correct */
706 /* to use it here. On a 64 bit machine, it never is. */
707 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
709 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
712 int rtype
= cif
->rtype
->type
;
714 /* the likelyhood of object, int, or void return is very high,
715 * so those are checked before the switch */
716 if (rtype
== FFI_TYPE_POINTER
)
718 PUSHA (*(jobject
*)&rvalue
);
720 else if (rtype
== FFI_TYPE_SINT32
)
722 PUSHI (*(jint
*)&rvalue
);
724 else if (rtype
== FFI_TYPE_VOID
)
732 jbyte value
= (*(jint
*)&rvalue
) & 0xff;
737 case FFI_TYPE_SINT16
:
739 jshort value
= (*(jint
*)&rvalue
) & 0xffff;
744 case FFI_TYPE_UINT16
:
746 jint value
= (*(jint
*)&rvalue
) & 0xffff;
752 PUSHF (*(jfloat
*)&rvalue
);
755 case FFI_TYPE_DOUBLE
:
759 case FFI_TYPE_SINT64
:
760 PUSHL (*(jlong
*)&rvalue
);
764 throw_internal_error ("unknown return type in invokeXXX");
839 PUSHI (get2s(pc
)); pc
+= 2;
844 int index
= get1u (pc
++);
845 PUSHA(pool_data
[index
].o
);
851 int index
= get2u (pc
); pc
+= 2;
852 PUSHA(pool_data
[index
].o
);
858 int index
= get2u (pc
); pc
+= 2;
859 memcpy (sp
, &pool_data
[index
], 2*sizeof (_Jv_word
));
865 LOADL (get1u (pc
++));
869 LOADF (get1u (pc
++));
873 LOADD (get1u (pc
++));
877 LOADA (get1u (pc
++));
956 jintArray arr
= (jintArray
) POPA();
958 if (index
< 0 || index
>= arr
->length
)
960 _Jv_ThrowBadArrayIndex (index
);
962 PUSHI( elements(arr
)[index
] );
970 jlongArray arr
= (jlongArray
) POPA();
972 if (index
< 0 || index
>= arr
->length
)
974 _Jv_ThrowBadArrayIndex (index
);
976 PUSHL( elements(arr
)[index
] );
984 jfloatArray arr
= (jfloatArray
) POPA();
986 if (index
< 0 || index
>= arr
->length
)
988 _Jv_ThrowBadArrayIndex (index
);
990 PUSHF( elements(arr
)[index
] );
998 jdoubleArray arr
= (jdoubleArray
) POPA();
1000 if (index
< 0 || index
>= arr
->length
)
1002 _Jv_ThrowBadArrayIndex (index
);
1004 PUSHD( elements(arr
)[index
] );
1011 jint index
= POPI();
1012 jobjectArray arr
= (jobjectArray
) POPA();
1014 if (index
< 0 || index
>= arr
->length
)
1016 _Jv_ThrowBadArrayIndex (index
);
1018 PUSHA( elements(arr
)[index
] );
1025 jint index
= POPI();
1026 jbyteArray arr
= (jbyteArray
) POPA();
1028 if (index
< 0 || index
>= arr
->length
)
1030 _Jv_ThrowBadArrayIndex (index
);
1032 PUSHI( elements(arr
)[index
] );
1039 jint index
= POPI();
1040 jcharArray arr
= (jcharArray
) POPA();
1042 if (index
< 0 || index
>= arr
->length
)
1044 _Jv_ThrowBadArrayIndex (index
);
1046 PUSHI( elements(arr
)[index
] );
1053 jint index
= POPI();
1054 jshortArray arr
= (jshortArray
) POPA();
1056 if (index
< 0 || index
>= arr
->length
)
1058 _Jv_ThrowBadArrayIndex (index
);
1060 PUSHI( elements(arr
)[index
] );
1065 STOREI (get1u (pc
++));
1069 STOREL (get1u (pc
++));
1073 STOREF (get1u (pc
++));
1077 STORED (get1u (pc
++));
1081 STOREA (get1u (pc
++));
1167 jint value
= POPI();
1168 jint index
= POPI();
1169 jintArray arr
= (jintArray
) POPA();
1171 if (index
< 0 || index
>= arr
->length
)
1173 _Jv_ThrowBadArrayIndex (index
);
1175 elements(arr
)[index
] = value
;
1182 jlong value
= POPL();
1183 jint index
= POPI();
1184 jlongArray arr
= (jlongArray
) POPA();
1186 if (index
< 0 || index
>= arr
->length
)
1188 _Jv_ThrowBadArrayIndex (index
);
1190 elements(arr
)[index
] = value
;
1197 jfloat value
= POPF();
1198 jint index
= POPI();
1199 jfloatArray arr
= (jfloatArray
) POPA();
1201 if (index
< 0 || index
>= arr
->length
)
1203 _Jv_ThrowBadArrayIndex (index
);
1205 elements(arr
)[index
] = value
;
1212 jdouble value
= POPD();
1213 jint index
= POPI();
1214 jdoubleArray arr
= (jdoubleArray
) POPA();
1216 if (index
< 0 || index
>= arr
->length
)
1218 _Jv_ThrowBadArrayIndex (index
);
1220 elements(arr
)[index
] = value
;
1227 jobject value
= POPA();
1228 jint index
= POPI();
1229 jobjectArray arr
= (jobjectArray
) POPA();
1231 if (index
< 0 || index
>= arr
->length
)
1233 _Jv_ThrowBadArrayIndex (index
);
1235 _Jv_CheckArrayStore (arr
, value
);
1236 elements(arr
)[index
] = value
;
1243 jbyte value
= (jbyte
) POPI();
1244 jint index
= POPI();
1245 jbyteArray arr
= (jbyteArray
) POPA();
1247 if (index
< 0 || index
>= arr
->length
)
1249 _Jv_ThrowBadArrayIndex (index
);
1251 elements(arr
)[index
] = value
;
1258 jchar value
= (jchar
) POPI();
1259 jint index
= POPI();
1260 jcharArray arr
= (jcharArray
) POPA();
1262 if (index
< 0 || index
>= arr
->length
)
1264 _Jv_ThrowBadArrayIndex (index
);
1266 elements(arr
)[index
] = value
;
1273 jshort value
= (jshort
) POPI();
1274 jint index
= POPI();
1275 jshortArray arr
= (jshortArray
) POPA();
1277 if (index
< 0 || index
>= arr
->length
)
1279 _Jv_ThrowBadArrayIndex (index
);
1281 elements(arr
)[index
] = value
;
1299 dupx (sp
, 1, 1); sp
+=1;
1303 dupx (sp
, 1, 2); sp
+=1;
1313 dupx (sp
, 2, 1); sp
+=2;
1317 dupx (sp
, 2, 2); sp
+=2;
1322 jobject tmp1
= POPA();
1323 jobject tmp2
= POPA();
1380 jint value2
= POPI();
1381 jint value1
= POPI();
1382 jint res
= _Jv_divI (value1
, value2
);
1390 jlong value2
= POPL();
1391 jlong value1
= POPL();
1392 jlong res
= _Jv_divJ (value1
, value2
);
1400 jfloat value2
= POPF();
1401 jfloat value1
= POPF();
1402 jfloat res
= value1
/ value2
;
1410 jdouble value2
= POPD();
1411 jdouble value1
= POPD();
1412 jdouble res
= value1
/ value2
;
1420 jint value2
= POPI();
1421 jint value1
= POPI();
1422 jint res
= _Jv_remI (value1
, value2
);
1430 jlong value2
= POPL();
1431 jlong value1
= POPL();
1432 jlong res
= _Jv_remJ (value1
, value2
);
1440 jfloat value2
= POPF();
1441 jfloat value1
= POPF();
1442 jfloat res
= __ieee754_fmod (value1
, value2
);
1450 jdouble value2
= POPD();
1451 jdouble value1
= POPD();
1452 jdouble res
= __ieee754_fmod (value1
, value2
);
1459 jint value
= POPI();
1466 jlong value
= POPL();
1473 jfloat value
= POPF();
1480 jdouble value
= POPD();
1487 jint shift
= (POPI() & 0x1f);
1488 jint value
= POPI();
1489 PUSHI (value
<< shift
);
1495 jint shift
= (POPI() & 0x3f);
1496 jlong value
= POPL();
1497 PUSHL (value
<< shift
);
1503 jint shift
= (POPI() & 0x1f);
1504 jint value
= POPI();
1505 PUSHI (value
>> shift
);
1511 jint shift
= (POPI() & 0x3f);
1512 jlong value
= POPL();
1513 PUSHL (value
>> shift
);
1519 jint shift
= (POPI() & 0x1f);
1520 unsigned long value
= POPI();
1521 PUSHI ((jint
) (value
>> shift
));
1527 jint shift
= (POPI() & 0x3f);
1528 UINT64 value
= (UINT64
) POPL();
1529 PUSHL ((value
>> shift
));
1559 jint index
= get1u (pc
++);
1560 jint amount
= get1s (pc
++);
1561 locals
[index
].i
+= amount
;
1566 {jlong value
= POPI(); PUSHL (value
);}
1570 {jfloat value
= POPI(); PUSHF (value
);}
1574 {jdouble value
= POPI(); PUSHD (value
);}
1578 {jint value
= POPL(); PUSHI (value
);}
1582 {jfloat value
= POPL(); PUSHF (value
);}
1586 {jdouble value
= POPL(); PUSHD (value
);}
1590 { jint value
= (jint
)POPF (); PUSHI(value
); }
1594 { jlong value
= (jlong
)POPF (); PUSHL(value
); }
1598 { jdouble value
= POPF (); PUSHD(value
); }
1602 { jint value
= (jint
)POPD (); PUSHI(value
); }
1606 { jlong value
= (jlong
)POPD (); PUSHL(value
); }
1610 { jfloat value
= POPD (); PUSHF(value
); }
1614 { jbyte value
= POPI (); PUSHI(value
); }
1618 { jchar value
= POPI (); PUSHI(value
); }
1622 { jshort value
= POPI (); PUSHI(value
); }
1627 jlong value2
= POPL ();
1628 jlong value1
= POPL ();
1629 if (value1
> value2
)
1631 else if (value1
== value2
)
1641 jfloat value2
= POPF ();
1642 jfloat value1
= POPF ();
1643 if (value1
> value2
)
1645 else if (value1
== value2
)
1647 else if (value1
< value2
)
1649 else if ((*(pc
-1)) == op_fcmpg
)
1659 jdouble value2
= POPD ();
1660 jdouble value1
= POPD ();
1661 if (value1
> value2
)
1663 else if (value1
== value2
)
1665 else if (value1
< value2
)
1667 else if ((*(pc
-1)) == op_dcmpg
)
1676 jint offset
= get2s (pc
);
1686 jint offset
= get2s (pc
);
1696 jint offset
= get2s (pc
);
1706 jint offset
= get2s (pc
);
1716 jint offset
= get2s (pc
);
1726 jint offset
= get2s (pc
);
1736 jint offset
= get2s (pc
);
1737 jint value2
= POPI();
1738 jint value1
= POPI();
1739 if (value1
== value2
)
1748 jint offset
= get2s (pc
);
1749 jint value2
= POPI();
1750 jint value1
= POPI();
1751 if (value1
!= value2
)
1760 jint offset
= get2s (pc
);
1761 jint value2
= POPI();
1762 jint value1
= POPI();
1763 if (value1
< value2
)
1772 jint offset
= get2s (pc
);
1773 jint value2
= POPI();
1774 jint value1
= POPI();
1775 if (value1
>= value2
)
1784 jint offset
= get2s (pc
);
1785 jint value2
= POPI();
1786 jint value1
= POPI();
1787 if (value1
> value2
)
1796 jint offset
= get2s (pc
);
1797 jint value2
= POPI();
1798 jint value1
= POPI();
1799 if (value1
<= value2
)
1808 jint offset
= get2s (pc
);
1809 jobject value2
= POPA();
1810 jobject value1
= POPA();
1811 if (value1
== value2
)
1820 jint offset
= get2s (pc
);
1821 jobject value2
= POPA();
1822 jobject value1
= POPA();
1823 if (value1
!= value2
)
1832 jint offset
= get2s (pc
);
1839 unsigned char *base_pc
= pc
-1;
1840 jint offset
= get2s (pc
); pc
+= 2;
1841 PUSHA ((jobject
)pc
);
1842 pc
= base_pc
+offset
;
1848 jint index
= get1u (pc
);
1849 pc
= (unsigned char*) PEEKA (index
);
1855 unsigned char *base_pc
= pc
-1;
1858 unsigned char* base
= bytecode ();
1859 while ((pc
-base
) % 4 != 0)
1862 jint def
= get4 (pc
);
1863 jint low
= get4 (pc
+4);
1864 jint high
= get4 (pc
+8);
1866 if (index
< low
|| index
> high
)
1869 pc
= base_pc
+ get4 (pc
+4*(index
-low
+3));
1875 unsigned char *base_pc
= pc
-1;
1878 unsigned char* base
= bytecode ();
1879 while ((pc
-base
) % 4 != 0)
1882 jint def
= get4 (pc
);
1883 jint npairs
= get4 (pc
+4);
1888 // simple binary search...
1891 int half
= (min
+max
)/2;
1892 int match
= get4 (pc
+ 4*(2 + 2*half
));
1897 else if (index
< match
)
1904 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1905 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1911 /* on return, just save the sp and return to caller */
1924 jint fieldref_index
= get2u (pc
); pc
+= 2;
1925 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1926 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1928 if ((field
->flags
& Modifier::STATIC
) == 0)
1929 throw_incompatible_class_change_error
1930 (JvNewStringLatin1 ("field no longer static"));
1932 jclass type
= field
->type
;
1934 if (type
->isPrimitive ())
1936 switch (type
->size_in_bytes
)
1939 PUSHI (*(jbyte
*) (field
->u
.addr
));
1942 if (type
== JvPrimClass (char))
1943 PUSHI(*(jchar
*) (field
->u
.addr
));
1945 PUSHI(*(jshort
*) (field
->u
.addr
));
1949 PUSHI(*(jint
*) (field
->u
.addr
));
1953 PUSHL(*(jlong
*) (field
->u
.addr
));
1959 PUSHA(*(jobject
*) (field
->u
.addr
));
1967 jint fieldref_index
= get2u (pc
); pc
+= 2;
1968 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1969 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1971 if ((field
->flags
& Modifier::STATIC
) != 0)
1972 throw_incompatible_class_change_error
1973 (JvNewStringLatin1 ("field is static"));
1975 jclass type
= field
->type
;
1976 jint field_offset
= field
->u
.boffset
;
1977 if (field_offset
> 0xffff)
1978 JvThrow (new java::lang::VirtualMachineError
);
1980 jobject obj
= POPA();
1983 if (type
->isPrimitive ())
1985 switch (type
->size_in_bytes
)
1988 PUSHI (*(jbyte
*) ((char*)obj
+ field_offset
));
1992 if (type
== JvPrimClass (char))
1993 PUSHI (*(jchar
*) ((char*)obj
+ field_offset
));
1995 PUSHI (*(jshort
*) ((char*)obj
+ field_offset
));
1999 PUSHI (*(jint
*) ((char*)obj
+ field_offset
));
2003 PUSHL(*(jlong
*) ((char*)obj
+ field_offset
));
2009 PUSHA(*(jobject
*) ((char*)obj
+ field_offset
));
2017 jint fieldref_index
= get2u (pc
); pc
+= 2;
2018 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2019 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2021 jclass type
= field
->type
;
2023 // ResolvePoolEntry cannot check this
2024 if ((field
->flags
& Modifier::STATIC
) == 0)
2025 throw_incompatible_class_change_error
2026 (JvNewStringLatin1 ("field no longer static"));
2028 if (type
->isPrimitive ())
2030 switch (type
->size_in_bytes
)
2034 jint value
= POPI();
2035 *(jbyte
*) (field
->u
.addr
) = value
;
2041 jint value
= POPI();
2042 *(jchar
*) (field
->u
.addr
) = value
;
2048 jint value
= POPI();
2049 *(jint
*) (field
->u
.addr
) = value
;
2055 jlong value
= POPL();
2056 *(jlong
*) (field
->u
.addr
) = value
;
2063 jobject value
= POPA();
2064 *(jobject
*) (field
->u
.addr
) = value
;
2073 jint fieldref_index
= get2u (pc
); pc
+= 2;
2074 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2075 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2077 jclass type
= field
->type
;
2079 if ((field
->flags
& Modifier::STATIC
) != 0)
2080 throw_incompatible_class_change_error
2081 (JvNewStringLatin1 ("field is static"));
2083 jint field_offset
= field
->u
.boffset
;
2084 if (field_offset
> 0xffff)
2085 JvThrow (new java::lang::VirtualMachineError
);
2087 if (type
->isPrimitive ())
2089 switch (type
->size_in_bytes
)
2093 jint value
= POPI();
2094 jobject obj
= POPA();
2096 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2102 jint value
= POPI();
2103 jobject obj
= POPA();
2105 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2111 jint value
= POPI();
2112 jobject obj
= POPA();
2114 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2120 jlong value
= POPL();
2121 jobject obj
= POPA();
2123 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2130 jobject value
= POPA();
2131 jobject obj
= POPA();
2133 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2141 int index
= get2u (pc
); pc
+= 2;
2143 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2145 sp
-= rmeth
->stack_item_count
;
2149 fun
= (void (*) (...))rmeth
->method
->ncode
;
2151 goto perform_invoke
;
2156 int index
= get2u (pc
); pc
+= 2;
2158 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2160 sp
-= rmeth
->stack_item_count
;
2162 _Jv_InitClass (rmeth
->klass
);
2163 fun
= (void (*) (...))rmeth
->method
->ncode
;
2165 goto perform_invoke
;
2167 insn_invokeinterface
:
2170 int index
= get2u (pc
); pc
+= 2;
2172 // invokeinterface has two unused bytes...
2175 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2177 sp
-= rmeth
->stack_item_count
;
2180 jobject rcv
= sp
[0].o
;
2182 fun
= (void (*) (...))
2183 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2184 rmeth
->method
->name
,
2185 rmeth
->method
->signature
);
2187 goto perform_invoke
;
2193 int index
= get2u (pc
); pc
+= 2;
2194 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2195 _Jv_InitClass (klass
);
2196 jobject res
= _Jv_AllocObject (klass
, klass
->size_in_bytes
);
2204 int atype
= get1u (pc
++);
2206 jobject result
= _Jv_NewArray (atype
, size
);
2214 int index
= get2u (pc
); pc
+= 2;
2215 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2217 _Jv_InitClass (klass
);
2218 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2226 __JArray
*arr
= (__JArray
*)POPA();
2227 PUSHI (arr
->length
);
2234 jobject value
= POPA();
2242 jobject value
= POPA();
2243 jint index
= get2u (pc
); pc
+= 2;
2244 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2246 if (value
!= NULL
&& ! to
->isInstance (value
))
2248 JvThrow (new java::lang::ClassCastException
2259 jobject value
= POPA();
2260 jint index
= get2u (pc
); pc
+= 2;
2261 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2262 PUSHI (to
->isInstance (value
));
2269 jobject value
= POPA();
2271 _Jv_MonitorEnter (value
);
2278 jobject value
= POPA();
2280 _Jv_MonitorExit (value
);
2286 unsigned char* base_pc
= pc
-1;
2287 jint offset
= get2s (pc
); pc
+= 2;
2288 jobject val
= POPA();
2290 pc
= base_pc
+offset
;
2296 unsigned char* base_pc
= pc
-1;
2297 jint offset
= get2s (pc
); pc
+= 2;
2298 jobject val
= POPA();
2300 pc
= base_pc
+offset
;
2307 jint the_mod_op
= get1u (pc
++);
2308 jint wide
= get2u (pc
); pc
+= 2;
2349 pc
= (unsigned char*) PEEKA (wide
);
2354 jint amount
= get2s (pc
); pc
+= 2;
2355 jint value
= PEEKI (wide
);
2356 POKEI (wide
, value
+amount
);
2361 throw_internal_error ("illegal bytecode modified by wide");
2366 insn_multianewarray
:
2369 int kind_index
= get2u (pc
); pc
+= 2;
2370 int dim
= get1u (pc
); pc
+= 1;
2373 = (_Jv_ResolvePoolEntry (defining_class
, kind_index
)).clazz
;
2374 _Jv_InitClass (type
);
2375 jint
*sizes
= (jint
*) alloca (sizeof (jint
)*dim
);
2377 for (int i
= dim
- 1; i
>= 0; i
--)
2382 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2390 unsigned char* base_pc
= pc
-1;
2391 int offset
= get4 (pc
); pc
+= 4;
2392 pc
= base_pc
+offset
;
2398 unsigned char* base_pc
= pc
-1;
2399 int offset
= get4 (pc
); pc
+= 4;
2401 pc
= base_pc
+offset
;
2408 throw_internal_error (char *msg
)
2410 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg
)));
2414 throw_incompatible_class_change_error (jstring msg
)
2416 JvThrow (new java::lang::IncompatibleClassChangeError (msg
));
2420 static java::lang::NullPointerException
*null_pointer_exc
;
2422 throw_null_pointer_exception ()
2424 if (null_pointer_exc
== NULL
)
2425 null_pointer_exc
= new java::lang::NullPointerException
;
2427 JvThrow (null_pointer_exc
);
2431 #endif // INTERPRETER