1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001 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>
40 static _Jv_Utf8Const
*init_name
= _Jv_makeUtf8Const ("<init>", 6);
42 static void throw_internal_error (char *msg
)
43 __attribute__ ((__noreturn__
));
44 static void throw_incompatible_class_change_error (jstring msg
)
45 __attribute__ ((__noreturn__
));
47 static void throw_null_pointer_exception ()
48 __attribute__ ((__noreturn__
));
51 extern "C" double __ieee754_fmod (double,double);
53 static inline void dupx (_Jv_word
*sp
, int n
, int x
)
55 // first "slide" n+x elements n to the right
57 for (int i
= 0; i
< n
+x
; i
++)
59 sp
[(top
-i
)] = sp
[(top
-i
)-n
];
62 // next, copy the n top elements, n+x down
63 for (int i
= 0; i
< n
; i
++)
65 sp
[top
-(n
+x
)-i
] = sp
[top
-i
];
71 #define PUSHA(V) (sp++)->o = (V)
72 #define PUSHI(V) (sp++)->i = (V)
73 #define PUSHF(V) (sp++)->f = (V)
74 #if SIZEOF_VOID_P == 8
75 # define PUSHL(V) (sp->l = (V), sp += 2)
76 # define PUSHD(V) (sp->d = (V), sp += 2)
78 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
79 (sp++)->ia[0] = w2.ia[0]; \
80 (sp++)->ia[0] = w2.ia[1]; } while (0)
81 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
82 (sp++)->ia[0] = w2.ia[0]; \
83 (sp++)->ia[0] = w2.ia[1]; } while (0)
86 #define POPA() ((--sp)->o)
87 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
88 #define POPF() ((jfloat) (--sp)->f)
89 #if SIZEOF_VOID_P == 8
90 # define POPL() (sp -= 2, (jlong) sp->l)
91 # define POPD() (sp -= 2, (jdouble) sp->d)
93 # define POPL() ({ _Jv_word2 w2; \
94 w2.ia[1] = (--sp)->ia[0]; \
95 w2.ia[0] = (--sp)->ia[0]; w2.l; })
96 # define POPD() ({ _Jv_word2 w2; \
97 w2.ia[1] = (--sp)->ia[0]; \
98 w2.ia[0] = (--sp)->ia[0]; w2.d; })
101 #define LOADA(I) (sp++)->o = locals[I].o
102 #define LOADI(I) (sp++)->i = locals[I].i
103 #define LOADF(I) (sp++)->f = locals[I].f
104 #if SIZEOF_VOID_P == 8
105 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
106 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
108 # define LOADL(I) do { jint __idx = (I); \
109 (sp++)->ia[0] = locals[__idx].ia[0]; \
110 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
112 # define LOADD(I) LOADL(I)
115 #define STOREA(I) locals[I].o = (--sp)->o
116 #define STOREI(I) locals[I].i = (--sp)->i
117 #define STOREF(I) locals[I].f = (--sp)->f
118 #if SIZEOF_VOID_P == 8
119 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
120 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
122 # define STOREL(I) do { jint __idx = (I); \
123 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
124 locals[__idx].ia[0] = (--sp)->ia[0]; \
126 # define STORED(I) STOREL(I)
129 #define PEEKI(I) (locals+(I))->i
130 #define PEEKA(I) (locals+(I))->o
132 #define POKEI(I,V) ((locals+(I))->i = (V))
135 #define BINOPI(OP) { \
136 jint value2 = POPI(); \
137 jint value1 = POPI(); \
138 PUSHI(value1 OP value2); \
141 #define BINOPF(OP) { \
142 jfloat value2 = POPF(); \
143 jfloat value1 = POPF(); \
144 PUSHF(value1 OP value2); \
147 #define BINOPL(OP) { \
148 jlong value2 = POPL(); \
149 jlong value1 = POPL(); \
150 PUSHL(value1 OP value2); \
153 #define BINOPD(OP) { \
154 jdouble value2 = POPD(); \
155 jdouble value1 = POPD(); \
156 PUSHD(value1 OP value2); \
159 static inline jint
get1s(unsigned char* loc
) {
160 return *(signed char*)loc
;
163 static inline jint
get1u(unsigned char* loc
) {
167 static inline jint
get2s(unsigned char* loc
) {
168 return (((jint
)*(signed char*)loc
) << 8) | ((jint
)*(loc
+1));
171 static inline jint
get2u(unsigned char* loc
) {
172 return (((jint
)(*loc
)) << 8) | ((jint
)*(loc
+1));
175 static jint
get4(unsigned char* loc
) {
176 return (((jint
)(loc
[0])) << 24)
177 | (((jint
)(loc
[1])) << 16)
178 | (((jint
)(loc
[2])) << 8)
179 | (((jint
)(loc
[3])) << 0);
186 #define NULLCHECK(X) \
187 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
191 // this method starts the actual running of the method. It is inlined
192 // in three different variants in the static methods run_normal,
193 // run_sync_object and run_sync_class (see below). Those static methods
194 // are installed directly in the stub for this method (by
195 // _Jv_InterpMethod::ncode, in resolve.cc).
198 _Jv_InterpMethod::run (ffi_cif
* cif
,
201 _Jv_InterpMethodInvocation
*inv
)
204 inv
->pc
= bytecode ();
205 inv
->sp
= inv
->stack_base ();
206 _Jv_word
*locals
= inv
->local_base ();
208 /* Go straight at it! the ffi raw format matches the internal
209 stack representation exactly. At least, that's the idea.
211 memcpy ((void*) locals
, (void*) args
, args_raw_size
);
221 catch (java::lang::Throwable
*ex2
)
226 if (ex
== 0) // no exception...
228 /* define sp locally, so the POP? macros will pick it up */
229 _Jv_word
*sp
= inv
->sp
;
230 int rtype
= cif
->rtype
->type
;
232 if (rtype
== FFI_TYPE_POINTER
)
235 *(jobject
*) retp
= r
;
238 else if (rtype
== FFI_TYPE_SINT32
)
244 else if (rtype
== FFI_TYPE_VOID
)
257 case FFI_TYPE_DOUBLE
:
265 case FFI_TYPE_UINT16
:
266 case FFI_TYPE_UINT32
:
268 case FFI_TYPE_SINT16
:
275 case FFI_TYPE_SINT64
:
283 throw_internal_error ("unknown return type");
287 /** handle an exception */
288 if ( find_exception (ex
, inv
) )
294 bool _Jv_InterpMethod::find_exception (jobject ex
,
295 _Jv_InterpMethodInvocation
*inv
)
297 int logical_pc
= inv
->pc
- bytecode ();
298 _Jv_InterpException
*exc
= exceptions ();
299 jclass exc_class
= ex
->getClass ();
301 for (int i
= 0; i
< exc_count
; i
++)
303 if (exc
[i
].start_pc
<= logical_pc
&& logical_pc
< exc
[i
].end_pc
)
307 if (exc
[i
].handler_type
!= 0)
308 handler
= (_Jv_ResolvePoolEntry (defining_class
,
309 exc
[i
].handler_type
)).clazz
;
313 if (handler
==NULL
|| handler
->isAssignableFrom (exc_class
))
315 inv
->pc
= bytecode () + exc
[i
].handler_pc
;
316 inv
->sp
= inv
->stack_base (); // reset stack
317 (inv
->sp
++)->o
= ex
; // push exception
325 void _Jv_InterpMethod::run_normal (ffi_cif
* cif
,
330 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
332 // we do the alloca of the method invocation here, to allow the method
333 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
334 int storage_size
= _this
->max_stack
+_this
->max_locals
;
335 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
336 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation
)
337 + storage_size
* sizeof (_Jv_word
));
339 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
340 if (ex
!= 0) throw static_cast<jthrowable
>(ex
);
343 void _Jv_InterpMethod::run_synch_object (ffi_cif
* cif
,
348 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
349 jobject rcv
= (jobject
)args
[0].ptr
;
351 int storage_size
= _this
->max_stack
+_this
->max_locals
;
352 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
353 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation
)
354 + storage_size
* sizeof (_Jv_word
));
356 _Jv_MonitorEnter (rcv
);
357 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
358 _Jv_MonitorExit (rcv
);
360 if (ex
!= 0) throw static_cast<jthrowable
>(ex
);
363 void _Jv_InterpMethod::run_synch_class (ffi_cif
* cif
,
368 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
369 jclass sync
= _this
->defining_class
;
371 int storage_size
= _this
->max_stack
+_this
->max_locals
;
372 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
373 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation
)
374 + storage_size
* sizeof (_Jv_word
));
376 _Jv_MonitorEnter (sync
);
377 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
378 _Jv_MonitorExit (sync
);
380 if (ex
!= 0) throw static_cast<jthrowable
>(ex
);
384 This proceeds execution, as designated in "inv". If an exception
385 happens, then it is simply thrown, and handled in Java. Thus, the pc
386 needs to be stored in the inv->pc at all times, so we can figure
387 out which handler (if any) to invoke.
389 One design issue, which I have not completely considered, is if it
390 should be possible to have interpreted classes linked in! Seldom used
391 (or non-critical) classes could reasonably be interpreted.
395 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation
*inv
)
397 using namespace java::lang::reflect
;
399 _Jv_word
*sp
= inv
->sp
;
400 unsigned char *pc
= inv
->pc
;
401 _Jv_word
*locals
= inv
->local_base ();
403 _Jv_word
*pool_data
= defining_class
->constants
.data
;
405 /* these two are used in the invokeXXX instructions */
407 _Jv_ResolvedMethod
* rmeth
;
409 #define INSN_LABEL(op) &&insn_##op
410 #define GOTO_INSN(op) goto *(insn_target[op])
412 static const void *const insn_target
[] =
415 INSN_LABEL(aconst_null
),
416 INSN_LABEL(iconst_m1
),
417 INSN_LABEL(iconst_0
),
418 INSN_LABEL(iconst_1
),
419 INSN_LABEL(iconst_2
),
420 INSN_LABEL(iconst_3
),
421 INSN_LABEL(iconst_4
),
422 INSN_LABEL(iconst_5
),
423 INSN_LABEL(lconst_0
),
424 INSN_LABEL(lconst_1
),
425 INSN_LABEL(fconst_0
),
426 INSN_LABEL(fconst_1
),
427 INSN_LABEL(fconst_2
),
428 INSN_LABEL(dconst_0
),
429 INSN_LABEL(dconst_1
),
473 INSN_LABEL(istore_0
),
474 INSN_LABEL(istore_1
),
475 INSN_LABEL(istore_2
),
476 INSN_LABEL(istore_3
),
477 INSN_LABEL(lstore_0
),
478 INSN_LABEL(lstore_1
),
479 INSN_LABEL(lstore_2
),
480 INSN_LABEL(lstore_3
),
481 INSN_LABEL(fstore_0
),
482 INSN_LABEL(fstore_1
),
483 INSN_LABEL(fstore_2
),
484 INSN_LABEL(fstore_3
),
485 INSN_LABEL(dstore_0
),
486 INSN_LABEL(dstore_1
),
487 INSN_LABEL(dstore_2
),
488 INSN_LABEL(dstore_3
),
489 INSN_LABEL(astore_0
),
490 INSN_LABEL(astore_1
),
491 INSN_LABEL(astore_2
),
492 INSN_LABEL(astore_3
),
573 INSN_LABEL(if_icmpeq
),
574 INSN_LABEL(if_icmpne
),
575 INSN_LABEL(if_icmplt
),
576 INSN_LABEL(if_icmpge
),
577 INSN_LABEL(if_icmpgt
),
578 INSN_LABEL(if_icmple
),
579 INSN_LABEL(if_acmpeq
),
580 INSN_LABEL(if_acmpne
),
584 INSN_LABEL(tableswitch
),
585 INSN_LABEL(lookupswitch
),
592 INSN_LABEL(getstatic
),
593 INSN_LABEL(putstatic
),
594 INSN_LABEL(getfield
),
595 INSN_LABEL(putfield
),
596 INSN_LABEL(invokevirtual
),
597 INSN_LABEL(invokespecial
),
598 INSN_LABEL(invokestatic
),
599 INSN_LABEL(invokeinterface
),
600 0, /* op_xxxunusedxxx1, */
602 INSN_LABEL(newarray
),
603 INSN_LABEL(anewarray
),
604 INSN_LABEL(arraylength
),
606 INSN_LABEL(checkcast
),
607 INSN_LABEL(instanceof
),
608 INSN_LABEL(monitorenter
),
609 INSN_LABEL(monitorexit
),
611 INSN_LABEL(multianewarray
),
613 INSN_LABEL(ifnonnull
),
618 #define SAVE_PC inv->pc = pc-1
620 /* If the macro INLINE_SWITCH is not defined, then the main loop
621 operates as one big (normal) switch statement. If it is defined,
622 then the case selection is performed `inline' in the end of the
623 code for each case. The latter saves a native branch instruction
624 for each java-instruction, but expands the code size somewhat.
626 NOTE: On i386 defining INLINE_SWITCH improves over all
627 performance approximately seven percent, but it may be different
628 for other machines. At some point, this may be made into a proper
629 configuration parameter. */
631 #define INLINE_SWITCH
635 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
641 #define NEXT_INSN goto next_insn
648 /* The first few instructions here are ordered according to their
649 frequency, in the hope that this will improve code locality a
652 insn_aload_0
: // 0x2a
657 LOADI (get1u (pc
++));
660 insn_iload_1
: // 0x1b
664 insn_invokevirtual
: // 0xb6
667 int index
= get2u (pc
); pc
+= 2;
669 /* _Jv_ResolvePoolEntry returns immediately if the value already
670 * is resolved. If we want to clutter up the code here to gain
671 * a little performance, then we can check the corresponding bit
672 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
673 * don't think it is worth it. */
675 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
677 sp
-= rmeth
->stack_item_count
;
678 // We don't use NULLCHECK here because we can't rely on that
679 // working if the method is final. So instead we do an
682 throw new java::lang::NullPointerException
;
684 if (rmeth
->vtable_index
== -1)
686 // final methods do not appear in the vtable,
687 // if it does not appear in the superclass.
688 fun
= (void (*)()) rmeth
->method
->ncode
;
692 jobject rcv
= sp
[0].o
;
693 _Jv_VTable
*table
= *(_Jv_VTable
**)rcv
;
694 fun
= (void (*)()) table
->method
[rmeth
->vtable_index
];
701 /* here goes the magic again... */
702 ffi_cif
*cif
= &rmeth
->cif
;
703 ffi_raw
*raw
= (ffi_raw
*) sp
;
707 #if FFI_NATIVE_RAW_API
708 /* We assume that this is only implemented if it's correct */
709 /* to use it here. On a 64 bit machine, it never is. */
710 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
712 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
715 int rtype
= cif
->rtype
->type
;
717 /* the likelyhood of object, int, or void return is very high,
718 * so those are checked before the switch */
719 if (rtype
== FFI_TYPE_POINTER
)
721 PUSHA (*(jobject
*)&rvalue
);
723 else if (rtype
== FFI_TYPE_SINT32
)
725 PUSHI (*(jint
*)&rvalue
);
727 else if (rtype
== FFI_TYPE_VOID
)
735 jbyte value
= (*(jint
*)&rvalue
) & 0xff;
740 case FFI_TYPE_SINT16
:
742 jshort value
= (*(jint
*)&rvalue
) & 0xffff;
747 case FFI_TYPE_UINT16
:
749 jint value
= (*(jint
*)&rvalue
) & 0xffff;
755 PUSHF (*(jfloat
*)&rvalue
);
758 case FFI_TYPE_DOUBLE
:
762 case FFI_TYPE_SINT64
:
763 PUSHL (*(jlong
*)&rvalue
);
767 throw_internal_error ("unknown return type in invokeXXX");
842 PUSHI (get2s(pc
)); pc
+= 2;
847 int index
= get1u (pc
++);
848 PUSHA(pool_data
[index
].o
);
854 int index
= get2u (pc
); pc
+= 2;
855 PUSHA(pool_data
[index
].o
);
861 int index
= get2u (pc
); pc
+= 2;
862 memcpy (sp
, &pool_data
[index
], 2*sizeof (_Jv_word
));
868 LOADL (get1u (pc
++));
872 LOADF (get1u (pc
++));
876 LOADD (get1u (pc
++));
880 LOADA (get1u (pc
++));
959 jintArray arr
= (jintArray
) POPA();
961 if (index
< 0 || index
>= arr
->length
)
963 _Jv_ThrowBadArrayIndex (index
);
965 PUSHI( elements(arr
)[index
] );
973 jlongArray arr
= (jlongArray
) POPA();
975 if (index
< 0 || index
>= arr
->length
)
977 _Jv_ThrowBadArrayIndex (index
);
979 PUSHL( elements(arr
)[index
] );
987 jfloatArray arr
= (jfloatArray
) POPA();
989 if (index
< 0 || index
>= arr
->length
)
991 _Jv_ThrowBadArrayIndex (index
);
993 PUSHF( elements(arr
)[index
] );
1000 jint index
= POPI();
1001 jdoubleArray arr
= (jdoubleArray
) POPA();
1003 if (index
< 0 || index
>= arr
->length
)
1005 _Jv_ThrowBadArrayIndex (index
);
1007 PUSHD( elements(arr
)[index
] );
1014 jint index
= POPI();
1015 jobjectArray arr
= (jobjectArray
) POPA();
1017 if (index
< 0 || index
>= arr
->length
)
1019 _Jv_ThrowBadArrayIndex (index
);
1021 PUSHA( elements(arr
)[index
] );
1028 jint index
= POPI();
1029 jbyteArray arr
= (jbyteArray
) POPA();
1031 if (index
< 0 || index
>= arr
->length
)
1033 _Jv_ThrowBadArrayIndex (index
);
1035 PUSHI( elements(arr
)[index
] );
1042 jint index
= POPI();
1043 jcharArray arr
= (jcharArray
) POPA();
1045 if (index
< 0 || index
>= arr
->length
)
1047 _Jv_ThrowBadArrayIndex (index
);
1049 PUSHI( elements(arr
)[index
] );
1056 jint index
= POPI();
1057 jshortArray arr
= (jshortArray
) POPA();
1059 if (index
< 0 || index
>= arr
->length
)
1061 _Jv_ThrowBadArrayIndex (index
);
1063 PUSHI( elements(arr
)[index
] );
1068 STOREI (get1u (pc
++));
1072 STOREL (get1u (pc
++));
1076 STOREF (get1u (pc
++));
1080 STORED (get1u (pc
++));
1084 STOREA (get1u (pc
++));
1170 jint value
= POPI();
1171 jint index
= POPI();
1172 jintArray arr
= (jintArray
) POPA();
1174 if (index
< 0 || index
>= arr
->length
)
1176 _Jv_ThrowBadArrayIndex (index
);
1178 elements(arr
)[index
] = value
;
1185 jlong value
= POPL();
1186 jint index
= POPI();
1187 jlongArray arr
= (jlongArray
) POPA();
1189 if (index
< 0 || index
>= arr
->length
)
1191 _Jv_ThrowBadArrayIndex (index
);
1193 elements(arr
)[index
] = value
;
1200 jfloat value
= POPF();
1201 jint index
= POPI();
1202 jfloatArray arr
= (jfloatArray
) POPA();
1204 if (index
< 0 || index
>= arr
->length
)
1206 _Jv_ThrowBadArrayIndex (index
);
1208 elements(arr
)[index
] = value
;
1215 jdouble value
= POPD();
1216 jint index
= POPI();
1217 jdoubleArray arr
= (jdoubleArray
) POPA();
1219 if (index
< 0 || index
>= arr
->length
)
1221 _Jv_ThrowBadArrayIndex (index
);
1223 elements(arr
)[index
] = value
;
1230 jobject value
= POPA();
1231 jint index
= POPI();
1232 jobjectArray arr
= (jobjectArray
) POPA();
1234 if (index
< 0 || index
>= arr
->length
)
1236 _Jv_ThrowBadArrayIndex (index
);
1238 _Jv_CheckArrayStore (arr
, value
);
1239 elements(arr
)[index
] = value
;
1246 jbyte value
= (jbyte
) POPI();
1247 jint index
= POPI();
1248 jbyteArray arr
= (jbyteArray
) POPA();
1250 if (index
< 0 || index
>= arr
->length
)
1252 _Jv_ThrowBadArrayIndex (index
);
1254 elements(arr
)[index
] = value
;
1261 jchar value
= (jchar
) POPI();
1262 jint index
= POPI();
1263 jcharArray arr
= (jcharArray
) POPA();
1265 if (index
< 0 || index
>= arr
->length
)
1267 _Jv_ThrowBadArrayIndex (index
);
1269 elements(arr
)[index
] = value
;
1276 jshort value
= (jshort
) POPI();
1277 jint index
= POPI();
1278 jshortArray arr
= (jshortArray
) POPA();
1280 if (index
< 0 || index
>= arr
->length
)
1282 _Jv_ThrowBadArrayIndex (index
);
1284 elements(arr
)[index
] = value
;
1302 dupx (sp
, 1, 1); sp
+=1;
1306 dupx (sp
, 1, 2); sp
+=1;
1316 dupx (sp
, 2, 1); sp
+=2;
1320 dupx (sp
, 2, 2); sp
+=2;
1325 jobject tmp1
= POPA();
1326 jobject tmp2
= POPA();
1383 jint value2
= POPI();
1384 jint value1
= POPI();
1385 jint res
= _Jv_divI (value1
, value2
);
1393 jlong value2
= POPL();
1394 jlong value1
= POPL();
1395 jlong res
= _Jv_divJ (value1
, value2
);
1403 jfloat value2
= POPF();
1404 jfloat value1
= POPF();
1405 jfloat res
= value1
/ value2
;
1413 jdouble value2
= POPD();
1414 jdouble value1
= POPD();
1415 jdouble res
= value1
/ value2
;
1423 jint value2
= POPI();
1424 jint value1
= POPI();
1425 jint res
= _Jv_remI (value1
, value2
);
1433 jlong value2
= POPL();
1434 jlong value1
= POPL();
1435 jlong res
= _Jv_remJ (value1
, value2
);
1443 jfloat value2
= POPF();
1444 jfloat value1
= POPF();
1445 jfloat res
= __ieee754_fmod (value1
, value2
);
1453 jdouble value2
= POPD();
1454 jdouble value1
= POPD();
1455 jdouble res
= __ieee754_fmod (value1
, value2
);
1462 jint value
= POPI();
1469 jlong value
= POPL();
1476 jfloat value
= POPF();
1483 jdouble value
= POPD();
1490 jint shift
= (POPI() & 0x1f);
1491 jint value
= POPI();
1492 PUSHI (value
<< shift
);
1498 jint shift
= (POPI() & 0x3f);
1499 jlong value
= POPL();
1500 PUSHL (value
<< shift
);
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 unsigned long value
= POPI();
1524 PUSHI ((jint
) (value
>> shift
));
1530 jint shift
= (POPI() & 0x3f);
1531 UINT64 value
= (UINT64
) POPL();
1532 PUSHL ((value
>> shift
));
1562 jint index
= get1u (pc
++);
1563 jint amount
= get1s (pc
++);
1564 locals
[index
].i
+= amount
;
1569 {jlong value
= POPI(); PUSHL (value
);}
1573 {jfloat value
= POPI(); PUSHF (value
);}
1577 {jdouble value
= POPI(); PUSHD (value
);}
1581 {jint value
= POPL(); PUSHI (value
);}
1585 {jfloat value
= POPL(); PUSHF (value
);}
1589 {jdouble value
= POPL(); PUSHD (value
);}
1593 { jint value
= (jint
)POPF (); PUSHI(value
); }
1597 { jlong value
= (jlong
)POPF (); PUSHL(value
); }
1601 { jdouble value
= POPF (); PUSHD(value
); }
1605 { jint value
= (jint
)POPD (); PUSHI(value
); }
1609 { jlong value
= (jlong
)POPD (); PUSHL(value
); }
1613 { jfloat value
= POPD (); PUSHF(value
); }
1617 { jbyte value
= POPI (); PUSHI(value
); }
1621 { jchar value
= POPI (); PUSHI(value
); }
1625 { jshort value
= POPI (); PUSHI(value
); }
1630 jlong value2
= POPL ();
1631 jlong value1
= POPL ();
1632 if (value1
> value2
)
1634 else if (value1
== value2
)
1644 jfloat value2
= POPF ();
1645 jfloat value1
= POPF ();
1646 if (value1
> value2
)
1648 else if (value1
== value2
)
1650 else if (value1
< value2
)
1652 else if ((*(pc
-1)) == op_fcmpg
)
1662 jdouble value2
= POPD ();
1663 jdouble value1
= POPD ();
1664 if (value1
> value2
)
1666 else if (value1
== value2
)
1668 else if (value1
< value2
)
1670 else if ((*(pc
-1)) == op_dcmpg
)
1679 jint offset
= get2s (pc
);
1689 jint offset
= get2s (pc
);
1699 jint offset
= get2s (pc
);
1709 jint offset
= get2s (pc
);
1719 jint offset
= get2s (pc
);
1729 jint offset
= get2s (pc
);
1739 jint offset
= get2s (pc
);
1740 jint value2
= POPI();
1741 jint value1
= POPI();
1742 if (value1
== value2
)
1751 jint offset
= get2s (pc
);
1752 jint value2
= POPI();
1753 jint value1
= POPI();
1754 if (value1
!= value2
)
1763 jint offset
= get2s (pc
);
1764 jint value2
= POPI();
1765 jint value1
= POPI();
1766 if (value1
< value2
)
1775 jint offset
= get2s (pc
);
1776 jint value2
= POPI();
1777 jint value1
= POPI();
1778 if (value1
>= value2
)
1787 jint offset
= get2s (pc
);
1788 jint value2
= POPI();
1789 jint value1
= POPI();
1790 if (value1
> value2
)
1799 jint offset
= get2s (pc
);
1800 jint value2
= POPI();
1801 jint value1
= POPI();
1802 if (value1
<= value2
)
1811 jint offset
= get2s (pc
);
1812 jobject value2
= POPA();
1813 jobject value1
= POPA();
1814 if (value1
== value2
)
1823 jint offset
= get2s (pc
);
1824 jobject value2
= POPA();
1825 jobject value1
= POPA();
1826 if (value1
!= value2
)
1835 jint offset
= get2s (pc
);
1842 unsigned char *base_pc
= pc
-1;
1843 jint offset
= get2s (pc
); pc
+= 2;
1844 PUSHA ((jobject
)pc
);
1845 pc
= base_pc
+offset
;
1851 jint index
= get1u (pc
);
1852 pc
= (unsigned char*) PEEKA (index
);
1858 unsigned char *base_pc
= pc
-1;
1861 unsigned char* base
= bytecode ();
1862 while ((pc
-base
) % 4 != 0)
1865 jint def
= get4 (pc
);
1866 jint low
= get4 (pc
+4);
1867 jint high
= get4 (pc
+8);
1869 if (index
< low
|| index
> high
)
1872 pc
= base_pc
+ get4 (pc
+4*(index
-low
+3));
1878 unsigned char *base_pc
= pc
-1;
1881 unsigned char* base
= bytecode ();
1882 while ((pc
-base
) % 4 != 0)
1885 jint def
= get4 (pc
);
1886 jint npairs
= get4 (pc
+4);
1891 // simple binary search...
1894 int half
= (min
+max
)/2;
1895 int match
= get4 (pc
+ 4*(2 + 2*half
));
1900 else if (index
< match
)
1907 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1908 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1914 /* on return, just save the sp and return to caller */
1927 jint fieldref_index
= get2u (pc
); pc
+= 2;
1928 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1929 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1931 if ((field
->flags
& Modifier::STATIC
) == 0)
1932 throw_incompatible_class_change_error
1933 (JvNewStringLatin1 ("field no longer static"));
1935 jclass type
= field
->type
;
1937 if (type
->isPrimitive ())
1939 switch (type
->size_in_bytes
)
1942 PUSHI (*(jbyte
*) (field
->u
.addr
));
1946 if (type
== JvPrimClass (char))
1947 PUSHI(*(jchar
*) (field
->u
.addr
));
1949 PUSHI(*(jshort
*) (field
->u
.addr
));
1953 PUSHI(*(jint
*) (field
->u
.addr
));
1957 PUSHL(*(jlong
*) (field
->u
.addr
));
1963 PUSHA(*(jobject
*) (field
->u
.addr
));
1971 jint fieldref_index
= get2u (pc
); pc
+= 2;
1972 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1973 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1975 if ((field
->flags
& Modifier::STATIC
) != 0)
1976 throw_incompatible_class_change_error
1977 (JvNewStringLatin1 ("field is static"));
1979 jclass type
= field
->type
;
1980 jint field_offset
= field
->u
.boffset
;
1981 if (field_offset
> 0xffff)
1982 throw new java::lang::VirtualMachineError
;
1984 jobject obj
= POPA();
1987 if (type
->isPrimitive ())
1989 switch (type
->size_in_bytes
)
1992 PUSHI (*(jbyte
*) ((char*)obj
+ field_offset
));
1996 if (type
== JvPrimClass (char))
1997 PUSHI (*(jchar
*) ((char*)obj
+ field_offset
));
1999 PUSHI (*(jshort
*) ((char*)obj
+ field_offset
));
2003 PUSHI (*(jint
*) ((char*)obj
+ field_offset
));
2007 PUSHL(*(jlong
*) ((char*)obj
+ field_offset
));
2013 PUSHA(*(jobject
*) ((char*)obj
+ field_offset
));
2021 jint fieldref_index
= get2u (pc
); pc
+= 2;
2022 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2023 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2025 jclass type
= field
->type
;
2027 // ResolvePoolEntry cannot check this
2028 if ((field
->flags
& Modifier::STATIC
) == 0)
2029 throw_incompatible_class_change_error
2030 (JvNewStringLatin1 ("field no longer static"));
2032 if (type
->isPrimitive ())
2034 switch (type
->size_in_bytes
)
2038 jint value
= POPI();
2039 *(jbyte
*) (field
->u
.addr
) = value
;
2045 jint value
= POPI();
2046 *(jchar
*) (field
->u
.addr
) = value
;
2052 jint value
= POPI();
2053 *(jint
*) (field
->u
.addr
) = value
;
2059 jlong value
= POPL();
2060 *(jlong
*) (field
->u
.addr
) = value
;
2067 jobject value
= POPA();
2068 *(jobject
*) (field
->u
.addr
) = value
;
2077 jint fieldref_index
= get2u (pc
); pc
+= 2;
2078 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2079 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2081 jclass type
= field
->type
;
2083 if ((field
->flags
& Modifier::STATIC
) != 0)
2084 throw_incompatible_class_change_error
2085 (JvNewStringLatin1 ("field is static"));
2087 jint field_offset
= field
->u
.boffset
;
2088 if (field_offset
> 0xffff)
2089 throw new java::lang::VirtualMachineError
;
2091 if (type
->isPrimitive ())
2093 switch (type
->size_in_bytes
)
2097 jint value
= POPI();
2098 jobject obj
= POPA();
2100 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2106 jint value
= POPI();
2107 jobject obj
= POPA();
2109 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2115 jint value
= POPI();
2116 jobject obj
= POPA();
2118 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2124 jlong value
= POPL();
2125 jobject obj
= POPA();
2127 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2134 jobject value
= POPA();
2135 jobject obj
= POPA();
2137 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2145 int index
= get2u (pc
); pc
+= 2;
2147 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2149 sp
-= rmeth
->stack_item_count
;
2151 NULLCHECK (sp
[0].o
);
2153 fun
= (void (*)()) rmeth
->method
->ncode
;
2155 goto perform_invoke
;
2160 int index
= get2u (pc
); pc
+= 2;
2162 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2164 sp
-= rmeth
->stack_item_count
;
2166 _Jv_InitClass (rmeth
->klass
);
2167 fun
= (void (*)()) rmeth
->method
->ncode
;
2169 goto perform_invoke
;
2171 insn_invokeinterface
:
2174 int index
= get2u (pc
); pc
+= 2;
2176 // invokeinterface has two unused bytes...
2179 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2181 sp
-= rmeth
->stack_item_count
;
2183 jobject rcv
= sp
[0].o
;
2188 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2189 rmeth
->method
->name
,
2190 rmeth
->method
->signature
);
2192 goto perform_invoke
;
2198 int index
= get2u (pc
); pc
+= 2;
2199 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2200 _Jv_InitClass (klass
);
2201 jobject res
= _Jv_AllocObject (klass
, klass
->size_in_bytes
);
2209 int atype
= get1u (pc
++);
2211 jobject result
= _Jv_NewArray (atype
, size
);
2219 int index
= get2u (pc
); pc
+= 2;
2220 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2222 _Jv_InitClass (klass
);
2223 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2231 __JArray
*arr
= (__JArray
*)POPA();
2232 PUSHI (arr
->length
);
2239 jobject value
= POPA();
2240 throw static_cast<jthrowable
>(value
);
2247 jobject value
= POPA();
2248 jint index
= get2u (pc
); pc
+= 2;
2249 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2251 if (value
!= NULL
&& ! to
->isInstance (value
))
2253 throw new java::lang::ClassCastException (to
->getName());
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
*) __builtin_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 throw new java::lang::InternalError (JvNewStringLatin1 (msg
));
2418 throw_incompatible_class_change_error (jstring msg
)
2420 throw 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 throw null_pointer_exc
;
2435 #endif // INTERPRETER