* config/arm/netbsd.h (TARGET_OS_CPP_BUILTINS): Use
[official-gcc.git] / libjava / interpret.cc
blob4db9dca08ec7a051655d98ff99f234e78a138b19
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 #pragma implementation "java-interp.h"
17 #include <jvm.h>
18 #include <java-cpool.h>
19 #include <java-interp.h>
20 // #include <java/lang/fdlibm.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/Long.h>
25 #include <java/lang/StringBuffer.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/ClassCastException.h>
29 #include <java/lang/VirtualMachineError.h>
30 #include <java/lang/InternalError.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/ArithmeticException.h>
33 #include <java/lang/IncompatibleClassChangeError.h>
34 #include <java-insns.h>
35 #include <java-signal.h>
37 #ifdef INTERPRETER
39 #include <stdlib.h>
41 using namespace gcj;
43 static void throw_internal_error (char *msg)
44 __attribute__ ((__noreturn__));
45 static void throw_incompatible_class_change_error (jstring msg)
46 __attribute__ ((__noreturn__));
47 #ifndef HANDLE_SEGV
48 static void throw_null_pointer_exception ()
49 __attribute__ ((__noreturn__));
50 #endif
52 extern "C" double __ieee754_fmod (double,double);
54 static inline void dupx (_Jv_word *sp, int n, int x)
56 // first "slide" n+x elements n to the right
57 int top = n-1;
58 for (int i = 0; i < n+x; i++)
60 sp[(top-i)] = sp[(top-i)-n];
63 // next, copy the n top elements, n+x down
64 for (int i = 0; i < n; i++)
66 sp[top-(n+x)-i] = sp[top-i];
71 // Used to convert from floating types to integral types.
72 template<typename TO, typename FROM>
73 static inline TO
74 convert (FROM val, TO min, TO max)
76 TO ret;
77 if (val >= (FROM) max)
78 ret = max;
79 else if (val <= (FROM) min)
80 ret = min;
81 else if (val != val)
82 ret = 0;
83 else
84 ret = (TO) val;
85 return ret;
88 #define PUSHA(V) (sp++)->o = (V)
89 #define PUSHI(V) (sp++)->i = (V)
90 #define PUSHF(V) (sp++)->f = (V)
91 #if SIZEOF_VOID_P == 8
92 # define PUSHL(V) (sp->l = (V), sp += 2)
93 # define PUSHD(V) (sp->d = (V), sp += 2)
94 #else
95 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
96 (sp++)->ia[0] = w2.ia[0]; \
97 (sp++)->ia[0] = w2.ia[1]; } while (0)
98 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
99 (sp++)->ia[0] = w2.ia[0]; \
100 (sp++)->ia[0] = w2.ia[1]; } while (0)
101 #endif
103 #define POPA() ((--sp)->o)
104 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
105 #define POPF() ((jfloat) (--sp)->f)
106 #if SIZEOF_VOID_P == 8
107 # define POPL() (sp -= 2, (jlong) sp->l)
108 # define POPD() (sp -= 2, (jdouble) sp->d)
109 #else
110 # define POPL() ({ _Jv_word2 w2; \
111 w2.ia[1] = (--sp)->ia[0]; \
112 w2.ia[0] = (--sp)->ia[0]; w2.l; })
113 # define POPD() ({ _Jv_word2 w2; \
114 w2.ia[1] = (--sp)->ia[0]; \
115 w2.ia[0] = (--sp)->ia[0]; w2.d; })
116 #endif
118 #define LOADA(I) (sp++)->o = locals[I].o
119 #define LOADI(I) (sp++)->i = locals[I].i
120 #define LOADF(I) (sp++)->f = locals[I].f
121 #if SIZEOF_VOID_P == 8
122 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
123 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
124 #else
125 # define LOADL(I) do { jint __idx = (I); \
126 (sp++)->ia[0] = locals[__idx].ia[0]; \
127 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
128 } while (0)
129 # define LOADD(I) LOADL(I)
130 #endif
132 #define STOREA(I) locals[I].o = (--sp)->o
133 #define STOREI(I) locals[I].i = (--sp)->i
134 #define STOREF(I) locals[I].f = (--sp)->f
135 #if SIZEOF_VOID_P == 8
136 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
137 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
138 #else
139 # define STOREL(I) do { jint __idx = (I); \
140 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
141 locals[__idx].ia[0] = (--sp)->ia[0]; \
142 } while (0)
143 # define STORED(I) STOREL(I)
144 #endif
146 #define PEEKI(I) (locals+(I))->i
147 #define PEEKA(I) (locals+(I))->o
149 #define POKEI(I,V) ((locals+(I))->i = (V))
152 #define BINOPI(OP) { \
153 jint value2 = POPI(); \
154 jint value1 = POPI(); \
155 PUSHI(value1 OP value2); \
158 #define BINOPF(OP) { \
159 jfloat value2 = POPF(); \
160 jfloat value1 = POPF(); \
161 PUSHF(value1 OP value2); \
164 #define BINOPL(OP) { \
165 jlong value2 = POPL(); \
166 jlong value1 = POPL(); \
167 PUSHL(value1 OP value2); \
170 #define BINOPD(OP) { \
171 jdouble value2 = POPD(); \
172 jdouble value1 = POPD(); \
173 PUSHD(value1 OP value2); \
176 static inline jint get1s(unsigned char* loc) {
177 return *(signed char*)loc;
180 static inline jint get1u(unsigned char* loc) {
181 return *loc;
184 static inline jint get2s(unsigned char* loc) {
185 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
188 static inline jint get2u(unsigned char* loc) {
189 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
192 static jint get4(unsigned char* loc) {
193 return (((jint)(loc[0])) << 24)
194 | (((jint)(loc[1])) << 16)
195 | (((jint)(loc[2])) << 8)
196 | (((jint)(loc[3])) << 0);
200 #ifdef HANDLE_SEGV
201 #define NULLCHECK(X)
202 #define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)
203 #else
204 #define NULLCHECK(X) \
205 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
206 #define NULLARRAYCHECK(X) \
207 do { if ((X)==NULL) { SAVE_PC; throw_null_pointer_exception (); } } while (0)
208 #endif
210 #define ARRAYBOUNDSCHECK(array, index) \
211 do \
213 if (((unsigned) index) >= (unsigned) (array->length)) \
214 _Jv_ThrowBadArrayIndex (index); \
216 while (0)
218 // this method starts the actual running of the method. It is inlined
219 // in three different variants in the static methods run_normal,
220 // run_sync_object and run_sync_class (see below). Those static methods
221 // are installed directly in the stub for this method (by
222 // _Jv_InterpMethod::ncode, in resolve.cc).
224 inline jobject
225 _Jv_InterpMethod::run (ffi_cif* cif,
226 void *retp,
227 ffi_raw *args,
228 _Jv_InterpMethodInvocation *inv)
230 inv->running = this;
231 inv->pc = bytecode ();
232 inv->sp = inv->stack_base ();
233 _Jv_word *locals = inv->local_base ();
235 /* Go straight at it! the ffi raw format matches the internal
236 stack representation exactly. At least, that's the idea.
238 memcpy ((void*) locals, (void*) args, args_raw_size);
240 next_segment:
242 jobject ex = NULL;
246 continue1 (inv);
248 catch (java::lang::Throwable *ex2)
250 ex = ex2;
253 if (ex == 0) // no exception...
255 /* define sp locally, so the POP? macros will pick it up */
256 _Jv_word *sp = inv->sp;
257 int rtype = cif->rtype->type;
259 if (rtype == FFI_TYPE_POINTER)
261 jobject r = POPA();
262 *(jobject*) retp = r;
263 return 0;
265 else if (rtype == FFI_TYPE_SINT32)
267 jint r = POPI();
268 *(jint*)retp = r;
269 return 0;
271 else if (rtype == FFI_TYPE_VOID)
273 return 0;
275 else switch (rtype)
277 case FFI_TYPE_FLOAT:
279 jfloat r = POPF();
280 *(jfloat*)retp = r;
281 return 0;
284 case FFI_TYPE_DOUBLE:
286 jdouble r = POPD();
287 *(jdouble*)retp = r;
288 return 0;
291 case FFI_TYPE_UINT8:
292 case FFI_TYPE_UINT16:
293 case FFI_TYPE_UINT32:
294 case FFI_TYPE_SINT8:
295 case FFI_TYPE_SINT16:
297 jint r = POPI();
298 *(jint*)retp = r;
299 return 0;
302 case FFI_TYPE_SINT64:
304 jlong r = POPL();
305 *(jlong*)retp = r;
306 return 0;
309 default:
310 throw_internal_error ("unknown return type");
314 /** handle an exception */
315 if ( find_exception (ex, inv) )
316 goto next_segment;
318 return ex;
321 #define SAVE_PC inv->pc = pc
323 bool _Jv_InterpMethod::find_exception (jobject ex,
324 _Jv_InterpMethodInvocation *inv)
326 // We subtract one because the PC was incremented before it was
327 // saved.
328 int logical_pc = inv->pc - 1 - bytecode ();
329 _Jv_InterpException *exc = exceptions ();
330 jclass exc_class = ex->getClass ();
332 for (int i = 0; i < exc_count; i++)
334 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
336 jclass handler;
338 if (exc[i].handler_type != 0)
339 handler = (_Jv_ResolvePoolEntry (defining_class,
340 exc[i].handler_type)).clazz;
341 else
342 handler = NULL;
344 if (handler==NULL || handler->isAssignableFrom (exc_class))
346 inv->pc = bytecode () + exc[i].handler_pc;
347 inv->sp = inv->stack_base (); // reset stack
348 (inv->sp++)->o = ex; // push exception
349 return true;
353 return false;
356 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
357 void* ret,
358 ffi_raw * args,
359 void* __this)
361 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
363 // we do the alloca of the method invocation here, to allow the method
364 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
365 int storage_size = _this->max_stack+_this->max_locals;
366 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
367 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
368 + storage_size * sizeof (_Jv_word));
370 jobject ex = _this->run (cif, ret, args, inv);
371 if (ex != 0) throw static_cast<jthrowable>(ex);
374 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
375 void* ret,
376 ffi_raw * args,
377 void* __this)
379 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
380 jobject rcv = (jobject)args[0].ptr;
382 int storage_size = _this->max_stack+_this->max_locals;
383 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
384 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
385 + storage_size * sizeof (_Jv_word));
387 _Jv_MonitorEnter (rcv);
388 jobject ex = _this->run (cif, ret, args, inv);
389 _Jv_MonitorExit (rcv);
391 if (ex != 0) throw static_cast<jthrowable>(ex);
394 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
395 void* ret,
396 ffi_raw * args,
397 void* __this)
399 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
400 jclass sync = _this->defining_class;
402 int storage_size = _this->max_stack+_this->max_locals;
403 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
404 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
405 + storage_size * sizeof (_Jv_word));
407 _Jv_MonitorEnter (sync);
408 jobject ex = _this->run (cif, ret, args, inv);
409 _Jv_MonitorExit (sync);
411 if (ex != 0) throw static_cast<jthrowable>(ex);
415 This proceeds execution, as designated in "inv". If an exception
416 happens, then it is simply thrown, and handled in Java. Thus, the pc
417 needs to be stored in the inv->pc at all times, so we can figure
418 out which handler (if any) to invoke.
420 One design issue, which I have not completely considered, is if it
421 should be possible to have interpreted classes linked in! Seldom used
422 (or non-critical) classes could reasonably be interpreted.
426 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
428 using namespace java::lang::reflect;
430 _Jv_word *sp = inv->sp;
431 unsigned char *pc = inv->pc;
432 _Jv_word *locals = inv->local_base ();
434 _Jv_word *pool_data = defining_class->constants.data;
436 /* these two are used in the invokeXXX instructions */
437 void (*fun)();
438 _Jv_ResolvedMethod* rmeth;
440 #define INSN_LABEL(op) &&insn_##op
441 #define GOTO_INSN(op) goto *(insn_target[op])
443 static const void *const insn_target[] =
445 INSN_LABEL(nop),
446 INSN_LABEL(aconst_null),
447 INSN_LABEL(iconst_m1),
448 INSN_LABEL(iconst_0),
449 INSN_LABEL(iconst_1),
450 INSN_LABEL(iconst_2),
451 INSN_LABEL(iconst_3),
452 INSN_LABEL(iconst_4),
453 INSN_LABEL(iconst_5),
454 INSN_LABEL(lconst_0),
455 INSN_LABEL(lconst_1),
456 INSN_LABEL(fconst_0),
457 INSN_LABEL(fconst_1),
458 INSN_LABEL(fconst_2),
459 INSN_LABEL(dconst_0),
460 INSN_LABEL(dconst_1),
461 INSN_LABEL(bipush),
462 INSN_LABEL(sipush),
463 INSN_LABEL(ldc),
464 INSN_LABEL(ldc_w),
465 INSN_LABEL(ldc2_w),
466 INSN_LABEL(iload),
467 INSN_LABEL(lload),
468 INSN_LABEL(fload),
469 INSN_LABEL(dload),
470 INSN_LABEL(aload),
471 INSN_LABEL(iload_0),
472 INSN_LABEL(iload_1),
473 INSN_LABEL(iload_2),
474 INSN_LABEL(iload_3),
475 INSN_LABEL(lload_0),
476 INSN_LABEL(lload_1),
477 INSN_LABEL(lload_2),
478 INSN_LABEL(lload_3),
479 INSN_LABEL(fload_0),
480 INSN_LABEL(fload_1),
481 INSN_LABEL(fload_2),
482 INSN_LABEL(fload_3),
483 INSN_LABEL(dload_0),
484 INSN_LABEL(dload_1),
485 INSN_LABEL(dload_2),
486 INSN_LABEL(dload_3),
487 INSN_LABEL(aload_0),
488 INSN_LABEL(aload_1),
489 INSN_LABEL(aload_2),
490 INSN_LABEL(aload_3),
491 INSN_LABEL(iaload),
492 INSN_LABEL(laload),
493 INSN_LABEL(faload),
494 INSN_LABEL(daload),
495 INSN_LABEL(aaload),
496 INSN_LABEL(baload),
497 INSN_LABEL(caload),
498 INSN_LABEL(saload),
499 INSN_LABEL(istore),
500 INSN_LABEL(lstore),
501 INSN_LABEL(fstore),
502 INSN_LABEL(dstore),
503 INSN_LABEL(astore),
504 INSN_LABEL(istore_0),
505 INSN_LABEL(istore_1),
506 INSN_LABEL(istore_2),
507 INSN_LABEL(istore_3),
508 INSN_LABEL(lstore_0),
509 INSN_LABEL(lstore_1),
510 INSN_LABEL(lstore_2),
511 INSN_LABEL(lstore_3),
512 INSN_LABEL(fstore_0),
513 INSN_LABEL(fstore_1),
514 INSN_LABEL(fstore_2),
515 INSN_LABEL(fstore_3),
516 INSN_LABEL(dstore_0),
517 INSN_LABEL(dstore_1),
518 INSN_LABEL(dstore_2),
519 INSN_LABEL(dstore_3),
520 INSN_LABEL(astore_0),
521 INSN_LABEL(astore_1),
522 INSN_LABEL(astore_2),
523 INSN_LABEL(astore_3),
524 INSN_LABEL(iastore),
525 INSN_LABEL(lastore),
526 INSN_LABEL(fastore),
527 INSN_LABEL(dastore),
528 INSN_LABEL(aastore),
529 INSN_LABEL(bastore),
530 INSN_LABEL(castore),
531 INSN_LABEL(sastore),
532 INSN_LABEL(pop),
533 INSN_LABEL(pop2),
534 INSN_LABEL(dup),
535 INSN_LABEL(dup_x1),
536 INSN_LABEL(dup_x2),
537 INSN_LABEL(dup2),
538 INSN_LABEL(dup2_x1),
539 INSN_LABEL(dup2_x2),
540 INSN_LABEL(swap),
541 INSN_LABEL(iadd),
542 INSN_LABEL(ladd),
543 INSN_LABEL(fadd),
544 INSN_LABEL(dadd),
545 INSN_LABEL(isub),
546 INSN_LABEL(lsub),
547 INSN_LABEL(fsub),
548 INSN_LABEL(dsub),
549 INSN_LABEL(imul),
550 INSN_LABEL(lmul),
551 INSN_LABEL(fmul),
552 INSN_LABEL(dmul),
553 INSN_LABEL(idiv),
554 INSN_LABEL(ldiv),
555 INSN_LABEL(fdiv),
556 INSN_LABEL(ddiv),
557 INSN_LABEL(irem),
558 INSN_LABEL(lrem),
559 INSN_LABEL(frem),
560 INSN_LABEL(drem),
561 INSN_LABEL(ineg),
562 INSN_LABEL(lneg),
563 INSN_LABEL(fneg),
564 INSN_LABEL(dneg),
565 INSN_LABEL(ishl),
566 INSN_LABEL(lshl),
567 INSN_LABEL(ishr),
568 INSN_LABEL(lshr),
569 INSN_LABEL(iushr),
570 INSN_LABEL(lushr),
571 INSN_LABEL(iand),
572 INSN_LABEL(land),
573 INSN_LABEL(ior),
574 INSN_LABEL(lor),
575 INSN_LABEL(ixor),
576 INSN_LABEL(lxor),
577 INSN_LABEL(iinc),
578 INSN_LABEL(i2l),
579 INSN_LABEL(i2f),
580 INSN_LABEL(i2d),
581 INSN_LABEL(l2i),
582 INSN_LABEL(l2f),
583 INSN_LABEL(l2d),
584 INSN_LABEL(f2i),
585 INSN_LABEL(f2l),
586 INSN_LABEL(f2d),
587 INSN_LABEL(d2i),
588 INSN_LABEL(d2l),
589 INSN_LABEL(d2f),
590 INSN_LABEL(i2b),
591 INSN_LABEL(i2c),
592 INSN_LABEL(i2s),
593 INSN_LABEL(lcmp),
594 INSN_LABEL(fcmpl),
595 INSN_LABEL(fcmpg),
596 INSN_LABEL(dcmpl),
597 INSN_LABEL(dcmpg),
598 INSN_LABEL(ifeq),
599 INSN_LABEL(ifne),
600 INSN_LABEL(iflt),
601 INSN_LABEL(ifge),
602 INSN_LABEL(ifgt),
603 INSN_LABEL(ifle),
604 INSN_LABEL(if_icmpeq),
605 INSN_LABEL(if_icmpne),
606 INSN_LABEL(if_icmplt),
607 INSN_LABEL(if_icmpge),
608 INSN_LABEL(if_icmpgt),
609 INSN_LABEL(if_icmple),
610 INSN_LABEL(if_acmpeq),
611 INSN_LABEL(if_acmpne),
612 INSN_LABEL(goto),
613 INSN_LABEL(jsr),
614 INSN_LABEL(ret),
615 INSN_LABEL(tableswitch),
616 INSN_LABEL(lookupswitch),
617 INSN_LABEL(ireturn),
618 INSN_LABEL(lreturn),
619 INSN_LABEL(freturn),
620 INSN_LABEL(dreturn),
621 INSN_LABEL(areturn),
622 INSN_LABEL(return),
623 INSN_LABEL(getstatic),
624 INSN_LABEL(putstatic),
625 INSN_LABEL(getfield),
626 INSN_LABEL(putfield),
627 INSN_LABEL(invokevirtual),
628 INSN_LABEL(invokespecial),
629 INSN_LABEL(invokestatic),
630 INSN_LABEL(invokeinterface),
631 0, /* Unused. */
632 INSN_LABEL(new),
633 INSN_LABEL(newarray),
634 INSN_LABEL(anewarray),
635 INSN_LABEL(arraylength),
636 INSN_LABEL(athrow),
637 INSN_LABEL(checkcast),
638 INSN_LABEL(instanceof),
639 INSN_LABEL(monitorenter),
640 INSN_LABEL(monitorexit),
641 INSN_LABEL(wide),
642 INSN_LABEL(multianewarray),
643 INSN_LABEL(ifnull),
644 INSN_LABEL(ifnonnull),
645 INSN_LABEL(goto_w),
646 INSN_LABEL(jsr_w),
649 /* If the macro INLINE_SWITCH is not defined, then the main loop
650 operates as one big (normal) switch statement. If it is defined,
651 then the case selection is performed `inline' in the end of the
652 code for each case. The latter saves a native branch instruction
653 for each java-instruction, but expands the code size somewhat.
655 NOTE: On i386 defining INLINE_SWITCH improves over all
656 performance approximately seven percent, but it may be different
657 for other machines. At some point, this may be made into a proper
658 configuration parameter. */
660 #define INLINE_SWITCH
662 #ifdef INLINE_SWITCH
664 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
667 NEXT_INSN;
668 #else
670 #define NEXT_INSN goto next_insn
672 next_insn:
673 GOTO_INSN (*pc++);
675 #endif
677 /* The first few instructions here are ordered according to their
678 frequency, in the hope that this will improve code locality a
679 little. */
681 insn_aload_0: // 0x2a
682 LOADA(0);
683 NEXT_INSN;
685 insn_iload: // 0x15
686 LOADI (get1u (pc++));
687 NEXT_INSN;
689 insn_iload_1: // 0x1b
690 LOADI (1);
691 NEXT_INSN;
693 insn_invokevirtual: // 0xb6
694 SAVE_PC;
696 int index = get2u (pc); pc += 2;
698 /* _Jv_ResolvePoolEntry returns immediately if the value already
699 * is resolved. If we want to clutter up the code here to gain
700 * a little performance, then we can check the corresponding bit
701 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
702 * don't think it is worth it. */
704 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
706 sp -= rmeth->stack_item_count;
707 // We don't use NULLCHECK here because we can't rely on that
708 // working if the method is final. So instead we do an
709 // explicit test.
710 if (! sp[0].o)
711 throw new java::lang::NullPointerException;
713 if (rmeth->vtable_index == -1)
715 // final methods do not appear in the vtable,
716 // if it does not appear in the superclass.
717 fun = (void (*)()) rmeth->method->ncode;
719 else
721 jobject rcv = sp[0].o;
722 _Jv_VTable *table = *(_Jv_VTable**)rcv;
723 fun = (void (*)()) table->get_method(rmeth->vtable_index);
726 goto perform_invoke;
728 perform_invoke:
730 /* here goes the magic again... */
731 ffi_cif *cif = &rmeth->cif;
732 ffi_raw *raw = (ffi_raw*) sp;
734 jdouble rvalue;
736 #if FFI_NATIVE_RAW_API
737 /* We assume that this is only implemented if it's correct */
738 /* to use it here. On a 64 bit machine, it never is. */
739 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
740 #else
741 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
742 #endif
744 int rtype = cif->rtype->type;
746 /* the likelyhood of object, int, or void return is very high,
747 * so those are checked before the switch */
748 if (rtype == FFI_TYPE_POINTER)
750 PUSHA (*(jobject*)&rvalue);
752 else if (rtype == FFI_TYPE_SINT32)
754 PUSHI (*(jint*)&rvalue);
756 else if (rtype == FFI_TYPE_VOID)
758 /* skip */
760 else switch (rtype)
762 case FFI_TYPE_SINT8:
764 jbyte value = (*(jint*)&rvalue) & 0xff;
765 PUSHI (value);
767 break;
769 case FFI_TYPE_SINT16:
771 jshort value = (*(jint*)&rvalue) & 0xffff;
772 PUSHI (value);
774 break;
776 case FFI_TYPE_UINT16:
778 jint value = (*(jint*)&rvalue) & 0xffff;
779 PUSHI (value);
781 break;
783 case FFI_TYPE_FLOAT:
784 PUSHF (*(jfloat*)&rvalue);
785 break;
787 case FFI_TYPE_DOUBLE:
788 PUSHD (rvalue);
789 break;
791 case FFI_TYPE_SINT64:
792 PUSHL (*(jlong*)&rvalue);
793 break;
795 default:
796 throw_internal_error ("unknown return type in invokeXXX");
800 NEXT_INSN;
803 insn_nop:
804 NEXT_INSN;
806 insn_aconst_null:
807 PUSHA (NULL);
808 NEXT_INSN;
810 insn_iconst_m1:
811 PUSHI (-1);
812 NEXT_INSN;
814 insn_iconst_0:
815 PUSHI (0);
816 NEXT_INSN;
818 insn_iconst_1:
819 PUSHI (1);
820 NEXT_INSN;
822 insn_iconst_2:
823 PUSHI (2);
824 NEXT_INSN;
826 insn_iconst_3:
827 PUSHI (3);
828 NEXT_INSN;
830 insn_iconst_4:
831 PUSHI (4);
832 NEXT_INSN;
834 insn_iconst_5:
835 PUSHI (5);
836 NEXT_INSN;
838 insn_lconst_0:
839 PUSHL (0);
840 NEXT_INSN;
842 insn_lconst_1:
843 PUSHL (1);
844 NEXT_INSN;
846 insn_fconst_0:
847 PUSHF (0);
848 NEXT_INSN;
850 insn_fconst_1:
851 PUSHF (1);
852 NEXT_INSN;
854 insn_fconst_2:
855 PUSHF (2);
856 NEXT_INSN;
858 insn_dconst_0:
859 PUSHD (0);
860 NEXT_INSN;
862 insn_dconst_1:
863 PUSHD (1);
864 NEXT_INSN;
866 insn_bipush:
867 PUSHI (get1s(pc++));
868 NEXT_INSN;
870 insn_sipush:
871 PUSHI (get2s(pc)); pc += 2;
872 NEXT_INSN;
874 insn_ldc:
876 int index = get1u (pc++);
877 PUSHA(pool_data[index].o);
879 NEXT_INSN;
881 insn_ldc_w:
883 int index = get2u (pc); pc += 2;
884 PUSHA(pool_data[index].o);
886 NEXT_INSN;
888 insn_ldc2_w:
890 int index = get2u (pc); pc += 2;
891 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
892 sp += 2;
894 NEXT_INSN;
896 insn_lload:
897 LOADL (get1u (pc++));
898 NEXT_INSN;
900 insn_fload:
901 LOADF (get1u (pc++));
902 NEXT_INSN;
904 insn_dload:
905 LOADD (get1u (pc++));
906 NEXT_INSN;
908 insn_aload:
909 LOADA (get1u (pc++));
910 NEXT_INSN;
912 insn_iload_0:
913 LOADI (0);
914 NEXT_INSN;
916 insn_iload_2:
917 LOADI (2);
918 NEXT_INSN;
920 insn_iload_3:
921 LOADI (3);
922 NEXT_INSN;
924 insn_lload_0:
925 LOADL (0);
926 NEXT_INSN;
928 insn_lload_1:
929 LOADL (1);
930 NEXT_INSN;
932 insn_lload_2:
933 LOADL (2);
934 NEXT_INSN;
936 insn_lload_3:
937 LOADL (3);
938 NEXT_INSN;
940 insn_fload_0:
941 LOADF (0);
942 NEXT_INSN;
944 insn_fload_1:
945 LOADF (1);
946 NEXT_INSN;
948 insn_fload_2:
949 LOADF (2);
950 NEXT_INSN;
952 insn_fload_3:
953 LOADF (3);
954 NEXT_INSN;
956 insn_dload_0:
957 LOADD (0);
958 NEXT_INSN;
960 insn_dload_1:
961 LOADD (1);
962 NEXT_INSN;
964 insn_dload_2:
965 LOADD (2);
966 NEXT_INSN;
968 insn_dload_3:
969 LOADD (3);
970 NEXT_INSN;
972 insn_aload_1:
973 LOADA(1);
974 NEXT_INSN;
976 insn_aload_2:
977 LOADA(2);
978 NEXT_INSN;
980 insn_aload_3:
981 LOADA(3);
982 NEXT_INSN;
984 insn_iaload:
986 jint index = POPI();
987 jintArray arr = (jintArray) POPA();
988 NULLARRAYCHECK (arr);
989 ARRAYBOUNDSCHECK (arr, index);
990 PUSHI( elements(arr)[index] );
992 NEXT_INSN;
994 insn_laload:
996 jint index = POPI();
997 jlongArray arr = (jlongArray) POPA();
998 NULLARRAYCHECK (arr);
999 ARRAYBOUNDSCHECK (arr, index);
1000 PUSHL( elements(arr)[index] );
1002 NEXT_INSN;
1004 insn_faload:
1006 jint index = POPI();
1007 jfloatArray arr = (jfloatArray) POPA();
1008 NULLARRAYCHECK (arr);
1009 ARRAYBOUNDSCHECK (arr, index);
1010 PUSHF( elements(arr)[index] );
1012 NEXT_INSN;
1014 insn_daload:
1016 jint index = POPI();
1017 jdoubleArray arr = (jdoubleArray) POPA();
1018 NULLARRAYCHECK (arr);
1019 ARRAYBOUNDSCHECK (arr, index);
1020 PUSHD( elements(arr)[index] );
1022 NEXT_INSN;
1024 insn_aaload:
1026 jint index = POPI();
1027 jobjectArray arr = (jobjectArray) POPA();
1028 NULLARRAYCHECK (arr);
1029 ARRAYBOUNDSCHECK (arr, index);
1030 PUSHA( elements(arr)[index] );
1032 NEXT_INSN;
1034 insn_baload:
1036 jint index = POPI();
1037 jbyteArray arr = (jbyteArray) POPA();
1038 NULLARRAYCHECK (arr);
1039 ARRAYBOUNDSCHECK (arr, index);
1040 PUSHI( elements(arr)[index] );
1042 NEXT_INSN;
1044 insn_caload:
1046 jint index = POPI();
1047 jcharArray arr = (jcharArray) POPA();
1048 NULLARRAYCHECK (arr);
1049 ARRAYBOUNDSCHECK (arr, index);
1050 PUSHI( elements(arr)[index] );
1052 NEXT_INSN;
1054 insn_saload:
1056 jint index = POPI();
1057 jshortArray arr = (jshortArray) POPA();
1058 NULLARRAYCHECK (arr);
1059 ARRAYBOUNDSCHECK (arr, index);
1060 PUSHI( elements(arr)[index] );
1062 NEXT_INSN;
1064 insn_istore:
1065 STOREI (get1u (pc++));
1066 NEXT_INSN;
1068 insn_lstore:
1069 STOREL (get1u (pc++));
1070 NEXT_INSN;
1072 insn_fstore:
1073 STOREF (get1u (pc++));
1074 NEXT_INSN;
1076 insn_dstore:
1077 STORED (get1u (pc++));
1078 NEXT_INSN;
1080 insn_astore:
1081 STOREA (get1u (pc++));
1082 NEXT_INSN;
1084 insn_istore_0:
1085 STOREI (0);
1086 NEXT_INSN;
1088 insn_istore_1:
1089 STOREI (1);
1090 NEXT_INSN;
1092 insn_istore_2:
1093 STOREI (2);
1094 NEXT_INSN;
1096 insn_istore_3:
1097 STOREI (3);
1098 NEXT_INSN;
1100 insn_lstore_0:
1101 STOREL (0);
1102 NEXT_INSN;
1104 insn_lstore_1:
1105 STOREL (1);
1106 NEXT_INSN;
1108 insn_lstore_2:
1109 STOREL (2);
1110 NEXT_INSN;
1112 insn_lstore_3:
1113 STOREL (3);
1114 NEXT_INSN;
1116 insn_fstore_0:
1117 STOREF (0);
1118 NEXT_INSN;
1120 insn_fstore_1:
1121 STOREF (1);
1122 NEXT_INSN;
1124 insn_fstore_2:
1125 STOREF (2);
1126 NEXT_INSN;
1128 insn_fstore_3:
1129 STOREF (3);
1130 NEXT_INSN;
1132 insn_dstore_0:
1133 STORED (0);
1134 NEXT_INSN;
1136 insn_dstore_1:
1137 STORED (1);
1138 NEXT_INSN;
1140 insn_dstore_2:
1141 STORED (2);
1142 NEXT_INSN;
1144 insn_dstore_3:
1145 STORED (3);
1146 NEXT_INSN;
1148 insn_astore_0:
1149 STOREA(0);
1150 NEXT_INSN;
1152 insn_astore_1:
1153 STOREA(1);
1154 NEXT_INSN;
1156 insn_astore_2:
1157 STOREA(2);
1158 NEXT_INSN;
1160 insn_astore_3:
1161 STOREA(3);
1162 NEXT_INSN;
1164 insn_iastore:
1166 jint value = POPI();
1167 jint index = POPI();
1168 jintArray arr = (jintArray) POPA();
1169 NULLARRAYCHECK (arr);
1170 ARRAYBOUNDSCHECK (arr, index);
1171 elements(arr)[index] = value;
1173 NEXT_INSN;
1175 insn_lastore:
1177 jlong value = POPL();
1178 jint index = POPI();
1179 jlongArray arr = (jlongArray) POPA();
1180 NULLARRAYCHECK (arr);
1181 ARRAYBOUNDSCHECK (arr, index);
1182 elements(arr)[index] = value;
1184 NEXT_INSN;
1186 insn_fastore:
1188 jfloat value = POPF();
1189 jint index = POPI();
1190 jfloatArray arr = (jfloatArray) POPA();
1191 NULLARRAYCHECK (arr);
1192 ARRAYBOUNDSCHECK (arr, index);
1193 elements(arr)[index] = value;
1195 NEXT_INSN;
1197 insn_dastore:
1199 jdouble value = POPD();
1200 jint index = POPI();
1201 jdoubleArray arr = (jdoubleArray) POPA();
1202 NULLARRAYCHECK (arr);
1203 ARRAYBOUNDSCHECK (arr, index);
1204 elements(arr)[index] = value;
1206 NEXT_INSN;
1208 insn_aastore:
1210 jobject value = POPA();
1211 jint index = POPI();
1212 jobjectArray arr = (jobjectArray) POPA();
1213 NULLARRAYCHECK (arr);
1214 ARRAYBOUNDSCHECK (arr, index);
1215 _Jv_CheckArrayStore (arr, value);
1216 elements(arr)[index] = value;
1218 NEXT_INSN;
1220 insn_bastore:
1222 jbyte value = (jbyte) POPI();
1223 jint index = POPI();
1224 jbyteArray arr = (jbyteArray) POPA();
1225 NULLARRAYCHECK (arr);
1226 ARRAYBOUNDSCHECK (arr, index);
1227 elements(arr)[index] = value;
1229 NEXT_INSN;
1231 insn_castore:
1233 jchar value = (jchar) POPI();
1234 jint index = POPI();
1235 jcharArray arr = (jcharArray) POPA();
1236 NULLARRAYCHECK (arr);
1237 ARRAYBOUNDSCHECK (arr, index);
1238 elements(arr)[index] = value;
1240 NEXT_INSN;
1242 insn_sastore:
1244 jshort value = (jshort) POPI();
1245 jint index = POPI();
1246 jshortArray arr = (jshortArray) POPA();
1247 NULLARRAYCHECK (arr);
1248 ARRAYBOUNDSCHECK (arr, index);
1249 elements(arr)[index] = value;
1251 NEXT_INSN;
1253 insn_pop:
1254 sp -= 1;
1255 NEXT_INSN;
1257 insn_pop2:
1258 sp -= 2;
1259 NEXT_INSN;
1261 insn_dup:
1262 sp[0] = sp[-1];
1263 sp += 1;
1264 NEXT_INSN;
1266 insn_dup_x1:
1267 dupx (sp, 1, 1); sp+=1;
1268 NEXT_INSN;
1270 insn_dup_x2:
1271 dupx (sp, 1, 2); sp+=1;
1272 NEXT_INSN;
1274 insn_dup2:
1275 sp[0] = sp[-2];
1276 sp[1] = sp[-1];
1277 sp += 2;
1278 NEXT_INSN;
1280 insn_dup2_x1:
1281 dupx (sp, 2, 1); sp+=2;
1282 NEXT_INSN;
1284 insn_dup2_x2:
1285 dupx (sp, 2, 2); sp+=2;
1286 NEXT_INSN;
1288 insn_swap:
1290 jobject tmp1 = POPA();
1291 jobject tmp2 = POPA();
1292 PUSHA (tmp1);
1293 PUSHA (tmp2);
1295 NEXT_INSN;
1297 insn_iadd:
1298 BINOPI(+);
1299 NEXT_INSN;
1301 insn_ladd:
1302 BINOPL(+);
1303 NEXT_INSN;
1305 insn_fadd:
1306 BINOPF(+);
1307 NEXT_INSN;
1309 insn_dadd:
1310 BINOPD(+);
1311 NEXT_INSN;
1313 insn_isub:
1314 BINOPI(-);
1315 NEXT_INSN;
1317 insn_lsub:
1318 BINOPL(-);
1319 NEXT_INSN;
1321 insn_fsub:
1322 BINOPF(-);
1323 NEXT_INSN;
1325 insn_dsub:
1326 BINOPD(-);
1327 NEXT_INSN;
1329 insn_imul:
1330 BINOPI(*);
1331 NEXT_INSN;
1333 insn_lmul:
1334 BINOPL(*);
1335 NEXT_INSN;
1337 insn_fmul:
1338 BINOPF(*);
1339 NEXT_INSN;
1341 insn_dmul:
1342 BINOPD(*);
1343 NEXT_INSN;
1345 insn_idiv:
1346 SAVE_PC;
1348 jint value2 = POPI();
1349 jint value1 = POPI();
1350 jint res = _Jv_divI (value1, value2);
1351 PUSHI (res);
1353 NEXT_INSN;
1355 insn_ldiv:
1356 SAVE_PC;
1358 jlong value2 = POPL();
1359 jlong value1 = POPL();
1360 jlong res = _Jv_divJ (value1, value2);
1361 PUSHL (res);
1363 NEXT_INSN;
1365 insn_fdiv:
1367 jfloat value2 = POPF();
1368 jfloat value1 = POPF();
1369 jfloat res = value1 / value2;
1370 PUSHF (res);
1372 NEXT_INSN;
1374 insn_ddiv:
1376 jdouble value2 = POPD();
1377 jdouble value1 = POPD();
1378 jdouble res = value1 / value2;
1379 PUSHD (res);
1381 NEXT_INSN;
1383 insn_irem:
1384 SAVE_PC;
1386 jint value2 = POPI();
1387 jint value1 = POPI();
1388 jint res = _Jv_remI (value1, value2);
1389 PUSHI (res);
1391 NEXT_INSN;
1393 insn_lrem:
1394 SAVE_PC;
1396 jlong value2 = POPL();
1397 jlong value1 = POPL();
1398 jlong res = _Jv_remJ (value1, value2);
1399 PUSHL (res);
1401 NEXT_INSN;
1403 insn_frem:
1405 jfloat value2 = POPF();
1406 jfloat value1 = POPF();
1407 jfloat res = __ieee754_fmod (value1, value2);
1408 PUSHF (res);
1410 NEXT_INSN;
1412 insn_drem:
1414 jdouble value2 = POPD();
1415 jdouble value1 = POPD();
1416 jdouble res = __ieee754_fmod (value1, value2);
1417 PUSHD (res);
1419 NEXT_INSN;
1421 insn_ineg:
1423 jint value = POPI();
1424 PUSHI (value * -1);
1426 NEXT_INSN;
1428 insn_lneg:
1430 jlong value = POPL();
1431 PUSHL (value * -1);
1433 NEXT_INSN;
1435 insn_fneg:
1437 jfloat value = POPF();
1438 PUSHF (value * -1);
1440 NEXT_INSN;
1442 insn_dneg:
1444 jdouble value = POPD();
1445 PUSHD (value * -1);
1447 NEXT_INSN;
1449 insn_ishl:
1451 jint shift = (POPI() & 0x1f);
1452 jint value = POPI();
1453 PUSHI (value << shift);
1455 NEXT_INSN;
1457 insn_lshl:
1459 jint shift = (POPI() & 0x3f);
1460 jlong value = POPL();
1461 PUSHL (value << shift);
1463 NEXT_INSN;
1465 insn_ishr:
1467 jint shift = (POPI() & 0x1f);
1468 jint value = POPI();
1469 PUSHI (value >> shift);
1471 NEXT_INSN;
1473 insn_lshr:
1475 jint shift = (POPI() & 0x3f);
1476 jlong value = POPL();
1477 PUSHL (value >> shift);
1479 NEXT_INSN;
1481 insn_iushr:
1483 jint shift = (POPI() & 0x1f);
1484 unsigned long value = POPI();
1485 PUSHI ((jint) (value >> shift));
1487 NEXT_INSN;
1489 insn_lushr:
1491 jint shift = (POPI() & 0x3f);
1492 UINT64 value = (UINT64) POPL();
1493 PUSHL ((value >> shift));
1495 NEXT_INSN;
1497 insn_iand:
1498 BINOPI (&);
1499 NEXT_INSN;
1501 insn_land:
1502 BINOPL (&);
1503 NEXT_INSN;
1505 insn_ior:
1506 BINOPI (|);
1507 NEXT_INSN;
1509 insn_lor:
1510 BINOPL (|);
1511 NEXT_INSN;
1513 insn_ixor:
1514 BINOPI (^);
1515 NEXT_INSN;
1517 insn_lxor:
1518 BINOPL (^);
1519 NEXT_INSN;
1521 insn_iinc:
1523 jint index = get1u (pc++);
1524 jint amount = get1s (pc++);
1525 locals[index].i += amount;
1527 NEXT_INSN;
1529 insn_i2l:
1530 {jlong value = POPI(); PUSHL (value);}
1531 NEXT_INSN;
1533 insn_i2f:
1534 {jfloat value = POPI(); PUSHF (value);}
1535 NEXT_INSN;
1537 insn_i2d:
1538 {jdouble value = POPI(); PUSHD (value);}
1539 NEXT_INSN;
1541 insn_l2i:
1542 {jint value = POPL(); PUSHI (value);}
1543 NEXT_INSN;
1545 insn_l2f:
1546 {jfloat value = POPL(); PUSHF (value);}
1547 NEXT_INSN;
1549 insn_l2d:
1550 {jdouble value = POPL(); PUSHD (value);}
1551 NEXT_INSN;
1553 insn_f2i:
1555 using namespace java::lang;
1556 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1557 PUSHI(value);
1559 NEXT_INSN;
1561 insn_f2l:
1563 using namespace java::lang;
1564 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1565 PUSHL(value);
1567 NEXT_INSN;
1569 insn_f2d:
1570 { jdouble value = POPF (); PUSHD(value); }
1571 NEXT_INSN;
1573 insn_d2i:
1575 using namespace java::lang;
1576 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1577 PUSHI(value);
1579 NEXT_INSN;
1581 insn_d2l:
1583 using namespace java::lang;
1584 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1585 PUSHL(value);
1587 NEXT_INSN;
1589 insn_d2f:
1590 { jfloat value = POPD (); PUSHF(value); }
1591 NEXT_INSN;
1593 insn_i2b:
1594 { jbyte value = POPI (); PUSHI(value); }
1595 NEXT_INSN;
1597 insn_i2c:
1598 { jchar value = POPI (); PUSHI(value); }
1599 NEXT_INSN;
1601 insn_i2s:
1602 { jshort value = POPI (); PUSHI(value); }
1603 NEXT_INSN;
1605 insn_lcmp:
1607 jlong value2 = POPL ();
1608 jlong value1 = POPL ();
1609 if (value1 > value2)
1610 { PUSHI (1); }
1611 else if (value1 == value2)
1612 { PUSHI (0); }
1613 else
1614 { PUSHI (-1); }
1616 NEXT_INSN;
1618 insn_fcmpl:
1619 insn_fcmpg:
1621 jfloat value2 = POPF ();
1622 jfloat value1 = POPF ();
1623 if (value1 > value2)
1624 PUSHI (1);
1625 else if (value1 == value2)
1626 PUSHI (0);
1627 else if (value1 < value2)
1628 PUSHI (-1);
1629 else if ((*(pc-1)) == op_fcmpg)
1630 PUSHI (1);
1631 else
1632 PUSHI (-1);
1634 NEXT_INSN;
1636 insn_dcmpl:
1637 insn_dcmpg:
1639 jdouble value2 = POPD ();
1640 jdouble value1 = POPD ();
1641 if (value1 > value2)
1642 PUSHI (1);
1643 else if (value1 == value2)
1644 PUSHI (0);
1645 else if (value1 < value2)
1646 PUSHI (-1);
1647 else if ((*(pc-1)) == op_dcmpg)
1648 PUSHI (1);
1649 else
1650 PUSHI (-1);
1652 NEXT_INSN;
1654 insn_ifeq:
1656 jint offset = get2s (pc);
1657 if (POPI() == 0)
1658 pc = pc-1+offset;
1659 else
1660 pc = pc+2;
1662 NEXT_INSN;
1664 insn_ifne:
1666 jint offset = get2s (pc);
1667 if (POPI() != 0)
1668 pc = pc-1+offset;
1669 else
1670 pc = pc+2;
1672 NEXT_INSN;
1674 insn_iflt:
1676 jint offset = get2s (pc);
1677 if (POPI() < 0)
1678 pc = pc-1+offset;
1679 else
1680 pc = pc+2;
1682 NEXT_INSN;
1684 insn_ifge:
1686 jint offset = get2s (pc);
1687 if (POPI() >= 0)
1688 pc = pc-1+offset;
1689 else
1690 pc = pc+2;
1692 NEXT_INSN;
1694 insn_ifgt:
1696 jint offset = get2s (pc);
1697 if (POPI() > 0)
1698 pc = pc-1+offset;
1699 else
1700 pc = pc+2;
1702 NEXT_INSN;
1704 insn_ifle:
1706 jint offset = get2s (pc);
1707 if (POPI() <= 0)
1708 pc = pc-1+offset;
1709 else
1710 pc = pc+2;
1712 NEXT_INSN;
1714 insn_if_icmpeq:
1716 jint offset = get2s (pc);
1717 jint value2 = POPI();
1718 jint value1 = POPI();
1719 if (value1 == value2)
1720 pc = pc-1+offset;
1721 else
1722 pc = pc+2;
1724 NEXT_INSN;
1726 insn_if_icmpne:
1728 jint offset = get2s (pc);
1729 jint value2 = POPI();
1730 jint value1 = POPI();
1731 if (value1 != value2)
1732 pc = pc-1+offset;
1733 else
1734 pc = pc+2;
1736 NEXT_INSN;
1738 insn_if_icmplt:
1740 jint offset = get2s (pc);
1741 jint value2 = POPI();
1742 jint value1 = POPI();
1743 if (value1 < value2)
1744 pc = pc-1+offset;
1745 else
1746 pc = pc+2;
1748 NEXT_INSN;
1750 insn_if_icmpge:
1752 jint offset = get2s (pc);
1753 jint value2 = POPI();
1754 jint value1 = POPI();
1755 if (value1 >= value2)
1756 pc = pc-1+offset;
1757 else
1758 pc = pc+2;
1760 NEXT_INSN;
1762 insn_if_icmpgt:
1764 jint offset = get2s (pc);
1765 jint value2 = POPI();
1766 jint value1 = POPI();
1767 if (value1 > value2)
1768 pc = pc-1+offset;
1769 else
1770 pc = pc+2;
1772 NEXT_INSN;
1774 insn_if_icmple:
1776 jint offset = get2s (pc);
1777 jint value2 = POPI();
1778 jint value1 = POPI();
1779 if (value1 <= value2)
1780 pc = pc-1+offset;
1781 else
1782 pc = pc+2;
1784 NEXT_INSN;
1786 insn_if_acmpeq:
1788 jint offset = get2s (pc);
1789 jobject value2 = POPA();
1790 jobject value1 = POPA();
1791 if (value1 == value2)
1792 pc = pc-1+offset;
1793 else
1794 pc = pc+2;
1796 NEXT_INSN;
1798 insn_if_acmpne:
1800 jint offset = get2s (pc);
1801 jobject value2 = POPA();
1802 jobject value1 = POPA();
1803 if (value1 != value2)
1804 pc = pc-1+offset;
1805 else
1806 pc = pc+2;
1808 NEXT_INSN;
1810 insn_goto:
1812 jint offset = get2s (pc);
1813 pc = pc-1+offset;
1815 NEXT_INSN;
1817 insn_jsr:
1819 unsigned char *base_pc = pc-1;
1820 jint offset = get2s (pc); pc += 2;
1821 PUSHA ((jobject)pc);
1822 pc = base_pc+offset;
1824 NEXT_INSN;
1826 insn_ret:
1828 jint index = get1u (pc);
1829 pc = (unsigned char*) PEEKA (index);
1831 NEXT_INSN;
1833 insn_tableswitch:
1835 unsigned char *base_pc = pc-1;
1836 int index = POPI();
1838 unsigned char* base = bytecode ();
1839 while ((pc-base) % 4 != 0)
1840 pc++;
1842 jint def = get4 (pc);
1843 jint low = get4 (pc+4);
1844 jint high = get4 (pc+8);
1846 if (index < low || index > high)
1847 pc = base_pc + def;
1848 else
1849 pc = base_pc + get4 (pc+4*(index-low+3));
1851 NEXT_INSN;
1853 insn_lookupswitch:
1855 unsigned char *base_pc = pc-1;
1856 int index = POPI();
1858 unsigned char* base = bytecode ();
1859 while ((pc-base) % 4 != 0)
1860 pc++;
1862 jint def = get4 (pc);
1863 jint npairs = get4 (pc+4);
1865 int max = npairs-1;
1866 int min = 0;
1868 // simple binary search...
1869 while (min < max)
1871 int half = (min+max)/2;
1872 int match = get4 (pc+ 4*(2 + 2*half));
1874 if (index == match)
1875 min = max = half;
1877 else if (index < match)
1878 max = half-1;
1880 else
1881 min = half+1;
1884 if (index == get4 (pc+ 4*(2 + 2*min)))
1885 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1886 else
1887 pc = base_pc + def;
1889 NEXT_INSN;
1891 /* on return, just save the sp and return to caller */
1892 insn_ireturn:
1893 insn_lreturn:
1894 insn_freturn:
1895 insn_dreturn:
1896 insn_areturn:
1897 insn_return:
1898 inv->sp = sp;
1899 return;
1901 insn_getstatic:
1902 SAVE_PC;
1904 jint fieldref_index = get2u (pc); pc += 2;
1905 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1906 _Jv_Field *field = pool_data[fieldref_index].field;
1908 if ((field->flags & Modifier::STATIC) == 0)
1909 throw_incompatible_class_change_error
1910 (JvNewStringLatin1 ("field no longer static"));
1912 jclass type = field->type;
1914 if (type->isPrimitive ())
1916 switch (type->size_in_bytes)
1918 case 1:
1919 PUSHI (*(jbyte*) (field->u.addr));
1920 break;
1922 case 2:
1923 if (type == JvPrimClass (char))
1924 PUSHI(*(jchar*) (field->u.addr));
1925 else
1926 PUSHI(*(jshort*) (field->u.addr));
1927 break;
1929 case 4:
1930 PUSHI(*(jint*) (field->u.addr));
1931 break;
1933 case 8:
1934 PUSHL(*(jlong*) (field->u.addr));
1935 break;
1938 else
1940 PUSHA(*(jobject*) (field->u.addr));
1943 NEXT_INSN;
1945 insn_getfield:
1946 SAVE_PC;
1948 jint fieldref_index = get2u (pc); pc += 2;
1949 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1950 _Jv_Field *field = pool_data[fieldref_index].field;
1952 if ((field->flags & Modifier::STATIC) != 0)
1953 throw_incompatible_class_change_error
1954 (JvNewStringLatin1 ("field is static"));
1956 jclass type = field->type;
1957 jint field_offset = field->u.boffset;
1958 if (field_offset > 0xffff)
1959 throw new java::lang::VirtualMachineError;
1961 jobject obj = POPA();
1962 NULLCHECK(obj);
1964 if (type->isPrimitive ())
1966 switch (type->size_in_bytes)
1968 case 1:
1969 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1970 break;
1972 case 2:
1973 if (type == JvPrimClass (char))
1974 PUSHI (*(jchar*) ((char*)obj + field_offset));
1975 else
1976 PUSHI (*(jshort*) ((char*)obj + field_offset));
1977 break;
1979 case 4:
1980 PUSHI (*(jint*) ((char*)obj + field_offset));
1981 break;
1983 case 8:
1984 PUSHL(*(jlong*) ((char*)obj + field_offset));
1985 break;
1988 else
1990 PUSHA(*(jobject*) ((char*)obj + field_offset));
1993 NEXT_INSN;
1995 insn_putstatic:
1996 SAVE_PC;
1998 jint fieldref_index = get2u (pc); pc += 2;
1999 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2000 _Jv_Field *field = pool_data[fieldref_index].field;
2002 jclass type = field->type;
2004 // ResolvePoolEntry cannot check this
2005 if ((field->flags & Modifier::STATIC) == 0)
2006 throw_incompatible_class_change_error
2007 (JvNewStringLatin1 ("field no longer static"));
2009 if (type->isPrimitive ())
2011 switch (type->size_in_bytes)
2013 case 1:
2015 jint value = POPI();
2016 *(jbyte*) (field->u.addr) = value;
2017 break;
2020 case 2:
2022 jint value = POPI();
2023 *(jchar*) (field->u.addr) = value;
2024 break;
2027 case 4:
2029 jint value = POPI();
2030 *(jint*) (field->u.addr) = value;
2031 break;
2034 case 8:
2036 jlong value = POPL();
2037 *(jlong*) (field->u.addr) = value;
2038 break;
2042 else
2044 jobject value = POPA();
2045 *(jobject*) (field->u.addr) = value;
2048 NEXT_INSN;
2051 insn_putfield:
2052 SAVE_PC;
2054 jint fieldref_index = get2u (pc); pc += 2;
2055 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2056 _Jv_Field *field = pool_data[fieldref_index].field;
2058 jclass type = field->type;
2060 if ((field->flags & Modifier::STATIC) != 0)
2061 throw_incompatible_class_change_error
2062 (JvNewStringLatin1 ("field is static"));
2064 jint field_offset = field->u.boffset;
2065 if (field_offset > 0xffff)
2066 throw new java::lang::VirtualMachineError;
2068 if (type->isPrimitive ())
2070 switch (type->size_in_bytes)
2072 case 1:
2074 jint value = POPI();
2075 jobject obj = POPA();
2076 NULLCHECK(obj);
2077 *(jbyte*) ((char*)obj + field_offset) = value;
2078 break;
2081 case 2:
2083 jint value = POPI();
2084 jobject obj = POPA();
2085 NULLCHECK(obj);
2086 *(jchar*) ((char*)obj + field_offset) = value;
2087 break;
2090 case 4:
2092 jint value = POPI();
2093 jobject obj = POPA();
2094 NULLCHECK(obj);
2095 *(jint*) ((char*)obj + field_offset) = value;
2096 break;
2099 case 8:
2101 jlong value = POPL();
2102 jobject obj = POPA();
2103 NULLCHECK(obj);
2104 *(jlong*) ((char*)obj + field_offset) = value;
2105 break;
2109 else
2111 jobject value = POPA();
2112 jobject obj = POPA();
2113 NULLCHECK(obj);
2114 *(jobject*) ((char*)obj + field_offset) = value;
2117 NEXT_INSN;
2119 insn_invokespecial:
2120 SAVE_PC;
2122 int index = get2u (pc); pc += 2;
2124 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2126 sp -= rmeth->stack_item_count;
2128 NULLCHECK (sp[0].o);
2130 fun = (void (*)()) rmeth->method->ncode;
2132 goto perform_invoke;
2134 insn_invokestatic:
2135 SAVE_PC;
2137 int index = get2u (pc); pc += 2;
2139 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2141 sp -= rmeth->stack_item_count;
2143 _Jv_InitClass (rmeth->klass);
2144 fun = (void (*)()) rmeth->method->ncode;
2146 goto perform_invoke;
2148 insn_invokeinterface:
2149 SAVE_PC;
2151 int index = get2u (pc); pc += 2;
2153 // invokeinterface has two unused bytes...
2154 pc += 2;
2156 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2158 sp -= rmeth->stack_item_count;
2160 jobject rcv = sp[0].o;
2162 NULLCHECK (rcv);
2164 fun = (void (*)())
2165 _Jv_LookupInterfaceMethod (rcv->getClass (),
2166 rmeth->method->name,
2167 rmeth->method->signature);
2169 goto perform_invoke;
2172 insn_new:
2173 SAVE_PC;
2175 int index = get2u (pc); pc += 2;
2176 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2177 _Jv_InitClass (klass);
2178 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2179 PUSHA (res);
2181 NEXT_INSN;
2183 insn_newarray:
2184 SAVE_PC;
2186 int atype = get1u (pc++);
2187 int size = POPI();
2188 jobject result = _Jv_NewArray (atype, size);
2189 PUSHA (result);
2191 NEXT_INSN;
2193 insn_anewarray:
2194 SAVE_PC;
2196 int index = get2u (pc); pc += 2;
2197 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2198 int size = POPI();
2199 _Jv_InitClass (klass);
2200 jobject result = _Jv_NewObjectArray (size, klass, 0);
2201 PUSHA (result);
2203 NEXT_INSN;
2205 insn_arraylength:
2207 __JArray *arr = (__JArray*)POPA();
2208 NULLARRAYCHECK (arr);
2209 PUSHI (arr->length);
2211 NEXT_INSN;
2213 insn_athrow:
2214 SAVE_PC;
2216 jobject value = POPA();
2217 throw static_cast<jthrowable>(value);
2219 NEXT_INSN;
2221 insn_checkcast:
2222 SAVE_PC;
2224 jobject value = POPA();
2225 jint index = get2u (pc); pc += 2;
2226 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2228 if (value != NULL && ! to->isInstance (value))
2230 throw new java::lang::ClassCastException (to->getName());
2233 PUSHA (value);
2235 NEXT_INSN;
2237 insn_instanceof:
2238 SAVE_PC;
2240 jobject value = POPA();
2241 jint index = get2u (pc); pc += 2;
2242 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2243 PUSHI (to->isInstance (value));
2245 NEXT_INSN;
2247 insn_monitorenter:
2248 SAVE_PC;
2250 jobject value = POPA();
2251 NULLCHECK(value);
2252 _Jv_MonitorEnter (value);
2254 NEXT_INSN;
2256 insn_monitorexit:
2257 SAVE_PC;
2259 jobject value = POPA();
2260 NULLCHECK(value);
2261 _Jv_MonitorExit (value);
2263 NEXT_INSN;
2265 insn_ifnull:
2267 unsigned char* base_pc = pc-1;
2268 jint offset = get2s (pc); pc += 2;
2269 jobject val = POPA();
2270 if (val == NULL)
2271 pc = base_pc+offset;
2273 NEXT_INSN;
2275 insn_ifnonnull:
2277 unsigned char* base_pc = pc-1;
2278 jint offset = get2s (pc); pc += 2;
2279 jobject val = POPA();
2280 if (val != NULL)
2281 pc = base_pc+offset;
2283 NEXT_INSN;
2285 insn_wide:
2286 SAVE_PC;
2288 jint the_mod_op = get1u (pc++);
2289 jint wide = get2u (pc); pc += 2;
2291 switch (the_mod_op)
2293 case op_istore:
2294 STOREI (wide);
2295 NEXT_INSN;
2297 case op_fstore:
2298 STOREF (wide);
2299 NEXT_INSN;
2301 case op_astore:
2302 STOREA (wide);
2303 NEXT_INSN;
2305 case op_lload:
2306 LOADL (wide);
2307 NEXT_INSN;
2309 case op_dload:
2310 LOADD (wide);
2311 NEXT_INSN;
2313 case op_iload:
2314 LOADI (wide);
2315 NEXT_INSN;
2317 case op_aload:
2318 LOADA (wide);
2319 NEXT_INSN;
2321 case op_lstore:
2322 STOREL (wide);
2323 NEXT_INSN;
2325 case op_dstore:
2326 STORED (wide);
2327 NEXT_INSN;
2329 case op_ret:
2330 pc = (unsigned char*) PEEKA (wide);
2331 NEXT_INSN;
2333 case op_iinc:
2335 jint amount = get2s (pc); pc += 2;
2336 jint value = PEEKI (wide);
2337 POKEI (wide, value+amount);
2339 NEXT_INSN;
2341 default:
2342 throw_internal_error ("illegal bytecode modified by wide");
2347 insn_multianewarray:
2348 SAVE_PC;
2350 int kind_index = get2u (pc); pc += 2;
2351 int dim = get1u (pc); pc += 1;
2353 jclass type
2354 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2355 _Jv_InitClass (type);
2356 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2358 for (int i = dim - 1; i >= 0; i--)
2360 sizes[i] = POPI ();
2363 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2365 PUSHA (res);
2367 NEXT_INSN;
2369 insn_goto_w:
2371 unsigned char* base_pc = pc-1;
2372 int offset = get4 (pc); pc += 4;
2373 pc = base_pc+offset;
2375 NEXT_INSN;
2377 insn_jsr_w:
2379 unsigned char* base_pc = pc-1;
2380 int offset = get4 (pc); pc += 4;
2381 PUSHA((jobject)pc);
2382 pc = base_pc+offset;
2384 NEXT_INSN;
2388 static void
2389 throw_internal_error (char *msg)
2391 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
2394 static void
2395 throw_incompatible_class_change_error (jstring msg)
2397 throw new java::lang::IncompatibleClassChangeError (msg);
2400 #ifndef HANDLE_SEGV
2401 static java::lang::NullPointerException *null_pointer_exc;
2402 static void
2403 throw_null_pointer_exception ()
2405 if (null_pointer_exc == NULL)
2406 null_pointer_exc = new java::lang::NullPointerException;
2408 throw null_pointer_exc;
2410 #endif
2412 #endif // INTERPRETER