1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999 Cygnus Solutions
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/io/PrintStream.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>
39 #include <gnu/gcj/runtime/MethodInvocation.h>
41 /* This should never happen. */
43 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData
*,
46 JvFail ("no interpreter");
51 #define ClassError _CL_Q34java4lang5Error
52 extern java::lang::Class ClassError
;
54 static _Jv_Utf8Const
*init_name
= _Jv_makeUtf8Const ("<init>", 6);
56 static void throw_internal_error (char *msg
)
57 __attribute__ ((__noreturn__
));
58 static void throw_incompatible_class_change_error (jstring msg
)
59 __attribute__ ((__noreturn__
));
61 static void throw_null_pointer_exception ()
62 __attribute__ ((__noreturn__
));
65 static void throw_arithmetic_exception ()
66 __attribute__ ((__noreturn__
));
70 static inline void dupx (_Jv_word
*sp
, int n
, int x
)
72 // first "slide" n+x elements n to the right
74 for (int i
= 0; i
< n
+x
; i
++)
76 sp
[(top
-i
)] = sp
[(top
-i
)-n
];
79 // next, copy the n top elements, n+x down
80 for (int i
= 0; i
< n
; i
++)
82 sp
[top
-(n
+x
)-i
] = sp
[top
-i
];
88 #define PUSHA(V) (sp++)->o = (V)
89 #define PUSHI(V) (sp++)->i = (V)
90 #define PUSHF(V) (sp++)->f = (V)
91 #define PUSHL(V) ({ _Jv_word2 w2; w2.l=(V); \
92 (sp++)->ia[0] = w2.ia[0]; \
93 (sp++)->ia[0] = w2.ia[1]; })
94 #define PUSHD(V) ({ _Jv_word2 w2; w2.d=(V); \
95 (sp++)->ia[0] = w2.ia[0]; \
96 (sp++)->ia[0] = w2.ia[1]; })
98 #define POPA() ((--sp)->o)
99 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
100 #define POPF() ((jfloat) (--sp)->f)
101 #define POPL() ({ _Jv_word2 w2; \
102 w2.ia[1] = (--sp)->ia[0]; \
103 w2.ia[0] = (--sp)->ia[0]; w2.l; })
104 #define POPD() ({ _Jv_word2 w2; \
105 w2.ia[1] = (--sp)->ia[0]; \
106 w2.ia[0] = (--sp)->ia[0]; w2.d; })
108 #define LOADA(I) (sp++)->o = locals[I].o
109 #define LOADI(I) (sp++)->i = locals[I].i
110 #define LOADF(I) (sp++)->f = locals[I].f
111 #define LOADL(I) ({ jint __idx = (I); \
112 (sp++)->ia[0] = locals[__idx].ia[0]; \
113 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
115 #define LOADD(I) LOADL(I)
118 #define STOREA(I) locals[I].o = (--sp)->o
119 #define STOREI(I) locals[I].i = (--sp)->i
120 #define STOREF(I) locals[I].f = (--sp)->f
121 #define STOREL(I) ({ jint __idx = (I); \
122 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
123 locals[__idx].ia[0] = (--sp)->ia[0]; \
125 #define STORED(I) STOREL(I)
127 #define PEEKI(I) (locals+(I))->i
128 #define PEEKA(I) (locals+(I))->o
130 #define POKEI(I,V) ((locals+(I))->i = (V))
133 #define BINOPI(OP) { \
134 jint value2 = POPI(); \
135 jint value1 = POPI(); \
136 PUSHI(value1 OP value2); \
139 #define BINOPF(OP) { \
140 jfloat value2 = POPF(); \
141 jfloat value1 = POPF(); \
142 PUSHF(value1 OP value2); \
145 #define BINOPL(OP) { \
146 jlong value2 = POPL(); \
147 jlong value1 = POPL(); \
148 PUSHL(value1 OP value2); \
151 #define BINOPD(OP) { \
152 jdouble value2 = POPD(); \
153 jdouble value1 = POPD(); \
154 PUSHD(value1 OP value2); \
157 static inline jint
get1s(unsigned char* loc
) {
158 return *(signed char*)loc
;
161 static inline jint
get1u(unsigned char* loc
) {
165 static inline jint
get2s(unsigned char* loc
) {
166 return (((jint
)*(signed char*)loc
) << 8) | ((jint
)*(loc
+1));
169 static inline jint
get2u(unsigned char* loc
) {
170 return (((jint
)(*loc
)) << 8) | ((jint
)*(loc
+1));
173 static jint
get4(unsigned char* loc
) {
174 return (((jint
)(loc
[0])) << 24)
175 | (((jint
)(loc
[1])) << 16)
176 | (((jint
)(loc
[2])) << 8)
177 | (((jint
)(loc
[3])) << 0);
184 #define NULLCHECK(X) \
185 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
191 #define ZEROCHECK(X) \
192 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
195 // this method starts the actual running of the method. It is inlined
196 // in three different variants in the static methods run_normal,
197 // run_sync_object and run_sync_class (see below). Those static methods
198 // are installed directly in the stub for this method (by
199 // _Jv_InterpMethod::ncode, in resolve.cc).
202 _Jv_InterpMethod::run (ffi_cif
* cif
,
205 _Jv_InterpMethodInvocation
*inv
)
208 inv
->pc
= bytecode ();
209 inv
->sp
= inv
->stack_base ();
210 _Jv_word
*locals
= inv
->local_base ();
212 /* Go straight at it! the ffi raw format matches the internal
213 stack representation exactly. At leat, that's the idea.
215 memcpy ((void*) locals
, (void*) args
, args_raw_size
);
218 /* this will call the method _Jv_InterpMethod::continue0, see below */
220 gnu::gcj::runtime::MethodInvocation::continue0
221 ((gnu::gcj::RawData
*)this, (gnu::gcj::RawData
*)inv
);
223 if (ex
== 0) // no exception...
225 /* define sp locally, so the POP? macros will pick it up */
226 _Jv_word
*sp
= inv
->sp
;
227 int rtype
= cif
->rtype
->type
;
229 if (rtype
== FFI_TYPE_POINTER
)
232 *(jobject
*) retp
= r
;
235 else if (rtype
== FFI_TYPE_SINT32
)
241 else if (rtype
== FFI_TYPE_VOID
)
254 case FFI_TYPE_DOUBLE
:
262 case FFI_TYPE_UINT16
:
263 case FFI_TYPE_UINT32
:
265 case FFI_TYPE_SINT16
:
272 case FFI_TYPE_SINT64
:
280 throw_internal_error ("unknown return type");
285 /** handle an exception */
286 if ( find_exception (ex
, inv
) )
289 java::lang::System::out
->println
290 (_Jv_NewStringUTF (self
->name
->data
));
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
);
384 /* this is the exception handler hack, for the interpreter */
386 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData
*meth
,
387 gnu::gcj::RawData
*inv
)
389 _Jv_InterpMethod
*meth0
= (_Jv_InterpMethod
*)meth
;
390 _Jv_InterpMethodInvocation
*inv0
= (_Jv_InterpMethodInvocation
*)inv
;
391 meth0
->continue1 (inv0
);
395 This proceeds execution, as designated in "inv". If an exception
396 happens, then it is simply thrown, and handled in Java. Thus, the pc
397 needs to be stored in the inv->pc at all times, so we can figure
398 out which handler (if any) to invoke.
400 One design issue, which I have not completely considered, is if it
401 should be possible to have interpreted classes linked in! Seldom used
402 (or non-critical) classes could reasonably be interpreted.
407 #define PC_REGISTER_ASM asm("%esi")
409 #define PC_REGISTER_ASM
412 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation
*inv
)
414 using namespace java::lang::reflect
;
416 register _Jv_word
*sp
= inv
->sp
;
417 register unsigned char *pc PC_REGISTER_ASM
= inv
->pc
;
418 _Jv_word
*locals
= inv
->local_base ();
420 _Jv_word
*pool_data
= defining_class
->constants
.data
;
422 /* these two are used in the invokeXXX instructions */
424 _Jv_ResolvedMethod
* rmeth
;
426 #define INSN_LABEL(op) &&insn_##op
427 #define GOTO_INSN(op) goto *(insn_target[op])
429 static const void *const insn_target
[] =
432 INSN_LABEL(aconst_null
),
433 INSN_LABEL(iconst_m1
),
434 INSN_LABEL(iconst_0
),
435 INSN_LABEL(iconst_1
),
436 INSN_LABEL(iconst_2
),
437 INSN_LABEL(iconst_3
),
438 INSN_LABEL(iconst_4
),
439 INSN_LABEL(iconst_5
),
440 INSN_LABEL(lconst_0
),
441 INSN_LABEL(lconst_1
),
442 INSN_LABEL(fconst_0
),
443 INSN_LABEL(fconst_1
),
444 INSN_LABEL(fconst_2
),
445 INSN_LABEL(dconst_0
),
446 INSN_LABEL(dconst_1
),
490 INSN_LABEL(istore_0
),
491 INSN_LABEL(istore_1
),
492 INSN_LABEL(istore_2
),
493 INSN_LABEL(istore_3
),
494 INSN_LABEL(lstore_0
),
495 INSN_LABEL(lstore_1
),
496 INSN_LABEL(lstore_2
),
497 INSN_LABEL(lstore_3
),
498 INSN_LABEL(fstore_0
),
499 INSN_LABEL(fstore_1
),
500 INSN_LABEL(fstore_2
),
501 INSN_LABEL(fstore_3
),
502 INSN_LABEL(dstore_0
),
503 INSN_LABEL(dstore_1
),
504 INSN_LABEL(dstore_2
),
505 INSN_LABEL(dstore_3
),
506 INSN_LABEL(astore_0
),
507 INSN_LABEL(astore_1
),
508 INSN_LABEL(astore_2
),
509 INSN_LABEL(astore_3
),
590 INSN_LABEL(if_icmpeq
),
591 INSN_LABEL(if_icmpne
),
592 INSN_LABEL(if_icmplt
),
593 INSN_LABEL(if_icmpge
),
594 INSN_LABEL(if_icmpgt
),
595 INSN_LABEL(if_icmple
),
596 INSN_LABEL(if_acmpeq
),
597 INSN_LABEL(if_acmpne
),
601 INSN_LABEL(tableswitch
),
602 INSN_LABEL(lookupswitch
),
609 INSN_LABEL(getstatic
),
610 INSN_LABEL(putstatic
),
611 INSN_LABEL(getfield
),
612 INSN_LABEL(putfield
),
613 INSN_LABEL(invokevirtual
),
614 INSN_LABEL(invokespecial
),
615 INSN_LABEL(invokestatic
),
616 INSN_LABEL(invokeinterface
),
617 0, /* op_xxxunusedxxx1, */
619 INSN_LABEL(newarray
),
620 INSN_LABEL(anewarray
),
621 INSN_LABEL(arraylength
),
623 INSN_LABEL(checkcast
),
624 INSN_LABEL(instanceof
),
625 INSN_LABEL(monitorenter
),
626 INSN_LABEL(monitorexit
),
628 INSN_LABEL(multianewarray
),
630 INSN_LABEL(ifnonnull
),
634 INSN_LABEL(putfield_1
),
635 INSN_LABEL(putfield_2
),
636 INSN_LABEL(putfield_4
),
637 INSN_LABEL(putfield_8
),
638 INSN_LABEL(putfield_a
),
640 INSN_LABEL(putstatic_1
),
641 INSN_LABEL(putstatic_2
),
642 INSN_LABEL(putstatic_4
),
643 INSN_LABEL(putstatic_8
),
644 INSN_LABEL(putstatic_a
),
646 INSN_LABEL(getfield_1
),
647 INSN_LABEL(getfield_2s
),
648 INSN_LABEL(getfield_2u
),
649 INSN_LABEL(getfield_4
),
650 INSN_LABEL(getfield_8
),
651 INSN_LABEL(getfield_a
),
653 INSN_LABEL(getstatic_1
),
654 INSN_LABEL(getstatic_2s
),
655 INSN_LABEL(getstatic_2u
),
656 INSN_LABEL(getstatic_4
),
657 INSN_LABEL(getstatic_8
),
658 INSN_LABEL(getstatic_a
),
661 #define SAVE_PC inv->pc = pc-1
663 /* If the macro INLINE_SWITCH is not defined, then the main loop
664 operates as one big (normal) switch statement. If it is defined,
665 then the case selection is performed `inline' in the end of the
666 code for each case. The latter saves a native branch instruction
667 for each java-instruction, but expands the code size somewhat.
669 NOTE: On i386 defining INLINE_SWITCH improves over all
670 performance approximately seven percent, but it may be different
671 for other machines. At some point, this may be made into a proper
672 configuration parameter. */
674 #define INLINE_SWITCH
678 #define NEXT_INSN GOTO_INSN(*pc++)
682 #define NEXT_INSN goto next_insn
689 /* The first few instructions here are ordered according to their
690 frequency, in the hope that this will improve code locality a
693 insn_aload_0
: // 0x2a
698 LOADI (get1u (pc
++));
701 insn_getfield_4
: // 0xd8
704 jobject obj
= POPA();
706 jint field_offset
= get2u (pc
); pc
+= 2;
707 PUSHI (*(jint
*) ((char*)obj
+ field_offset
));
711 insn_iload_1
: // 0x1b
715 insn_getfield_a
: // 0xda
718 jobject obj
= POPA();
720 jint field_offset
= get2u (pc
); pc
+= 2;
721 PUSHA(*(jobject
*) ((char*)obj
+ field_offset
));
725 insn_invokevirtual
: // 0xb6
728 int index
= get2u (pc
); pc
+= 2;
730 /* _Jv_ResolvePoolEntry returns immediately if the value already
731 * is resolved. If we want to clutter up the code here to gain
732 * a little performance, then we can check the corresponding bit
733 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
734 * don't think it is worth it. */
736 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
738 sp
-= rmeth
->stack_item_count
;
741 if (rmeth
->vtable_index
== -1)
743 // final methods do not appear in the vtable,
744 // if it does not appear in the superclass.
745 fun
= (void (*) (...)) rmeth
->method
->ncode
;
749 jobject rcv
= sp
[0].o
;
750 _Jv_VTable
*table
= *(_Jv_VTable
**)rcv
;
751 fun
= (void (*) (...))table
->method
[rmeth
->vtable_index
];
758 /* here goes the magic again... */
759 ffi_cif
*cif
= &rmeth
->cif
;
760 ffi_raw
*raw
= (ffi_raw
*) sp
;
764 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
766 int rtype
= cif
->rtype
->type
;
768 /* the likelyhood of object, int, or void return is very high,
769 * so those are checked before the switch */
770 if (rtype
== FFI_TYPE_POINTER
)
772 PUSHA (*(jobject
*)&rvalue
);
774 else if (rtype
== FFI_TYPE_SINT32
)
776 PUSHI (*(jint
*)&rvalue
);
778 else if (rtype
== FFI_TYPE_VOID
)
786 jbyte value
= (*(jint
*)&rvalue
) & 0xff;
791 case FFI_TYPE_SINT16
:
793 jshort value
= (*(jint
*)&rvalue
) & 0xffff;
798 case FFI_TYPE_UINT16
:
800 jint value
= (*(jint
*)&rvalue
) & 0xffff;
806 PUSHF (*(jfloat
*)&rvalue
);
809 case FFI_TYPE_DOUBLE
:
813 case FFI_TYPE_SINT64
:
814 PUSHL (*(jlong
*)&rvalue
);
818 throw_internal_error ("unknown return type in invokeXXX");
893 PUSHI (get2s(pc
)); pc
+= 2;
898 int index
= get1u (pc
++);
899 PUSHA(pool_data
[index
].o
);
905 int index
= get2u (pc
); pc
+= 2;
906 PUSHA(pool_data
[index
].o
);
912 int index
= get2u (pc
); pc
+= 2;
913 memcpy (sp
, &pool_data
[index
], 2*sizeof (_Jv_word
));
919 LOADL (get1u (pc
++));
923 LOADF (get1u (pc
++));
927 LOADD (get1u (pc
++));
931 LOADA (get1u (pc
++));
1009 jint index
= POPI();
1010 jintArray arr
= (jintArray
) POPA();
1012 if (index
< 0 || index
>= arr
->length
)
1014 _Jv_ThrowBadArrayIndex (index
);
1016 PUSHI( elements(arr
)[index
] );
1023 jint index
= POPI();
1024 jlongArray arr
= (jlongArray
) POPA();
1026 if (index
< 0 || index
>= arr
->length
)
1028 _Jv_ThrowBadArrayIndex (index
);
1030 PUSHL( elements(arr
)[index
] );
1037 jint index
= POPI();
1038 jfloatArray arr
= (jfloatArray
) POPA();
1040 if (index
< 0 || index
>= arr
->length
)
1042 _Jv_ThrowBadArrayIndex (index
);
1044 PUSHF( elements(arr
)[index
] );
1051 jint index
= POPI();
1052 jdoubleArray arr
= (jdoubleArray
) POPA();
1054 if (index
< 0 || index
>= arr
->length
)
1056 _Jv_ThrowBadArrayIndex (index
);
1058 PUSHD( elements(arr
)[index
] );
1065 jint index
= POPI();
1066 jobjectArray arr
= (jobjectArray
) POPA();
1068 if (index
< 0 || index
>= arr
->length
)
1070 _Jv_ThrowBadArrayIndex (index
);
1072 PUSHA( elements(arr
)[index
] );
1079 jint index
= POPI();
1080 jbyteArray arr
= (jbyteArray
) POPA();
1082 if (index
< 0 || index
>= arr
->length
)
1084 _Jv_ThrowBadArrayIndex (index
);
1086 PUSHI( elements(arr
)[index
] );
1093 jint index
= POPI();
1094 jcharArray arr
= (jcharArray
) POPA();
1096 if (index
< 0 || index
>= arr
->length
)
1098 _Jv_ThrowBadArrayIndex (index
);
1100 PUSHI( elements(arr
)[index
] );
1107 jint index
= POPI();
1108 jshortArray arr
= (jshortArray
) POPA();
1110 if (index
< 0 || index
>= arr
->length
)
1112 _Jv_ThrowBadArrayIndex (index
);
1114 PUSHI( elements(arr
)[index
] );
1119 STOREI (get1u (pc
++));
1123 STOREL (get1u (pc
++));
1127 STOREF (get1u (pc
++));
1131 STORED (get1u (pc
++));
1135 STOREI (get1u (pc
++));
1221 jint value
= POPI();
1222 jint index
= POPI();
1223 jintArray arr
= (jintArray
) POPA();
1225 if (index
< 0 || index
>= arr
->length
)
1227 _Jv_ThrowBadArrayIndex (index
);
1229 elements(arr
)[index
] = value
;
1236 jlong value
= POPL();
1237 jint index
= POPI();
1238 jlongArray arr
= (jlongArray
) POPA();
1240 if (index
< 0 || index
>= arr
->length
)
1242 _Jv_ThrowBadArrayIndex (index
);
1244 elements(arr
)[index
] = value
;
1251 jfloat value
= POPF();
1252 jint index
= POPI();
1253 jfloatArray arr
= (jfloatArray
) POPA();
1255 if (index
< 0 || index
>= arr
->length
)
1257 _Jv_ThrowBadArrayIndex (index
);
1259 elements(arr
)[index
] = value
;
1266 jdouble value
= POPD();
1267 jint index
= POPI();
1268 jdoubleArray arr
= (jdoubleArray
) POPA();
1270 if (index
< 0 || index
>= arr
->length
)
1272 _Jv_ThrowBadArrayIndex (index
);
1274 elements(arr
)[index
] = value
;
1281 jobject value
= POPA();
1282 jint index
= POPI();
1283 jobjectArray arr
= (jobjectArray
) POPA();
1285 if (index
< 0 || index
>= arr
->length
)
1287 _Jv_ThrowBadArrayIndex (index
);
1289 _Jv_CheckArrayStore (arr
, value
);
1290 elements(arr
)[index
] = value
;
1297 jbyte value
= (jbyte
) POPI();
1298 jint index
= POPI();
1299 jbyteArray arr
= (jbyteArray
) POPA();
1301 if (index
< 0 || index
>= arr
->length
)
1303 _Jv_ThrowBadArrayIndex (index
);
1305 elements(arr
)[index
] = value
;
1312 jchar value
= (jchar
) POPI();
1313 jint index
= POPI();
1314 jcharArray arr
= (jcharArray
) POPA();
1316 if (index
< 0 || index
>= arr
->length
)
1318 _Jv_ThrowBadArrayIndex (index
);
1320 elements(arr
)[index
] = value
;
1327 jshort value
= (jshort
) POPI();
1328 jint index
= POPI();
1329 jshortArray arr
= (jshortArray
) POPA();
1331 if (index
< 0 || index
>= arr
->length
)
1333 _Jv_ThrowBadArrayIndex (index
);
1335 elements(arr
)[index
] = value
;
1353 dupx (sp
, 1, 1); sp
+=1;
1357 dupx (sp
, 1, 2); sp
+=1;
1367 dupx (sp
, 2, 1); sp
+=2;
1371 dupx (sp
, 2, 2); sp
+=2;
1376 jobject tmp1
= POPA();
1377 jobject tmp2
= POPA();
1434 jint value2
= POPI();
1435 jint value1
= POPI();
1437 jint res
= value1
/ value2
;
1445 jlong value2
= POPL();
1446 jlong value1
= POPL();
1448 jlong res
= value1
/ value2
;
1456 jfloat value2
= POPF();
1457 jfloat value1
= POPF();
1459 jfloat res
= value1
/ value2
;
1467 jdouble value2
= POPD();
1468 jdouble value1
= POPD();
1470 jdouble res
= value1
/ value2
;
1478 jint value2
= POPI();
1479 jint value1
= POPI();
1481 jint res
= value1
% value2
;
1489 jlong value2
= POPL();
1490 jlong value1
= POPL();
1492 jlong res
= value1
% value2
;
1500 jfloat value2
= POPF();
1501 jfloat value1
= POPF();
1503 jfloat res
= __ieee754_fmod (value1
, value2
);
1511 jdouble value2
= POPD();
1512 jdouble value1
= POPD();
1514 jdouble res
= __ieee754_fmod (value1
, value2
);
1521 jint value
= POPI();
1528 jlong value
= POPL();
1535 jfloat value
= POPF();
1542 jdouble value
= POPD();
1549 jint shift
= (POPI() & 0x1f);
1550 jint value
= POPI();
1551 PUSHI (value
<< shift
);
1557 jint shift
= (POPI() & 0x3f);
1558 jlong value
= POPL();
1559 PUSHL (value
<< shift
);
1565 jint shift
= (POPI() & 0x1f);
1566 jint value
= POPI();
1567 PUSHI (value
>> shift
);
1573 jint shift
= (POPI() & 0x3f);
1574 jlong value
= POPL();
1575 PUSHL (value
>> shift
);
1581 jint shift
= (POPI() & 0x1f);
1582 unsigned long value
= POPI();
1583 PUSHI ((jint
) (value
>> shift
));
1589 jint shift
= (POPI() & 0x3f);
1590 UINT64 value
= (UINT64
) POPL();
1591 PUSHL ((value
>> shift
));
1621 jint index
= get1u (pc
++);
1622 jint amount
= get1s (pc
++);
1623 locals
[index
].i
+= amount
;
1628 {jlong value
= POPI(); PUSHL (value
);}
1632 {jfloat value
= POPI(); PUSHF (value
);}
1636 {jdouble value
= POPI(); PUSHD (value
);}
1640 {jint value
= POPL(); PUSHI (value
);}
1644 {jfloat value
= POPL(); PUSHF (value
);}
1648 {jdouble value
= POPL(); PUSHD (value
);}
1652 { jint value
= (jint
)POPF (); PUSHI(value
); }
1656 { jlong value
= (jlong
)POPF (); PUSHL(value
); }
1660 { jdouble value
= POPF (); PUSHD(value
); }
1664 { jint value
= (jint
)POPD (); PUSHI(value
); }
1668 { jlong value
= (jlong
)POPD (); PUSHL(value
); }
1672 { jfloat value
= POPD (); PUSHF(value
); }
1676 { jbyte value
= POPI (); PUSHI(value
); }
1680 { jchar value
= POPI (); PUSHI(value
); }
1684 { jshort value
= POPI (); PUSHI(value
); }
1689 jlong value2
= POPL ();
1690 jlong value1
= POPL ();
1691 if (value1
> value2
)
1693 else if (value1
== value2
)
1703 jfloat value2
= POPF ();
1704 jfloat value1
= POPF ();
1705 if (value1
> value2
)
1707 else if (value1
== value2
)
1709 else if (value1
< value2
)
1711 else if ((*(pc
-1)) == op_fcmpg
)
1721 jdouble value2
= POPD ();
1722 jdouble value1
= POPD ();
1723 if (value1
> value2
)
1725 else if (value1
== value2
)
1727 else if (value1
< value2
)
1729 else if ((*(pc
-1)) == op_dcmpg
)
1738 jint offset
= get2s (pc
);
1748 jint offset
= get2s (pc
);
1758 jint offset
= get2s (pc
);
1768 jint offset
= get2s (pc
);
1778 jint offset
= get2s (pc
);
1788 jint offset
= get2s (pc
);
1798 jint offset
= get2s (pc
);
1799 jint value2
= POPI();
1800 jint value1
= POPI();
1801 if (value1
== value2
)
1810 jint offset
= get2s (pc
);
1811 jint value2
= POPI();
1812 jint value1
= POPI();
1813 if (value1
!= value2
)
1822 jint offset
= get2s (pc
);
1823 jint value2
= POPI();
1824 jint value1
= POPI();
1825 if (value1
< value2
)
1834 jint offset
= get2s (pc
);
1835 jint value2
= POPI();
1836 jint value1
= POPI();
1837 if (value1
>= value2
)
1846 jint offset
= get2s (pc
);
1847 jint value2
= POPI();
1848 jint value1
= POPI();
1849 if (value1
> value2
)
1858 jint offset
= get2s (pc
);
1859 jint value2
= POPI();
1860 jint value1
= POPI();
1861 if (value1
<= value2
)
1870 jint offset
= get2s (pc
);
1871 jobject value2
= POPA();
1872 jobject value1
= POPA();
1873 if (value1
== value2
)
1882 jint offset
= get2s (pc
);
1883 jobject value2
= POPA();
1884 jobject value1
= POPA();
1885 if (value1
!= value2
)
1894 jint offset
= get2s (pc
);
1901 unsigned char *base_pc
= pc
-1;
1902 jint offset
= get2s (pc
); pc
+= 2;
1903 PUSHA ((jobject
)pc
);
1904 pc
= base_pc
+offset
;
1910 jint index
= get1u (pc
);
1911 pc
= (unsigned char*) PEEKA (index
);
1917 unsigned char *base_pc
= pc
-1;
1920 unsigned char* base
= bytecode ();
1921 while ((pc
-base
) % 4 != 0)
1924 jint def
= get4 (pc
);
1925 jint low
= get4 (pc
+4);
1926 jint high
= get4 (pc
+8);
1928 if (index
< low
|| index
> high
)
1931 pc
= base_pc
+ get4 (pc
+4*(index
-low
+3));
1937 unsigned char *base_pc
= pc
-1;
1940 unsigned char* base
= bytecode ();
1941 while ((pc
-base
) % 4 != 0)
1944 jint def
= get4 (pc
);
1945 jint npairs
= get4 (pc
+4);
1950 // simple binary search...
1953 int half
= (min
+max
)/2;
1954 int match
= get4 (pc
+ 4*(2 + 2*half
));
1959 else if (index
< match
)
1966 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1967 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1973 /* on return, just save the sp and return to caller */
1986 unsigned char *base_pc
= pc
-1;
1987 jint fieldref_index
= get2u (pc
); pc
+= 2;
1988 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
1989 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1991 if ((field
->flags
& Modifier::STATIC
) == 0)
1992 throw_incompatible_class_change_error
1993 (JvNewStringLatin1 ("field no longer static"));
1995 jclass type
= field
->type
;
1997 if (type
->isPrimitive ())
1999 switch (type
->size_in_bytes
)
2002 *base_pc
= op_getstatic_1
;
2006 if (type
== JvPrimClass (char))
2007 *base_pc
= op_getstatic_2u
;
2009 *base_pc
= op_getstatic_2s
;
2013 *base_pc
= op_getstatic_4
;
2017 *base_pc
= op_getstatic_8
;
2023 *base_pc
= op_getstatic_a
;
2033 unsigned char *base_pc
= pc
-1;
2034 jint fieldref_index
= get2u (pc
); pc
+= 2;
2035 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2036 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2038 if ((field
->flags
& Modifier::STATIC
) != 0)
2039 throw_incompatible_class_change_error
2040 (JvNewStringLatin1 ("field is static"));
2042 jclass type
= field
->type
;
2044 if (type
->isPrimitive ())
2046 switch (type
->size_in_bytes
)
2049 *base_pc
= op_getfield_1
;
2053 if (type
== JvPrimClass (char))
2054 *base_pc
= op_getfield_2u
;
2056 *base_pc
= op_getfield_2s
;
2060 *base_pc
= op_getfield_4
;
2064 *base_pc
= op_getfield_8
;
2070 *base_pc
= op_getfield_a
;
2073 if (field
->u
.boffset
> 0xffff)
2074 JvThrow (new java::lang::VirtualMachineError
);
2076 base_pc
[1] = (field
->u
.boffset
>>8) & 0xff;
2077 base_pc
[2] = field
->u
.boffset
& 0xff;
2086 unsigned char* base_pc
= pc
-1;
2087 jint fieldref_index
= get2u (pc
); pc
+= 2;
2088 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2089 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2091 jclass type
= field
->type
;
2093 // ResolvePoolEntry cannot check this
2094 if ((field
->flags
& Modifier::STATIC
) == 0)
2095 throw_incompatible_class_change_error
2096 (JvNewStringLatin1 ("field no longer static"));
2098 /* if this is patented, then maybe we could install
2099 a function in the constant pool, to do the right thing */
2101 if (type
->isPrimitive ())
2103 switch (type
->size_in_bytes
)
2106 *base_pc
= op_putstatic_1
;
2110 *base_pc
= op_putstatic_2
;
2114 *base_pc
= op_putstatic_4
;
2118 *base_pc
= op_putstatic_8
;
2124 *base_pc
= op_putstatic_a
;
2127 // do the instruction again!
2136 unsigned char* base_pc
= pc
-1;
2137 jint fieldref_index
= get2u (pc
); pc
+= 2;
2138 _Jv_ResolvePoolEntry (defining_class
, fieldref_index
);
2139 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2141 jclass type
= field
->type
;
2143 if ((field
->flags
& Modifier::STATIC
) != 0)
2144 throw_incompatible_class_change_error
2145 (JvNewStringLatin1 ("field is static"));
2147 if (type
->isPrimitive ())
2149 switch (type
->size_in_bytes
)
2152 *base_pc
= op_putfield_1
;
2156 *base_pc
= op_putfield_2
;
2160 *base_pc
= op_putfield_4
;
2164 *base_pc
= op_putfield_8
;
2170 *base_pc
= op_putfield_a
;
2173 if (field
->u
.boffset
> 0xffff)
2174 JvThrow (new java::lang::VirtualMachineError
);
2176 base_pc
[1] = (field
->u
.boffset
>>8) & 0xff;
2177 base_pc
[2] = field
->u
.boffset
& 0xff;
2179 // do the instruction again!
2188 jobject obj
= POPA();
2190 jint field_offset
= get2u (pc
); pc
+= 2;
2191 PUSHI (*(jbyte
*) ((char*)obj
+ field_offset
));
2198 jobject obj
= POPA();
2200 jint field_offset
= get2u (pc
); pc
+= 2;
2201 PUSHI (*(jshort
*) ((char*)obj
+ field_offset
));
2208 jobject obj
= POPA();
2210 jint field_offset
= get2u (pc
); pc
+= 2;
2211 PUSHI (*(jchar
*) ((char*)obj
+ field_offset
));
2218 jobject obj
= POPA();
2220 jint field_offset
= get2u (pc
); pc
+= 2;
2221 PUSHL(*(jlong
*) ((char*)obj
+ field_offset
));
2227 jint fieldref_index
= get2u (pc
); pc
+= 2;
2228 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2229 PUSHI (*(jbyte
*) (field
->u
.addr
));
2235 jint fieldref_index
= get2u (pc
); pc
+= 2;
2236 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2237 PUSHI(*(jshort
*) (field
->u
.addr
));
2243 jint fieldref_index
= get2u (pc
); pc
+= 2;
2244 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2245 PUSHI(*(jchar
*) (field
->u
.addr
));
2251 jint fieldref_index
= get2u (pc
); pc
+= 2;
2252 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2253 PUSHI(*(jint
*) (field
->u
.addr
));
2259 jint fieldref_index
= get2u (pc
); pc
+= 2;
2260 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2261 PUSHL(*(jlong
*) (field
->u
.addr
));
2267 jint fieldref_index
= get2u (pc
); pc
+= 2;
2268 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2269 PUSHA(*(jobject
*) (field
->u
.addr
));
2276 jint value
= POPI();
2277 jobject obj
= POPA();
2279 jint field_offset
= get2u (pc
); pc
+= 2;
2280 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2287 jint value
= POPI();
2288 jobject obj
= POPA();
2290 jint field_offset
= get2u (pc
); pc
+= 2;
2291 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2298 jint value
= POPI();
2299 jobject obj
= POPA();
2301 jint field_offset
= get2u (pc
); pc
+= 2;
2302 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2309 jlong value
= POPL();
2310 jobject obj
= POPA();
2312 jint field_offset
= get2u (pc
); pc
+= 2;
2313 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2320 jobject value
= POPA();
2321 jobject obj
= POPA();
2323 jint field_offset
= get2u (pc
); pc
+= 2;
2324 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2330 jint value
= POPI();
2331 jint fieldref_index
= get2u (pc
); pc
+= 2;
2332 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2333 *(jbyte
*) (field
->u
.addr
) = value
;
2339 jint value
= POPI();
2340 jint fieldref_index
= get2u (pc
); pc
+= 2;
2341 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2342 *(jchar
*) (field
->u
.addr
) = value
;
2348 jint value
= POPI();
2349 jint fieldref_index
= get2u (pc
); pc
+= 2;
2350 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2351 *(jint
*) (field
->u
.addr
) = value
;
2357 jlong value
= POPL();
2358 jint fieldref_index
= get2u (pc
); pc
+= 2;
2359 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2360 *(jlong
*) (field
->u
.addr
) = value
;
2366 jobject value
= POPA();
2367 jint fieldref_index
= get2u (pc
); pc
+= 2;
2368 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2369 *(jobject
*) (field
->u
.addr
) = value
;
2376 int index
= get2u (pc
); pc
+= 2;
2378 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2380 sp
-= rmeth
->stack_item_count
;
2384 fun
= (void (*) (...))rmeth
->method
->ncode
;
2386 goto perform_invoke
;
2391 int index
= get2u (pc
); pc
+= 2;
2393 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2395 sp
-= rmeth
->stack_item_count
;
2397 _Jv_InitClass (rmeth
->klass
);
2398 fun
= (void (*) (...))rmeth
->method
->ncode
;
2400 goto perform_invoke
;
2402 insn_invokeinterface
:
2405 int index
= get2u (pc
); pc
+= 2;
2407 // invokeinterface has two unused bytes...
2410 rmeth
= (_Jv_ResolvePoolEntry (defining_class
, index
)).rmethod
;
2412 sp
-= rmeth
->stack_item_count
;
2415 jobject rcv
= sp
[0].o
;
2417 fun
= (void (*) (...))
2418 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2419 rmeth
->method
->name
,
2420 rmeth
->method
->signature
);
2422 goto perform_invoke
;
2428 int index
= get2u (pc
); pc
+= 2;
2429 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2430 _Jv_InitClass (klass
);
2431 jobject res
= _Jv_AllocObject (klass
, klass
->size_in_bytes
);
2439 int atype
= get1u (pc
++);
2441 jobject result
= _Jv_NewArray (atype
, size
);
2449 int index
= get2u (pc
); pc
+= 2;
2450 jclass klass
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2452 _Jv_InitClass (klass
);
2453 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2461 __JArray
*arr
= (__JArray
*)POPA();
2462 PUSHI (arr
->length
);
2469 jobject value
= POPA();
2477 jobject value
= POPA();
2478 jint index
= get2u (pc
); pc
+= 2;
2479 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2481 if (value
!= NULL
&& ! to
->isInstance (value
))
2483 JvThrow (new java::lang::ClassCastException
2494 jobject value
= POPA();
2495 jint index
= get2u (pc
); pc
+= 2;
2496 jclass to
= (_Jv_ResolvePoolEntry (defining_class
, index
)).clazz
;
2497 PUSHI (to
->isInstance (value
));
2504 jobject value
= POPA();
2506 _Jv_MonitorEnter (value
);
2513 jobject value
= POPA();
2515 _Jv_MonitorExit (value
);
2521 unsigned char* base_pc
= pc
-1;
2522 jint offset
= get2s (pc
); pc
+= 2;
2523 jobject val
= POPA();
2525 pc
= base_pc
+offset
;
2531 unsigned char* base_pc
= pc
-1;
2532 jint offset
= get2s (pc
); pc
+= 2;
2533 jobject val
= POPA();
2535 pc
= base_pc
+offset
;
2542 jint the_mod_op
= get1u (pc
++);
2543 jint wide
= get2u (pc
); pc
+= 2;
2584 pc
= (unsigned char*) PEEKA (wide
);
2589 jint amount
= get2s (pc
); pc
+= 2;
2590 jint value
= PEEKI (wide
);
2591 POKEI (wide
, value
+amount
);
2596 throw_internal_error ("illegal bytecode modified by wide");
2601 insn_multianewarray
:
2604 int kind_index
= get2u (pc
); pc
+= 2;
2605 int dim
= get1u (pc
); pc
+= 1;
2608 = (_Jv_ResolvePoolEntry (defining_class
, kind_index
)).clazz
;
2609 _Jv_InitClass (type
);
2610 jint
*sizes
= (jint
*) alloca (sizeof (jint
)*dim
);
2612 for (int i
= dim
- 1; i
>= 0; i
--)
2617 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2625 unsigned char* base_pc
= pc
-1;
2626 int offset
= get4 (pc
); pc
+= 4;
2627 pc
= base_pc
+offset
;
2633 unsigned char* base_pc
= pc
-1;
2634 int offset
= get4 (pc
); pc
+= 4;
2636 pc
= base_pc
+offset
;
2643 throw_internal_error (char *msg
)
2645 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg
)));
2649 throw_incompatible_class_change_error (jstring msg
)
2651 JvThrow (new java::lang::IncompatibleClassChangeError (msg
));
2655 static java::lang::NullPointerException
*null_pointer_exc
;
2657 throw_null_pointer_exception ()
2659 if (null_pointer_exc
== NULL
)
2660 null_pointer_exc
= new java::lang::NullPointerException
;
2662 JvThrow (null_pointer_exc
);
2667 static java::lang::ArithmeticException
*arithmetic_exc
;
2669 throw_arithmetic_exception ()
2671 if (arithmetic_exc
== NULL
)
2672 arithmetic_exc
= new java::lang::ArithmeticException
2673 (JvNewStringLatin1 ("/ by zero"));
2675 JvThrow (arithmetic_exc
);
2680 #endif // INTERPRETER