* config/arm/arm-protos.h (arm_gen_return_addr_mask): New
[official-gcc.git] / libjava / interpret.cc
blobd231387dc9a40b1b48ca2d6904329efcb39bb1c8
1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
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 extern "C" double __ieee754_fmod (double,double);
59 // This represents a single slot in the "compiled" form of the
60 // bytecode.
61 union insn_slot
63 // Address of code.
64 void *insn;
65 // An integer value used by an instruction.
66 jint int_val;
67 // A pointer value used by an instruction.
68 void *datum;
71 // The type of the PC depends on whether we're doing direct threading
72 // or a more ordinary bytecode interpreter.
73 #ifdef DIRECT_THREADED
74 typedef insn_slot *pc_t;
75 #else
76 typedef unsigned char *pc_t;
77 #endif
79 static inline void dupx (_Jv_word *sp, int n, int x)
81 // first "slide" n+x elements n to the right
82 int top = n-1;
83 for (int i = 0; i < n+x; i++)
85 sp[(top-i)] = sp[(top-i)-n];
88 // next, copy the n top elements, n+x down
89 for (int i = 0; i < n; i++)
91 sp[top-(n+x)-i] = sp[top-i];
96 // Used to convert from floating types to integral types.
97 template<typename TO, typename FROM>
98 static inline TO
99 convert (FROM val, TO min, TO max)
101 TO ret;
102 if (val >= (FROM) max)
103 ret = max;
104 else if (val <= (FROM) min)
105 ret = min;
106 else if (val != val)
107 ret = 0;
108 else
109 ret = (TO) val;
110 return ret;
113 #define PUSHA(V) (sp++)->o = (V)
114 #define PUSHI(V) (sp++)->i = (V)
115 #define PUSHF(V) (sp++)->f = (V)
116 #if SIZEOF_VOID_P == 8
117 # define PUSHL(V) (sp->l = (V), sp += 2)
118 # define PUSHD(V) (sp->d = (V), sp += 2)
119 #else
120 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
121 (sp++)->ia[0] = w2.ia[0]; \
122 (sp++)->ia[0] = w2.ia[1]; } while (0)
123 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
124 (sp++)->ia[0] = w2.ia[0]; \
125 (sp++)->ia[0] = w2.ia[1]; } while (0)
126 #endif
128 #define POPA() ((--sp)->o)
129 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
130 #define POPF() ((jfloat) (--sp)->f)
131 #if SIZEOF_VOID_P == 8
132 # define POPL() (sp -= 2, (jlong) sp->l)
133 # define POPD() (sp -= 2, (jdouble) sp->d)
134 #else
135 # define POPL() ({ _Jv_word2 w2; \
136 w2.ia[1] = (--sp)->ia[0]; \
137 w2.ia[0] = (--sp)->ia[0]; w2.l; })
138 # define POPD() ({ _Jv_word2 w2; \
139 w2.ia[1] = (--sp)->ia[0]; \
140 w2.ia[0] = (--sp)->ia[0]; w2.d; })
141 #endif
143 #define LOADA(I) (sp++)->o = locals[I].o
144 #define LOADI(I) (sp++)->i = locals[I].i
145 #define LOADF(I) (sp++)->f = locals[I].f
146 #if SIZEOF_VOID_P == 8
147 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
148 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
149 #else
150 # define LOADL(I) do { jint __idx = (I); \
151 (sp++)->ia[0] = locals[__idx].ia[0]; \
152 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
153 } while (0)
154 # define LOADD(I) LOADL(I)
155 #endif
157 #define STOREA(I) locals[I].o = (--sp)->o
158 #define STOREI(I) locals[I].i = (--sp)->i
159 #define STOREF(I) locals[I].f = (--sp)->f
160 #if SIZEOF_VOID_P == 8
161 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
162 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
163 #else
164 # define STOREL(I) do { jint __idx = (I); \
165 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
166 locals[__idx].ia[0] = (--sp)->ia[0]; \
167 } while (0)
168 # define STORED(I) STOREL(I)
169 #endif
171 #define PEEKI(I) (locals+(I))->i
172 #define PEEKA(I) (locals+(I))->o
174 #define POKEI(I,V) ((locals+(I))->i = (V))
177 #define BINOPI(OP) { \
178 jint value2 = POPI(); \
179 jint value1 = POPI(); \
180 PUSHI(value1 OP value2); \
183 #define BINOPF(OP) { \
184 jfloat value2 = POPF(); \
185 jfloat value1 = POPF(); \
186 PUSHF(value1 OP value2); \
189 #define BINOPL(OP) { \
190 jlong value2 = POPL(); \
191 jlong value1 = POPL(); \
192 PUSHL(value1 OP value2); \
195 #define BINOPD(OP) { \
196 jdouble value2 = POPD(); \
197 jdouble value1 = POPD(); \
198 PUSHD(value1 OP value2); \
201 static inline jint get1s(unsigned char* loc) {
202 return *(signed char*)loc;
205 static inline jint get1u(unsigned char* loc) {
206 return *loc;
209 static inline jint get2s(unsigned char* loc) {
210 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
213 static inline jint get2u(unsigned char* loc) {
214 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
217 static jint get4(unsigned char* loc) {
218 return (((jint)(loc[0])) << 24)
219 | (((jint)(loc[1])) << 16)
220 | (((jint)(loc[2])) << 8)
221 | (((jint)(loc[3])) << 0);
225 #ifdef HANDLE_SEGV
226 #define NULLCHECK(X)
227 #define NULLARRAYCHECK(X)
228 #else
229 #define NULLCHECK(X) \
230 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
231 #define NULLARRAYCHECK(X) \
232 do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
233 #endif
235 #define ARRAYBOUNDSCHECK(array, index) \
236 do \
238 if (((unsigned) index) >= (unsigned) (array->length)) \
239 _Jv_ThrowBadArrayIndex (index); \
241 while (0)
243 void _Jv_InterpMethod::run_normal (ffi_cif *,
244 void* ret,
245 ffi_raw * args,
246 void* __this)
248 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
249 _this->run (ret, args);
252 void _Jv_InterpMethod::run_synch_object (ffi_cif *,
253 void* ret,
254 ffi_raw * args,
255 void* __this)
257 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
259 jobject rcv = (jobject) args[0].ptr;
260 JvSynchronize mutex (rcv);
262 _this->run (ret, args);
265 void _Jv_InterpMethod::run_synch_class (ffi_cif *,
266 void* ret,
267 ffi_raw * args,
268 void* __this)
270 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
272 jclass sync = _this->defining_class;
273 JvSynchronize mutex (sync);
275 _this->run (ret, args);
278 #ifdef DIRECT_THREADED
279 // "Compile" a method by turning it from bytecode to direct-threaded
280 // code.
281 void
282 _Jv_InterpMethod::compile (const void * const *insn_targets)
284 insn_slot *insns = NULL;
285 int next = 0;
286 unsigned char *codestart = bytecode ();
287 unsigned char *end = codestart + code_length;
288 _Jv_word *pool_data = defining_class->constants.data;
290 #define SET_ONE(Field, Value) \
291 do \
293 if (first_pass) \
294 ++next; \
295 else \
296 insns[next++].Field = Value; \
298 while (0)
300 #define SET_INSN(Value) SET_ONE (insn, (void *) Value)
301 #define SET_INT(Value) SET_ONE (int_val, Value)
302 #define SET_DATUM(Value) SET_ONE (datum, Value)
304 // Map from bytecode PC to slot in INSNS.
305 int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
306 for (int i = 0; i < code_length; ++i)
307 pc_mapping[i] = -1;
309 for (int i = 0; i < 2; ++i)
311 jboolean first_pass = i == 0;
313 if (! first_pass)
315 insns = (insn_slot *) _Jv_Malloc (sizeof (insn_slot) * next);
316 next = 0;
319 unsigned char *pc = codestart;
320 while (pc < end)
322 int base_pc_val = pc - codestart;
323 if (first_pass)
324 pc_mapping[base_pc_val] = next;
326 java_opcode opcode = (java_opcode) *pc++;
327 // Just elide NOPs.
328 if (opcode == op_nop)
329 continue;
330 SET_INSN (insn_targets[opcode]);
332 switch (opcode)
334 case op_nop:
335 case op_aconst_null:
336 case op_iconst_m1:
337 case op_iconst_0:
338 case op_iconst_1:
339 case op_iconst_2:
340 case op_iconst_3:
341 case op_iconst_4:
342 case op_iconst_5:
343 case op_lconst_0:
344 case op_lconst_1:
345 case op_fconst_0:
346 case op_fconst_1:
347 case op_fconst_2:
348 case op_dconst_0:
349 case op_dconst_1:
350 case op_iload_0:
351 case op_iload_1:
352 case op_iload_2:
353 case op_iload_3:
354 case op_lload_0:
355 case op_lload_1:
356 case op_lload_2:
357 case op_lload_3:
358 case op_fload_0:
359 case op_fload_1:
360 case op_fload_2:
361 case op_fload_3:
362 case op_dload_0:
363 case op_dload_1:
364 case op_dload_2:
365 case op_dload_3:
366 case op_aload_0:
367 case op_aload_1:
368 case op_aload_2:
369 case op_aload_3:
370 case op_iaload:
371 case op_laload:
372 case op_faload:
373 case op_daload:
374 case op_aaload:
375 case op_baload:
376 case op_caload:
377 case op_saload:
378 case op_istore_0:
379 case op_istore_1:
380 case op_istore_2:
381 case op_istore_3:
382 case op_lstore_0:
383 case op_lstore_1:
384 case op_lstore_2:
385 case op_lstore_3:
386 case op_fstore_0:
387 case op_fstore_1:
388 case op_fstore_2:
389 case op_fstore_3:
390 case op_dstore_0:
391 case op_dstore_1:
392 case op_dstore_2:
393 case op_dstore_3:
394 case op_astore_0:
395 case op_astore_1:
396 case op_astore_2:
397 case op_astore_3:
398 case op_iastore:
399 case op_lastore:
400 case op_fastore:
401 case op_dastore:
402 case op_aastore:
403 case op_bastore:
404 case op_castore:
405 case op_sastore:
406 case op_pop:
407 case op_pop2:
408 case op_dup:
409 case op_dup_x1:
410 case op_dup_x2:
411 case op_dup2:
412 case op_dup2_x1:
413 case op_dup2_x2:
414 case op_swap:
415 case op_iadd:
416 case op_isub:
417 case op_imul:
418 case op_idiv:
419 case op_irem:
420 case op_ishl:
421 case op_ishr:
422 case op_iushr:
423 case op_iand:
424 case op_ior:
425 case op_ixor:
426 case op_ladd:
427 case op_lsub:
428 case op_lmul:
429 case op_ldiv:
430 case op_lrem:
431 case op_lshl:
432 case op_lshr:
433 case op_lushr:
434 case op_land:
435 case op_lor:
436 case op_lxor:
437 case op_fadd:
438 case op_fsub:
439 case op_fmul:
440 case op_fdiv:
441 case op_frem:
442 case op_dadd:
443 case op_dsub:
444 case op_dmul:
445 case op_ddiv:
446 case op_drem:
447 case op_ineg:
448 case op_i2b:
449 case op_i2c:
450 case op_i2s:
451 case op_lneg:
452 case op_fneg:
453 case op_dneg:
454 case op_i2l:
455 case op_i2f:
456 case op_i2d:
457 case op_l2i:
458 case op_l2f:
459 case op_l2d:
460 case op_f2i:
461 case op_f2l:
462 case op_f2d:
463 case op_d2i:
464 case op_d2l:
465 case op_d2f:
466 case op_lcmp:
467 case op_fcmpl:
468 case op_fcmpg:
469 case op_dcmpl:
470 case op_dcmpg:
471 case op_monitorenter:
472 case op_monitorexit:
473 case op_ireturn:
474 case op_lreturn:
475 case op_freturn:
476 case op_dreturn:
477 case op_areturn:
478 case op_return:
479 case op_athrow:
480 case op_arraylength:
481 // No argument, nothing else to do.
482 break;
484 case op_bipush:
485 SET_INT (get1s (pc));
486 ++pc;
487 break;
489 case op_ldc:
491 int index = get1u (pc);
492 ++pc;
493 SET_DATUM (pool_data[index].o);
495 break;
497 case op_ret:
498 case op_iload:
499 case op_lload:
500 case op_fload:
501 case op_dload:
502 case op_aload:
503 case op_istore:
504 case op_lstore:
505 case op_fstore:
506 case op_dstore:
507 case op_astore:
508 case op_newarray:
509 SET_INT (get1u (pc));
510 ++pc;
511 break;
513 case op_iinc:
514 SET_INT (get1u (pc));
515 SET_INT (get1s (pc + 1));
516 pc += 2;
517 break;
519 case op_ldc_w:
521 int index = get2u (pc);
522 pc += 2;
523 SET_DATUM (pool_data[index].o);
525 break;
527 case op_ldc2_w:
529 int index = get2u (pc);
530 pc += 2;
531 SET_DATUM (&pool_data[index]);
533 break;
535 case op_sipush:
536 SET_INT (get2s (pc));
537 pc += 2;
538 break;
540 case op_new:
541 case op_getstatic:
542 case op_getfield:
543 case op_putfield:
544 case op_putstatic:
545 case op_anewarray:
546 case op_instanceof:
547 case op_checkcast:
548 case op_invokespecial:
549 case op_invokestatic:
550 case op_invokevirtual:
551 SET_INT (get2u (pc));
552 pc += 2;
553 break;
555 case op_multianewarray:
556 SET_INT (get2u (pc));
557 SET_INT (get1u (pc + 2));
558 pc += 3;
559 break;
561 case op_jsr:
562 case op_ifeq:
563 case op_ifne:
564 case op_iflt:
565 case op_ifge:
566 case op_ifgt:
567 case op_ifle:
568 case op_if_icmpeq:
569 case op_if_icmpne:
570 case op_if_icmplt:
571 case op_if_icmpge:
572 case op_if_icmpgt:
573 case op_if_icmple:
574 case op_if_acmpeq:
575 case op_if_acmpne:
576 case op_ifnull:
577 case op_ifnonnull:
578 case op_goto:
580 int offset = get2s (pc);
581 pc += 2;
583 int new_pc = base_pc_val + offset;
585 bool orig_was_goto = opcode == op_goto;
587 // Thread jumps. We limit the loop count; this lets
588 // us avoid infinite loops if the bytecode contains
589 // such. `10' is arbitrary.
590 int count = 10;
591 while (codestart[new_pc] == op_goto && count-- > 0)
592 new_pc += get2s (&codestart[new_pc + 1]);
594 // If the jump takes us to a `return' instruction and
595 // the original branch was an unconditional goto, then
596 // we hoist the return.
597 opcode = (java_opcode) codestart[new_pc];
598 if (orig_was_goto
599 && (opcode == op_ireturn || opcode == op_lreturn
600 || opcode == op_freturn || opcode == op_dreturn
601 || opcode == op_areturn || opcode == op_return))
603 --next;
604 SET_INSN (insn_targets[opcode]);
606 else
607 SET_DATUM (&insns[pc_mapping[new_pc]]);
609 break;
611 case op_tableswitch:
613 while ((pc - codestart) % 4 != 0)
614 ++pc;
616 jint def = get4 (pc);
617 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
618 pc += 4;
620 int low = get4 (pc);
621 SET_INT (low);
622 pc += 4;
623 int high = get4 (pc);
624 SET_INT (high);
625 pc += 4;
627 for (int i = low; i <= high; ++i)
629 SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
630 pc += 4;
633 break;
635 case op_lookupswitch:
637 while ((pc - codestart) % 4 != 0)
638 ++pc;
640 jint def = get4 (pc);
641 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
642 pc += 4;
644 jint npairs = get4 (pc);
645 pc += 4;
646 SET_INT (npairs);
648 while (npairs-- > 0)
650 jint match = get4 (pc);
651 jint offset = get4 (pc + 4);
652 SET_INT (match);
653 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
654 pc += 8;
657 break;
659 case op_invokeinterface:
661 jint index = get2u (pc);
662 pc += 2;
663 // We ignore the next two bytes.
664 pc += 2;
665 SET_INT (index);
667 break;
669 case op_wide:
671 opcode = (java_opcode) get1u (pc);
672 pc += 1;
673 jint val = get2u (pc);
674 pc += 2;
676 // We implement narrow and wide instructions using the
677 // same code in the interpreter. So we rewrite the
678 // instruction slot here.
679 if (! first_pass)
680 insns[next - 1].insn = (void *) insn_targets[opcode];
681 SET_INT (val);
683 if (opcode == op_iinc)
685 SET_INT (get2s (pc));
686 pc += 2;
689 break;
691 case op_jsr_w:
692 case op_goto_w:
694 jint offset = get4 (pc);
695 pc += 4;
696 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
698 break;
700 // Some "can't happen" cases that we include for
701 // error-checking purposes.
702 case op_putfield_1:
703 case op_putfield_2:
704 case op_putfield_4:
705 case op_putfield_8:
706 case op_putfield_a:
707 case op_putstatic_1:
708 case op_putstatic_2:
709 case op_putstatic_4:
710 case op_putstatic_8:
711 case op_putstatic_a:
712 case op_getfield_1:
713 case op_getfield_2s:
714 case op_getfield_2u:
715 case op_getfield_4:
716 case op_getfield_8:
717 case op_getfield_a:
718 case op_getstatic_1:
719 case op_getstatic_2s:
720 case op_getstatic_2u:
721 case op_getstatic_4:
722 case op_getstatic_8:
723 case op_getstatic_a:
724 default:
725 // Fail somehow.
726 break;
731 // Now update exceptions.
732 _Jv_InterpException *exc = exceptions ();
733 for (int i = 0; i < exc_count; ++i)
735 exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
736 exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
737 exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
738 jclass handler = (_Jv_ResolvePoolEntry (defining_class,
739 exc[i].handler_type.i)).clazz;
740 exc[i].handler_type.p = handler;
743 prepared = insns;
745 #endif /* DIRECT_THREADED */
747 // This function exists so that the stack-tracing code can find the
748 // boundaries of the interpreter.
749 void
750 _Jv_StartOfInterpreter (void)
754 void
755 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
757 using namespace java::lang::reflect;
759 // FRAME_DESC registers this particular invocation as the top-most
760 // interpreter frame. This lets the stack tracing code (for
761 // Throwable) print information about the method being interpreted
762 // rather than about the interpreter itself. FRAME_DESC has a
763 // destructor so it cleans up automatically when the interpreter
764 // returns.
765 java::lang::Thread *thread = java::lang::Thread::currentThread();
766 _Jv_MethodChain frame_desc (this,
767 (_Jv_MethodChain **) &thread->interp_frame);
769 _Jv_word stack[max_stack];
770 _Jv_word *sp = stack;
772 _Jv_word locals[max_locals];
774 /* Go straight at it! the ffi raw format matches the internal
775 stack representation exactly. At least, that's the idea.
777 memcpy ((void*) locals, (void*) args, args_raw_size);
779 _Jv_word *pool_data = defining_class->constants.data;
781 /* These three are temporaries for common code used by several
782 instructions. */
783 void (*fun)();
784 _Jv_ResolvedMethod* rmeth;
785 int tmpval;
787 #define INSN_LABEL(op) &&insn_##op
789 static const void *const insn_target[] =
791 INSN_LABEL(nop),
792 INSN_LABEL(aconst_null),
793 INSN_LABEL(iconst_m1),
794 INSN_LABEL(iconst_0),
795 INSN_LABEL(iconst_1),
796 INSN_LABEL(iconst_2),
797 INSN_LABEL(iconst_3),
798 INSN_LABEL(iconst_4),
799 INSN_LABEL(iconst_5),
800 INSN_LABEL(lconst_0),
801 INSN_LABEL(lconst_1),
802 INSN_LABEL(fconst_0),
803 INSN_LABEL(fconst_1),
804 INSN_LABEL(fconst_2),
805 INSN_LABEL(dconst_0),
806 INSN_LABEL(dconst_1),
807 INSN_LABEL(bipush),
808 INSN_LABEL(sipush),
809 INSN_LABEL(ldc),
810 INSN_LABEL(ldc_w),
811 INSN_LABEL(ldc2_w),
812 INSN_LABEL(iload),
813 INSN_LABEL(lload),
814 INSN_LABEL(fload),
815 INSN_LABEL(dload),
816 INSN_LABEL(aload),
817 INSN_LABEL(iload_0),
818 INSN_LABEL(iload_1),
819 INSN_LABEL(iload_2),
820 INSN_LABEL(iload_3),
821 INSN_LABEL(lload_0),
822 INSN_LABEL(lload_1),
823 INSN_LABEL(lload_2),
824 INSN_LABEL(lload_3),
825 INSN_LABEL(fload_0),
826 INSN_LABEL(fload_1),
827 INSN_LABEL(fload_2),
828 INSN_LABEL(fload_3),
829 INSN_LABEL(dload_0),
830 INSN_LABEL(dload_1),
831 INSN_LABEL(dload_2),
832 INSN_LABEL(dload_3),
833 INSN_LABEL(aload_0),
834 INSN_LABEL(aload_1),
835 INSN_LABEL(aload_2),
836 INSN_LABEL(aload_3),
837 INSN_LABEL(iaload),
838 INSN_LABEL(laload),
839 INSN_LABEL(faload),
840 INSN_LABEL(daload),
841 INSN_LABEL(aaload),
842 INSN_LABEL(baload),
843 INSN_LABEL(caload),
844 INSN_LABEL(saload),
845 INSN_LABEL(istore),
846 INSN_LABEL(lstore),
847 INSN_LABEL(fstore),
848 INSN_LABEL(dstore),
849 INSN_LABEL(astore),
850 INSN_LABEL(istore_0),
851 INSN_LABEL(istore_1),
852 INSN_LABEL(istore_2),
853 INSN_LABEL(istore_3),
854 INSN_LABEL(lstore_0),
855 INSN_LABEL(lstore_1),
856 INSN_LABEL(lstore_2),
857 INSN_LABEL(lstore_3),
858 INSN_LABEL(fstore_0),
859 INSN_LABEL(fstore_1),
860 INSN_LABEL(fstore_2),
861 INSN_LABEL(fstore_3),
862 INSN_LABEL(dstore_0),
863 INSN_LABEL(dstore_1),
864 INSN_LABEL(dstore_2),
865 INSN_LABEL(dstore_3),
866 INSN_LABEL(astore_0),
867 INSN_LABEL(astore_1),
868 INSN_LABEL(astore_2),
869 INSN_LABEL(astore_3),
870 INSN_LABEL(iastore),
871 INSN_LABEL(lastore),
872 INSN_LABEL(fastore),
873 INSN_LABEL(dastore),
874 INSN_LABEL(aastore),
875 INSN_LABEL(bastore),
876 INSN_LABEL(castore),
877 INSN_LABEL(sastore),
878 INSN_LABEL(pop),
879 INSN_LABEL(pop2),
880 INSN_LABEL(dup),
881 INSN_LABEL(dup_x1),
882 INSN_LABEL(dup_x2),
883 INSN_LABEL(dup2),
884 INSN_LABEL(dup2_x1),
885 INSN_LABEL(dup2_x2),
886 INSN_LABEL(swap),
887 INSN_LABEL(iadd),
888 INSN_LABEL(ladd),
889 INSN_LABEL(fadd),
890 INSN_LABEL(dadd),
891 INSN_LABEL(isub),
892 INSN_LABEL(lsub),
893 INSN_LABEL(fsub),
894 INSN_LABEL(dsub),
895 INSN_LABEL(imul),
896 INSN_LABEL(lmul),
897 INSN_LABEL(fmul),
898 INSN_LABEL(dmul),
899 INSN_LABEL(idiv),
900 INSN_LABEL(ldiv),
901 INSN_LABEL(fdiv),
902 INSN_LABEL(ddiv),
903 INSN_LABEL(irem),
904 INSN_LABEL(lrem),
905 INSN_LABEL(frem),
906 INSN_LABEL(drem),
907 INSN_LABEL(ineg),
908 INSN_LABEL(lneg),
909 INSN_LABEL(fneg),
910 INSN_LABEL(dneg),
911 INSN_LABEL(ishl),
912 INSN_LABEL(lshl),
913 INSN_LABEL(ishr),
914 INSN_LABEL(lshr),
915 INSN_LABEL(iushr),
916 INSN_LABEL(lushr),
917 INSN_LABEL(iand),
918 INSN_LABEL(land),
919 INSN_LABEL(ior),
920 INSN_LABEL(lor),
921 INSN_LABEL(ixor),
922 INSN_LABEL(lxor),
923 INSN_LABEL(iinc),
924 INSN_LABEL(i2l),
925 INSN_LABEL(i2f),
926 INSN_LABEL(i2d),
927 INSN_LABEL(l2i),
928 INSN_LABEL(l2f),
929 INSN_LABEL(l2d),
930 INSN_LABEL(f2i),
931 INSN_LABEL(f2l),
932 INSN_LABEL(f2d),
933 INSN_LABEL(d2i),
934 INSN_LABEL(d2l),
935 INSN_LABEL(d2f),
936 INSN_LABEL(i2b),
937 INSN_LABEL(i2c),
938 INSN_LABEL(i2s),
939 INSN_LABEL(lcmp),
940 INSN_LABEL(fcmpl),
941 INSN_LABEL(fcmpg),
942 INSN_LABEL(dcmpl),
943 INSN_LABEL(dcmpg),
944 INSN_LABEL(ifeq),
945 INSN_LABEL(ifne),
946 INSN_LABEL(iflt),
947 INSN_LABEL(ifge),
948 INSN_LABEL(ifgt),
949 INSN_LABEL(ifle),
950 INSN_LABEL(if_icmpeq),
951 INSN_LABEL(if_icmpne),
952 INSN_LABEL(if_icmplt),
953 INSN_LABEL(if_icmpge),
954 INSN_LABEL(if_icmpgt),
955 INSN_LABEL(if_icmple),
956 INSN_LABEL(if_acmpeq),
957 INSN_LABEL(if_acmpne),
958 INSN_LABEL(goto),
959 INSN_LABEL(jsr),
960 INSN_LABEL(ret),
961 INSN_LABEL(tableswitch),
962 INSN_LABEL(lookupswitch),
963 INSN_LABEL(ireturn),
964 INSN_LABEL(lreturn),
965 INSN_LABEL(freturn),
966 INSN_LABEL(dreturn),
967 INSN_LABEL(areturn),
968 INSN_LABEL(return),
969 INSN_LABEL(getstatic),
970 INSN_LABEL(putstatic),
971 INSN_LABEL(getfield),
972 INSN_LABEL(putfield),
973 INSN_LABEL(invokevirtual),
974 INSN_LABEL(invokespecial),
975 INSN_LABEL(invokestatic),
976 INSN_LABEL(invokeinterface),
977 0, /* Unused. */
978 INSN_LABEL(new),
979 INSN_LABEL(newarray),
980 INSN_LABEL(anewarray),
981 INSN_LABEL(arraylength),
982 INSN_LABEL(athrow),
983 INSN_LABEL(checkcast),
984 INSN_LABEL(instanceof),
985 INSN_LABEL(monitorenter),
986 INSN_LABEL(monitorexit),
987 #ifdef DIRECT_THREADED
988 0, // wide
989 #else
990 INSN_LABEL(wide),
991 #endif
992 INSN_LABEL(multianewarray),
993 INSN_LABEL(ifnull),
994 INSN_LABEL(ifnonnull),
995 INSN_LABEL(goto_w),
996 INSN_LABEL(jsr_w),
1000 pc_t pc;
1002 #ifdef DIRECT_THREADED
1004 #define NEXT_INSN goto *((pc++)->insn)
1005 #define INTVAL() ((pc++)->int_val)
1006 #define AVAL() ((pc++)->datum)
1008 #define GET1S() INTVAL ()
1009 #define GET2S() INTVAL ()
1010 #define GET1U() INTVAL ()
1011 #define GET2U() INTVAL ()
1012 #define AVAL1U() AVAL ()
1013 #define AVAL2U() AVAL ()
1014 #define AVAL2UP() AVAL ()
1015 #define SKIP_GOTO ++pc
1016 #define GOTO_VAL() (insn_slot *) pc->datum
1017 #define PCVAL(unionval) unionval.p
1018 #define AMPAMP(label) &&label
1020 // Compile if we must.
1021 if (prepared == NULL)
1022 compile (insn_target);
1023 pc = (insn_slot *) prepared;
1025 #else
1027 #define NEXT_INSN goto *(insn_target[*pc++])
1029 #define GET1S() get1s (pc++)
1030 #define GET2S() (pc += 2, get2s (pc- 2))
1031 #define GET1U() get1u (pc++)
1032 #define GET2U() (pc += 2, get2u (pc - 2))
1033 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1034 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1035 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1036 #define SKIP_GOTO pc += 2
1037 #define GOTO_VAL() pc - 1 + get2s (pc)
1038 #define PCVAL(unionval) unionval.i
1039 #define AMPAMP(label) NULL
1041 pc = bytecode ();
1043 #endif /* DIRECT_THREADED */
1045 #define TAKE_GOTO pc = GOTO_VAL ()
1049 // We keep nop around. It is used if we're interpreting the
1050 // bytecodes and not doing direct threading.
1051 insn_nop:
1052 NEXT_INSN;
1054 /* The first few instructions here are ordered according to their
1055 frequency, in the hope that this will improve code locality a
1056 little. */
1058 insn_aload_0: // 0x2a
1059 LOADA (0);
1060 NEXT_INSN;
1062 insn_iload: // 0x15
1063 LOADI (GET1U ());
1064 NEXT_INSN;
1066 insn_iload_1: // 0x1b
1067 LOADI (1);
1068 NEXT_INSN;
1070 insn_invokevirtual: // 0xb6
1072 int index = GET2U ();
1074 /* _Jv_ResolvePoolEntry returns immediately if the value already
1075 * is resolved. If we want to clutter up the code here to gain
1076 * a little performance, then we can check the corresponding bit
1077 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
1078 * don't think it is worth it. */
1080 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
1082 sp -= rmeth->stack_item_count;
1083 // We don't use NULLCHECK here because we can't rely on that
1084 // working if the method is final. So instead we do an
1085 // explicit test.
1086 if (! sp[0].o)
1087 throw new java::lang::NullPointerException;
1089 if (rmeth->vtable_index == -1)
1091 // final methods do not appear in the vtable,
1092 // if it does not appear in the superclass.
1093 fun = (void (*)()) rmeth->method->ncode;
1095 else
1097 jobject rcv = sp[0].o;
1098 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1099 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1102 #ifdef DIRECT_THREADED
1103 // Rewrite instruction so that we use a faster pre-resolved
1104 // method.
1105 pc[-2].insn = &&invokevirtual_resolved;
1106 pc[-1].datum = rmeth;
1107 #endif /* DIRECT_THREADED */
1109 goto perform_invoke;
1111 #ifdef DIRECT_THREADED
1112 invokevirtual_resolved:
1114 rmeth = (_Jv_ResolvedMethod *) AVAL ();
1115 sp -= rmeth->stack_item_count;
1116 // We don't use NULLCHECK here because we can't rely on that
1117 // working if the method is final. So instead we do an
1118 // explicit test.
1119 if (! sp[0].o)
1120 throw new java::lang::NullPointerException;
1122 if (rmeth->vtable_index == -1)
1124 // final methods do not appear in the vtable,
1125 // if it does not appear in the superclass.
1126 fun = (void (*)()) rmeth->method->ncode;
1128 else
1130 jobject rcv = sp[0].o;
1131 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1132 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1135 goto perform_invoke;
1136 #endif /* DIRECT_THREADED */
1138 perform_invoke:
1140 /* here goes the magic again... */
1141 ffi_cif *cif = &rmeth->cif;
1142 ffi_raw *raw = (ffi_raw*) sp;
1144 jdouble rvalue;
1146 #if FFI_NATIVE_RAW_API
1147 /* We assume that this is only implemented if it's correct */
1148 /* to use it here. On a 64 bit machine, it never is. */
1149 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
1150 #else
1151 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
1152 #endif
1154 int rtype = cif->rtype->type;
1156 /* the likelyhood of object, int, or void return is very high,
1157 * so those are checked before the switch */
1158 if (rtype == FFI_TYPE_POINTER)
1160 PUSHA (*(jobject*)&rvalue);
1162 else if (rtype == FFI_TYPE_SINT32)
1164 PUSHI (*(jint*)&rvalue);
1166 else if (rtype == FFI_TYPE_VOID)
1168 /* skip */
1170 else
1172 switch (rtype)
1174 case FFI_TYPE_SINT8:
1176 jbyte value = (*(jint*)&rvalue) & 0xff;
1177 PUSHI (value);
1179 break;
1181 case FFI_TYPE_SINT16:
1183 jshort value = (*(jint*)&rvalue) & 0xffff;
1184 PUSHI (value);
1186 break;
1188 case FFI_TYPE_UINT16:
1190 jint value = (*(jint*)&rvalue) & 0xffff;
1191 PUSHI (value);
1193 break;
1195 case FFI_TYPE_FLOAT:
1196 PUSHF (*(jfloat*)&rvalue);
1197 break;
1199 case FFI_TYPE_DOUBLE:
1200 PUSHD (rvalue);
1201 break;
1203 case FFI_TYPE_SINT64:
1204 PUSHL (*(jlong*)&rvalue);
1205 break;
1207 default:
1208 throw_internal_error ("unknown return type in invokeXXX");
1212 NEXT_INSN;
1214 insn_aconst_null:
1215 PUSHA (NULL);
1216 NEXT_INSN;
1218 insn_iconst_m1:
1219 PUSHI (-1);
1220 NEXT_INSN;
1222 insn_iconst_0:
1223 PUSHI (0);
1224 NEXT_INSN;
1226 insn_iconst_1:
1227 PUSHI (1);
1228 NEXT_INSN;
1230 insn_iconst_2:
1231 PUSHI (2);
1232 NEXT_INSN;
1234 insn_iconst_3:
1235 PUSHI (3);
1236 NEXT_INSN;
1238 insn_iconst_4:
1239 PUSHI (4);
1240 NEXT_INSN;
1242 insn_iconst_5:
1243 PUSHI (5);
1244 NEXT_INSN;
1246 insn_lconst_0:
1247 PUSHL (0);
1248 NEXT_INSN;
1250 insn_lconst_1:
1251 PUSHL (1);
1252 NEXT_INSN;
1254 insn_fconst_0:
1255 PUSHF (0);
1256 NEXT_INSN;
1258 insn_fconst_1:
1259 PUSHF (1);
1260 NEXT_INSN;
1262 insn_fconst_2:
1263 PUSHF (2);
1264 NEXT_INSN;
1266 insn_dconst_0:
1267 PUSHD (0);
1268 NEXT_INSN;
1270 insn_dconst_1:
1271 PUSHD (1);
1272 NEXT_INSN;
1274 insn_bipush:
1275 // For direct threaded, bipush and sipush are the same.
1276 #ifndef DIRECT_THREADED
1277 PUSHI (GET1S ());
1278 NEXT_INSN;
1279 #endif /* DIRECT_THREADED */
1280 insn_sipush:
1281 PUSHI (GET2S ());
1282 NEXT_INSN;
1284 insn_ldc:
1285 // For direct threaded, ldc and ldc_w are the same.
1286 #ifndef DIRECT_THREADED
1287 PUSHA ((jobject) AVAL1U ());
1288 NEXT_INSN;
1289 #endif /* DIRECT_THREADED */
1290 insn_ldc_w:
1291 PUSHA ((jobject) AVAL2U ());
1292 NEXT_INSN;
1294 insn_ldc2_w:
1296 void *where = AVAL2UP ();
1297 memcpy (sp, where, 2*sizeof (_Jv_word));
1298 sp += 2;
1300 NEXT_INSN;
1302 insn_lload:
1303 LOADL (GET1U ());
1304 NEXT_INSN;
1306 insn_fload:
1307 LOADF (GET1U ());
1308 NEXT_INSN;
1310 insn_dload:
1311 LOADD (GET1U ());
1312 NEXT_INSN;
1314 insn_aload:
1315 LOADA (GET1U ());
1316 NEXT_INSN;
1318 insn_iload_0:
1319 LOADI (0);
1320 NEXT_INSN;
1322 insn_iload_2:
1323 LOADI (2);
1324 NEXT_INSN;
1326 insn_iload_3:
1327 LOADI (3);
1328 NEXT_INSN;
1330 insn_lload_0:
1331 LOADL (0);
1332 NEXT_INSN;
1334 insn_lload_1:
1335 LOADL (1);
1336 NEXT_INSN;
1338 insn_lload_2:
1339 LOADL (2);
1340 NEXT_INSN;
1342 insn_lload_3:
1343 LOADL (3);
1344 NEXT_INSN;
1346 insn_fload_0:
1347 LOADF (0);
1348 NEXT_INSN;
1350 insn_fload_1:
1351 LOADF (1);
1352 NEXT_INSN;
1354 insn_fload_2:
1355 LOADF (2);
1356 NEXT_INSN;
1358 insn_fload_3:
1359 LOADF (3);
1360 NEXT_INSN;
1362 insn_dload_0:
1363 LOADD (0);
1364 NEXT_INSN;
1366 insn_dload_1:
1367 LOADD (1);
1368 NEXT_INSN;
1370 insn_dload_2:
1371 LOADD (2);
1372 NEXT_INSN;
1374 insn_dload_3:
1375 LOADD (3);
1376 NEXT_INSN;
1378 insn_aload_1:
1379 LOADA(1);
1380 NEXT_INSN;
1382 insn_aload_2:
1383 LOADA(2);
1384 NEXT_INSN;
1386 insn_aload_3:
1387 LOADA(3);
1388 NEXT_INSN;
1390 insn_iaload:
1392 jint index = POPI();
1393 jintArray arr = (jintArray) POPA();
1394 NULLARRAYCHECK (arr);
1395 ARRAYBOUNDSCHECK (arr, index);
1396 PUSHI( elements(arr)[index] );
1398 NEXT_INSN;
1400 insn_laload:
1402 jint index = POPI();
1403 jlongArray arr = (jlongArray) POPA();
1404 NULLARRAYCHECK (arr);
1405 ARRAYBOUNDSCHECK (arr, index);
1406 PUSHL( elements(arr)[index] );
1408 NEXT_INSN;
1410 insn_faload:
1412 jint index = POPI();
1413 jfloatArray arr = (jfloatArray) POPA();
1414 NULLARRAYCHECK (arr);
1415 ARRAYBOUNDSCHECK (arr, index);
1416 PUSHF( elements(arr)[index] );
1418 NEXT_INSN;
1420 insn_daload:
1422 jint index = POPI();
1423 jdoubleArray arr = (jdoubleArray) POPA();
1424 NULLARRAYCHECK (arr);
1425 ARRAYBOUNDSCHECK (arr, index);
1426 PUSHD( elements(arr)[index] );
1428 NEXT_INSN;
1430 insn_aaload:
1432 jint index = POPI();
1433 jobjectArray arr = (jobjectArray) POPA();
1434 NULLARRAYCHECK (arr);
1435 ARRAYBOUNDSCHECK (arr, index);
1436 PUSHA( elements(arr)[index] );
1438 NEXT_INSN;
1440 insn_baload:
1442 jint index = POPI();
1443 jbyteArray arr = (jbyteArray) POPA();
1444 NULLARRAYCHECK (arr);
1445 ARRAYBOUNDSCHECK (arr, index);
1446 PUSHI( elements(arr)[index] );
1448 NEXT_INSN;
1450 insn_caload:
1452 jint index = POPI();
1453 jcharArray arr = (jcharArray) POPA();
1454 NULLARRAYCHECK (arr);
1455 ARRAYBOUNDSCHECK (arr, index);
1456 PUSHI( elements(arr)[index] );
1458 NEXT_INSN;
1460 insn_saload:
1462 jint index = POPI();
1463 jshortArray arr = (jshortArray) POPA();
1464 NULLARRAYCHECK (arr);
1465 ARRAYBOUNDSCHECK (arr, index);
1466 PUSHI( elements(arr)[index] );
1468 NEXT_INSN;
1470 insn_istore:
1471 STOREI (GET1U ());
1472 NEXT_INSN;
1474 insn_lstore:
1475 STOREL (GET1U ());
1476 NEXT_INSN;
1478 insn_fstore:
1479 STOREF (GET1U ());
1480 NEXT_INSN;
1482 insn_dstore:
1483 STORED (GET1U ());
1484 NEXT_INSN;
1486 insn_astore:
1487 STOREA (GET1U ());
1488 NEXT_INSN;
1490 insn_istore_0:
1491 STOREI (0);
1492 NEXT_INSN;
1494 insn_istore_1:
1495 STOREI (1);
1496 NEXT_INSN;
1498 insn_istore_2:
1499 STOREI (2);
1500 NEXT_INSN;
1502 insn_istore_3:
1503 STOREI (3);
1504 NEXT_INSN;
1506 insn_lstore_0:
1507 STOREL (0);
1508 NEXT_INSN;
1510 insn_lstore_1:
1511 STOREL (1);
1512 NEXT_INSN;
1514 insn_lstore_2:
1515 STOREL (2);
1516 NEXT_INSN;
1518 insn_lstore_3:
1519 STOREL (3);
1520 NEXT_INSN;
1522 insn_fstore_0:
1523 STOREF (0);
1524 NEXT_INSN;
1526 insn_fstore_1:
1527 STOREF (1);
1528 NEXT_INSN;
1530 insn_fstore_2:
1531 STOREF (2);
1532 NEXT_INSN;
1534 insn_fstore_3:
1535 STOREF (3);
1536 NEXT_INSN;
1538 insn_dstore_0:
1539 STORED (0);
1540 NEXT_INSN;
1542 insn_dstore_1:
1543 STORED (1);
1544 NEXT_INSN;
1546 insn_dstore_2:
1547 STORED (2);
1548 NEXT_INSN;
1550 insn_dstore_3:
1551 STORED (3);
1552 NEXT_INSN;
1554 insn_astore_0:
1555 STOREA(0);
1556 NEXT_INSN;
1558 insn_astore_1:
1559 STOREA(1);
1560 NEXT_INSN;
1562 insn_astore_2:
1563 STOREA(2);
1564 NEXT_INSN;
1566 insn_astore_3:
1567 STOREA(3);
1568 NEXT_INSN;
1570 insn_iastore:
1572 jint value = POPI();
1573 jint index = POPI();
1574 jintArray arr = (jintArray) POPA();
1575 NULLARRAYCHECK (arr);
1576 ARRAYBOUNDSCHECK (arr, index);
1577 elements(arr)[index] = value;
1579 NEXT_INSN;
1581 insn_lastore:
1583 jlong value = POPL();
1584 jint index = POPI();
1585 jlongArray arr = (jlongArray) POPA();
1586 NULLARRAYCHECK (arr);
1587 ARRAYBOUNDSCHECK (arr, index);
1588 elements(arr)[index] = value;
1590 NEXT_INSN;
1592 insn_fastore:
1594 jfloat value = POPF();
1595 jint index = POPI();
1596 jfloatArray arr = (jfloatArray) POPA();
1597 NULLARRAYCHECK (arr);
1598 ARRAYBOUNDSCHECK (arr, index);
1599 elements(arr)[index] = value;
1601 NEXT_INSN;
1603 insn_dastore:
1605 jdouble value = POPD();
1606 jint index = POPI();
1607 jdoubleArray arr = (jdoubleArray) POPA();
1608 NULLARRAYCHECK (arr);
1609 ARRAYBOUNDSCHECK (arr, index);
1610 elements(arr)[index] = value;
1612 NEXT_INSN;
1614 insn_aastore:
1616 jobject value = POPA();
1617 jint index = POPI();
1618 jobjectArray arr = (jobjectArray) POPA();
1619 NULLARRAYCHECK (arr);
1620 ARRAYBOUNDSCHECK (arr, index);
1621 _Jv_CheckArrayStore (arr, value);
1622 elements(arr)[index] = value;
1624 NEXT_INSN;
1626 insn_bastore:
1628 jbyte value = (jbyte) POPI();
1629 jint index = POPI();
1630 jbyteArray arr = (jbyteArray) POPA();
1631 NULLARRAYCHECK (arr);
1632 ARRAYBOUNDSCHECK (arr, index);
1633 elements(arr)[index] = value;
1635 NEXT_INSN;
1637 insn_castore:
1639 jchar value = (jchar) POPI();
1640 jint index = POPI();
1641 jcharArray arr = (jcharArray) POPA();
1642 NULLARRAYCHECK (arr);
1643 ARRAYBOUNDSCHECK (arr, index);
1644 elements(arr)[index] = value;
1646 NEXT_INSN;
1648 insn_sastore:
1650 jshort value = (jshort) POPI();
1651 jint index = POPI();
1652 jshortArray arr = (jshortArray) POPA();
1653 NULLARRAYCHECK (arr);
1654 ARRAYBOUNDSCHECK (arr, index);
1655 elements(arr)[index] = value;
1657 NEXT_INSN;
1659 insn_pop:
1660 sp -= 1;
1661 NEXT_INSN;
1663 insn_pop2:
1664 sp -= 2;
1665 NEXT_INSN;
1667 insn_dup:
1668 sp[0] = sp[-1];
1669 sp += 1;
1670 NEXT_INSN;
1672 insn_dup_x1:
1673 dupx (sp, 1, 1); sp+=1;
1674 NEXT_INSN;
1676 insn_dup_x2:
1677 dupx (sp, 1, 2); sp+=1;
1678 NEXT_INSN;
1680 insn_dup2:
1681 sp[0] = sp[-2];
1682 sp[1] = sp[-1];
1683 sp += 2;
1684 NEXT_INSN;
1686 insn_dup2_x1:
1687 dupx (sp, 2, 1); sp+=2;
1688 NEXT_INSN;
1690 insn_dup2_x2:
1691 dupx (sp, 2, 2); sp+=2;
1692 NEXT_INSN;
1694 insn_swap:
1696 jobject tmp1 = POPA();
1697 jobject tmp2 = POPA();
1698 PUSHA (tmp1);
1699 PUSHA (tmp2);
1701 NEXT_INSN;
1703 insn_iadd:
1704 BINOPI(+);
1705 NEXT_INSN;
1707 insn_ladd:
1708 BINOPL(+);
1709 NEXT_INSN;
1711 insn_fadd:
1712 BINOPF(+);
1713 NEXT_INSN;
1715 insn_dadd:
1716 BINOPD(+);
1717 NEXT_INSN;
1719 insn_isub:
1720 BINOPI(-);
1721 NEXT_INSN;
1723 insn_lsub:
1724 BINOPL(-);
1725 NEXT_INSN;
1727 insn_fsub:
1728 BINOPF(-);
1729 NEXT_INSN;
1731 insn_dsub:
1732 BINOPD(-);
1733 NEXT_INSN;
1735 insn_imul:
1736 BINOPI(*);
1737 NEXT_INSN;
1739 insn_lmul:
1740 BINOPL(*);
1741 NEXT_INSN;
1743 insn_fmul:
1744 BINOPF(*);
1745 NEXT_INSN;
1747 insn_dmul:
1748 BINOPD(*);
1749 NEXT_INSN;
1751 insn_idiv:
1753 jint value2 = POPI();
1754 jint value1 = POPI();
1755 jint res = _Jv_divI (value1, value2);
1756 PUSHI (res);
1758 NEXT_INSN;
1760 insn_ldiv:
1762 jlong value2 = POPL();
1763 jlong value1 = POPL();
1764 jlong res = _Jv_divJ (value1, value2);
1765 PUSHL (res);
1767 NEXT_INSN;
1769 insn_fdiv:
1771 jfloat value2 = POPF();
1772 jfloat value1 = POPF();
1773 jfloat res = value1 / value2;
1774 PUSHF (res);
1776 NEXT_INSN;
1778 insn_ddiv:
1780 jdouble value2 = POPD();
1781 jdouble value1 = POPD();
1782 jdouble res = value1 / value2;
1783 PUSHD (res);
1785 NEXT_INSN;
1787 insn_irem:
1789 jint value2 = POPI();
1790 jint value1 = POPI();
1791 jint res = _Jv_remI (value1, value2);
1792 PUSHI (res);
1794 NEXT_INSN;
1796 insn_lrem:
1798 jlong value2 = POPL();
1799 jlong value1 = POPL();
1800 jlong res = _Jv_remJ (value1, value2);
1801 PUSHL (res);
1803 NEXT_INSN;
1805 insn_frem:
1807 jfloat value2 = POPF();
1808 jfloat value1 = POPF();
1809 jfloat res = __ieee754_fmod (value1, value2);
1810 PUSHF (res);
1812 NEXT_INSN;
1814 insn_drem:
1816 jdouble value2 = POPD();
1817 jdouble value1 = POPD();
1818 jdouble res = __ieee754_fmod (value1, value2);
1819 PUSHD (res);
1821 NEXT_INSN;
1823 insn_ineg:
1825 jint value = POPI();
1826 PUSHI (value * -1);
1828 NEXT_INSN;
1830 insn_lneg:
1832 jlong value = POPL();
1833 PUSHL (value * -1);
1835 NEXT_INSN;
1837 insn_fneg:
1839 jfloat value = POPF();
1840 PUSHF (value * -1);
1842 NEXT_INSN;
1844 insn_dneg:
1846 jdouble value = POPD();
1847 PUSHD (value * -1);
1849 NEXT_INSN;
1851 insn_ishl:
1853 jint shift = (POPI() & 0x1f);
1854 jint value = POPI();
1855 PUSHI (value << shift);
1857 NEXT_INSN;
1859 insn_lshl:
1861 jint shift = (POPI() & 0x3f);
1862 jlong value = POPL();
1863 PUSHL (value << shift);
1865 NEXT_INSN;
1867 insn_ishr:
1869 jint shift = (POPI() & 0x1f);
1870 jint value = POPI();
1871 PUSHI (value >> shift);
1873 NEXT_INSN;
1875 insn_lshr:
1877 jint shift = (POPI() & 0x3f);
1878 jlong value = POPL();
1879 PUSHL (value >> shift);
1881 NEXT_INSN;
1883 insn_iushr:
1885 jint shift = (POPI() & 0x1f);
1886 unsigned long value = POPI();
1887 PUSHI ((jint) (value >> shift));
1889 NEXT_INSN;
1891 insn_lushr:
1893 jint shift = (POPI() & 0x3f);
1894 UINT64 value = (UINT64) POPL();
1895 PUSHL ((value >> shift));
1897 NEXT_INSN;
1899 insn_iand:
1900 BINOPI (&);
1901 NEXT_INSN;
1903 insn_land:
1904 BINOPL (&);
1905 NEXT_INSN;
1907 insn_ior:
1908 BINOPI (|);
1909 NEXT_INSN;
1911 insn_lor:
1912 BINOPL (|);
1913 NEXT_INSN;
1915 insn_ixor:
1916 BINOPI (^);
1917 NEXT_INSN;
1919 insn_lxor:
1920 BINOPL (^);
1921 NEXT_INSN;
1923 insn_iinc:
1925 jint index = GET1U ();
1926 jint amount = GET1S ();
1927 locals[index].i += amount;
1929 NEXT_INSN;
1931 insn_i2l:
1932 {jlong value = POPI(); PUSHL (value);}
1933 NEXT_INSN;
1935 insn_i2f:
1936 {jfloat value = POPI(); PUSHF (value);}
1937 NEXT_INSN;
1939 insn_i2d:
1940 {jdouble value = POPI(); PUSHD (value);}
1941 NEXT_INSN;
1943 insn_l2i:
1944 {jint value = POPL(); PUSHI (value);}
1945 NEXT_INSN;
1947 insn_l2f:
1948 {jfloat value = POPL(); PUSHF (value);}
1949 NEXT_INSN;
1951 insn_l2d:
1952 {jdouble value = POPL(); PUSHD (value);}
1953 NEXT_INSN;
1955 insn_f2i:
1957 using namespace java::lang;
1958 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1959 PUSHI(value);
1961 NEXT_INSN;
1963 insn_f2l:
1965 using namespace java::lang;
1966 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1967 PUSHL(value);
1969 NEXT_INSN;
1971 insn_f2d:
1972 { jdouble value = POPF (); PUSHD(value); }
1973 NEXT_INSN;
1975 insn_d2i:
1977 using namespace java::lang;
1978 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1979 PUSHI(value);
1981 NEXT_INSN;
1983 insn_d2l:
1985 using namespace java::lang;
1986 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1987 PUSHL(value);
1989 NEXT_INSN;
1991 insn_d2f:
1992 { jfloat value = POPD (); PUSHF(value); }
1993 NEXT_INSN;
1995 insn_i2b:
1996 { jbyte value = POPI (); PUSHI(value); }
1997 NEXT_INSN;
1999 insn_i2c:
2000 { jchar value = POPI (); PUSHI(value); }
2001 NEXT_INSN;
2003 insn_i2s:
2004 { jshort value = POPI (); PUSHI(value); }
2005 NEXT_INSN;
2007 insn_lcmp:
2009 jlong value2 = POPL ();
2010 jlong value1 = POPL ();
2011 if (value1 > value2)
2012 { PUSHI (1); }
2013 else if (value1 == value2)
2014 { PUSHI (0); }
2015 else
2016 { PUSHI (-1); }
2018 NEXT_INSN;
2020 insn_fcmpl:
2021 tmpval = -1;
2022 goto fcmp;
2024 insn_fcmpg:
2025 tmpval = 1;
2027 fcmp:
2029 jfloat value2 = POPF ();
2030 jfloat value1 = POPF ();
2031 if (value1 > value2)
2032 PUSHI (1);
2033 else if (value1 == value2)
2034 PUSHI (0);
2035 else if (value1 < value2)
2036 PUSHI (-1);
2037 else
2038 PUSHI (tmpval);
2040 NEXT_INSN;
2042 insn_dcmpl:
2043 tmpval = 1;
2044 goto dcmp;
2046 insn_dcmpg:
2047 tmpval = -1;
2049 dcmp:
2051 jdouble value2 = POPD ();
2052 jdouble value1 = POPD ();
2053 if (value1 > value2)
2054 PUSHI (1);
2055 else if (value1 == value2)
2056 PUSHI (0);
2057 else if (value1 < value2)
2058 PUSHI (-1);
2059 else
2060 PUSHI (tmpval);
2062 NEXT_INSN;
2064 insn_ifeq:
2066 if (POPI() == 0)
2067 TAKE_GOTO;
2068 else
2069 SKIP_GOTO;
2071 NEXT_INSN;
2073 insn_ifne:
2075 if (POPI() != 0)
2076 TAKE_GOTO;
2077 else
2078 SKIP_GOTO;
2080 NEXT_INSN;
2082 insn_iflt:
2084 if (POPI() < 0)
2085 TAKE_GOTO;
2086 else
2087 SKIP_GOTO;
2089 NEXT_INSN;
2091 insn_ifge:
2093 if (POPI() >= 0)
2094 TAKE_GOTO;
2095 else
2096 SKIP_GOTO;
2098 NEXT_INSN;
2100 insn_ifgt:
2102 if (POPI() > 0)
2103 TAKE_GOTO;
2104 else
2105 SKIP_GOTO;
2107 NEXT_INSN;
2109 insn_ifle:
2111 if (POPI() <= 0)
2112 TAKE_GOTO;
2113 else
2114 SKIP_GOTO;
2116 NEXT_INSN;
2118 insn_if_icmpeq:
2120 jint value2 = POPI();
2121 jint value1 = POPI();
2122 if (value1 == value2)
2123 TAKE_GOTO;
2124 else
2125 SKIP_GOTO;
2127 NEXT_INSN;
2129 insn_if_icmpne:
2131 jint value2 = POPI();
2132 jint value1 = POPI();
2133 if (value1 != value2)
2134 TAKE_GOTO;
2135 else
2136 SKIP_GOTO;
2138 NEXT_INSN;
2140 insn_if_icmplt:
2142 jint value2 = POPI();
2143 jint value1 = POPI();
2144 if (value1 < value2)
2145 TAKE_GOTO;
2146 else
2147 SKIP_GOTO;
2149 NEXT_INSN;
2151 insn_if_icmpge:
2153 jint value2 = POPI();
2154 jint value1 = POPI();
2155 if (value1 >= value2)
2156 TAKE_GOTO;
2157 else
2158 SKIP_GOTO;
2160 NEXT_INSN;
2162 insn_if_icmpgt:
2164 jint value2 = POPI();
2165 jint value1 = POPI();
2166 if (value1 > value2)
2167 TAKE_GOTO;
2168 else
2169 SKIP_GOTO;
2171 NEXT_INSN;
2173 insn_if_icmple:
2175 jint value2 = POPI();
2176 jint value1 = POPI();
2177 if (value1 <= value2)
2178 TAKE_GOTO;
2179 else
2180 SKIP_GOTO;
2182 NEXT_INSN;
2184 insn_if_acmpeq:
2186 jobject value2 = POPA();
2187 jobject value1 = POPA();
2188 if (value1 == value2)
2189 TAKE_GOTO;
2190 else
2191 SKIP_GOTO;
2193 NEXT_INSN;
2195 insn_if_acmpne:
2197 jobject value2 = POPA();
2198 jobject value1 = POPA();
2199 if (value1 != value2)
2200 TAKE_GOTO;
2201 else
2202 SKIP_GOTO;
2204 NEXT_INSN;
2206 insn_goto_w:
2207 #ifndef DIRECT_THREADED
2208 // For direct threaded, goto and goto_w are the same.
2209 pc = pc - 1 + get4 (pc);
2210 NEXT_INSN;
2211 #endif /* DIRECT_THREADED */
2212 insn_goto:
2213 TAKE_GOTO;
2214 NEXT_INSN;
2216 insn_jsr_w:
2217 #ifndef DIRECT_THREADED
2218 // For direct threaded, jsr and jsr_w are the same.
2220 pc_t next = pc - 1 + get4 (pc);
2221 pc += 4;
2222 PUSHA ((jobject) pc);
2223 pc = next;
2225 NEXT_INSN;
2226 #endif /* DIRECT_THREADED */
2227 insn_jsr:
2229 pc_t next = GOTO_VAL();
2230 SKIP_GOTO;
2231 PUSHA ((jobject) pc);
2232 pc = next;
2234 NEXT_INSN;
2236 insn_ret:
2238 jint index = GET1U ();
2239 pc = (pc_t) PEEKA (index);
2241 NEXT_INSN;
2243 insn_tableswitch:
2245 #ifdef DIRECT_THREADED
2246 void *def = (pc++)->datum;
2248 int index = POPI();
2250 jint low = INTVAL ();
2251 jint high = INTVAL ();
2253 if (index < low || index > high)
2254 pc = (insn_slot *) def;
2255 else
2256 pc = (insn_slot *) ((pc + index - low)->datum);
2257 #else
2258 pc_t base_pc = pc - 1;
2259 int index = POPI ();
2261 pc_t base = (pc_t) bytecode ();
2262 while ((pc - base) % 4 != 0)
2263 ++pc;
2265 jint def = get4 (pc);
2266 jint low = get4 (pc + 4);
2267 jint high = get4 (pc + 8);
2268 if (index < low || index > high)
2269 pc = base_pc + def;
2270 else
2271 pc = base_pc + get4 (pc + 4 * (index - low + 3));
2272 #endif /* DIRECT_THREADED */
2274 NEXT_INSN;
2276 insn_lookupswitch:
2278 #ifdef DIRECT_THREADED
2279 void *def = (pc++)->insn;
2281 int index = POPI();
2283 jint npairs = INTVAL ();
2285 int max = npairs - 1;
2286 int min = 0;
2288 // Simple binary search...
2289 while (min < max)
2291 int half = (min + max) / 2;
2292 int match = pc[2 * half].int_val;
2294 if (index == match)
2296 // Found it.
2297 pc = (insn_slot *) pc[2 * half + 1].datum;
2298 NEXT_INSN;
2300 else if (index < match)
2301 // We can use HALF - 1 here because we check again on
2302 // loop exit.
2303 max = half - 1;
2304 else
2305 // We can use HALF + 1 here because we check again on
2306 // loop exit.
2307 min = half + 1;
2309 if (index == pc[2 * min].int_val)
2310 pc = (insn_slot *) pc[2 * min + 1].datum;
2311 else
2312 pc = (insn_slot *) def;
2313 #else
2314 unsigned char *base_pc = pc-1;
2315 int index = POPI();
2317 unsigned char* base = bytecode ();
2318 while ((pc-base) % 4 != 0)
2319 ++pc;
2321 jint def = get4 (pc);
2322 jint npairs = get4 (pc+4);
2324 int max = npairs-1;
2325 int min = 0;
2327 // Simple binary search...
2328 while (min < max)
2330 int half = (min+max)/2;
2331 int match = get4 (pc+ 4*(2 + 2*half));
2333 if (index == match)
2334 min = max = half;
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;
2345 if (index == get4 (pc+ 4*(2 + 2*min)))
2346 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
2347 else
2348 pc = base_pc + def;
2349 #endif /* DIRECT_THREADED */
2351 NEXT_INSN;
2353 insn_areturn:
2354 *(jobject *) retp = POPA ();
2355 return;
2357 insn_lreturn:
2358 *(jlong *) retp = POPL ();
2359 return;
2361 insn_freturn:
2362 *(jfloat *) retp = POPF ();
2363 return;
2365 insn_dreturn:
2366 *(jdouble *) retp = POPD ();
2367 return;
2369 insn_ireturn:
2370 *(jint *) retp = POPI ();
2371 return;
2373 insn_return:
2374 return;
2376 insn_getstatic:
2378 jint fieldref_index = GET2U ();
2379 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2380 _Jv_Field *field = pool_data[fieldref_index].field;
2382 if ((field->flags & Modifier::STATIC) == 0)
2383 throw_incompatible_class_change_error
2384 (JvNewStringLatin1 ("field no longer static"));
2386 jclass type = field->type;
2388 // We rewrite the instruction once we discover what it refers
2389 // to.
2390 void *newinsn = NULL;
2391 if (type->isPrimitive ())
2393 switch (type->size_in_bytes)
2395 case 1:
2396 PUSHI (*(jbyte*) (field->u.addr));
2397 newinsn = AMPAMP (getstatic_resolved_1);
2398 break;
2400 case 2:
2401 if (type == JvPrimClass (char))
2403 PUSHI(*(jchar*) (field->u.addr));
2404 newinsn = AMPAMP (getstatic_resolved_char);
2406 else
2408 PUSHI(*(jshort*) (field->u.addr));
2409 newinsn = AMPAMP (getstatic_resolved_short);
2411 break;
2413 case 4:
2414 PUSHI(*(jint*) (field->u.addr));
2415 newinsn = AMPAMP (getstatic_resolved_4);
2416 break;
2418 case 8:
2419 PUSHL(*(jlong*) (field->u.addr));
2420 newinsn = AMPAMP (getstatic_resolved_8);
2421 break;
2424 else
2426 PUSHA(*(jobject*) (field->u.addr));
2427 newinsn = AMPAMP (getstatic_resolved_obj);
2430 #ifdef DIRECT_THREADED
2431 pc[-2].insn = newinsn;
2432 pc[-1].datum = field->u.addr;
2433 #endif /* DIRECT_THREADED */
2435 NEXT_INSN;
2437 #ifdef DIRECT_THREADED
2438 getstatic_resolved_1:
2439 PUSHI (*(jbyte *) AVAL ());
2440 NEXT_INSN;
2442 getstatic_resolved_char:
2443 PUSHI (*(jchar *) AVAL ());
2444 NEXT_INSN;
2446 getstatic_resolved_short:
2447 PUSHI (*(jshort *) AVAL ());
2448 NEXT_INSN;
2450 getstatic_resolved_4:
2451 PUSHI (*(jint *) AVAL ());
2452 NEXT_INSN;
2454 getstatic_resolved_8:
2455 PUSHL (*(jlong *) AVAL ());
2456 NEXT_INSN;
2458 getstatic_resolved_obj:
2459 PUSHA (*(jobject *) AVAL ());
2460 NEXT_INSN;
2461 #endif /* DIRECT_THREADED */
2463 insn_getfield:
2465 jint fieldref_index = GET2U ();
2466 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2467 _Jv_Field *field = pool_data[fieldref_index].field;
2469 if ((field->flags & Modifier::STATIC) != 0)
2470 throw_incompatible_class_change_error
2471 (JvNewStringLatin1 ("field is static"));
2473 jclass type = field->type;
2474 jint field_offset = field->u.boffset;
2475 if (field_offset > 0xffff)
2476 throw new java::lang::VirtualMachineError;
2478 jobject obj = POPA();
2479 NULLCHECK(obj);
2481 void *newinsn = NULL;
2482 if (type->isPrimitive ())
2484 switch (type->size_in_bytes)
2486 case 1:
2487 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2488 newinsn = AMPAMP (getfield_resolved_1);
2489 break;
2491 case 2:
2492 if (type == JvPrimClass (char))
2494 PUSHI (*(jchar*) ((char*)obj + field_offset));
2495 newinsn = AMPAMP (getfield_resolved_char);
2497 else
2499 PUSHI (*(jshort*) ((char*)obj + field_offset));
2500 newinsn = AMPAMP (getfield_resolved_short);
2502 break;
2504 case 4:
2505 PUSHI (*(jint*) ((char*)obj + field_offset));
2506 newinsn = AMPAMP (getfield_resolved_4);
2507 break;
2509 case 8:
2510 PUSHL(*(jlong*) ((char*)obj + field_offset));
2511 newinsn = AMPAMP (getfield_resolved_8);
2512 break;
2515 else
2517 PUSHA(*(jobject*) ((char*)obj + field_offset));
2518 newinsn = AMPAMP (getfield_resolved_obj);
2521 #ifdef DIRECT_THREADED
2522 pc[-2].insn = newinsn;
2523 pc[-1].int_val = field_offset;
2524 #endif /* DIRECT_THREADED */
2526 NEXT_INSN;
2528 #ifdef DIRECT_THREADED
2529 getfield_resolved_1:
2531 char *obj = (char *) POPA ();
2532 NULLCHECK (obj);
2533 PUSHI (*(jbyte *) (obj + INTVAL ()));
2535 NEXT_INSN;
2537 getfield_resolved_char:
2539 char *obj = (char *) POPA ();
2540 NULLCHECK (obj);
2541 PUSHI (*(jchar *) (obj + INTVAL ()));
2543 NEXT_INSN;
2545 getfield_resolved_short:
2547 char *obj = (char *) POPA ();
2548 NULLCHECK (obj);
2549 PUSHI (*(jshort *) (obj + INTVAL ()));
2551 NEXT_INSN;
2553 getfield_resolved_4:
2555 char *obj = (char *) POPA ();
2556 NULLCHECK (obj);
2557 PUSHI (*(jint *) (obj + INTVAL ()));
2559 NEXT_INSN;
2561 getfield_resolved_8:
2563 char *obj = (char *) POPA ();
2564 NULLCHECK (obj);
2565 PUSHL (*(jlong *) (obj + INTVAL ()));
2567 NEXT_INSN;
2569 getfield_resolved_obj:
2571 char *obj = (char *) POPA ();
2572 NULLCHECK (obj);
2573 PUSHA (*(jobject *) (obj + INTVAL ()));
2575 NEXT_INSN;
2576 #endif /* DIRECT_THREADED */
2578 insn_putstatic:
2580 jint fieldref_index = GET2U ();
2581 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2582 _Jv_Field *field = pool_data[fieldref_index].field;
2584 jclass type = field->type;
2586 // ResolvePoolEntry cannot check this
2587 if ((field->flags & Modifier::STATIC) == 0)
2588 throw_incompatible_class_change_error
2589 (JvNewStringLatin1 ("field no longer static"));
2591 void *newinsn = NULL;
2592 if (type->isPrimitive ())
2594 switch (type->size_in_bytes)
2596 case 1:
2598 jint value = POPI();
2599 *(jbyte*) (field->u.addr) = value;
2600 newinsn = AMPAMP (putstatic_resolved_1);
2601 break;
2604 case 2:
2606 jint value = POPI();
2607 *(jchar*) (field->u.addr) = value;
2608 newinsn = AMPAMP (putstatic_resolved_2);
2609 break;
2612 case 4:
2614 jint value = POPI();
2615 *(jint*) (field->u.addr) = value;
2616 newinsn = AMPAMP (putstatic_resolved_4);
2617 break;
2620 case 8:
2622 jlong value = POPL();
2623 *(jlong*) (field->u.addr) = value;
2624 newinsn = AMPAMP (putstatic_resolved_8);
2625 break;
2629 else
2631 jobject value = POPA();
2632 *(jobject*) (field->u.addr) = value;
2633 newinsn = AMPAMP (putstatic_resolved_obj);
2636 #ifdef DIRECT_THREADED
2637 pc[-2].insn = newinsn;
2638 pc[-1].datum = field->u.addr;
2639 #endif /* DIRECT_THREADED */
2641 NEXT_INSN;
2643 #ifdef DIRECT_THREADED
2644 putstatic_resolved_1:
2645 *(jbyte *) AVAL () = POPI ();
2646 NEXT_INSN;
2648 putstatic_resolved_2:
2649 *(jchar *) AVAL () = POPI ();
2650 NEXT_INSN;
2652 putstatic_resolved_4:
2653 *(jint *) AVAL () = POPI ();
2654 NEXT_INSN;
2656 putstatic_resolved_8:
2657 *(jlong *) AVAL () = POPL ();
2658 NEXT_INSN;
2660 putstatic_resolved_obj:
2661 *(jobject *) AVAL () = POPA ();
2662 NEXT_INSN;
2663 #endif /* DIRECT_THREADED */
2665 insn_putfield:
2667 jint fieldref_index = GET2U ();
2668 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2669 _Jv_Field *field = pool_data[fieldref_index].field;
2671 jclass type = field->type;
2673 if ((field->flags & Modifier::STATIC) != 0)
2674 throw_incompatible_class_change_error
2675 (JvNewStringLatin1 ("field is static"));
2677 jint field_offset = field->u.boffset;
2678 if (field_offset > 0xffff)
2679 throw new java::lang::VirtualMachineError;
2681 void *newinsn = NULL;
2682 if (type->isPrimitive ())
2684 switch (type->size_in_bytes)
2686 case 1:
2688 jint value = POPI();
2689 jobject obj = POPA();
2690 NULLCHECK(obj);
2691 *(jbyte*) ((char*)obj + field_offset) = value;
2692 newinsn = AMPAMP (putfield_resolved_1);
2693 break;
2696 case 2:
2698 jint value = POPI();
2699 jobject obj = POPA();
2700 NULLCHECK(obj);
2701 *(jchar*) ((char*)obj + field_offset) = value;
2702 newinsn = AMPAMP (putfield_resolved_2);
2703 break;
2706 case 4:
2708 jint value = POPI();
2709 jobject obj = POPA();
2710 NULLCHECK(obj);
2711 *(jint*) ((char*)obj + field_offset) = value;
2712 newinsn = AMPAMP (putfield_resolved_4);
2713 break;
2716 case 8:
2718 jlong value = POPL();
2719 jobject obj = POPA();
2720 NULLCHECK(obj);
2721 *(jlong*) ((char*)obj + field_offset) = value;
2722 newinsn = AMPAMP (putfield_resolved_8);
2723 break;
2727 else
2729 jobject value = POPA();
2730 jobject obj = POPA();
2731 NULLCHECK(obj);
2732 *(jobject*) ((char*)obj + field_offset) = value;
2733 newinsn = AMPAMP (putfield_resolved_obj);
2736 #ifdef DIRECT_THREADED
2737 pc[-2].insn = newinsn;
2738 pc[-1].int_val = field_offset;
2739 #endif /* DIRECT_THREADED */
2741 NEXT_INSN;
2743 #ifdef DIRECT_THREADED
2744 putfield_resolved_1:
2746 jint val = POPI ();
2747 char *obj = (char *) POPA ();
2748 NULLCHECK (obj);
2749 *(jbyte *) (obj + INTVAL ()) = val;
2751 NEXT_INSN;
2753 putfield_resolved_2:
2755 jint val = POPI ();
2756 char *obj = (char *) POPA ();
2757 NULLCHECK (obj);
2758 *(jchar *) (obj + INTVAL ()) = val;
2760 NEXT_INSN;
2762 putfield_resolved_4:
2764 jint val = POPI ();
2765 char *obj = (char *) POPA ();
2766 NULLCHECK (obj);
2767 *(jint *) (obj + INTVAL ()) = val;
2769 NEXT_INSN;
2771 putfield_resolved_8:
2773 jlong val = POPL ();
2774 char *obj = (char *) POPA ();
2775 NULLCHECK (obj);
2776 *(jlong *) (obj + INTVAL ()) = val;
2778 NEXT_INSN;
2780 putfield_resolved_obj:
2782 jobject val = POPA ();
2783 char *obj = (char *) POPA ();
2784 NULLCHECK (obj);
2785 *(jobject *) (obj + INTVAL ()) = val;
2787 NEXT_INSN;
2788 #endif /* DIRECT_THREADED */
2790 insn_invokespecial:
2792 int index = GET2U ();
2794 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2796 sp -= rmeth->stack_item_count;
2798 NULLCHECK (sp[0].o);
2800 fun = (void (*)()) rmeth->method->ncode;
2802 #ifdef DIRECT_THREADED
2803 // Rewrite instruction so that we use a faster pre-resolved
2804 // method.
2805 pc[-2].insn = &&invokespecial_resolved;
2806 pc[-1].datum = rmeth;
2807 #endif /* DIRECT_THREADED */
2809 goto perform_invoke;
2811 #ifdef DIRECT_THREADED
2812 invokespecial_resolved:
2814 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2815 sp -= rmeth->stack_item_count;
2816 NULLCHECK (sp[0].o);
2817 fun = (void (*)()) rmeth->method->ncode;
2819 goto perform_invoke;
2820 #endif /* DIRECT_THREADED */
2822 insn_invokestatic:
2824 int index = GET2U ();
2826 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2828 sp -= rmeth->stack_item_count;
2830 _Jv_InitClass (rmeth->klass);
2831 fun = (void (*)()) rmeth->method->ncode;
2833 #ifdef DIRECT_THREADED
2834 // Rewrite instruction so that we use a faster pre-resolved
2835 // method.
2836 pc[-2].insn = &&invokestatic_resolved;
2837 pc[-1].datum = rmeth;
2838 #endif /* DIRECT_THREADED */
2840 goto perform_invoke;
2842 #ifdef DIRECT_THREADED
2843 invokestatic_resolved:
2845 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2846 sp -= rmeth->stack_item_count;
2847 fun = (void (*)()) rmeth->method->ncode;
2849 goto perform_invoke;
2850 #endif /* DIRECT_THREADED */
2852 insn_invokeinterface:
2854 int index = GET2U ();
2856 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2858 sp -= rmeth->stack_item_count;
2860 jobject rcv = sp[0].o;
2862 NULLCHECK (rcv);
2864 fun = (void (*)())
2865 _Jv_LookupInterfaceMethod (rcv->getClass (),
2866 rmeth->method->name,
2867 rmeth->method->signature);
2869 #ifdef DIRECT_THREADED
2870 // Rewrite instruction so that we use a faster pre-resolved
2871 // method.
2872 pc[-2].insn = &&invokeinterface_resolved;
2873 pc[-1].datum = rmeth;
2874 #else
2875 // Skip dummy bytes.
2876 pc += 2;
2877 #endif /* DIRECT_THREADED */
2879 goto perform_invoke;
2881 #ifdef DIRECT_THREADED
2882 invokeinterface_resolved:
2884 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2885 sp -= rmeth->stack_item_count;
2886 jobject rcv = sp[0].o;
2887 NULLCHECK (rcv);
2888 fun = (void (*)())
2889 _Jv_LookupInterfaceMethod (rcv->getClass (),
2890 rmeth->method->name,
2891 rmeth->method->signature);
2893 goto perform_invoke;
2894 #endif /* DIRECT_THREADED */
2896 insn_new:
2898 int index = GET2U ();
2899 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2900 _Jv_InitClass (klass);
2901 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2902 PUSHA (res);
2904 #ifdef DIRECT_THREADED
2905 pc[-2].insn = &&new_resolved;
2906 pc[-1].datum = klass;
2907 #endif /* DIRECT_THREADED */
2909 NEXT_INSN;
2911 #ifdef DIRECT_THREADED
2912 new_resolved:
2914 jclass klass = (jclass) AVAL ();
2915 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2916 PUSHA (res);
2918 NEXT_INSN;
2919 #endif /* DIRECT_THREADED */
2921 insn_newarray:
2923 int atype = GET1U ();
2924 int size = POPI();
2925 jobject result = _Jv_NewArray (atype, size);
2926 PUSHA (result);
2928 NEXT_INSN;
2930 insn_anewarray:
2932 int index = GET2U ();
2933 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2934 int size = POPI();
2935 _Jv_InitClass (klass);
2936 jobject result = _Jv_NewObjectArray (size, klass, 0);
2937 PUSHA (result);
2939 #ifdef DIRECT_THREADED
2940 pc[-2].insn = &&anewarray_resolved;
2941 pc[-1].datum = klass;
2942 #endif /* DIRECT_THREADED */
2944 NEXT_INSN;
2946 #ifdef DIRECT_THREADED
2947 anewarray_resolved:
2949 jclass klass = (jclass) AVAL ();
2950 int size = POPI ();
2951 jobject result = _Jv_NewObjectArray (size, klass, 0);
2952 PUSHA (result);
2954 NEXT_INSN;
2955 #endif /* DIRECT_THREADED */
2957 insn_arraylength:
2959 __JArray *arr = (__JArray*)POPA();
2960 NULLARRAYCHECK (arr);
2961 PUSHI (arr->length);
2963 NEXT_INSN;
2965 insn_athrow:
2967 jobject value = POPA();
2968 throw static_cast<jthrowable>(value);
2970 NEXT_INSN;
2972 insn_checkcast:
2974 jobject value = POPA();
2975 jint index = GET2U ();
2976 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2978 if (value != NULL && ! to->isInstance (value))
2979 throw new java::lang::ClassCastException (to->getName());
2981 PUSHA (value);
2983 #ifdef DIRECT_THREADED
2984 pc[-2].insn = &&checkcast_resolved;
2985 pc[-1].datum = to;
2986 #endif /* DIRECT_THREADED */
2988 NEXT_INSN;
2990 #ifdef DIRECT_THREADED
2991 checkcast_resolved:
2993 jobject value = POPA ();
2994 jclass to = (jclass) AVAL ();
2995 if (value != NULL && ! to->isInstance (value))
2996 throw new java::lang::ClassCastException (to->getName());
2997 PUSHA (value);
2999 NEXT_INSN;
3000 #endif /* DIRECT_THREADED */
3002 insn_instanceof:
3004 jobject value = POPA();
3005 jint index = GET2U ();
3006 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3007 PUSHI (to->isInstance (value));
3009 #ifdef DIRECT_THREADED
3010 pc[-2].insn = &&instanceof_resolved;
3011 pc[-1].datum = to;
3012 #endif /* DIRECT_THREADED */
3014 NEXT_INSN;
3016 #ifdef DIRECT_THREADED
3017 instanceof_resolved:
3019 jobject value = POPA ();
3020 jclass to = (jclass) AVAL ();
3021 PUSHI (to->isInstance (value));
3023 NEXT_INSN;
3024 #endif /* DIRECT_THREADED */
3026 insn_monitorenter:
3028 jobject value = POPA();
3029 NULLCHECK(value);
3030 _Jv_MonitorEnter (value);
3032 NEXT_INSN;
3034 insn_monitorexit:
3036 jobject value = POPA();
3037 NULLCHECK(value);
3038 _Jv_MonitorExit (value);
3040 NEXT_INSN;
3042 insn_ifnull:
3044 jobject val = POPA();
3045 if (val == NULL)
3046 TAKE_GOTO;
3047 else
3048 SKIP_GOTO;
3050 NEXT_INSN;
3052 insn_ifnonnull:
3054 jobject val = POPA();
3055 if (val != NULL)
3056 TAKE_GOTO;
3057 else
3058 SKIP_GOTO;
3060 NEXT_INSN;
3062 insn_multianewarray:
3064 int kind_index = GET2U ();
3065 int dim = GET1U ();
3067 jclass type
3068 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
3069 _Jv_InitClass (type);
3070 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
3072 for (int i = dim - 1; i >= 0; i--)
3074 sizes[i] = POPI ();
3077 jobject res = _Jv_NewMultiArray (type,dim, sizes);
3079 PUSHA (res);
3081 NEXT_INSN;
3083 #ifndef DIRECT_THREADED
3084 insn_wide:
3086 jint the_mod_op = get1u (pc++);
3087 jint wide = get2u (pc); pc += 2;
3089 switch (the_mod_op)
3091 case op_istore:
3092 STOREI (wide);
3093 NEXT_INSN;
3095 case op_fstore:
3096 STOREF (wide);
3097 NEXT_INSN;
3099 case op_astore:
3100 STOREA (wide);
3101 NEXT_INSN;
3103 case op_lload:
3104 LOADL (wide);
3105 NEXT_INSN;
3107 case op_dload:
3108 LOADD (wide);
3109 NEXT_INSN;
3111 case op_iload:
3112 LOADI (wide);
3113 NEXT_INSN;
3115 case op_aload:
3116 LOADA (wide);
3117 NEXT_INSN;
3119 case op_lstore:
3120 STOREL (wide);
3121 NEXT_INSN;
3123 case op_dstore:
3124 STORED (wide);
3125 NEXT_INSN;
3127 case op_ret:
3128 pc = (unsigned char*) PEEKA (wide);
3129 NEXT_INSN;
3131 case op_iinc:
3133 jint amount = get2s (pc); pc += 2;
3134 jint value = PEEKI (wide);
3135 POKEI (wide, value+amount);
3137 NEXT_INSN;
3139 default:
3140 throw_internal_error ("illegal bytecode modified by wide");
3144 #endif /* DIRECT_THREADED */
3146 catch (java::lang::Throwable *ex)
3148 #ifdef DIRECT_THREADED
3149 void *logical_pc = (void *) ((insn_slot *) pc - 1);
3150 #else
3151 int logical_pc = pc - 1 - bytecode ();
3152 #endif
3153 _Jv_InterpException *exc = exceptions ();
3154 jclass exc_class = ex->getClass ();
3156 for (int i = 0; i < exc_count; i++)
3158 if (PCVAL (exc[i].start_pc) <= logical_pc
3159 && logical_pc < PCVAL (exc[i].end_pc))
3161 #ifdef DIRECT_THREADED
3162 jclass handler = (jclass) exc[i].handler_type.p;
3163 #else
3164 jclass handler = NULL;
3165 if (exc[i].handler_type.i != 0)
3166 handler = (_Jv_ResolvePoolEntry (defining_class,
3167 exc[i].handler_type.i)).clazz;
3168 #endif /* DIRECT_THREADED */
3170 if (handler == NULL || handler->isAssignableFrom (exc_class))
3172 #ifdef DIRECT_THREADED
3173 pc = (insn_slot *) exc[i].handler_pc.p;
3174 #else
3175 pc = bytecode () + exc[i].handler_pc.i;
3176 #endif /* DIRECT_THREADED */
3177 sp = stack;
3178 sp++->o = ex; // Push exception.
3179 NEXT_INSN;
3184 // No handler, so re-throw.
3185 throw ex;
3189 // This function exists so that the stack-tracing code can find the
3190 // boundaries of the interpreter.
3191 void
3192 _Jv_EndOfInterpreter (void)
3196 static void
3197 throw_internal_error (char *msg)
3199 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
3202 static void
3203 throw_incompatible_class_change_error (jstring msg)
3205 throw new java::lang::IncompatibleClassChangeError (msg);
3208 #ifndef HANDLE_SEGV
3209 static java::lang::NullPointerException *null_pointer_exc;
3210 static void
3211 throw_null_pointer_exception ()
3213 if (null_pointer_exc == NULL)
3214 null_pointer_exc = new java::lang::NullPointerException;
3216 throw null_pointer_exc;
3218 #endif
3220 #endif // INTERPRETER