1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
15 #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/Long.h>
25 #include <java/lang/StringBuffer.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/ClassCastException.h>
29 #include <java/lang/VirtualMachineError.h>
30 #include <java/lang/InternalError.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/ArithmeticException.h>
33 #include <java/lang/IncompatibleClassChangeError.h>
34 #include <java-insns.h>
35 #include <java-signal.h>
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 (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
];
71 // Used to convert from floating types to integral types.
72 template<typename TO
, typename FROM
>
74 convert (FROM val
, TO min
, TO max
)
77 if (val
>= (FROM
) max
)
79 else if (val
<= (FROM
) min
)
88 #define PUSHA(V) (sp++)->o = (V)
89 #define PUSHI(V) (sp++)->i = (V)
90 #define PUSHF(V) (sp++)->f = (V)
91 #if SIZEOF_VOID_P == 8
92 # define PUSHL(V) (sp->l = (V), sp += 2)
93 # define PUSHD(V) (sp->d = (V), sp += 2)
95 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
96 (sp++)->ia[0] = w2.ia[0]; \
97 (sp++)->ia[0] = w2.ia[1]; } while (0)
98 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
99 (sp++)->ia[0] = w2.ia[0]; \
100 (sp++)->ia[0] = w2.ia[1]; } while (0)
103 #define POPA() ((--sp)->o)
104 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
105 #define POPF() ((jfloat) (--sp)->f)
106 #if SIZEOF_VOID_P == 8
107 # define POPL() (sp -= 2, (jlong) sp->l)
108 # define POPD() (sp -= 2, (jdouble) sp->d)
110 # define POPL() ({ _Jv_word2 w2; \
111 w2.ia[1] = (--sp)->ia[0]; \
112 w2.ia[0] = (--sp)->ia[0]; w2.l; })
113 # define POPD() ({ _Jv_word2 w2; \
114 w2.ia[1] = (--sp)->ia[0]; \
115 w2.ia[0] = (--sp)->ia[0]; w2.d; })
118 #define LOADA(I) (sp++)->o = locals[I].o
119 #define LOADI(I) (sp++)->i = locals[I].i
120 #define LOADF(I) (sp++)->f = locals[I].f
121 #if SIZEOF_VOID_P == 8
122 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
123 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
125 # define LOADL(I) do { jint __idx = (I); \
126 (sp++)->ia[0] = locals[__idx].ia[0]; \
127 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
129 # define LOADD(I) LOADL(I)
132 #define STOREA(I) locals[I].o = (--sp)->o
133 #define STOREI(I) locals[I].i = (--sp)->i
134 #define STOREF(I) locals[I].f = (--sp)->f
135 #if SIZEOF_VOID_P == 8
136 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
137 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
139 # define STOREL(I) do { jint __idx = (I); \
140 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
141 locals[__idx].ia[0] = (--sp)->ia[0]; \
143 # define STORED(I) STOREL(I)
146 #define PEEKI(I) (locals+(I))->i
147 #define PEEKA(I) (locals+(I))->o
149 #define POKEI(I,V) ((locals+(I))->i = (V))
152 #define BINOPI(OP) { \
153 jint value2 = POPI(); \
154 jint value1 = POPI(); \
155 PUSHI(value1 OP value2); \
158 #define BINOPF(OP) { \
159 jfloat value2 = POPF(); \
160 jfloat value1 = POPF(); \
161 PUSHF(value1 OP value2); \
164 #define BINOPL(OP) { \
165 jlong value2 = POPL(); \
166 jlong value1 = POPL(); \
167 PUSHL(value1 OP value2); \
170 #define BINOPD(OP) { \
171 jdouble value2 = POPD(); \
172 jdouble value1 = POPD(); \
173 PUSHD(value1 OP value2); \
176 static inline jint
get1s(unsigned char* loc
) {
177 return *(signed char*)loc
;
180 static inline jint
get1u(unsigned char* loc
) {
184 static inline jint
get2s(unsigned char* loc
) {
185 return (((jint
)*(signed char*)loc
) << 8) | ((jint
)*(loc
+1));
188 static inline jint
get2u(unsigned char* loc
) {
189 return (((jint
)(*loc
)) << 8) | ((jint
)*(loc
+1));
192 static jint
get4(unsigned char* loc
) {
193 return (((jint
)(loc
[0])) << 24)
194 | (((jint
)(loc
[1])) << 16)
195 | (((jint
)(loc
[2])) << 8)
196 | (((jint
)(loc
[3])) << 0);
202 #define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)
204 #define NULLCHECK(X) \
205 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
206 #define NULLARRAYCHECK(X) \
207 do { if ((X)==NULL) { SAVE_PC; throw_null_pointer_exception (); } } while (0)
210 #define ARRAYBOUNDSCHECK(array, index) \
213 if (((unsigned) index) >= (unsigned) (array->length)) \
214 _Jv_ThrowBadArrayIndex (index); \
218 // this method starts the actual running of the method. It is inlined
219 // in three different variants in the static methods run_normal,
220 // run_sync_object and run_sync_class (see below). Those static methods
221 // are installed directly in the stub for this method (by
222 // _Jv_InterpMethod::ncode, in resolve.cc).
225 _Jv_InterpMethod::run (ffi_cif
* cif
,
228 _Jv_InterpMethodInvocation
*inv
)
231 inv
->pc
= bytecode ();
232 inv
->sp
= inv
->stack_base ();
233 _Jv_word
*locals
= inv
->local_base ();
235 /* Go straight at it! the ffi raw format matches the internal
236 stack representation exactly. At least, that's the idea.
238 memcpy ((void*) locals
, (void*) args
, args_raw_size
);
248 catch (java::lang::Throwable
*ex2
)
253 if (ex
== 0) // no exception...
255 /* define sp locally, so the POP? macros will pick it up */
256 _Jv_word
*sp
= inv
->sp
;
257 int rtype
= cif
->rtype
->type
;
259 if (rtype
== FFI_TYPE_POINTER
)
262 *(jobject
*) retp
= r
;
265 else if (rtype
== FFI_TYPE_SINT32
)
271 else if (rtype
== FFI_TYPE_VOID
)
284 case FFI_TYPE_DOUBLE
:
292 case FFI_TYPE_UINT16
:
293 case FFI_TYPE_UINT32
:
295 case FFI_TYPE_SINT16
:
302 case FFI_TYPE_SINT64
:
310 throw_internal_error ("unknown return type");
314 /** handle an exception */
315 if ( find_exception (ex
, inv
) )
321 #define SAVE_PC inv->pc = pc
323 bool _Jv_InterpMethod::find_exception (jobject ex
,
324 _Jv_InterpMethodInvocation
*inv
)
326 // We subtract one because the PC was incremented before it was
328 int logical_pc
= inv
->pc
- 1 - bytecode ();
329 _Jv_InterpException
*exc
= exceptions ();
330 jclass exc_class
= ex
->getClass ();
332 for (int i
= 0; i
< exc_count
; i
++)
334 if (exc
[i
].start_pc
<= logical_pc
&& logical_pc
< exc
[i
].end_pc
)
338 if (exc
[i
].handler_type
!= 0)
339 handler
= (_Jv_ResolvePoolEntry (defining_class
,
340 exc
[i
].handler_type
)).clazz
;
344 if (handler
==NULL
|| handler
->isAssignableFrom (exc_class
))
346 inv
->pc
= bytecode () + exc
[i
].handler_pc
;
347 inv
->sp
= inv
->stack_base (); // reset stack
348 (inv
->sp
++)->o
= ex
; // push exception
356 void _Jv_InterpMethod::run_normal (ffi_cif
* cif
,
361 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
363 // we do the alloca of the method invocation here, to allow the method
364 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
365 int storage_size
= _this
->max_stack
+_this
->max_locals
;
366 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
367 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation
)
368 + storage_size
* sizeof (_Jv_word
));
370 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
371 if (ex
!= 0) throw static_cast<jthrowable
>(ex
);
374 void _Jv_InterpMethod::run_synch_object (ffi_cif
* cif
,
379 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
380 jobject rcv
= (jobject
)args
[0].ptr
;
382 int storage_size
= _this
->max_stack
+_this
->max_locals
;
383 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
384 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation
)
385 + storage_size
* sizeof (_Jv_word
));
387 _Jv_MonitorEnter (rcv
);
388 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
389 _Jv_MonitorExit (rcv
);
391 if (ex
!= 0) throw static_cast<jthrowable
>(ex
);
394 void _Jv_InterpMethod::run_synch_class (ffi_cif
* cif
,
399 _Jv_InterpMethod
* _this
= (_Jv_InterpMethod
*)__this
;
400 jclass sync
= _this
->defining_class
;
402 int storage_size
= _this
->max_stack
+_this
->max_locals
;
403 _Jv_InterpMethodInvocation
* inv
= (_Jv_InterpMethodInvocation
*)
404 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation
)
405 + storage_size
* sizeof (_Jv_word
));
407 _Jv_MonitorEnter (sync
);
408 jobject ex
= _this
->run (cif
, ret
, args
, inv
);
409 _Jv_MonitorExit (sync
);
411 if (ex
!= 0) throw static_cast<jthrowable
>(ex
);
415 This proceeds execution, as designated in "inv". If an exception
416 happens, then it is simply thrown, and handled in Java. Thus, the pc
417 needs to be stored in the inv->pc at all times, so we can figure
418 out which handler (if any) to invoke.
420 One design issue, which I have not completely considered, is if it
421 should be possible to have interpreted classes linked in! Seldom used
422 (or non-critical) classes could reasonably be interpreted.
426 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation
*inv
)
428 using namespace java::lang::reflect
;
430 _Jv_word
*sp
= inv
->sp
;
431 unsigned char *pc
= inv
->pc
;
432 _Jv_word
*locals
= inv
->local_base ();
434 _Jv_word
*pool_data
= defining_class
->constants
.data
;
436 /* these two are used in the invokeXXX instructions */
438 _Jv_ResolvedMethod
* rmeth
;
440 #define INSN_LABEL(op) &&insn_##op
441 #define GOTO_INSN(op) goto *(insn_target[op])
443 static const void *const insn_target
[] =
446 INSN_LABEL(aconst_null
),
447 INSN_LABEL(iconst_m1
),
448 INSN_LABEL(iconst_0
),
449 INSN_LABEL(iconst_1
),
450 INSN_LABEL(iconst_2
),
451 INSN_LABEL(iconst_3
),
452 INSN_LABEL(iconst_4
),
453 INSN_LABEL(iconst_5
),
454 INSN_LABEL(lconst_0
),
455 INSN_LABEL(lconst_1
),
456 INSN_LABEL(fconst_0
),
457 INSN_LABEL(fconst_1
),
458 INSN_LABEL(fconst_2
),
459 INSN_LABEL(dconst_0
),
460 INSN_LABEL(dconst_1
),
504 INSN_LABEL(istore_0
),
505 INSN_LABEL(istore_1
),
506 INSN_LABEL(istore_2
),
507 INSN_LABEL(istore_3
),
508 INSN_LABEL(lstore_0
),
509 INSN_LABEL(lstore_1
),
510 INSN_LABEL(lstore_2
),
511 INSN_LABEL(lstore_3
),
512 INSN_LABEL(fstore_0
),
513 INSN_LABEL(fstore_1
),
514 INSN_LABEL(fstore_2
),
515 INSN_LABEL(fstore_3
),
516 INSN_LABEL(dstore_0
),
517 INSN_LABEL(dstore_1
),
518 INSN_LABEL(dstore_2
),
519 INSN_LABEL(dstore_3
),
520 INSN_LABEL(astore_0
),
521 INSN_LABEL(astore_1
),
522 INSN_LABEL(astore_2
),
523 INSN_LABEL(astore_3
),
604 INSN_LABEL(if_icmpeq
),
605 INSN_LABEL(if_icmpne
),
606 INSN_LABEL(if_icmplt
),
607 INSN_LABEL(if_icmpge
),
608 INSN_LABEL(if_icmpgt
),
609 INSN_LABEL(if_icmple
),
610 INSN_LABEL(if_acmpeq
),
611 INSN_LABEL(if_acmpne
),
615 INSN_LABEL(tableswitch
),
616 INSN_LABEL(lookupswitch
),
623 INSN_LABEL(getstatic
),
624 INSN_LABEL(putstatic
),
625 INSN_LABEL(getfield
),
626 INSN_LABEL(putfield
),
627 INSN_LABEL(invokevirtual
),
628 INSN_LABEL(invokespecial
),
629 INSN_LABEL(invokestatic
),
630 INSN_LABEL(invokeinterface
),
633 INSN_LABEL(newarray
),
634 INSN_LABEL(anewarray
),
635 INSN_LABEL(arraylength
),
637 INSN_LABEL(checkcast
),
638 INSN_LABEL(instanceof
),
639 INSN_LABEL(monitorenter
),
640 INSN_LABEL(monitorexit
),
642 INSN_LABEL(multianewarray
),
644 INSN_LABEL(ifnonnull
),
649 /* If the macro INLINE_SWITCH is not defined, then the main loop
650 operates as one big (normal) switch statement. If it is defined,
651 then the case selection is performed `inline' in the end of the
652 code for each case. The latter saves a native branch instruction
653 for each java-instruction, but expands the code size somewhat.
655 NOTE: On i386 defining INLINE_SWITCH improves over all
656 performance approximately seven percent, but it may be different
657 for other machines. At some point, this may be made into a proper
658 configuration parameter. */
660 #define INLINE_SWITCH
664 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
670 #define NEXT_INSN goto next_insn
677 /* The first few instructions here are ordered according to their
678 frequency, in the hope that this will improve code locality a
681 insn_aload_0
: // 0x2a
686 LOADI (get1u (pc
++));
689 insn_iload_1
: // 0x1b
693 insn_invokevirtual
: // 0xb6
696 int index
= get2u (pc
); pc
+= 2;
698 /* _Jv_ResolvePoolEntry returns immediately if the value already
699 * is resolved. If we want to clutter up the code here to gain
700 * a little performance, then we can check the corresponding bit
701 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
702 * don't think it is worth it. */
704 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
706 sp
-= rmeth
->stack_item_count
;
707 // We don't use NULLCHECK here because we can't rely on that
708 // working if the method is final. So instead we do an
711 throw new java::lang::NullPointerException
;
713 if (rmeth
->vtable_index
== -1)
715 // final methods do not appear in the vtable,
716 // if it does not appear in the superclass.
717 fun
= (void (*)()) rmeth
->method
->ncode
;
721 jobject rcv
= sp
[0].o
;
722 _Jv_VTable
*table
= *(_Jv_VTable
**)rcv
;
723 fun
= (void (*)()) table
->get_method(rmeth
->vtable_index
);
730 /* here goes the magic again... */
731 ffi_cif
*cif
= &rmeth
->cif
;
732 ffi_raw
*raw
= (ffi_raw
*) sp
;
736 #if FFI_NATIVE_RAW_API
737 /* We assume that this is only implemented if it's correct */
738 /* to use it here. On a 64 bit machine, it never is. */
739 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
741 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
744 int rtype
= cif
->rtype
->type
;
746 /* the likelyhood of object, int, or void return is very high,
747 * so those are checked before the switch */
748 if (rtype
== FFI_TYPE_POINTER
)
750 PUSHA (*(jobject
*)&rvalue
);
752 else if (rtype
== FFI_TYPE_SINT32
)
754 PUSHI (*(jint
*)&rvalue
);
756 else if (rtype
== FFI_TYPE_VOID
)
764 jbyte value
= (*(jint
*)&rvalue
) & 0xff;
769 case FFI_TYPE_SINT16
:
771 jshort value
= (*(jint
*)&rvalue
) & 0xffff;
776 case FFI_TYPE_UINT16
:
778 jint value
= (*(jint
*)&rvalue
) & 0xffff;
784 PUSHF (*(jfloat
*)&rvalue
);
787 case FFI_TYPE_DOUBLE
:
791 case FFI_TYPE_SINT64
:
792 PUSHL (*(jlong
*)&rvalue
);
796 throw_internal_error ("unknown return type in invokeXXX");
871 PUSHI (get2s(pc
)); pc
+= 2;
876 int index
= get1u (pc
++);
877 PUSHA(pool_data
[index
].o
);
883 int index
= get2u (pc
); pc
+= 2;
884 PUSHA(pool_data
[index
].o
);
890 int index
= get2u (pc
); pc
+= 2;
891 memcpy (sp
, &pool_data
[index
], 2*sizeof (_Jv_word
));
897 LOADL (get1u (pc
++));
901 LOADF (get1u (pc
++));
905 LOADD (get1u (pc
++));
909 LOADA (get1u (pc
++));
987 jintArray arr
= (jintArray
) POPA();
988 NULLARRAYCHECK (arr
);
989 ARRAYBOUNDSCHECK (arr
, index
);
990 PUSHI( elements(arr
)[index
] );
997 jlongArray arr
= (jlongArray
) POPA();
998 NULLARRAYCHECK (arr
);
999 ARRAYBOUNDSCHECK (arr
, index
);
1000 PUSHL( elements(arr
)[index
] );
1006 jint index
= POPI();
1007 jfloatArray arr
= (jfloatArray
) POPA();
1008 NULLARRAYCHECK (arr
);
1009 ARRAYBOUNDSCHECK (arr
, index
);
1010 PUSHF( elements(arr
)[index
] );
1016 jint index
= POPI();
1017 jdoubleArray arr
= (jdoubleArray
) POPA();
1018 NULLARRAYCHECK (arr
);
1019 ARRAYBOUNDSCHECK (arr
, index
);
1020 PUSHD( elements(arr
)[index
] );
1026 jint index
= POPI();
1027 jobjectArray arr
= (jobjectArray
) POPA();
1028 NULLARRAYCHECK (arr
);
1029 ARRAYBOUNDSCHECK (arr
, index
);
1030 PUSHA( elements(arr
)[index
] );
1036 jint index
= POPI();
1037 jbyteArray arr
= (jbyteArray
) POPA();
1038 NULLARRAYCHECK (arr
);
1039 ARRAYBOUNDSCHECK (arr
, index
);
1040 PUSHI( elements(arr
)[index
] );
1046 jint index
= POPI();
1047 jcharArray arr
= (jcharArray
) POPA();
1048 NULLARRAYCHECK (arr
);
1049 ARRAYBOUNDSCHECK (arr
, index
);
1050 PUSHI( elements(arr
)[index
] );
1056 jint index
= POPI();
1057 jshortArray arr
= (jshortArray
) POPA();
1058 NULLARRAYCHECK (arr
);
1059 ARRAYBOUNDSCHECK (arr
, 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
++));
1166 jint value
= POPI();
1167 jint index
= POPI();
1168 jintArray arr
= (jintArray
) POPA();
1169 NULLARRAYCHECK (arr
);
1170 ARRAYBOUNDSCHECK (arr
, index
);
1171 elements(arr
)[index
] = value
;
1177 jlong value
= POPL();
1178 jint index
= POPI();
1179 jlongArray arr
= (jlongArray
) POPA();
1180 NULLARRAYCHECK (arr
);
1181 ARRAYBOUNDSCHECK (arr
, index
);
1182 elements(arr
)[index
] = value
;
1188 jfloat value
= POPF();
1189 jint index
= POPI();
1190 jfloatArray arr
= (jfloatArray
) POPA();
1191 NULLARRAYCHECK (arr
);
1192 ARRAYBOUNDSCHECK (arr
, index
);
1193 elements(arr
)[index
] = value
;
1199 jdouble value
= POPD();
1200 jint index
= POPI();
1201 jdoubleArray arr
= (jdoubleArray
) POPA();
1202 NULLARRAYCHECK (arr
);
1203 ARRAYBOUNDSCHECK (arr
, index
);
1204 elements(arr
)[index
] = value
;
1210 jobject value
= POPA();
1211 jint index
= POPI();
1212 jobjectArray arr
= (jobjectArray
) POPA();
1213 NULLARRAYCHECK (arr
);
1214 ARRAYBOUNDSCHECK (arr
, index
);
1215 _Jv_CheckArrayStore (arr
, value
);
1216 elements(arr
)[index
] = value
;
1222 jbyte value
= (jbyte
) POPI();
1223 jint index
= POPI();
1224 jbyteArray arr
= (jbyteArray
) POPA();
1225 NULLARRAYCHECK (arr
);
1226 ARRAYBOUNDSCHECK (arr
, index
);
1227 elements(arr
)[index
] = value
;
1233 jchar value
= (jchar
) POPI();
1234 jint index
= POPI();
1235 jcharArray arr
= (jcharArray
) POPA();
1236 NULLARRAYCHECK (arr
);
1237 ARRAYBOUNDSCHECK (arr
, index
);
1238 elements(arr
)[index
] = value
;
1244 jshort value
= (jshort
) POPI();
1245 jint index
= POPI();
1246 jshortArray arr
= (jshortArray
) POPA();
1247 NULLARRAYCHECK (arr
);
1248 ARRAYBOUNDSCHECK (arr
, index
);
1249 elements(arr
)[index
] = value
;
1267 dupx (sp
, 1, 1); sp
+=1;
1271 dupx (sp
, 1, 2); sp
+=1;
1281 dupx (sp
, 2, 1); sp
+=2;
1285 dupx (sp
, 2, 2); sp
+=2;
1290 jobject tmp1
= POPA();
1291 jobject tmp2
= POPA();
1348 jint value2
= POPI();
1349 jint value1
= POPI();
1350 jint res
= _Jv_divI (value1
, value2
);
1358 jlong value2
= POPL();
1359 jlong value1
= POPL();
1360 jlong res
= _Jv_divJ (value1
, value2
);
1367 jfloat value2
= POPF();
1368 jfloat value1
= POPF();
1369 jfloat res
= value1
/ value2
;
1376 jdouble value2
= POPD();
1377 jdouble value1
= POPD();
1378 jdouble res
= value1
/ value2
;
1386 jint value2
= POPI();
1387 jint value1
= POPI();
1388 jint res
= _Jv_remI (value1
, value2
);
1396 jlong value2
= POPL();
1397 jlong value1
= POPL();
1398 jlong res
= _Jv_remJ (value1
, value2
);
1405 jfloat value2
= POPF();
1406 jfloat value1
= POPF();
1407 jfloat res
= __ieee754_fmod (value1
, value2
);
1414 jdouble value2
= POPD();
1415 jdouble value1
= POPD();
1416 jdouble res
= __ieee754_fmod (value1
, value2
);
1423 jint value
= POPI();
1430 jlong value
= POPL();
1437 jfloat value
= POPF();
1444 jdouble value
= POPD();
1451 jint shift
= (POPI() & 0x1f);
1452 jint value
= POPI();
1453 PUSHI (value
<< shift
);
1459 jint shift
= (POPI() & 0x3f);
1460 jlong value
= POPL();
1461 PUSHL (value
<< shift
);
1467 jint shift
= (POPI() & 0x1f);
1468 jint value
= POPI();
1469 PUSHI (value
>> shift
);
1475 jint shift
= (POPI() & 0x3f);
1476 jlong value
= POPL();
1477 PUSHL (value
>> shift
);
1483 jint shift
= (POPI() & 0x1f);
1484 unsigned long value
= POPI();
1485 PUSHI ((jint
) (value
>> shift
));
1491 jint shift
= (POPI() & 0x3f);
1492 UINT64 value
= (UINT64
) POPL();
1493 PUSHL ((value
>> shift
));
1523 jint index
= get1u (pc
++);
1524 jint amount
= get1s (pc
++);
1525 locals
[index
].i
+= amount
;
1530 {jlong value
= POPI(); PUSHL (value
);}
1534 {jfloat value
= POPI(); PUSHF (value
);}
1538 {jdouble value
= POPI(); PUSHD (value
);}
1542 {jint value
= POPL(); PUSHI (value
);}
1546 {jfloat value
= POPL(); PUSHF (value
);}
1550 {jdouble value
= POPL(); PUSHD (value
);}
1555 using namespace java::lang
;
1556 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1563 using namespace java::lang
;
1564 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1570 { jdouble value
= POPF (); PUSHD(value
); }
1575 using namespace java::lang
;
1576 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1583 using namespace java::lang
;
1584 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1590 { jfloat value
= POPD (); PUSHF(value
); }
1594 { jbyte value
= POPI (); PUSHI(value
); }
1598 { jchar value
= POPI (); PUSHI(value
); }
1602 { jshort value
= POPI (); PUSHI(value
); }
1607 jlong value2
= POPL ();
1608 jlong value1
= POPL ();
1609 if (value1
> value2
)
1611 else if (value1
== value2
)
1621 jfloat value2
= POPF ();
1622 jfloat value1
= POPF ();
1623 if (value1
> value2
)
1625 else if (value1
== value2
)
1627 else if (value1
< value2
)
1629 else if ((*(pc
-1)) == op_fcmpg
)
1639 jdouble value2
= POPD ();
1640 jdouble value1
= POPD ();
1641 if (value1
> value2
)
1643 else if (value1
== value2
)
1645 else if (value1
< value2
)
1647 else if ((*(pc
-1)) == op_dcmpg
)
1656 jint offset
= get2s (pc
);
1666 jint offset
= get2s (pc
);
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
);
1717 jint value2
= POPI();
1718 jint value1
= POPI();
1719 if (value1
== value2
)
1728 jint offset
= get2s (pc
);
1729 jint value2
= POPI();
1730 jint value1
= POPI();
1731 if (value1
!= value2
)
1740 jint offset
= get2s (pc
);
1741 jint value2
= POPI();
1742 jint value1
= POPI();
1743 if (value1
< value2
)
1752 jint offset
= get2s (pc
);
1753 jint value2
= POPI();
1754 jint value1
= POPI();
1755 if (value1
>= value2
)
1764 jint offset
= get2s (pc
);
1765 jint value2
= POPI();
1766 jint value1
= POPI();
1767 if (value1
> value2
)
1776 jint offset
= get2s (pc
);
1777 jint value2
= POPI();
1778 jint value1
= POPI();
1779 if (value1
<= value2
)
1788 jint offset
= get2s (pc
);
1789 jobject value2
= POPA();
1790 jobject value1
= POPA();
1791 if (value1
== value2
)
1800 jint offset
= get2s (pc
);
1801 jobject value2
= POPA();
1802 jobject value1
= POPA();
1803 if (value1
!= value2
)
1812 jint offset
= get2s (pc
);
1819 unsigned char *base_pc
= pc
-1;
1820 jint offset
= get2s (pc
); pc
+= 2;
1821 PUSHA ((jobject
)pc
);
1822 pc
= base_pc
+offset
;
1828 jint index
= get1u (pc
);
1829 pc
= (unsigned char*) PEEKA (index
);
1835 unsigned char *base_pc
= pc
-1;
1838 unsigned char* base
= bytecode ();
1839 while ((pc
-base
) % 4 != 0)
1842 jint def
= get4 (pc
);
1843 jint low
= get4 (pc
+4);
1844 jint high
= get4 (pc
+8);
1846 if (index
< low
|| index
> high
)
1849 pc
= base_pc
+ get4 (pc
+4*(index
-low
+3));
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 npairs
= get4 (pc
+4);
1868 // simple binary search...
1871 int half
= (min
+max
)/2;
1872 int match
= get4 (pc
+ 4*(2 + 2*half
));
1877 else if (index
< match
)
1884 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1885 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1891 /* on return, just save the sp and return to caller */
1904 jint fieldref_index
= get2u (pc
); pc
+= 2;
1905 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1906 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1908 if ((field
->flags
& Modifier::STATIC
) == 0)
1909 throw_incompatible_class_change_error
1910 (JvNewStringLatin1 ("field no longer static"));
1912 jclass type
= field
->type
;
1914 if (type
->isPrimitive ())
1916 switch (type
->size_in_bytes
)
1919 PUSHI (*(jbyte
*) (field
->u
.addr
));
1923 if (type
== JvPrimClass (char))
1924 PUSHI(*(jchar
*) (field
->u
.addr
));
1926 PUSHI(*(jshort
*) (field
->u
.addr
));
1930 PUSHI(*(jint
*) (field
->u
.addr
));
1934 PUSHL(*(jlong
*) (field
->u
.addr
));
1940 PUSHA(*(jobject
*) (field
->u
.addr
));
1948 jint fieldref_index
= get2u (pc
); pc
+= 2;
1949 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1950 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1952 if ((field
->flags
& Modifier::STATIC
) != 0)
1953 throw_incompatible_class_change_error
1954 (JvNewStringLatin1 ("field is static"));
1956 jclass type
= field
->type
;
1957 jint field_offset
= field
->u
.boffset
;
1958 if (field_offset
> 0xffff)
1959 throw new java::lang::VirtualMachineError
;
1961 jobject obj
= POPA();
1964 if (type
->isPrimitive ())
1966 switch (type
->size_in_bytes
)
1969 PUSHI (*(jbyte
*) ((char*)obj
+ field_offset
));
1973 if (type
== JvPrimClass (char))
1974 PUSHI (*(jchar
*) ((char*)obj
+ field_offset
));
1976 PUSHI (*(jshort
*) ((char*)obj
+ field_offset
));
1980 PUSHI (*(jint
*) ((char*)obj
+ field_offset
));
1984 PUSHL(*(jlong
*) ((char*)obj
+ field_offset
));
1990 PUSHA(*(jobject
*) ((char*)obj
+ field_offset
));
1998 jint fieldref_index
= get2u (pc
); pc
+= 2;
1999 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2000 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2002 jclass type
= field
->type
;
2004 // ResolvePoolEntry cannot check this
2005 if ((field
->flags
& Modifier::STATIC
) == 0)
2006 throw_incompatible_class_change_error
2007 (JvNewStringLatin1 ("field no longer static"));
2009 if (type
->isPrimitive ())
2011 switch (type
->size_in_bytes
)
2015 jint value
= POPI();
2016 *(jbyte
*) (field
->u
.addr
) = value
;
2022 jint value
= POPI();
2023 *(jchar
*) (field
->u
.addr
) = value
;
2029 jint value
= POPI();
2030 *(jint
*) (field
->u
.addr
) = value
;
2036 jlong value
= POPL();
2037 *(jlong
*) (field
->u
.addr
) = value
;
2044 jobject value
= POPA();
2045 *(jobject
*) (field
->u
.addr
) = value
;
2054 jint fieldref_index
= get2u (pc
); pc
+= 2;
2055 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2056 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2058 jclass type
= field
->type
;
2060 if ((field
->flags
& Modifier::STATIC
) != 0)
2061 throw_incompatible_class_change_error
2062 (JvNewStringLatin1 ("field is static"));
2064 jint field_offset
= field
->u
.boffset
;
2065 if (field_offset
> 0xffff)
2066 throw new java::lang::VirtualMachineError
;
2068 if (type
->isPrimitive ())
2070 switch (type
->size_in_bytes
)
2074 jint value
= POPI();
2075 jobject obj
= POPA();
2077 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2083 jint value
= POPI();
2084 jobject obj
= POPA();
2086 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2092 jint value
= POPI();
2093 jobject obj
= POPA();
2095 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2101 jlong value
= POPL();
2102 jobject obj
= POPA();
2104 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2111 jobject value
= POPA();
2112 jobject obj
= POPA();
2114 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2122 int index
= get2u (pc
); pc
+= 2;
2124 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2126 sp
-= rmeth
->stack_item_count
;
2128 NULLCHECK (sp
[0].o
);
2130 fun
= (void (*)()) rmeth
->method
->ncode
;
2132 goto perform_invoke
;
2137 int index
= get2u (pc
); pc
+= 2;
2139 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2141 sp
-= rmeth
->stack_item_count
;
2143 _Jv_InitClass (rmeth
->klass
);
2144 fun
= (void (*)()) rmeth
->method
->ncode
;
2146 goto perform_invoke
;
2148 insn_invokeinterface
:
2151 int index
= get2u (pc
); pc
+= 2;
2153 // invokeinterface has two unused bytes...
2156 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2158 sp
-= rmeth
->stack_item_count
;
2160 jobject rcv
= sp
[0].o
;
2165 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2166 rmeth
->method
->name
,
2167 rmeth
->method
->signature
);
2169 goto perform_invoke
;
2175 int index
= get2u (pc
); pc
+= 2;
2176 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2177 _Jv_InitClass (klass
);
2178 jobject res
= _Jv_AllocObject (klass
, klass
->size_in_bytes
);
2186 int atype
= get1u (pc
++);
2188 jobject result
= _Jv_NewArray (atype
, size
);
2196 int index
= get2u (pc
); pc
+= 2;
2197 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2199 _Jv_InitClass (klass
);
2200 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2207 __JArray
*arr
= (__JArray
*)POPA();
2208 NULLARRAYCHECK (arr
);
2209 PUSHI (arr
->length
);
2216 jobject value
= POPA();
2217 throw static_cast<jthrowable
>(value
);
2224 jobject value
= POPA();
2225 jint index
= get2u (pc
); pc
+= 2;
2226 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2228 if (value
!= NULL
&& ! to
->isInstance (value
))
2230 throw new java::lang::ClassCastException (to
->getName());
2240 jobject value
= POPA();
2241 jint index
= get2u (pc
); pc
+= 2;
2242 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2243 PUSHI (to
->isInstance (value
));
2250 jobject value
= POPA();
2252 _Jv_MonitorEnter (value
);
2259 jobject value
= POPA();
2261 _Jv_MonitorExit (value
);
2267 unsigned char* base_pc
= pc
-1;
2268 jint offset
= get2s (pc
); pc
+= 2;
2269 jobject val
= POPA();
2271 pc
= base_pc
+offset
;
2277 unsigned char* base_pc
= pc
-1;
2278 jint offset
= get2s (pc
); pc
+= 2;
2279 jobject val
= POPA();
2281 pc
= base_pc
+offset
;
2288 jint the_mod_op
= get1u (pc
++);
2289 jint wide
= get2u (pc
); pc
+= 2;
2330 pc
= (unsigned char*) PEEKA (wide
);
2335 jint amount
= get2s (pc
); pc
+= 2;
2336 jint value
= PEEKI (wide
);
2337 POKEI (wide
, value
+amount
);
2342 throw_internal_error ("illegal bytecode modified by wide");
2347 insn_multianewarray
:
2350 int kind_index
= get2u (pc
); pc
+= 2;
2351 int dim
= get1u (pc
); pc
+= 1;
2354 = (_Jv_ResolvePoolEntry (defining_class
, kind_index
)).clazz
;
2355 _Jv_InitClass (type
);
2356 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2358 for (int i
= dim
- 1; i
>= 0; i
--)
2363 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2371 unsigned char* base_pc
= pc
-1;
2372 int offset
= get4 (pc
); pc
+= 4;
2373 pc
= base_pc
+offset
;
2379 unsigned char* base_pc
= pc
-1;
2380 int offset
= get4 (pc
); pc
+= 4;
2382 pc
= base_pc
+offset
;
2389 throw_internal_error (char *msg
)
2391 throw new java::lang::InternalError (JvNewStringLatin1 (msg
));
2395 throw_incompatible_class_change_error (jstring msg
)
2397 throw new java::lang::IncompatibleClassChangeError (msg
);
2401 static java::lang::NullPointerException
*null_pointer_exc
;
2403 throw_null_pointer_exception ()
2405 if (null_pointer_exc
== NULL
)
2406 null_pointer_exc
= new java::lang::NullPointerException
;
2408 throw null_pointer_exc
;
2412 #endif // INTERPRETER