fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / libjava / interpret.cc
blobc5d2afdb905325e5f4fe84ca9323de674dc00ac2
1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003 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
9 details. */
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
13 #include <config.h>
15 // Define this to get the direct-threaded interpreter. If undefined,
16 // we revert to a basic bytecode interpreter. The former is faster
17 // but uses more memory.
18 #define DIRECT_THREADED
20 #pragma implementation "java-interp.h"
22 #include <jvm.h>
23 #include <java-cpool.h>
24 #include <java-interp.h>
25 #include <java/lang/System.h>
26 #include <java/lang/String.h>
27 #include <java/lang/Integer.h>
28 #include <java/lang/Long.h>
29 #include <java/lang/StringBuffer.h>
30 #include <java/lang/Class.h>
31 #include <java/lang/reflect/Modifier.h>
32 #include <java/lang/ClassCastException.h>
33 #include <java/lang/VirtualMachineError.h>
34 #include <java/lang/InternalError.h>
35 #include <java/lang/NullPointerException.h>
36 #include <java/lang/ArithmeticException.h>
37 #include <java/lang/IncompatibleClassChangeError.h>
38 #include <java/lang/Thread.h>
39 #include <java-insns.h>
40 #include <java-signal.h>
42 #ifdef INTERPRETER
44 #include <stdlib.h>
46 using namespace gcj;
48 static void throw_internal_error (char *msg)
49 __attribute__ ((__noreturn__));
50 static void throw_incompatible_class_change_error (jstring msg)
51 __attribute__ ((__noreturn__));
52 #ifndef HANDLE_SEGV
53 static void throw_null_pointer_exception ()
54 __attribute__ ((__noreturn__));
55 #endif
57 #ifdef DIRECT_THREADED
58 // Lock to ensure that methods are not compiled concurrently.
59 // We could use a finer-grained lock here, however it is not safe to use
60 // the Class monitor as user code in another thread could hold it.
61 static _Jv_Mutex_t compile_mutex;
63 void
64 _Jv_InitInterpreter()
66 _Jv_MutexInit (&compile_mutex);
68 #else
69 void _Jv_InitInterpreter() {}
70 #endif
72 extern "C" double __ieee754_fmod (double,double);
74 // This represents a single slot in the "compiled" form of the
75 // bytecode.
76 union insn_slot
78 // Address of code.
79 void *insn;
80 // An integer value used by an instruction.
81 jint int_val;
82 // A pointer value used by an instruction.
83 void *datum;
86 // The type of the PC depends on whether we're doing direct threading
87 // or a more ordinary bytecode interpreter.
88 #ifdef DIRECT_THREADED
89 typedef insn_slot *pc_t;
90 #else
91 typedef unsigned char *pc_t;
92 #endif
94 static inline void dupx (_Jv_word *sp, int n, int x)
96 // first "slide" n+x elements n to the right
97 int top = n-1;
98 for (int i = 0; i < n+x; i++)
100 sp[(top-i)] = sp[(top-i)-n];
103 // next, copy the n top elements, n+x down
104 for (int i = 0; i < n; i++)
106 sp[top-(n+x)-i] = sp[top-i];
111 // Used to convert from floating types to integral types.
112 template<typename TO, typename FROM>
113 static inline TO
114 convert (FROM val, TO min, TO max)
116 TO ret;
117 if (val >= (FROM) max)
118 ret = max;
119 else if (val <= (FROM) min)
120 ret = min;
121 else if (val != val)
122 ret = 0;
123 else
124 ret = (TO) val;
125 return ret;
128 #define PUSHA(V) (sp++)->o = (V)
129 #define PUSHI(V) (sp++)->i = (V)
130 #define PUSHF(V) (sp++)->f = (V)
131 #if SIZEOF_VOID_P == 8
132 # define PUSHL(V) (sp->l = (V), sp += 2)
133 # define PUSHD(V) (sp->d = (V), sp += 2)
134 #else
135 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
136 (sp++)->ia[0] = w2.ia[0]; \
137 (sp++)->ia[0] = w2.ia[1]; } while (0)
138 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
139 (sp++)->ia[0] = w2.ia[0]; \
140 (sp++)->ia[0] = w2.ia[1]; } while (0)
141 #endif
143 #define POPA() ((--sp)->o)
144 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
145 #define POPF() ((jfloat) (--sp)->f)
146 #if SIZEOF_VOID_P == 8
147 # define POPL() (sp -= 2, (jlong) sp->l)
148 # define POPD() (sp -= 2, (jdouble) sp->d)
149 #else
150 # define POPL() ({ _Jv_word2 w2; \
151 w2.ia[1] = (--sp)->ia[0]; \
152 w2.ia[0] = (--sp)->ia[0]; w2.l; })
153 # define POPD() ({ _Jv_word2 w2; \
154 w2.ia[1] = (--sp)->ia[0]; \
155 w2.ia[0] = (--sp)->ia[0]; w2.d; })
156 #endif
158 #define LOADA(I) (sp++)->o = locals[I].o
159 #define LOADI(I) (sp++)->i = locals[I].i
160 #define LOADF(I) (sp++)->f = locals[I].f
161 #if SIZEOF_VOID_P == 8
162 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
163 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
164 #else
165 # define LOADL(I) do { jint __idx = (I); \
166 (sp++)->ia[0] = locals[__idx].ia[0]; \
167 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
168 } while (0)
169 # define LOADD(I) LOADL(I)
170 #endif
172 #define STOREA(I) locals[I].o = (--sp)->o
173 #define STOREI(I) locals[I].i = (--sp)->i
174 #define STOREF(I) locals[I].f = (--sp)->f
175 #if SIZEOF_VOID_P == 8
176 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
177 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
178 #else
179 # define STOREL(I) do { jint __idx = (I); \
180 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
181 locals[__idx].ia[0] = (--sp)->ia[0]; \
182 } while (0)
183 # define STORED(I) STOREL(I)
184 #endif
186 #define PEEKI(I) (locals+(I))->i
187 #define PEEKA(I) (locals+(I))->o
189 #define POKEI(I,V) ((locals+(I))->i = (V))
192 #define BINOPI(OP) { \
193 jint value2 = POPI(); \
194 jint value1 = POPI(); \
195 PUSHI(value1 OP value2); \
198 #define BINOPF(OP) { \
199 jfloat value2 = POPF(); \
200 jfloat value1 = POPF(); \
201 PUSHF(value1 OP value2); \
204 #define BINOPL(OP) { \
205 jlong value2 = POPL(); \
206 jlong value1 = POPL(); \
207 PUSHL(value1 OP value2); \
210 #define BINOPD(OP) { \
211 jdouble value2 = POPD(); \
212 jdouble value1 = POPD(); \
213 PUSHD(value1 OP value2); \
216 static inline jint get1s(unsigned char* loc) {
217 return *(signed char*)loc;
220 static inline jint get1u(unsigned char* loc) {
221 return *loc;
224 static inline jint get2s(unsigned char* loc) {
225 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
228 static inline jint get2u(unsigned char* loc) {
229 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
232 static jint get4(unsigned char* loc) {
233 return (((jint)(loc[0])) << 24)
234 | (((jint)(loc[1])) << 16)
235 | (((jint)(loc[2])) << 8)
236 | (((jint)(loc[3])) << 0);
240 #ifdef HANDLE_SEGV
241 #define NULLCHECK(X)
242 #define NULLARRAYCHECK(X)
243 #else
244 #define NULLCHECK(X) \
245 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
246 #define NULLARRAYCHECK(X) \
247 do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
248 #endif
250 #define ARRAYBOUNDSCHECK(array, index) \
251 do \
253 if (((unsigned) index) >= (unsigned) (array->length)) \
254 _Jv_ThrowBadArrayIndex (index); \
256 while (0)
258 void
259 _Jv_InterpMethod::run_normal (ffi_cif *,
260 void* ret,
261 ffi_raw * args,
262 void* __this)
264 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
265 _this->run (ret, args);
268 void
269 _Jv_InterpMethod::run_synch_object (ffi_cif *,
270 void* ret,
271 ffi_raw * args,
272 void* __this)
274 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
276 jobject rcv = (jobject) args[0].ptr;
277 JvSynchronize mutex (rcv);
279 _this->run (ret, args);
282 void
283 _Jv_InterpMethod::run_class (ffi_cif *,
284 void* ret,
285 ffi_raw * args,
286 void* __this)
288 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
289 _Jv_InitClass (_this->defining_class);
290 _this->run (ret, args);
293 void
294 _Jv_InterpMethod::run_synch_class (ffi_cif *,
295 void* ret,
296 ffi_raw * args,
297 void* __this)
299 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
301 jclass sync = _this->defining_class;
302 _Jv_InitClass (sync);
303 JvSynchronize mutex (sync);
305 _this->run (ret, args);
308 #ifdef DIRECT_THREADED
309 // "Compile" a method by turning it from bytecode to direct-threaded
310 // code.
311 void
312 _Jv_InterpMethod::compile (const void * const *insn_targets)
314 insn_slot *insns = NULL;
315 int next = 0;
316 unsigned char *codestart = bytecode ();
317 unsigned char *end = codestart + code_length;
318 _Jv_word *pool_data = defining_class->constants.data;
320 #define SET_ONE(Field, Value) \
321 do \
323 if (first_pass) \
324 ++next; \
325 else \
326 insns[next++].Field = Value; \
328 while (0)
330 #define SET_INSN(Value) SET_ONE (insn, (void *) Value)
331 #define SET_INT(Value) SET_ONE (int_val, Value)
332 #define SET_DATUM(Value) SET_ONE (datum, Value)
334 // Map from bytecode PC to slot in INSNS.
335 int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
336 for (int i = 0; i < code_length; ++i)
337 pc_mapping[i] = -1;
339 for (int i = 0; i < 2; ++i)
341 jboolean first_pass = i == 0;
343 if (! first_pass)
345 insns = (insn_slot *) _Jv_AllocBytes (sizeof (insn_slot) * next);
346 next = 0;
349 unsigned char *pc = codestart;
350 while (pc < end)
352 int base_pc_val = pc - codestart;
353 if (first_pass)
354 pc_mapping[base_pc_val] = next;
356 java_opcode opcode = (java_opcode) *pc++;
357 // Just elide NOPs.
358 if (opcode == op_nop)
359 continue;
360 SET_INSN (insn_targets[opcode]);
362 switch (opcode)
364 case op_nop:
365 case op_aconst_null:
366 case op_iconst_m1:
367 case op_iconst_0:
368 case op_iconst_1:
369 case op_iconst_2:
370 case op_iconst_3:
371 case op_iconst_4:
372 case op_iconst_5:
373 case op_lconst_0:
374 case op_lconst_1:
375 case op_fconst_0:
376 case op_fconst_1:
377 case op_fconst_2:
378 case op_dconst_0:
379 case op_dconst_1:
380 case op_iload_0:
381 case op_iload_1:
382 case op_iload_2:
383 case op_iload_3:
384 case op_lload_0:
385 case op_lload_1:
386 case op_lload_2:
387 case op_lload_3:
388 case op_fload_0:
389 case op_fload_1:
390 case op_fload_2:
391 case op_fload_3:
392 case op_dload_0:
393 case op_dload_1:
394 case op_dload_2:
395 case op_dload_3:
396 case op_aload_0:
397 case op_aload_1:
398 case op_aload_2:
399 case op_aload_3:
400 case op_iaload:
401 case op_laload:
402 case op_faload:
403 case op_daload:
404 case op_aaload:
405 case op_baload:
406 case op_caload:
407 case op_saload:
408 case op_istore_0:
409 case op_istore_1:
410 case op_istore_2:
411 case op_istore_3:
412 case op_lstore_0:
413 case op_lstore_1:
414 case op_lstore_2:
415 case op_lstore_3:
416 case op_fstore_0:
417 case op_fstore_1:
418 case op_fstore_2:
419 case op_fstore_3:
420 case op_dstore_0:
421 case op_dstore_1:
422 case op_dstore_2:
423 case op_dstore_3:
424 case op_astore_0:
425 case op_astore_1:
426 case op_astore_2:
427 case op_astore_3:
428 case op_iastore:
429 case op_lastore:
430 case op_fastore:
431 case op_dastore:
432 case op_aastore:
433 case op_bastore:
434 case op_castore:
435 case op_sastore:
436 case op_pop:
437 case op_pop2:
438 case op_dup:
439 case op_dup_x1:
440 case op_dup_x2:
441 case op_dup2:
442 case op_dup2_x1:
443 case op_dup2_x2:
444 case op_swap:
445 case op_iadd:
446 case op_isub:
447 case op_imul:
448 case op_idiv:
449 case op_irem:
450 case op_ishl:
451 case op_ishr:
452 case op_iushr:
453 case op_iand:
454 case op_ior:
455 case op_ixor:
456 case op_ladd:
457 case op_lsub:
458 case op_lmul:
459 case op_ldiv:
460 case op_lrem:
461 case op_lshl:
462 case op_lshr:
463 case op_lushr:
464 case op_land:
465 case op_lor:
466 case op_lxor:
467 case op_fadd:
468 case op_fsub:
469 case op_fmul:
470 case op_fdiv:
471 case op_frem:
472 case op_dadd:
473 case op_dsub:
474 case op_dmul:
475 case op_ddiv:
476 case op_drem:
477 case op_ineg:
478 case op_i2b:
479 case op_i2c:
480 case op_i2s:
481 case op_lneg:
482 case op_fneg:
483 case op_dneg:
484 case op_i2l:
485 case op_i2f:
486 case op_i2d:
487 case op_l2i:
488 case op_l2f:
489 case op_l2d:
490 case op_f2i:
491 case op_f2l:
492 case op_f2d:
493 case op_d2i:
494 case op_d2l:
495 case op_d2f:
496 case op_lcmp:
497 case op_fcmpl:
498 case op_fcmpg:
499 case op_dcmpl:
500 case op_dcmpg:
501 case op_monitorenter:
502 case op_monitorexit:
503 case op_ireturn:
504 case op_lreturn:
505 case op_freturn:
506 case op_dreturn:
507 case op_areturn:
508 case op_return:
509 case op_athrow:
510 case op_arraylength:
511 // No argument, nothing else to do.
512 break;
514 case op_bipush:
515 SET_INT (get1s (pc));
516 ++pc;
517 break;
519 case op_ldc:
521 int index = get1u (pc);
522 ++pc;
523 SET_DATUM (pool_data[index].o);
525 break;
527 case op_ret:
528 case op_iload:
529 case op_lload:
530 case op_fload:
531 case op_dload:
532 case op_aload:
533 case op_istore:
534 case op_lstore:
535 case op_fstore:
536 case op_dstore:
537 case op_astore:
538 case op_newarray:
539 SET_INT (get1u (pc));
540 ++pc;
541 break;
543 case op_iinc:
544 SET_INT (get1u (pc));
545 SET_INT (get1s (pc + 1));
546 pc += 2;
547 break;
549 case op_ldc_w:
551 int index = get2u (pc);
552 pc += 2;
553 SET_DATUM (pool_data[index].o);
555 break;
557 case op_ldc2_w:
559 int index = get2u (pc);
560 pc += 2;
561 SET_DATUM (&pool_data[index]);
563 break;
565 case op_sipush:
566 SET_INT (get2s (pc));
567 pc += 2;
568 break;
570 case op_new:
571 case op_getstatic:
572 case op_getfield:
573 case op_putfield:
574 case op_putstatic:
575 case op_anewarray:
576 case op_instanceof:
577 case op_checkcast:
578 case op_invokespecial:
579 case op_invokestatic:
580 case op_invokevirtual:
581 SET_INT (get2u (pc));
582 pc += 2;
583 break;
585 case op_multianewarray:
586 SET_INT (get2u (pc));
587 SET_INT (get1u (pc + 2));
588 pc += 3;
589 break;
591 case op_jsr:
592 case op_ifeq:
593 case op_ifne:
594 case op_iflt:
595 case op_ifge:
596 case op_ifgt:
597 case op_ifle:
598 case op_if_icmpeq:
599 case op_if_icmpne:
600 case op_if_icmplt:
601 case op_if_icmpge:
602 case op_if_icmpgt:
603 case op_if_icmple:
604 case op_if_acmpeq:
605 case op_if_acmpne:
606 case op_ifnull:
607 case op_ifnonnull:
608 case op_goto:
610 int offset = get2s (pc);
611 pc += 2;
613 int new_pc = base_pc_val + offset;
615 bool orig_was_goto = opcode == op_goto;
617 // Thread jumps. We limit the loop count; this lets
618 // us avoid infinite loops if the bytecode contains
619 // such. `10' is arbitrary.
620 int count = 10;
621 while (codestart[new_pc] == op_goto && count-- > 0)
622 new_pc += get2s (&codestart[new_pc + 1]);
624 // If the jump takes us to a `return' instruction and
625 // the original branch was an unconditional goto, then
626 // we hoist the return.
627 opcode = (java_opcode) codestart[new_pc];
628 if (orig_was_goto
629 && (opcode == op_ireturn || opcode == op_lreturn
630 || opcode == op_freturn || opcode == op_dreturn
631 || opcode == op_areturn || opcode == op_return))
633 --next;
634 SET_INSN (insn_targets[opcode]);
636 else
637 SET_DATUM (&insns[pc_mapping[new_pc]]);
639 break;
641 case op_tableswitch:
643 while ((pc - codestart) % 4 != 0)
644 ++pc;
646 jint def = get4 (pc);
647 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
648 pc += 4;
650 int low = get4 (pc);
651 SET_INT (low);
652 pc += 4;
653 int high = get4 (pc);
654 SET_INT (high);
655 pc += 4;
657 for (int i = low; i <= high; ++i)
659 SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
660 pc += 4;
663 break;
665 case op_lookupswitch:
667 while ((pc - codestart) % 4 != 0)
668 ++pc;
670 jint def = get4 (pc);
671 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
672 pc += 4;
674 jint npairs = get4 (pc);
675 pc += 4;
676 SET_INT (npairs);
678 while (npairs-- > 0)
680 jint match = get4 (pc);
681 jint offset = get4 (pc + 4);
682 SET_INT (match);
683 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
684 pc += 8;
687 break;
689 case op_invokeinterface:
691 jint index = get2u (pc);
692 pc += 2;
693 // We ignore the next two bytes.
694 pc += 2;
695 SET_INT (index);
697 break;
699 case op_wide:
701 opcode = (java_opcode) get1u (pc);
702 pc += 1;
703 jint val = get2u (pc);
704 pc += 2;
706 // We implement narrow and wide instructions using the
707 // same code in the interpreter. So we rewrite the
708 // instruction slot here.
709 if (! first_pass)
710 insns[next - 1].insn = (void *) insn_targets[opcode];
711 SET_INT (val);
713 if (opcode == op_iinc)
715 SET_INT (get2s (pc));
716 pc += 2;
719 break;
721 case op_jsr_w:
722 case op_goto_w:
724 jint offset = get4 (pc);
725 pc += 4;
726 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
728 break;
730 // Some "can't happen" cases that we include for
731 // error-checking purposes.
732 case op_putfield_1:
733 case op_putfield_2:
734 case op_putfield_4:
735 case op_putfield_8:
736 case op_putfield_a:
737 case op_putstatic_1:
738 case op_putstatic_2:
739 case op_putstatic_4:
740 case op_putstatic_8:
741 case op_putstatic_a:
742 case op_getfield_1:
743 case op_getfield_2s:
744 case op_getfield_2u:
745 case op_getfield_4:
746 case op_getfield_8:
747 case op_getfield_a:
748 case op_getstatic_1:
749 case op_getstatic_2s:
750 case op_getstatic_2u:
751 case op_getstatic_4:
752 case op_getstatic_8:
753 case op_getstatic_a:
754 default:
755 // Fail somehow.
756 break;
761 // Now update exceptions.
762 _Jv_InterpException *exc = exceptions ();
763 for (int i = 0; i < exc_count; ++i)
765 exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
766 exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
767 exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
768 jclass handler = (_Jv_ResolvePoolEntry (defining_class,
769 exc[i].handler_type.i)).clazz;
770 exc[i].handler_type.p = handler;
773 prepared = insns;
775 #endif /* DIRECT_THREADED */
777 // This function exists so that the stack-tracing code can find the
778 // boundaries of the interpreter.
779 void
780 _Jv_StartOfInterpreter (void)
784 void
785 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
787 using namespace java::lang::reflect;
789 // FRAME_DESC registers this particular invocation as the top-most
790 // interpreter frame. This lets the stack tracing code (for
791 // Throwable) print information about the method being interpreted
792 // rather than about the interpreter itself. FRAME_DESC has a
793 // destructor so it cleans up automatically when the interpreter
794 // returns.
795 java::lang::Thread *thread = java::lang::Thread::currentThread();
796 _Jv_MethodChain frame_desc (this,
797 (_Jv_MethodChain **) &thread->interp_frame);
799 _Jv_word stack[max_stack];
800 _Jv_word *sp = stack;
802 _Jv_word locals[max_locals];
804 /* Go straight at it! the ffi raw format matches the internal
805 stack representation exactly. At least, that's the idea.
807 memcpy ((void*) locals, (void*) args, args_raw_size);
809 _Jv_word *pool_data = defining_class->constants.data;
811 /* These three are temporaries for common code used by several
812 instructions. */
813 void (*fun)();
814 _Jv_ResolvedMethod* rmeth;
815 int tmpval;
817 #define INSN_LABEL(op) &&insn_##op
819 static const void *const insn_target[] =
821 INSN_LABEL(nop),
822 INSN_LABEL(aconst_null),
823 INSN_LABEL(iconst_m1),
824 INSN_LABEL(iconst_0),
825 INSN_LABEL(iconst_1),
826 INSN_LABEL(iconst_2),
827 INSN_LABEL(iconst_3),
828 INSN_LABEL(iconst_4),
829 INSN_LABEL(iconst_5),
830 INSN_LABEL(lconst_0),
831 INSN_LABEL(lconst_1),
832 INSN_LABEL(fconst_0),
833 INSN_LABEL(fconst_1),
834 INSN_LABEL(fconst_2),
835 INSN_LABEL(dconst_0),
836 INSN_LABEL(dconst_1),
837 INSN_LABEL(bipush),
838 INSN_LABEL(sipush),
839 INSN_LABEL(ldc),
840 INSN_LABEL(ldc_w),
841 INSN_LABEL(ldc2_w),
842 INSN_LABEL(iload),
843 INSN_LABEL(lload),
844 INSN_LABEL(fload),
845 INSN_LABEL(dload),
846 INSN_LABEL(aload),
847 INSN_LABEL(iload_0),
848 INSN_LABEL(iload_1),
849 INSN_LABEL(iload_2),
850 INSN_LABEL(iload_3),
851 INSN_LABEL(lload_0),
852 INSN_LABEL(lload_1),
853 INSN_LABEL(lload_2),
854 INSN_LABEL(lload_3),
855 INSN_LABEL(fload_0),
856 INSN_LABEL(fload_1),
857 INSN_LABEL(fload_2),
858 INSN_LABEL(fload_3),
859 INSN_LABEL(dload_0),
860 INSN_LABEL(dload_1),
861 INSN_LABEL(dload_2),
862 INSN_LABEL(dload_3),
863 INSN_LABEL(aload_0),
864 INSN_LABEL(aload_1),
865 INSN_LABEL(aload_2),
866 INSN_LABEL(aload_3),
867 INSN_LABEL(iaload),
868 INSN_LABEL(laload),
869 INSN_LABEL(faload),
870 INSN_LABEL(daload),
871 INSN_LABEL(aaload),
872 INSN_LABEL(baload),
873 INSN_LABEL(caload),
874 INSN_LABEL(saload),
875 INSN_LABEL(istore),
876 INSN_LABEL(lstore),
877 INSN_LABEL(fstore),
878 INSN_LABEL(dstore),
879 INSN_LABEL(astore),
880 INSN_LABEL(istore_0),
881 INSN_LABEL(istore_1),
882 INSN_LABEL(istore_2),
883 INSN_LABEL(istore_3),
884 INSN_LABEL(lstore_0),
885 INSN_LABEL(lstore_1),
886 INSN_LABEL(lstore_2),
887 INSN_LABEL(lstore_3),
888 INSN_LABEL(fstore_0),
889 INSN_LABEL(fstore_1),
890 INSN_LABEL(fstore_2),
891 INSN_LABEL(fstore_3),
892 INSN_LABEL(dstore_0),
893 INSN_LABEL(dstore_1),
894 INSN_LABEL(dstore_2),
895 INSN_LABEL(dstore_3),
896 INSN_LABEL(astore_0),
897 INSN_LABEL(astore_1),
898 INSN_LABEL(astore_2),
899 INSN_LABEL(astore_3),
900 INSN_LABEL(iastore),
901 INSN_LABEL(lastore),
902 INSN_LABEL(fastore),
903 INSN_LABEL(dastore),
904 INSN_LABEL(aastore),
905 INSN_LABEL(bastore),
906 INSN_LABEL(castore),
907 INSN_LABEL(sastore),
908 INSN_LABEL(pop),
909 INSN_LABEL(pop2),
910 INSN_LABEL(dup),
911 INSN_LABEL(dup_x1),
912 INSN_LABEL(dup_x2),
913 INSN_LABEL(dup2),
914 INSN_LABEL(dup2_x1),
915 INSN_LABEL(dup2_x2),
916 INSN_LABEL(swap),
917 INSN_LABEL(iadd),
918 INSN_LABEL(ladd),
919 INSN_LABEL(fadd),
920 INSN_LABEL(dadd),
921 INSN_LABEL(isub),
922 INSN_LABEL(lsub),
923 INSN_LABEL(fsub),
924 INSN_LABEL(dsub),
925 INSN_LABEL(imul),
926 INSN_LABEL(lmul),
927 INSN_LABEL(fmul),
928 INSN_LABEL(dmul),
929 INSN_LABEL(idiv),
930 INSN_LABEL(ldiv),
931 INSN_LABEL(fdiv),
932 INSN_LABEL(ddiv),
933 INSN_LABEL(irem),
934 INSN_LABEL(lrem),
935 INSN_LABEL(frem),
936 INSN_LABEL(drem),
937 INSN_LABEL(ineg),
938 INSN_LABEL(lneg),
939 INSN_LABEL(fneg),
940 INSN_LABEL(dneg),
941 INSN_LABEL(ishl),
942 INSN_LABEL(lshl),
943 INSN_LABEL(ishr),
944 INSN_LABEL(lshr),
945 INSN_LABEL(iushr),
946 INSN_LABEL(lushr),
947 INSN_LABEL(iand),
948 INSN_LABEL(land),
949 INSN_LABEL(ior),
950 INSN_LABEL(lor),
951 INSN_LABEL(ixor),
952 INSN_LABEL(lxor),
953 INSN_LABEL(iinc),
954 INSN_LABEL(i2l),
955 INSN_LABEL(i2f),
956 INSN_LABEL(i2d),
957 INSN_LABEL(l2i),
958 INSN_LABEL(l2f),
959 INSN_LABEL(l2d),
960 INSN_LABEL(f2i),
961 INSN_LABEL(f2l),
962 INSN_LABEL(f2d),
963 INSN_LABEL(d2i),
964 INSN_LABEL(d2l),
965 INSN_LABEL(d2f),
966 INSN_LABEL(i2b),
967 INSN_LABEL(i2c),
968 INSN_LABEL(i2s),
969 INSN_LABEL(lcmp),
970 INSN_LABEL(fcmpl),
971 INSN_LABEL(fcmpg),
972 INSN_LABEL(dcmpl),
973 INSN_LABEL(dcmpg),
974 INSN_LABEL(ifeq),
975 INSN_LABEL(ifne),
976 INSN_LABEL(iflt),
977 INSN_LABEL(ifge),
978 INSN_LABEL(ifgt),
979 INSN_LABEL(ifle),
980 INSN_LABEL(if_icmpeq),
981 INSN_LABEL(if_icmpne),
982 INSN_LABEL(if_icmplt),
983 INSN_LABEL(if_icmpge),
984 INSN_LABEL(if_icmpgt),
985 INSN_LABEL(if_icmple),
986 INSN_LABEL(if_acmpeq),
987 INSN_LABEL(if_acmpne),
988 INSN_LABEL(goto),
989 INSN_LABEL(jsr),
990 INSN_LABEL(ret),
991 INSN_LABEL(tableswitch),
992 INSN_LABEL(lookupswitch),
993 INSN_LABEL(ireturn),
994 INSN_LABEL(lreturn),
995 INSN_LABEL(freturn),
996 INSN_LABEL(dreturn),
997 INSN_LABEL(areturn),
998 INSN_LABEL(return),
999 INSN_LABEL(getstatic),
1000 INSN_LABEL(putstatic),
1001 INSN_LABEL(getfield),
1002 INSN_LABEL(putfield),
1003 INSN_LABEL(invokevirtual),
1004 INSN_LABEL(invokespecial),
1005 INSN_LABEL(invokestatic),
1006 INSN_LABEL(invokeinterface),
1007 0, /* Unused. */
1008 INSN_LABEL(new),
1009 INSN_LABEL(newarray),
1010 INSN_LABEL(anewarray),
1011 INSN_LABEL(arraylength),
1012 INSN_LABEL(athrow),
1013 INSN_LABEL(checkcast),
1014 INSN_LABEL(instanceof),
1015 INSN_LABEL(monitorenter),
1016 INSN_LABEL(monitorexit),
1017 #ifdef DIRECT_THREADED
1018 0, // wide
1019 #else
1020 INSN_LABEL(wide),
1021 #endif
1022 INSN_LABEL(multianewarray),
1023 INSN_LABEL(ifnull),
1024 INSN_LABEL(ifnonnull),
1025 INSN_LABEL(goto_w),
1026 INSN_LABEL(jsr_w),
1030 pc_t pc;
1032 #ifdef DIRECT_THREADED
1034 #define NEXT_INSN goto *((pc++)->insn)
1035 #define INTVAL() ((pc++)->int_val)
1036 #define AVAL() ((pc++)->datum)
1038 #define GET1S() INTVAL ()
1039 #define GET2S() INTVAL ()
1040 #define GET1U() INTVAL ()
1041 #define GET2U() INTVAL ()
1042 #define AVAL1U() AVAL ()
1043 #define AVAL2U() AVAL ()
1044 #define AVAL2UP() AVAL ()
1045 #define SKIP_GOTO ++pc
1046 #define GOTO_VAL() (insn_slot *) pc->datum
1047 #define PCVAL(unionval) unionval.p
1048 #define AMPAMP(label) &&label
1050 // Compile if we must. NOTE: Double-check locking.
1051 if (prepared == NULL)
1053 _Jv_MutexLock (&compile_mutex);
1054 if (prepared == NULL)
1055 compile (insn_target);
1056 _Jv_MutexUnlock (&compile_mutex);
1058 pc = (insn_slot *) prepared;
1060 #else
1062 #define NEXT_INSN goto *(insn_target[*pc++])
1064 #define GET1S() get1s (pc++)
1065 #define GET2S() (pc += 2, get2s (pc- 2))
1066 #define GET1U() get1u (pc++)
1067 #define GET2U() (pc += 2, get2u (pc - 2))
1068 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1069 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1070 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1071 #define SKIP_GOTO pc += 2
1072 #define GOTO_VAL() pc - 1 + get2s (pc)
1073 #define PCVAL(unionval) unionval.i
1074 #define AMPAMP(label) NULL
1076 pc = bytecode ();
1078 #endif /* DIRECT_THREADED */
1080 #define TAKE_GOTO pc = GOTO_VAL ()
1084 // We keep nop around. It is used if we're interpreting the
1085 // bytecodes and not doing direct threading.
1086 insn_nop:
1087 NEXT_INSN;
1089 /* The first few instructions here are ordered according to their
1090 frequency, in the hope that this will improve code locality a
1091 little. */
1093 insn_aload_0: // 0x2a
1094 LOADA (0);
1095 NEXT_INSN;
1097 insn_iload: // 0x15
1098 LOADI (GET1U ());
1099 NEXT_INSN;
1101 insn_iload_1: // 0x1b
1102 LOADI (1);
1103 NEXT_INSN;
1105 insn_invokevirtual: // 0xb6
1107 int index = GET2U ();
1109 /* _Jv_ResolvePoolEntry returns immediately if the value already
1110 * is resolved. If we want to clutter up the code here to gain
1111 * a little performance, then we can check the corresponding bit
1112 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
1113 * don't think it is worth it. */
1115 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
1117 sp -= rmeth->stack_item_count;
1118 // We don't use NULLCHECK here because we can't rely on that
1119 // working if the method is final. So instead we do an
1120 // explicit test.
1121 if (! sp[0].o)
1122 throw new java::lang::NullPointerException;
1124 if (rmeth->vtable_index == -1)
1126 // final methods do not appear in the vtable,
1127 // if it does not appear in the superclass.
1128 fun = (void (*)()) rmeth->method->ncode;
1130 else
1132 jobject rcv = sp[0].o;
1133 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1134 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1137 #ifdef DIRECT_THREADED
1138 // Rewrite instruction so that we use a faster pre-resolved
1139 // method.
1140 pc[-2].insn = &&invokevirtual_resolved;
1141 pc[-1].datum = rmeth;
1142 #endif /* DIRECT_THREADED */
1144 goto perform_invoke;
1146 #ifdef DIRECT_THREADED
1147 invokevirtual_resolved:
1149 rmeth = (_Jv_ResolvedMethod *) AVAL ();
1150 sp -= rmeth->stack_item_count;
1151 // We don't use NULLCHECK here because we can't rely on that
1152 // working if the method is final. So instead we do an
1153 // explicit test.
1154 if (! sp[0].o)
1155 throw new java::lang::NullPointerException;
1157 if (rmeth->vtable_index == -1)
1159 // final methods do not appear in the vtable,
1160 // if it does not appear in the superclass.
1161 fun = (void (*)()) rmeth->method->ncode;
1163 else
1165 jobject rcv = sp[0].o;
1166 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1167 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1170 goto perform_invoke;
1171 #endif /* DIRECT_THREADED */
1173 perform_invoke:
1175 /* here goes the magic again... */
1176 ffi_cif *cif = &rmeth->cif;
1177 ffi_raw *raw = (ffi_raw*) sp;
1179 jdouble rvalue;
1181 #if FFI_NATIVE_RAW_API
1182 /* We assume that this is only implemented if it's correct */
1183 /* to use it here. On a 64 bit machine, it never is. */
1184 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
1185 #else
1186 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
1187 #endif
1189 int rtype = cif->rtype->type;
1191 /* the likelyhood of object, int, or void return is very high,
1192 * so those are checked before the switch */
1193 if (rtype == FFI_TYPE_POINTER)
1195 PUSHA (*(jobject*)&rvalue);
1197 else if (rtype == FFI_TYPE_SINT32)
1199 PUSHI (*(jint*)&rvalue);
1201 else if (rtype == FFI_TYPE_VOID)
1203 /* skip */
1205 else
1207 switch (rtype)
1209 case FFI_TYPE_SINT8:
1211 jbyte value = (*(jint*)&rvalue) & 0xff;
1212 PUSHI (value);
1214 break;
1216 case FFI_TYPE_SINT16:
1218 jshort value = (*(jint*)&rvalue) & 0xffff;
1219 PUSHI (value);
1221 break;
1223 case FFI_TYPE_UINT16:
1225 jint value = (*(jint*)&rvalue) & 0xffff;
1226 PUSHI (value);
1228 break;
1230 case FFI_TYPE_FLOAT:
1231 PUSHF (*(jfloat*)&rvalue);
1232 break;
1234 case FFI_TYPE_DOUBLE:
1235 PUSHD (rvalue);
1236 break;
1238 case FFI_TYPE_SINT64:
1239 PUSHL (*(jlong*)&rvalue);
1240 break;
1242 default:
1243 throw_internal_error ("unknown return type in invokeXXX");
1247 NEXT_INSN;
1249 insn_aconst_null:
1250 PUSHA (NULL);
1251 NEXT_INSN;
1253 insn_iconst_m1:
1254 PUSHI (-1);
1255 NEXT_INSN;
1257 insn_iconst_0:
1258 PUSHI (0);
1259 NEXT_INSN;
1261 insn_iconst_1:
1262 PUSHI (1);
1263 NEXT_INSN;
1265 insn_iconst_2:
1266 PUSHI (2);
1267 NEXT_INSN;
1269 insn_iconst_3:
1270 PUSHI (3);
1271 NEXT_INSN;
1273 insn_iconst_4:
1274 PUSHI (4);
1275 NEXT_INSN;
1277 insn_iconst_5:
1278 PUSHI (5);
1279 NEXT_INSN;
1281 insn_lconst_0:
1282 PUSHL (0);
1283 NEXT_INSN;
1285 insn_lconst_1:
1286 PUSHL (1);
1287 NEXT_INSN;
1289 insn_fconst_0:
1290 PUSHF (0);
1291 NEXT_INSN;
1293 insn_fconst_1:
1294 PUSHF (1);
1295 NEXT_INSN;
1297 insn_fconst_2:
1298 PUSHF (2);
1299 NEXT_INSN;
1301 insn_dconst_0:
1302 PUSHD (0);
1303 NEXT_INSN;
1305 insn_dconst_1:
1306 PUSHD (1);
1307 NEXT_INSN;
1309 insn_bipush:
1310 // For direct threaded, bipush and sipush are the same.
1311 #ifndef DIRECT_THREADED
1312 PUSHI (GET1S ());
1313 NEXT_INSN;
1314 #endif /* DIRECT_THREADED */
1315 insn_sipush:
1316 PUSHI (GET2S ());
1317 NEXT_INSN;
1319 insn_ldc:
1320 // For direct threaded, ldc and ldc_w are the same.
1321 #ifndef DIRECT_THREADED
1322 PUSHA ((jobject) AVAL1U ());
1323 NEXT_INSN;
1324 #endif /* DIRECT_THREADED */
1325 insn_ldc_w:
1326 PUSHA ((jobject) AVAL2U ());
1327 NEXT_INSN;
1329 insn_ldc2_w:
1331 void *where = AVAL2UP ();
1332 memcpy (sp, where, 2*sizeof (_Jv_word));
1333 sp += 2;
1335 NEXT_INSN;
1337 insn_lload:
1338 LOADL (GET1U ());
1339 NEXT_INSN;
1341 insn_fload:
1342 LOADF (GET1U ());
1343 NEXT_INSN;
1345 insn_dload:
1346 LOADD (GET1U ());
1347 NEXT_INSN;
1349 insn_aload:
1350 LOADA (GET1U ());
1351 NEXT_INSN;
1353 insn_iload_0:
1354 LOADI (0);
1355 NEXT_INSN;
1357 insn_iload_2:
1358 LOADI (2);
1359 NEXT_INSN;
1361 insn_iload_3:
1362 LOADI (3);
1363 NEXT_INSN;
1365 insn_lload_0:
1366 LOADL (0);
1367 NEXT_INSN;
1369 insn_lload_1:
1370 LOADL (1);
1371 NEXT_INSN;
1373 insn_lload_2:
1374 LOADL (2);
1375 NEXT_INSN;
1377 insn_lload_3:
1378 LOADL (3);
1379 NEXT_INSN;
1381 insn_fload_0:
1382 LOADF (0);
1383 NEXT_INSN;
1385 insn_fload_1:
1386 LOADF (1);
1387 NEXT_INSN;
1389 insn_fload_2:
1390 LOADF (2);
1391 NEXT_INSN;
1393 insn_fload_3:
1394 LOADF (3);
1395 NEXT_INSN;
1397 insn_dload_0:
1398 LOADD (0);
1399 NEXT_INSN;
1401 insn_dload_1:
1402 LOADD (1);
1403 NEXT_INSN;
1405 insn_dload_2:
1406 LOADD (2);
1407 NEXT_INSN;
1409 insn_dload_3:
1410 LOADD (3);
1411 NEXT_INSN;
1413 insn_aload_1:
1414 LOADA(1);
1415 NEXT_INSN;
1417 insn_aload_2:
1418 LOADA(2);
1419 NEXT_INSN;
1421 insn_aload_3:
1422 LOADA(3);
1423 NEXT_INSN;
1425 insn_iaload:
1427 jint index = POPI();
1428 jintArray arr = (jintArray) POPA();
1429 NULLARRAYCHECK (arr);
1430 ARRAYBOUNDSCHECK (arr, index);
1431 PUSHI( elements(arr)[index] );
1433 NEXT_INSN;
1435 insn_laload:
1437 jint index = POPI();
1438 jlongArray arr = (jlongArray) POPA();
1439 NULLARRAYCHECK (arr);
1440 ARRAYBOUNDSCHECK (arr, index);
1441 PUSHL( elements(arr)[index] );
1443 NEXT_INSN;
1445 insn_faload:
1447 jint index = POPI();
1448 jfloatArray arr = (jfloatArray) POPA();
1449 NULLARRAYCHECK (arr);
1450 ARRAYBOUNDSCHECK (arr, index);
1451 PUSHF( elements(arr)[index] );
1453 NEXT_INSN;
1455 insn_daload:
1457 jint index = POPI();
1458 jdoubleArray arr = (jdoubleArray) POPA();
1459 NULLARRAYCHECK (arr);
1460 ARRAYBOUNDSCHECK (arr, index);
1461 PUSHD( elements(arr)[index] );
1463 NEXT_INSN;
1465 insn_aaload:
1467 jint index = POPI();
1468 jobjectArray arr = (jobjectArray) POPA();
1469 NULLARRAYCHECK (arr);
1470 ARRAYBOUNDSCHECK (arr, index);
1471 PUSHA( elements(arr)[index] );
1473 NEXT_INSN;
1475 insn_baload:
1477 jint index = POPI();
1478 jbyteArray arr = (jbyteArray) POPA();
1479 NULLARRAYCHECK (arr);
1480 ARRAYBOUNDSCHECK (arr, index);
1481 PUSHI( elements(arr)[index] );
1483 NEXT_INSN;
1485 insn_caload:
1487 jint index = POPI();
1488 jcharArray arr = (jcharArray) POPA();
1489 NULLARRAYCHECK (arr);
1490 ARRAYBOUNDSCHECK (arr, index);
1491 PUSHI( elements(arr)[index] );
1493 NEXT_INSN;
1495 insn_saload:
1497 jint index = POPI();
1498 jshortArray arr = (jshortArray) POPA();
1499 NULLARRAYCHECK (arr);
1500 ARRAYBOUNDSCHECK (arr, index);
1501 PUSHI( elements(arr)[index] );
1503 NEXT_INSN;
1505 insn_istore:
1506 STOREI (GET1U ());
1507 NEXT_INSN;
1509 insn_lstore:
1510 STOREL (GET1U ());
1511 NEXT_INSN;
1513 insn_fstore:
1514 STOREF (GET1U ());
1515 NEXT_INSN;
1517 insn_dstore:
1518 STORED (GET1U ());
1519 NEXT_INSN;
1521 insn_astore:
1522 STOREA (GET1U ());
1523 NEXT_INSN;
1525 insn_istore_0:
1526 STOREI (0);
1527 NEXT_INSN;
1529 insn_istore_1:
1530 STOREI (1);
1531 NEXT_INSN;
1533 insn_istore_2:
1534 STOREI (2);
1535 NEXT_INSN;
1537 insn_istore_3:
1538 STOREI (3);
1539 NEXT_INSN;
1541 insn_lstore_0:
1542 STOREL (0);
1543 NEXT_INSN;
1545 insn_lstore_1:
1546 STOREL (1);
1547 NEXT_INSN;
1549 insn_lstore_2:
1550 STOREL (2);
1551 NEXT_INSN;
1553 insn_lstore_3:
1554 STOREL (3);
1555 NEXT_INSN;
1557 insn_fstore_0:
1558 STOREF (0);
1559 NEXT_INSN;
1561 insn_fstore_1:
1562 STOREF (1);
1563 NEXT_INSN;
1565 insn_fstore_2:
1566 STOREF (2);
1567 NEXT_INSN;
1569 insn_fstore_3:
1570 STOREF (3);
1571 NEXT_INSN;
1573 insn_dstore_0:
1574 STORED (0);
1575 NEXT_INSN;
1577 insn_dstore_1:
1578 STORED (1);
1579 NEXT_INSN;
1581 insn_dstore_2:
1582 STORED (2);
1583 NEXT_INSN;
1585 insn_dstore_3:
1586 STORED (3);
1587 NEXT_INSN;
1589 insn_astore_0:
1590 STOREA(0);
1591 NEXT_INSN;
1593 insn_astore_1:
1594 STOREA(1);
1595 NEXT_INSN;
1597 insn_astore_2:
1598 STOREA(2);
1599 NEXT_INSN;
1601 insn_astore_3:
1602 STOREA(3);
1603 NEXT_INSN;
1605 insn_iastore:
1607 jint value = POPI();
1608 jint index = POPI();
1609 jintArray arr = (jintArray) POPA();
1610 NULLARRAYCHECK (arr);
1611 ARRAYBOUNDSCHECK (arr, index);
1612 elements(arr)[index] = value;
1614 NEXT_INSN;
1616 insn_lastore:
1618 jlong value = POPL();
1619 jint index = POPI();
1620 jlongArray arr = (jlongArray) POPA();
1621 NULLARRAYCHECK (arr);
1622 ARRAYBOUNDSCHECK (arr, index);
1623 elements(arr)[index] = value;
1625 NEXT_INSN;
1627 insn_fastore:
1629 jfloat value = POPF();
1630 jint index = POPI();
1631 jfloatArray arr = (jfloatArray) POPA();
1632 NULLARRAYCHECK (arr);
1633 ARRAYBOUNDSCHECK (arr, index);
1634 elements(arr)[index] = value;
1636 NEXT_INSN;
1638 insn_dastore:
1640 jdouble value = POPD();
1641 jint index = POPI();
1642 jdoubleArray arr = (jdoubleArray) POPA();
1643 NULLARRAYCHECK (arr);
1644 ARRAYBOUNDSCHECK (arr, index);
1645 elements(arr)[index] = value;
1647 NEXT_INSN;
1649 insn_aastore:
1651 jobject value = POPA();
1652 jint index = POPI();
1653 jobjectArray arr = (jobjectArray) POPA();
1654 NULLARRAYCHECK (arr);
1655 ARRAYBOUNDSCHECK (arr, index);
1656 _Jv_CheckArrayStore (arr, value);
1657 elements(arr)[index] = value;
1659 NEXT_INSN;
1661 insn_bastore:
1663 jbyte value = (jbyte) POPI();
1664 jint index = POPI();
1665 jbyteArray arr = (jbyteArray) POPA();
1666 NULLARRAYCHECK (arr);
1667 ARRAYBOUNDSCHECK (arr, index);
1668 elements(arr)[index] = value;
1670 NEXT_INSN;
1672 insn_castore:
1674 jchar value = (jchar) POPI();
1675 jint index = POPI();
1676 jcharArray arr = (jcharArray) POPA();
1677 NULLARRAYCHECK (arr);
1678 ARRAYBOUNDSCHECK (arr, index);
1679 elements(arr)[index] = value;
1681 NEXT_INSN;
1683 insn_sastore:
1685 jshort value = (jshort) POPI();
1686 jint index = POPI();
1687 jshortArray arr = (jshortArray) POPA();
1688 NULLARRAYCHECK (arr);
1689 ARRAYBOUNDSCHECK (arr, index);
1690 elements(arr)[index] = value;
1692 NEXT_INSN;
1694 insn_pop:
1695 sp -= 1;
1696 NEXT_INSN;
1698 insn_pop2:
1699 sp -= 2;
1700 NEXT_INSN;
1702 insn_dup:
1703 sp[0] = sp[-1];
1704 sp += 1;
1705 NEXT_INSN;
1707 insn_dup_x1:
1708 dupx (sp, 1, 1); sp+=1;
1709 NEXT_INSN;
1711 insn_dup_x2:
1712 dupx (sp, 1, 2); sp+=1;
1713 NEXT_INSN;
1715 insn_dup2:
1716 sp[0] = sp[-2];
1717 sp[1] = sp[-1];
1718 sp += 2;
1719 NEXT_INSN;
1721 insn_dup2_x1:
1722 dupx (sp, 2, 1); sp+=2;
1723 NEXT_INSN;
1725 insn_dup2_x2:
1726 dupx (sp, 2, 2); sp+=2;
1727 NEXT_INSN;
1729 insn_swap:
1731 jobject tmp1 = POPA();
1732 jobject tmp2 = POPA();
1733 PUSHA (tmp1);
1734 PUSHA (tmp2);
1736 NEXT_INSN;
1738 insn_iadd:
1739 BINOPI(+);
1740 NEXT_INSN;
1742 insn_ladd:
1743 BINOPL(+);
1744 NEXT_INSN;
1746 insn_fadd:
1747 BINOPF(+);
1748 NEXT_INSN;
1750 insn_dadd:
1751 BINOPD(+);
1752 NEXT_INSN;
1754 insn_isub:
1755 BINOPI(-);
1756 NEXT_INSN;
1758 insn_lsub:
1759 BINOPL(-);
1760 NEXT_INSN;
1762 insn_fsub:
1763 BINOPF(-);
1764 NEXT_INSN;
1766 insn_dsub:
1767 BINOPD(-);
1768 NEXT_INSN;
1770 insn_imul:
1771 BINOPI(*);
1772 NEXT_INSN;
1774 insn_lmul:
1775 BINOPL(*);
1776 NEXT_INSN;
1778 insn_fmul:
1779 BINOPF(*);
1780 NEXT_INSN;
1782 insn_dmul:
1783 BINOPD(*);
1784 NEXT_INSN;
1786 insn_idiv:
1788 jint value2 = POPI();
1789 jint value1 = POPI();
1790 jint res = _Jv_divI (value1, value2);
1791 PUSHI (res);
1793 NEXT_INSN;
1795 insn_ldiv:
1797 jlong value2 = POPL();
1798 jlong value1 = POPL();
1799 jlong res = _Jv_divJ (value1, value2);
1800 PUSHL (res);
1802 NEXT_INSN;
1804 insn_fdiv:
1806 jfloat value2 = POPF();
1807 jfloat value1 = POPF();
1808 jfloat res = value1 / value2;
1809 PUSHF (res);
1811 NEXT_INSN;
1813 insn_ddiv:
1815 jdouble value2 = POPD();
1816 jdouble value1 = POPD();
1817 jdouble res = value1 / value2;
1818 PUSHD (res);
1820 NEXT_INSN;
1822 insn_irem:
1824 jint value2 = POPI();
1825 jint value1 = POPI();
1826 jint res = _Jv_remI (value1, value2);
1827 PUSHI (res);
1829 NEXT_INSN;
1831 insn_lrem:
1833 jlong value2 = POPL();
1834 jlong value1 = POPL();
1835 jlong res = _Jv_remJ (value1, value2);
1836 PUSHL (res);
1838 NEXT_INSN;
1840 insn_frem:
1842 jfloat value2 = POPF();
1843 jfloat value1 = POPF();
1844 jfloat res = __ieee754_fmod (value1, value2);
1845 PUSHF (res);
1847 NEXT_INSN;
1849 insn_drem:
1851 jdouble value2 = POPD();
1852 jdouble value1 = POPD();
1853 jdouble res = __ieee754_fmod (value1, value2);
1854 PUSHD (res);
1856 NEXT_INSN;
1858 insn_ineg:
1860 jint value = POPI();
1861 PUSHI (value * -1);
1863 NEXT_INSN;
1865 insn_lneg:
1867 jlong value = POPL();
1868 PUSHL (value * -1);
1870 NEXT_INSN;
1872 insn_fneg:
1874 jfloat value = POPF();
1875 PUSHF (value * -1);
1877 NEXT_INSN;
1879 insn_dneg:
1881 jdouble value = POPD();
1882 PUSHD (value * -1);
1884 NEXT_INSN;
1886 insn_ishl:
1888 jint shift = (POPI() & 0x1f);
1889 jint value = POPI();
1890 PUSHI (value << shift);
1892 NEXT_INSN;
1894 insn_lshl:
1896 jint shift = (POPI() & 0x3f);
1897 jlong value = POPL();
1898 PUSHL (value << shift);
1900 NEXT_INSN;
1902 insn_ishr:
1904 jint shift = (POPI() & 0x1f);
1905 jint value = POPI();
1906 PUSHI (value >> shift);
1908 NEXT_INSN;
1910 insn_lshr:
1912 jint shift = (POPI() & 0x3f);
1913 jlong value = POPL();
1914 PUSHL (value >> shift);
1916 NEXT_INSN;
1918 insn_iushr:
1920 jint shift = (POPI() & 0x1f);
1921 _Jv_uint value = (_Jv_uint) POPI();
1922 PUSHI ((jint) (value >> shift));
1924 NEXT_INSN;
1926 insn_lushr:
1928 jint shift = (POPI() & 0x3f);
1929 _Jv_ulong value = (_Jv_ulong) POPL();
1930 PUSHL ((jlong) (value >> shift));
1932 NEXT_INSN;
1934 insn_iand:
1935 BINOPI (&);
1936 NEXT_INSN;
1938 insn_land:
1939 BINOPL (&);
1940 NEXT_INSN;
1942 insn_ior:
1943 BINOPI (|);
1944 NEXT_INSN;
1946 insn_lor:
1947 BINOPL (|);
1948 NEXT_INSN;
1950 insn_ixor:
1951 BINOPI (^);
1952 NEXT_INSN;
1954 insn_lxor:
1955 BINOPL (^);
1956 NEXT_INSN;
1958 insn_iinc:
1960 jint index = GET1U ();
1961 jint amount = GET1S ();
1962 locals[index].i += amount;
1964 NEXT_INSN;
1966 insn_i2l:
1967 {jlong value = POPI(); PUSHL (value);}
1968 NEXT_INSN;
1970 insn_i2f:
1971 {jfloat value = POPI(); PUSHF (value);}
1972 NEXT_INSN;
1974 insn_i2d:
1975 {jdouble value = POPI(); PUSHD (value);}
1976 NEXT_INSN;
1978 insn_l2i:
1979 {jint value = POPL(); PUSHI (value);}
1980 NEXT_INSN;
1982 insn_l2f:
1983 {jfloat value = POPL(); PUSHF (value);}
1984 NEXT_INSN;
1986 insn_l2d:
1987 {jdouble value = POPL(); PUSHD (value);}
1988 NEXT_INSN;
1990 insn_f2i:
1992 using namespace java::lang;
1993 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1994 PUSHI(value);
1996 NEXT_INSN;
1998 insn_f2l:
2000 using namespace java::lang;
2001 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
2002 PUSHL(value);
2004 NEXT_INSN;
2006 insn_f2d:
2007 { jdouble value = POPF (); PUSHD(value); }
2008 NEXT_INSN;
2010 insn_d2i:
2012 using namespace java::lang;
2013 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
2014 PUSHI(value);
2016 NEXT_INSN;
2018 insn_d2l:
2020 using namespace java::lang;
2021 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
2022 PUSHL(value);
2024 NEXT_INSN;
2026 insn_d2f:
2027 { jfloat value = POPD (); PUSHF(value); }
2028 NEXT_INSN;
2030 insn_i2b:
2031 { jbyte value = POPI (); PUSHI(value); }
2032 NEXT_INSN;
2034 insn_i2c:
2035 { jchar value = POPI (); PUSHI(value); }
2036 NEXT_INSN;
2038 insn_i2s:
2039 { jshort value = POPI (); PUSHI(value); }
2040 NEXT_INSN;
2042 insn_lcmp:
2044 jlong value2 = POPL ();
2045 jlong value1 = POPL ();
2046 if (value1 > value2)
2047 { PUSHI (1); }
2048 else if (value1 == value2)
2049 { PUSHI (0); }
2050 else
2051 { PUSHI (-1); }
2053 NEXT_INSN;
2055 insn_fcmpl:
2056 tmpval = -1;
2057 goto fcmp;
2059 insn_fcmpg:
2060 tmpval = 1;
2062 fcmp:
2064 jfloat value2 = POPF ();
2065 jfloat value1 = POPF ();
2066 if (value1 > value2)
2067 PUSHI (1);
2068 else if (value1 == value2)
2069 PUSHI (0);
2070 else if (value1 < value2)
2071 PUSHI (-1);
2072 else
2073 PUSHI (tmpval);
2075 NEXT_INSN;
2077 insn_dcmpl:
2078 tmpval = 1;
2079 goto dcmp;
2081 insn_dcmpg:
2082 tmpval = -1;
2084 dcmp:
2086 jdouble value2 = POPD ();
2087 jdouble value1 = POPD ();
2088 if (value1 > value2)
2089 PUSHI (1);
2090 else if (value1 == value2)
2091 PUSHI (0);
2092 else if (value1 < value2)
2093 PUSHI (-1);
2094 else
2095 PUSHI (tmpval);
2097 NEXT_INSN;
2099 insn_ifeq:
2101 if (POPI() == 0)
2102 TAKE_GOTO;
2103 else
2104 SKIP_GOTO;
2106 NEXT_INSN;
2108 insn_ifne:
2110 if (POPI() != 0)
2111 TAKE_GOTO;
2112 else
2113 SKIP_GOTO;
2115 NEXT_INSN;
2117 insn_iflt:
2119 if (POPI() < 0)
2120 TAKE_GOTO;
2121 else
2122 SKIP_GOTO;
2124 NEXT_INSN;
2126 insn_ifge:
2128 if (POPI() >= 0)
2129 TAKE_GOTO;
2130 else
2131 SKIP_GOTO;
2133 NEXT_INSN;
2135 insn_ifgt:
2137 if (POPI() > 0)
2138 TAKE_GOTO;
2139 else
2140 SKIP_GOTO;
2142 NEXT_INSN;
2144 insn_ifle:
2146 if (POPI() <= 0)
2147 TAKE_GOTO;
2148 else
2149 SKIP_GOTO;
2151 NEXT_INSN;
2153 insn_if_icmpeq:
2155 jint value2 = POPI();
2156 jint value1 = POPI();
2157 if (value1 == value2)
2158 TAKE_GOTO;
2159 else
2160 SKIP_GOTO;
2162 NEXT_INSN;
2164 insn_if_icmpne:
2166 jint value2 = POPI();
2167 jint value1 = POPI();
2168 if (value1 != value2)
2169 TAKE_GOTO;
2170 else
2171 SKIP_GOTO;
2173 NEXT_INSN;
2175 insn_if_icmplt:
2177 jint value2 = POPI();
2178 jint value1 = POPI();
2179 if (value1 < value2)
2180 TAKE_GOTO;
2181 else
2182 SKIP_GOTO;
2184 NEXT_INSN;
2186 insn_if_icmpge:
2188 jint value2 = POPI();
2189 jint value1 = POPI();
2190 if (value1 >= value2)
2191 TAKE_GOTO;
2192 else
2193 SKIP_GOTO;
2195 NEXT_INSN;
2197 insn_if_icmpgt:
2199 jint value2 = POPI();
2200 jint value1 = POPI();
2201 if (value1 > value2)
2202 TAKE_GOTO;
2203 else
2204 SKIP_GOTO;
2206 NEXT_INSN;
2208 insn_if_icmple:
2210 jint value2 = POPI();
2211 jint value1 = POPI();
2212 if (value1 <= value2)
2213 TAKE_GOTO;
2214 else
2215 SKIP_GOTO;
2217 NEXT_INSN;
2219 insn_if_acmpeq:
2221 jobject value2 = POPA();
2222 jobject value1 = POPA();
2223 if (value1 == value2)
2224 TAKE_GOTO;
2225 else
2226 SKIP_GOTO;
2228 NEXT_INSN;
2230 insn_if_acmpne:
2232 jobject value2 = POPA();
2233 jobject value1 = POPA();
2234 if (value1 != value2)
2235 TAKE_GOTO;
2236 else
2237 SKIP_GOTO;
2239 NEXT_INSN;
2241 insn_goto_w:
2242 #ifndef DIRECT_THREADED
2243 // For direct threaded, goto and goto_w are the same.
2244 pc = pc - 1 + get4 (pc);
2245 NEXT_INSN;
2246 #endif /* DIRECT_THREADED */
2247 insn_goto:
2248 TAKE_GOTO;
2249 NEXT_INSN;
2251 insn_jsr_w:
2252 #ifndef DIRECT_THREADED
2253 // For direct threaded, jsr and jsr_w are the same.
2255 pc_t next = pc - 1 + get4 (pc);
2256 pc += 4;
2257 PUSHA ((jobject) pc);
2258 pc = next;
2260 NEXT_INSN;
2261 #endif /* DIRECT_THREADED */
2262 insn_jsr:
2264 pc_t next = GOTO_VAL();
2265 SKIP_GOTO;
2266 PUSHA ((jobject) pc);
2267 pc = next;
2269 NEXT_INSN;
2271 insn_ret:
2273 jint index = GET1U ();
2274 pc = (pc_t) PEEKA (index);
2276 NEXT_INSN;
2278 insn_tableswitch:
2280 #ifdef DIRECT_THREADED
2281 void *def = (pc++)->datum;
2283 int index = POPI();
2285 jint low = INTVAL ();
2286 jint high = INTVAL ();
2288 if (index < low || index > high)
2289 pc = (insn_slot *) def;
2290 else
2291 pc = (insn_slot *) ((pc + index - low)->datum);
2292 #else
2293 pc_t base_pc = pc - 1;
2294 int index = POPI ();
2296 pc_t base = (pc_t) bytecode ();
2297 while ((pc - base) % 4 != 0)
2298 ++pc;
2300 jint def = get4 (pc);
2301 jint low = get4 (pc + 4);
2302 jint high = get4 (pc + 8);
2303 if (index < low || index > high)
2304 pc = base_pc + def;
2305 else
2306 pc = base_pc + get4 (pc + 4 * (index - low + 3));
2307 #endif /* DIRECT_THREADED */
2309 NEXT_INSN;
2311 insn_lookupswitch:
2313 #ifdef DIRECT_THREADED
2314 void *def = (pc++)->insn;
2316 int index = POPI();
2318 jint npairs = INTVAL ();
2320 int max = npairs - 1;
2321 int min = 0;
2323 // Simple binary search...
2324 while (min < max)
2326 int half = (min + max) / 2;
2327 int match = pc[2 * half].int_val;
2329 if (index == match)
2331 // Found it.
2332 pc = (insn_slot *) pc[2 * half + 1].datum;
2333 NEXT_INSN;
2335 else if (index < match)
2336 // We can use HALF - 1 here because we check again on
2337 // loop exit.
2338 max = half - 1;
2339 else
2340 // We can use HALF + 1 here because we check again on
2341 // loop exit.
2342 min = half + 1;
2344 if (index == pc[2 * min].int_val)
2345 pc = (insn_slot *) pc[2 * min + 1].datum;
2346 else
2347 pc = (insn_slot *) def;
2348 #else
2349 unsigned char *base_pc = pc-1;
2350 int index = POPI();
2352 unsigned char* base = bytecode ();
2353 while ((pc-base) % 4 != 0)
2354 ++pc;
2356 jint def = get4 (pc);
2357 jint npairs = get4 (pc+4);
2359 int max = npairs-1;
2360 int min = 0;
2362 // Simple binary search...
2363 while (min < max)
2365 int half = (min+max)/2;
2366 int match = get4 (pc+ 4*(2 + 2*half));
2368 if (index == match)
2369 min = max = half;
2370 else if (index < match)
2371 // We can use HALF - 1 here because we check again on
2372 // loop exit.
2373 max = half - 1;
2374 else
2375 // We can use HALF + 1 here because we check again on
2376 // loop exit.
2377 min = half + 1;
2380 if (index == get4 (pc+ 4*(2 + 2*min)))
2381 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
2382 else
2383 pc = base_pc + def;
2384 #endif /* DIRECT_THREADED */
2386 NEXT_INSN;
2388 insn_areturn:
2389 *(jobject *) retp = POPA ();
2390 return;
2392 insn_lreturn:
2393 *(jlong *) retp = POPL ();
2394 return;
2396 insn_freturn:
2397 *(jfloat *) retp = POPF ();
2398 return;
2400 insn_dreturn:
2401 *(jdouble *) retp = POPD ();
2402 return;
2404 insn_ireturn:
2405 *(jint *) retp = POPI ();
2406 return;
2408 insn_return:
2409 return;
2411 insn_getstatic:
2413 jint fieldref_index = GET2U ();
2414 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2415 _Jv_Field *field = pool_data[fieldref_index].field;
2417 if ((field->flags & Modifier::STATIC) == 0)
2418 throw_incompatible_class_change_error
2419 (JvNewStringLatin1 ("field no longer static"));
2421 jclass type = field->type;
2423 // We rewrite the instruction once we discover what it refers
2424 // to.
2425 void *newinsn = NULL;
2426 if (type->isPrimitive ())
2428 switch (type->size_in_bytes)
2430 case 1:
2431 PUSHI (*(jbyte*) (field->u.addr));
2432 newinsn = AMPAMP (getstatic_resolved_1);
2433 break;
2435 case 2:
2436 if (type == JvPrimClass (char))
2438 PUSHI(*(jchar*) (field->u.addr));
2439 newinsn = AMPAMP (getstatic_resolved_char);
2441 else
2443 PUSHI(*(jshort*) (field->u.addr));
2444 newinsn = AMPAMP (getstatic_resolved_short);
2446 break;
2448 case 4:
2449 PUSHI(*(jint*) (field->u.addr));
2450 newinsn = AMPAMP (getstatic_resolved_4);
2451 break;
2453 case 8:
2454 PUSHL(*(jlong*) (field->u.addr));
2455 newinsn = AMPAMP (getstatic_resolved_8);
2456 break;
2459 else
2461 PUSHA(*(jobject*) (field->u.addr));
2462 newinsn = AMPAMP (getstatic_resolved_obj);
2465 #ifdef DIRECT_THREADED
2466 pc[-2].insn = newinsn;
2467 pc[-1].datum = field->u.addr;
2468 #endif /* DIRECT_THREADED */
2470 NEXT_INSN;
2472 #ifdef DIRECT_THREADED
2473 getstatic_resolved_1:
2474 PUSHI (*(jbyte *) AVAL ());
2475 NEXT_INSN;
2477 getstatic_resolved_char:
2478 PUSHI (*(jchar *) AVAL ());
2479 NEXT_INSN;
2481 getstatic_resolved_short:
2482 PUSHI (*(jshort *) AVAL ());
2483 NEXT_INSN;
2485 getstatic_resolved_4:
2486 PUSHI (*(jint *) AVAL ());
2487 NEXT_INSN;
2489 getstatic_resolved_8:
2490 PUSHL (*(jlong *) AVAL ());
2491 NEXT_INSN;
2493 getstatic_resolved_obj:
2494 PUSHA (*(jobject *) AVAL ());
2495 NEXT_INSN;
2496 #endif /* DIRECT_THREADED */
2498 insn_getfield:
2500 jint fieldref_index = GET2U ();
2501 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2502 _Jv_Field *field = pool_data[fieldref_index].field;
2504 if ((field->flags & Modifier::STATIC) != 0)
2505 throw_incompatible_class_change_error
2506 (JvNewStringLatin1 ("field is static"));
2508 jclass type = field->type;
2509 jint field_offset = field->u.boffset;
2510 if (field_offset > 0xffff)
2511 throw new java::lang::VirtualMachineError;
2513 jobject obj = POPA();
2514 NULLCHECK(obj);
2516 void *newinsn = NULL;
2517 if (type->isPrimitive ())
2519 switch (type->size_in_bytes)
2521 case 1:
2522 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2523 newinsn = AMPAMP (getfield_resolved_1);
2524 break;
2526 case 2:
2527 if (type == JvPrimClass (char))
2529 PUSHI (*(jchar*) ((char*)obj + field_offset));
2530 newinsn = AMPAMP (getfield_resolved_char);
2532 else
2534 PUSHI (*(jshort*) ((char*)obj + field_offset));
2535 newinsn = AMPAMP (getfield_resolved_short);
2537 break;
2539 case 4:
2540 PUSHI (*(jint*) ((char*)obj + field_offset));
2541 newinsn = AMPAMP (getfield_resolved_4);
2542 break;
2544 case 8:
2545 PUSHL(*(jlong*) ((char*)obj + field_offset));
2546 newinsn = AMPAMP (getfield_resolved_8);
2547 break;
2550 else
2552 PUSHA(*(jobject*) ((char*)obj + field_offset));
2553 newinsn = AMPAMP (getfield_resolved_obj);
2556 #ifdef DIRECT_THREADED
2557 pc[-2].insn = newinsn;
2558 pc[-1].int_val = field_offset;
2559 #endif /* DIRECT_THREADED */
2561 NEXT_INSN;
2563 #ifdef DIRECT_THREADED
2564 getfield_resolved_1:
2566 char *obj = (char *) POPA ();
2567 NULLCHECK (obj);
2568 PUSHI (*(jbyte *) (obj + INTVAL ()));
2570 NEXT_INSN;
2572 getfield_resolved_char:
2574 char *obj = (char *) POPA ();
2575 NULLCHECK (obj);
2576 PUSHI (*(jchar *) (obj + INTVAL ()));
2578 NEXT_INSN;
2580 getfield_resolved_short:
2582 char *obj = (char *) POPA ();
2583 NULLCHECK (obj);
2584 PUSHI (*(jshort *) (obj + INTVAL ()));
2586 NEXT_INSN;
2588 getfield_resolved_4:
2590 char *obj = (char *) POPA ();
2591 NULLCHECK (obj);
2592 PUSHI (*(jint *) (obj + INTVAL ()));
2594 NEXT_INSN;
2596 getfield_resolved_8:
2598 char *obj = (char *) POPA ();
2599 NULLCHECK (obj);
2600 PUSHL (*(jlong *) (obj + INTVAL ()));
2602 NEXT_INSN;
2604 getfield_resolved_obj:
2606 char *obj = (char *) POPA ();
2607 NULLCHECK (obj);
2608 PUSHA (*(jobject *) (obj + INTVAL ()));
2610 NEXT_INSN;
2611 #endif /* DIRECT_THREADED */
2613 insn_putstatic:
2615 jint fieldref_index = GET2U ();
2616 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2617 _Jv_Field *field = pool_data[fieldref_index].field;
2619 jclass type = field->type;
2621 // ResolvePoolEntry cannot check this
2622 if ((field->flags & Modifier::STATIC) == 0)
2623 throw_incompatible_class_change_error
2624 (JvNewStringLatin1 ("field no longer static"));
2626 void *newinsn = NULL;
2627 if (type->isPrimitive ())
2629 switch (type->size_in_bytes)
2631 case 1:
2633 jint value = POPI();
2634 *(jbyte*) (field->u.addr) = value;
2635 newinsn = AMPAMP (putstatic_resolved_1);
2636 break;
2639 case 2:
2641 jint value = POPI();
2642 *(jchar*) (field->u.addr) = value;
2643 newinsn = AMPAMP (putstatic_resolved_2);
2644 break;
2647 case 4:
2649 jint value = POPI();
2650 *(jint*) (field->u.addr) = value;
2651 newinsn = AMPAMP (putstatic_resolved_4);
2652 break;
2655 case 8:
2657 jlong value = POPL();
2658 *(jlong*) (field->u.addr) = value;
2659 newinsn = AMPAMP (putstatic_resolved_8);
2660 break;
2664 else
2666 jobject value = POPA();
2667 *(jobject*) (field->u.addr) = value;
2668 newinsn = AMPAMP (putstatic_resolved_obj);
2671 #ifdef DIRECT_THREADED
2672 pc[-2].insn = newinsn;
2673 pc[-1].datum = field->u.addr;
2674 #endif /* DIRECT_THREADED */
2676 NEXT_INSN;
2678 #ifdef DIRECT_THREADED
2679 putstatic_resolved_1:
2680 *(jbyte *) AVAL () = POPI ();
2681 NEXT_INSN;
2683 putstatic_resolved_2:
2684 *(jchar *) AVAL () = POPI ();
2685 NEXT_INSN;
2687 putstatic_resolved_4:
2688 *(jint *) AVAL () = POPI ();
2689 NEXT_INSN;
2691 putstatic_resolved_8:
2692 *(jlong *) AVAL () = POPL ();
2693 NEXT_INSN;
2695 putstatic_resolved_obj:
2696 *(jobject *) AVAL () = POPA ();
2697 NEXT_INSN;
2698 #endif /* DIRECT_THREADED */
2700 insn_putfield:
2702 jint fieldref_index = GET2U ();
2703 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2704 _Jv_Field *field = pool_data[fieldref_index].field;
2706 jclass type = field->type;
2708 if ((field->flags & Modifier::STATIC) != 0)
2709 throw_incompatible_class_change_error
2710 (JvNewStringLatin1 ("field is static"));
2712 jint field_offset = field->u.boffset;
2713 if (field_offset > 0xffff)
2714 throw new java::lang::VirtualMachineError;
2716 void *newinsn = NULL;
2717 if (type->isPrimitive ())
2719 switch (type->size_in_bytes)
2721 case 1:
2723 jint value = POPI();
2724 jobject obj = POPA();
2725 NULLCHECK(obj);
2726 *(jbyte*) ((char*)obj + field_offset) = value;
2727 newinsn = AMPAMP (putfield_resolved_1);
2728 break;
2731 case 2:
2733 jint value = POPI();
2734 jobject obj = POPA();
2735 NULLCHECK(obj);
2736 *(jchar*) ((char*)obj + field_offset) = value;
2737 newinsn = AMPAMP (putfield_resolved_2);
2738 break;
2741 case 4:
2743 jint value = POPI();
2744 jobject obj = POPA();
2745 NULLCHECK(obj);
2746 *(jint*) ((char*)obj + field_offset) = value;
2747 newinsn = AMPAMP (putfield_resolved_4);
2748 break;
2751 case 8:
2753 jlong value = POPL();
2754 jobject obj = POPA();
2755 NULLCHECK(obj);
2756 *(jlong*) ((char*)obj + field_offset) = value;
2757 newinsn = AMPAMP (putfield_resolved_8);
2758 break;
2762 else
2764 jobject value = POPA();
2765 jobject obj = POPA();
2766 NULLCHECK(obj);
2767 *(jobject*) ((char*)obj + field_offset) = value;
2768 newinsn = AMPAMP (putfield_resolved_obj);
2771 #ifdef DIRECT_THREADED
2772 pc[-2].insn = newinsn;
2773 pc[-1].int_val = field_offset;
2774 #endif /* DIRECT_THREADED */
2776 NEXT_INSN;
2778 #ifdef DIRECT_THREADED
2779 putfield_resolved_1:
2781 jint val = POPI ();
2782 char *obj = (char *) POPA ();
2783 NULLCHECK (obj);
2784 *(jbyte *) (obj + INTVAL ()) = val;
2786 NEXT_INSN;
2788 putfield_resolved_2:
2790 jint val = POPI ();
2791 char *obj = (char *) POPA ();
2792 NULLCHECK (obj);
2793 *(jchar *) (obj + INTVAL ()) = val;
2795 NEXT_INSN;
2797 putfield_resolved_4:
2799 jint val = POPI ();
2800 char *obj = (char *) POPA ();
2801 NULLCHECK (obj);
2802 *(jint *) (obj + INTVAL ()) = val;
2804 NEXT_INSN;
2806 putfield_resolved_8:
2808 jlong val = POPL ();
2809 char *obj = (char *) POPA ();
2810 NULLCHECK (obj);
2811 *(jlong *) (obj + INTVAL ()) = val;
2813 NEXT_INSN;
2815 putfield_resolved_obj:
2817 jobject val = POPA ();
2818 char *obj = (char *) POPA ();
2819 NULLCHECK (obj);
2820 *(jobject *) (obj + INTVAL ()) = val;
2822 NEXT_INSN;
2823 #endif /* DIRECT_THREADED */
2825 insn_invokespecial:
2827 int index = GET2U ();
2829 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2831 sp -= rmeth->stack_item_count;
2833 // We don't use NULLCHECK here because we can't rely on that
2834 // working for <init>. So instead we do an explicit test.
2835 if (! sp[0].o)
2836 throw new java::lang::NullPointerException;
2838 fun = (void (*)()) rmeth->method->ncode;
2840 #ifdef DIRECT_THREADED
2841 // Rewrite instruction so that we use a faster pre-resolved
2842 // method.
2843 pc[-2].insn = &&invokespecial_resolved;
2844 pc[-1].datum = rmeth;
2845 #endif /* DIRECT_THREADED */
2847 goto perform_invoke;
2849 #ifdef DIRECT_THREADED
2850 invokespecial_resolved:
2852 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2853 sp -= rmeth->stack_item_count;
2854 // We don't use NULLCHECK here because we can't rely on that
2855 // working for <init>. So instead we do an explicit test.
2856 if (! sp[0].o)
2857 throw new java::lang::NullPointerException;
2858 fun = (void (*)()) rmeth->method->ncode;
2860 goto perform_invoke;
2861 #endif /* DIRECT_THREADED */
2863 insn_invokestatic:
2865 int index = GET2U ();
2867 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2869 sp -= rmeth->stack_item_count;
2871 fun = (void (*)()) rmeth->method->ncode;
2873 #ifdef DIRECT_THREADED
2874 // Rewrite instruction so that we use a faster pre-resolved
2875 // method.
2876 pc[-2].insn = &&invokestatic_resolved;
2877 pc[-1].datum = rmeth;
2878 #endif /* DIRECT_THREADED */
2880 goto perform_invoke;
2882 #ifdef DIRECT_THREADED
2883 invokestatic_resolved:
2885 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2886 sp -= rmeth->stack_item_count;
2887 fun = (void (*)()) rmeth->method->ncode;
2889 goto perform_invoke;
2890 #endif /* DIRECT_THREADED */
2892 insn_invokeinterface:
2894 int index = GET2U ();
2896 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2898 sp -= rmeth->stack_item_count;
2900 jobject rcv = sp[0].o;
2902 NULLCHECK (rcv);
2904 fun = (void (*)())
2905 _Jv_LookupInterfaceMethod (rcv->getClass (),
2906 rmeth->method->name,
2907 rmeth->method->signature);
2909 #ifdef DIRECT_THREADED
2910 // Rewrite instruction so that we use a faster pre-resolved
2911 // method.
2912 pc[-2].insn = &&invokeinterface_resolved;
2913 pc[-1].datum = rmeth;
2914 #else
2915 // Skip dummy bytes.
2916 pc += 2;
2917 #endif /* DIRECT_THREADED */
2919 goto perform_invoke;
2921 #ifdef DIRECT_THREADED
2922 invokeinterface_resolved:
2924 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2925 sp -= rmeth->stack_item_count;
2926 jobject rcv = sp[0].o;
2927 NULLCHECK (rcv);
2928 fun = (void (*)())
2929 _Jv_LookupInterfaceMethod (rcv->getClass (),
2930 rmeth->method->name,
2931 rmeth->method->signature);
2933 goto perform_invoke;
2934 #endif /* DIRECT_THREADED */
2936 insn_new:
2938 int index = GET2U ();
2939 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2940 // We initialize here because otherwise `size_in_bytes' may
2941 // not be set correctly, leading us to pass `0' as the size.
2942 // FIXME: fix in the allocator? There is a PR for this.
2943 _Jv_InitClass (klass);
2944 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2945 PUSHA (res);
2947 #ifdef DIRECT_THREADED
2948 pc[-2].insn = &&new_resolved;
2949 pc[-1].datum = klass;
2950 #endif /* DIRECT_THREADED */
2952 NEXT_INSN;
2954 #ifdef DIRECT_THREADED
2955 new_resolved:
2957 jclass klass = (jclass) AVAL ();
2958 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2959 PUSHA (res);
2961 NEXT_INSN;
2962 #endif /* DIRECT_THREADED */
2964 insn_newarray:
2966 int atype = GET1U ();
2967 int size = POPI();
2968 jobject result = _Jv_NewArray (atype, size);
2969 PUSHA (result);
2971 NEXT_INSN;
2973 insn_anewarray:
2975 int index = GET2U ();
2976 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2977 int size = POPI();
2978 jobject result = _Jv_NewObjectArray (size, klass, 0);
2979 PUSHA (result);
2981 #ifdef DIRECT_THREADED
2982 pc[-2].insn = &&anewarray_resolved;
2983 pc[-1].datum = klass;
2984 #endif /* DIRECT_THREADED */
2986 NEXT_INSN;
2988 #ifdef DIRECT_THREADED
2989 anewarray_resolved:
2991 jclass klass = (jclass) AVAL ();
2992 int size = POPI ();
2993 jobject result = _Jv_NewObjectArray (size, klass, 0);
2994 PUSHA (result);
2996 NEXT_INSN;
2997 #endif /* DIRECT_THREADED */
2999 insn_arraylength:
3001 __JArray *arr = (__JArray*)POPA();
3002 NULLARRAYCHECK (arr);
3003 PUSHI (arr->length);
3005 NEXT_INSN;
3007 insn_athrow:
3009 jobject value = POPA();
3010 throw static_cast<jthrowable>(value);
3012 NEXT_INSN;
3014 insn_checkcast:
3016 jobject value = POPA();
3017 jint index = GET2U ();
3018 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3020 if (value != NULL && ! to->isInstance (value))
3021 throw new java::lang::ClassCastException (to->getName());
3023 PUSHA (value);
3025 #ifdef DIRECT_THREADED
3026 pc[-2].insn = &&checkcast_resolved;
3027 pc[-1].datum = to;
3028 #endif /* DIRECT_THREADED */
3030 NEXT_INSN;
3032 #ifdef DIRECT_THREADED
3033 checkcast_resolved:
3035 jobject value = POPA ();
3036 jclass to = (jclass) AVAL ();
3037 if (value != NULL && ! to->isInstance (value))
3038 throw new java::lang::ClassCastException (to->getName());
3039 PUSHA (value);
3041 NEXT_INSN;
3042 #endif /* DIRECT_THREADED */
3044 insn_instanceof:
3046 jobject value = POPA();
3047 jint index = GET2U ();
3048 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3049 PUSHI (to->isInstance (value));
3051 #ifdef DIRECT_THREADED
3052 pc[-2].insn = &&instanceof_resolved;
3053 pc[-1].datum = to;
3054 #endif /* DIRECT_THREADED */
3056 NEXT_INSN;
3058 #ifdef DIRECT_THREADED
3059 instanceof_resolved:
3061 jobject value = POPA ();
3062 jclass to = (jclass) AVAL ();
3063 PUSHI (to->isInstance (value));
3065 NEXT_INSN;
3066 #endif /* DIRECT_THREADED */
3068 insn_monitorenter:
3070 jobject value = POPA();
3071 NULLCHECK(value);
3072 _Jv_MonitorEnter (value);
3074 NEXT_INSN;
3076 insn_monitorexit:
3078 jobject value = POPA();
3079 NULLCHECK(value);
3080 _Jv_MonitorExit (value);
3082 NEXT_INSN;
3084 insn_ifnull:
3086 jobject val = POPA();
3087 if (val == NULL)
3088 TAKE_GOTO;
3089 else
3090 SKIP_GOTO;
3092 NEXT_INSN;
3094 insn_ifnonnull:
3096 jobject val = POPA();
3097 if (val != NULL)
3098 TAKE_GOTO;
3099 else
3100 SKIP_GOTO;
3102 NEXT_INSN;
3104 insn_multianewarray:
3106 int kind_index = GET2U ();
3107 int dim = GET1U ();
3109 jclass type
3110 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
3111 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
3113 for (int i = dim - 1; i >= 0; i--)
3115 sizes[i] = POPI ();
3118 jobject res = _Jv_NewMultiArray (type,dim, sizes);
3120 PUSHA (res);
3122 NEXT_INSN;
3124 #ifndef DIRECT_THREADED
3125 insn_wide:
3127 jint the_mod_op = get1u (pc++);
3128 jint wide = get2u (pc); pc += 2;
3130 switch (the_mod_op)
3132 case op_istore:
3133 STOREI (wide);
3134 NEXT_INSN;
3136 case op_fstore:
3137 STOREF (wide);
3138 NEXT_INSN;
3140 case op_astore:
3141 STOREA (wide);
3142 NEXT_INSN;
3144 case op_lload:
3145 LOADL (wide);
3146 NEXT_INSN;
3148 case op_dload:
3149 LOADD (wide);
3150 NEXT_INSN;
3152 case op_iload:
3153 LOADI (wide);
3154 NEXT_INSN;
3156 case op_aload:
3157 LOADA (wide);
3158 NEXT_INSN;
3160 case op_lstore:
3161 STOREL (wide);
3162 NEXT_INSN;
3164 case op_dstore:
3165 STORED (wide);
3166 NEXT_INSN;
3168 case op_ret:
3169 pc = (unsigned char*) PEEKA (wide);
3170 NEXT_INSN;
3172 case op_iinc:
3174 jint amount = get2s (pc); pc += 2;
3175 jint value = PEEKI (wide);
3176 POKEI (wide, value+amount);
3178 NEXT_INSN;
3180 default:
3181 throw_internal_error ("illegal bytecode modified by wide");
3185 #endif /* DIRECT_THREADED */
3187 catch (java::lang::Throwable *ex)
3189 #ifdef DIRECT_THREADED
3190 void *logical_pc = (void *) ((insn_slot *) pc - 1);
3191 #else
3192 int logical_pc = pc - 1 - bytecode ();
3193 #endif
3194 _Jv_InterpException *exc = exceptions ();
3195 jclass exc_class = ex->getClass ();
3197 for (int i = 0; i < exc_count; i++)
3199 if (PCVAL (exc[i].start_pc) <= logical_pc
3200 && logical_pc < PCVAL (exc[i].end_pc))
3202 #ifdef DIRECT_THREADED
3203 jclass handler = (jclass) exc[i].handler_type.p;
3204 #else
3205 jclass handler = NULL;
3206 if (exc[i].handler_type.i != 0)
3207 handler = (_Jv_ResolvePoolEntry (defining_class,
3208 exc[i].handler_type.i)).clazz;
3209 #endif /* DIRECT_THREADED */
3211 if (handler == NULL || handler->isAssignableFrom (exc_class))
3213 #ifdef DIRECT_THREADED
3214 pc = (insn_slot *) exc[i].handler_pc.p;
3215 #else
3216 pc = bytecode () + exc[i].handler_pc.i;
3217 #endif /* DIRECT_THREADED */
3218 sp = stack;
3219 sp++->o = ex; // Push exception.
3220 NEXT_INSN;
3225 // No handler, so re-throw.
3226 throw ex;
3230 // This function exists so that the stack-tracing code can find the
3231 // boundaries of the interpreter.
3232 void
3233 _Jv_EndOfInterpreter (void)
3237 static void
3238 throw_internal_error (char *msg)
3240 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
3243 static void
3244 throw_incompatible_class_change_error (jstring msg)
3246 throw new java::lang::IncompatibleClassChangeError (msg);
3249 #ifndef HANDLE_SEGV
3250 static java::lang::NullPointerException *null_pointer_exc;
3251 static void
3252 throw_null_pointer_exception ()
3254 if (null_pointer_exc == NULL)
3255 null_pointer_exc = new java::lang::NullPointerException;
3257 throw null_pointer_exc;
3259 #endif
3261 #endif // INTERPRETER