Jumbo patch:
[gcc.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999, 2000 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
12
13 #include <config.h>
14
15 #pragma implementation "java-interp.h"
16
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/StringBuffer.h>
25 #include <java/lang/Class.h>
26 #include <java/lang/reflect/Modifier.h>
27 #include <java/lang/ClassCastException.h>
28 #include <java/lang/VirtualMachineError.h>
29 #include <java/lang/InternalError.h>
30 #include <java/lang/NullPointerException.h>
31 #include <java/lang/ArithmeticException.h>
32 #include <java/lang/IncompatibleClassChangeError.h>
33 #include <java-insns.h>
34 #include <java-signal.h>
35
36 #ifdef INTERPRETER
37
38 #define ClassError _CL_Q34java4lang5Error
39 extern java::lang::Class ClassError;
40
41 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
42
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
51
52 extern "C" double __ieee754_fmod __P((double,double));
53
54 static inline void dupx (_Jv_word *sp, int n, int x)
55 {
56 // first "slide" n+x elements n to the right
57 int top = n-1;
58 for (int i = 0; i < n+x; i++)
59 {
60 sp[(top-i)] = sp[(top-i)-n];
61 }
62
63 // next, copy the n top elements, n+x down
64 for (int i = 0; i < n; i++)
65 {
66 sp[top-(n+x)-i] = sp[top-i];
67 }
68
69 };
70
71
72 #define PUSHA(V) (sp++)->o = (V)
73 #define PUSHI(V) (sp++)->i = (V)
74 #define PUSHF(V) (sp++)->f = (V)
75 #if SIZEOF_VOID_P == 8
76 # define PUSHL(V) (sp->l = (V), sp += 2)
77 # define PUSHD(V) (sp->d = (V), sp += 2)
78 #else
79 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
80 (sp++)->ia[0] = w2.ia[0]; \
81 (sp++)->ia[0] = w2.ia[1]; } while (0)
82 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
83 (sp++)->ia[0] = w2.ia[0]; \
84 (sp++)->ia[0] = w2.ia[1]; } while (0)
85 #endif
86
87 #define POPA() ((--sp)->o)
88 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
89 #define POPF() ((jfloat) (--sp)->f)
90 #if SIZEOF_VOID_P == 8
91 # define POPL() (sp -= 2, (jlong) sp->l)
92 # define POPD() (sp -= 2, (jdouble) sp->d)
93 #else
94 # define POPL() ({ _Jv_word2 w2; \
95 w2.ia[1] = (--sp)->ia[0]; \
96 w2.ia[0] = (--sp)->ia[0]; w2.l; })
97 # define POPD() ({ _Jv_word2 w2; \
98 w2.ia[1] = (--sp)->ia[0]; \
99 w2.ia[0] = (--sp)->ia[0]; w2.d; })
100 #endif
101
102 #define LOADA(I) (sp++)->o = locals[I].o
103 #define LOADI(I) (sp++)->i = locals[I].i
104 #define LOADF(I) (sp++)->f = locals[I].f
105 #if SIZEOF_VOID_P == 8
106 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
107 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
108 #else
109 # define LOADL(I) do { jint __idx = (I); \
110 (sp++)->ia[0] = locals[__idx].ia[0]; \
111 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
112 } while (0)
113 # define LOADD(I) LOADL(I)
114 #endif
115
116 #define STOREA(I) locals[I].o = (--sp)->o
117 #define STOREI(I) locals[I].i = (--sp)->i
118 #define STOREF(I) locals[I].f = (--sp)->f
119 #if SIZEOF_VOID_P == 8
120 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
121 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
122 #else
123 # define STOREL(I) do { jint __idx = (I); \
124 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
125 locals[__idx].ia[0] = (--sp)->ia[0]; \
126 } while (0)
127 # define STORED(I) STOREL(I)
128 #endif
129
130 #define PEEKI(I) (locals+(I))->i
131 #define PEEKA(I) (locals+(I))->o
132
133 #define POKEI(I,V) ((locals+(I))->i = (V))
134
135
136 #define BINOPI(OP) { \
137 jint value2 = POPI(); \
138 jint value1 = POPI(); \
139 PUSHI(value1 OP value2); \
140 }
141
142 #define BINOPF(OP) { \
143 jfloat value2 = POPF(); \
144 jfloat value1 = POPF(); \
145 PUSHF(value1 OP value2); \
146 }
147
148 #define BINOPL(OP) { \
149 jlong value2 = POPL(); \
150 jlong value1 = POPL(); \
151 PUSHL(value1 OP value2); \
152 }
153
154 #define BINOPD(OP) { \
155 jdouble value2 = POPD(); \
156 jdouble value1 = POPD(); \
157 PUSHD(value1 OP value2); \
158 }
159
160 static inline jint get1s(unsigned char* loc) {
161 return *(signed char*)loc;
162 }
163
164 static inline jint get1u(unsigned char* loc) {
165 return *loc;
166 }
167
168 static inline jint get2s(unsigned char* loc) {
169 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
170 }
171
172 static inline jint get2u(unsigned char* loc) {
173 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
174 }
175
176 static jint get4(unsigned char* loc) {
177 return (((jint)(loc[0])) << 24)
178 | (((jint)(loc[1])) << 16)
179 | (((jint)(loc[2])) << 8)
180 | (((jint)(loc[3])) << 0);
181 }
182
183
184 #ifdef HANDLE_SEGV
185 #define NULLCHECK(X)
186 #else
187 #define NULLCHECK(X) \
188 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
189 #endif
190
191
192 // this method starts the actual running of the method. It is inlined
193 // in three different variants in the static methods run_normal,
194 // run_sync_object and run_sync_class (see below). Those static methods
195 // are installed directly in the stub for this method (by
196 // _Jv_InterpMethod::ncode, in resolve.cc).
197
198 inline jobject
199 _Jv_InterpMethod::run (ffi_cif* cif,
200 void *retp,
201 ffi_raw *args,
202 _Jv_InterpMethodInvocation *inv)
203 {
204 inv->running = this;
205 inv->pc = bytecode ();
206 inv->sp = inv->stack_base ();
207 _Jv_word *locals = inv->local_base ();
208
209 /* Go straight at it! the ffi raw format matches the internal
210 stack representation exactly. At least, that's the idea.
211 */
212 memcpy ((void*) locals, (void*) args, args_raw_size);
213
214 next_segment:
215
216 jobject ex = NULL;
217
218 try
219 {
220 continue1 (inv);
221 }
222 catch (java::lang::Throwable *ex2)
223 {
224 ex = ex2;
225 }
226
227 if (ex == 0) // no exception...
228 {
229 /* define sp locally, so the POP? macros will pick it up */
230 _Jv_word *sp = inv->sp;
231 int rtype = cif->rtype->type;
232
233 if (rtype == FFI_TYPE_POINTER)
234 {
235 jobject r = POPA();
236 *(jobject*) retp = r;
237 return 0;
238 }
239 else if (rtype == FFI_TYPE_SINT32)
240 {
241 jint r = POPI();
242 *(jint*)retp = r;
243 return 0;
244 }
245 else if (rtype == FFI_TYPE_VOID)
246 {
247 return 0;
248 }
249 else switch (rtype)
250 {
251 case FFI_TYPE_FLOAT:
252 {
253 jfloat r = POPF();
254 *(jfloat*)retp = r;
255 return 0;
256 }
257
258 case FFI_TYPE_DOUBLE:
259 {
260 jdouble r = POPD();
261 *(jdouble*)retp = r;
262 return 0;
263 }
264
265 case FFI_TYPE_UINT8:
266 case FFI_TYPE_UINT16:
267 case FFI_TYPE_UINT32:
268 case FFI_TYPE_SINT8:
269 case FFI_TYPE_SINT16:
270 {
271 jint r = POPI();
272 *(jint*)retp = r;
273 return 0;
274 }
275
276 case FFI_TYPE_SINT64:
277 {
278 jlong r = POPL();
279 *(jlong*)retp = r;
280 return 0;
281 }
282
283 default:
284 throw_internal_error ("unknown return type");
285 }
286 }
287
288 /** handle an exception */
289 if ( find_exception (ex, inv) )
290 goto next_segment;
291
292 return ex;
293 }
294
295 bool _Jv_InterpMethod::find_exception (jobject ex,
296 _Jv_InterpMethodInvocation *inv)
297 {
298 int logical_pc = inv->pc - bytecode ();
299 _Jv_InterpException *exc = exceptions ();
300 jclass exc_class = ex->getClass ();
301
302 for (int i = 0; i < exc_count; i++)
303 {
304 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
305 {
306 jclass handler;
307
308 if (exc[i].handler_type != 0)
309 handler = (_Jv_ResolvePoolEntry (defining_class,
310 exc[i].handler_type)).clazz;
311 else
312 handler = NULL;
313
314 if (handler==NULL || handler->isAssignableFrom (exc_class))
315 {
316 inv->pc = bytecode () + exc[i].handler_pc;
317 inv->sp = inv->stack_base (); // reset stack
318 (inv->sp++)->o = ex; // push exception
319 return true;
320 }
321 }
322 }
323 return false;
324 }
325
326 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
327 void* ret,
328 ffi_raw * args,
329 void* __this)
330 {
331 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
332
333 // we do the alloca of the method invocation here, to allow the method
334 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
335 int storage_size = _this->max_stack+_this->max_locals;
336 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
337 alloca (sizeof (_Jv_InterpMethodInvocation)
338 + storage_size * sizeof (_Jv_word));
339
340 jobject ex = _this->run (cif, ret, args, inv);
341 if (ex != 0) _Jv_Throw (ex);
342 }
343
344 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
345 void* ret,
346 ffi_raw * args,
347 void* __this)
348 {
349 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
350 jobject rcv = (jobject)args[0].ptr;
351
352 int storage_size = _this->max_stack+_this->max_locals;
353 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
354 alloca (sizeof (_Jv_InterpMethodInvocation)
355 + storage_size * sizeof (_Jv_word));
356
357 _Jv_MonitorEnter (rcv);
358 jobject ex = _this->run (cif, ret, args, inv);
359 _Jv_MonitorExit (rcv);
360
361 if (ex != 0) _Jv_Throw (ex);
362 }
363
364 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
365 void* ret,
366 ffi_raw * args,
367 void* __this)
368 {
369 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
370 jclass sync = _this->defining_class;
371
372 int storage_size = _this->max_stack+_this->max_locals;
373 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
374 alloca (sizeof (_Jv_InterpMethodInvocation)
375 + storage_size * sizeof (_Jv_word));
376
377 _Jv_MonitorEnter (sync);
378 jobject ex = _this->run (cif, ret, args, inv);
379 _Jv_MonitorExit (sync);
380
381 if (ex != 0) _Jv_Throw (ex);
382 }
383
384 /*
385 This proceeds execution, as designated in "inv". If an exception
386 happens, then it is simply thrown, and handled in Java. Thus, the pc
387 needs to be stored in the inv->pc at all times, so we can figure
388 out which handler (if any) to invoke.
389
390 One design issue, which I have not completely considered, is if it
391 should be possible to have interpreted classes linked in! Seldom used
392 (or non-critical) classes could reasonably be interpreted.
393 */
394
395
396 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
397 {
398 using namespace java::lang::reflect;
399
400 _Jv_word *sp = inv->sp;
401 unsigned char *pc = inv->pc;
402 _Jv_word *locals = inv->local_base ();
403
404 _Jv_word *pool_data = defining_class->constants.data;
405
406 /* these two are used in the invokeXXX instructions */
407 void (*fun)(...);
408 _Jv_ResolvedMethod* rmeth;
409
410 #define INSN_LABEL(op) &&insn_##op
411 #define GOTO_INSN(op) goto *(insn_target[op])
412
413 static const void *const insn_target[] =
414 {
415 INSN_LABEL(nop),
416 INSN_LABEL(aconst_null),
417 INSN_LABEL(iconst_m1),
418 INSN_LABEL(iconst_0),
419 INSN_LABEL(iconst_1),
420 INSN_LABEL(iconst_2),
421 INSN_LABEL(iconst_3),
422 INSN_LABEL(iconst_4),
423 INSN_LABEL(iconst_5),
424 INSN_LABEL(lconst_0),
425 INSN_LABEL(lconst_1),
426 INSN_LABEL(fconst_0),
427 INSN_LABEL(fconst_1),
428 INSN_LABEL(fconst_2),
429 INSN_LABEL(dconst_0),
430 INSN_LABEL(dconst_1),
431 INSN_LABEL(bipush),
432 INSN_LABEL(sipush),
433 INSN_LABEL(ldc),
434 INSN_LABEL(ldc_w),
435 INSN_LABEL(ldc2_w),
436 INSN_LABEL(iload),
437 INSN_LABEL(lload),
438 INSN_LABEL(fload),
439 INSN_LABEL(dload),
440 INSN_LABEL(aload),
441 INSN_LABEL(iload_0),
442 INSN_LABEL(iload_1),
443 INSN_LABEL(iload_2),
444 INSN_LABEL(iload_3),
445 INSN_LABEL(lload_0),
446 INSN_LABEL(lload_1),
447 INSN_LABEL(lload_2),
448 INSN_LABEL(lload_3),
449 INSN_LABEL(fload_0),
450 INSN_LABEL(fload_1),
451 INSN_LABEL(fload_2),
452 INSN_LABEL(fload_3),
453 INSN_LABEL(dload_0),
454 INSN_LABEL(dload_1),
455 INSN_LABEL(dload_2),
456 INSN_LABEL(dload_3),
457 INSN_LABEL(aload_0),
458 INSN_LABEL(aload_1),
459 INSN_LABEL(aload_2),
460 INSN_LABEL(aload_3),
461 INSN_LABEL(iaload),
462 INSN_LABEL(laload),
463 INSN_LABEL(faload),
464 INSN_LABEL(daload),
465 INSN_LABEL(aaload),
466 INSN_LABEL(baload),
467 INSN_LABEL(caload),
468 INSN_LABEL(saload),
469 INSN_LABEL(istore),
470 INSN_LABEL(lstore),
471 INSN_LABEL(fstore),
472 INSN_LABEL(dstore),
473 INSN_LABEL(astore),
474 INSN_LABEL(istore_0),
475 INSN_LABEL(istore_1),
476 INSN_LABEL(istore_2),
477 INSN_LABEL(istore_3),
478 INSN_LABEL(lstore_0),
479 INSN_LABEL(lstore_1),
480 INSN_LABEL(lstore_2),
481 INSN_LABEL(lstore_3),
482 INSN_LABEL(fstore_0),
483 INSN_LABEL(fstore_1),
484 INSN_LABEL(fstore_2),
485 INSN_LABEL(fstore_3),
486 INSN_LABEL(dstore_0),
487 INSN_LABEL(dstore_1),
488 INSN_LABEL(dstore_2),
489 INSN_LABEL(dstore_3),
490 INSN_LABEL(astore_0),
491 INSN_LABEL(astore_1),
492 INSN_LABEL(astore_2),
493 INSN_LABEL(astore_3),
494 INSN_LABEL(iastore),
495 INSN_LABEL(lastore),
496 INSN_LABEL(fastore),
497 INSN_LABEL(dastore),
498 INSN_LABEL(aastore),
499 INSN_LABEL(bastore),
500 INSN_LABEL(castore),
501 INSN_LABEL(sastore),
502 INSN_LABEL(pop),
503 INSN_LABEL(pop2),
504 INSN_LABEL(dup),
505 INSN_LABEL(dup_x1),
506 INSN_LABEL(dup_x2),
507 INSN_LABEL(dup2),
508 INSN_LABEL(dup2_x1),
509 INSN_LABEL(dup2_x2),
510 INSN_LABEL(swap),
511 INSN_LABEL(iadd),
512 INSN_LABEL(ladd),
513 INSN_LABEL(fadd),
514 INSN_LABEL(dadd),
515 INSN_LABEL(isub),
516 INSN_LABEL(lsub),
517 INSN_LABEL(fsub),
518 INSN_LABEL(dsub),
519 INSN_LABEL(imul),
520 INSN_LABEL(lmul),
521 INSN_LABEL(fmul),
522 INSN_LABEL(dmul),
523 INSN_LABEL(idiv),
524 INSN_LABEL(ldiv),
525 INSN_LABEL(fdiv),
526 INSN_LABEL(ddiv),
527 INSN_LABEL(irem),
528 INSN_LABEL(lrem),
529 INSN_LABEL(frem),
530 INSN_LABEL(drem),
531 INSN_LABEL(ineg),
532 INSN_LABEL(lneg),
533 INSN_LABEL(fneg),
534 INSN_LABEL(dneg),
535 INSN_LABEL(ishl),
536 INSN_LABEL(lshl),
537 INSN_LABEL(ishr),
538 INSN_LABEL(lshr),
539 INSN_LABEL(iushr),
540 INSN_LABEL(lushr),
541 INSN_LABEL(iand),
542 INSN_LABEL(land),
543 INSN_LABEL(ior),
544 INSN_LABEL(lor),
545 INSN_LABEL(ixor),
546 INSN_LABEL(lxor),
547 INSN_LABEL(iinc),
548 INSN_LABEL(i2l),
549 INSN_LABEL(i2f),
550 INSN_LABEL(i2d),
551 INSN_LABEL(l2i),
552 INSN_LABEL(l2f),
553 INSN_LABEL(l2d),
554 INSN_LABEL(f2i),
555 INSN_LABEL(f2l),
556 INSN_LABEL(f2d),
557 INSN_LABEL(d2i),
558 INSN_LABEL(d2l),
559 INSN_LABEL(d2f),
560 INSN_LABEL(i2b),
561 INSN_LABEL(i2c),
562 INSN_LABEL(i2s),
563 INSN_LABEL(lcmp),
564 INSN_LABEL(fcmpl),
565 INSN_LABEL(fcmpg),
566 INSN_LABEL(dcmpl),
567 INSN_LABEL(dcmpg),
568 INSN_LABEL(ifeq),
569 INSN_LABEL(ifne),
570 INSN_LABEL(iflt),
571 INSN_LABEL(ifge),
572 INSN_LABEL(ifgt),
573 INSN_LABEL(ifle),
574 INSN_LABEL(if_icmpeq),
575 INSN_LABEL(if_icmpne),
576 INSN_LABEL(if_icmplt),
577 INSN_LABEL(if_icmpge),
578 INSN_LABEL(if_icmpgt),
579 INSN_LABEL(if_icmple),
580 INSN_LABEL(if_acmpeq),
581 INSN_LABEL(if_acmpne),
582 INSN_LABEL(goto),
583 INSN_LABEL(jsr),
584 INSN_LABEL(ret),
585 INSN_LABEL(tableswitch),
586 INSN_LABEL(lookupswitch),
587 INSN_LABEL(ireturn),
588 INSN_LABEL(lreturn),
589 INSN_LABEL(freturn),
590 INSN_LABEL(dreturn),
591 INSN_LABEL(areturn),
592 INSN_LABEL(return),
593 INSN_LABEL(getstatic),
594 INSN_LABEL(putstatic),
595 INSN_LABEL(getfield),
596 INSN_LABEL(putfield),
597 INSN_LABEL(invokevirtual),
598 INSN_LABEL(invokespecial),
599 INSN_LABEL(invokestatic),
600 INSN_LABEL(invokeinterface),
601 0, /* op_xxxunusedxxx1, */
602 INSN_LABEL(new),
603 INSN_LABEL(newarray),
604 INSN_LABEL(anewarray),
605 INSN_LABEL(arraylength),
606 INSN_LABEL(athrow),
607 INSN_LABEL(checkcast),
608 INSN_LABEL(instanceof),
609 INSN_LABEL(monitorenter),
610 INSN_LABEL(monitorexit),
611 INSN_LABEL(wide),
612 INSN_LABEL(multianewarray),
613 INSN_LABEL(ifnull),
614 INSN_LABEL(ifnonnull),
615 INSN_LABEL(goto_w),
616 INSN_LABEL(jsr_w),
617 };
618
619 #define SAVE_PC inv->pc = pc-1
620
621 /* If the macro INLINE_SWITCH is not defined, then the main loop
622 operates as one big (normal) switch statement. If it is defined,
623 then the case selection is performed `inline' in the end of the
624 code for each case. The latter saves a native branch instruction
625 for each java-instruction, but expands the code size somewhat.
626
627 NOTE: On i386 defining INLINE_SWITCH improves over all
628 performance approximately seven percent, but it may be different
629 for other machines. At some point, this may be made into a proper
630 configuration parameter. */
631
632 #define INLINE_SWITCH
633
634 #ifdef INLINE_SWITCH
635
636 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
637
638
639 NEXT_INSN;
640 #else
641
642 #define NEXT_INSN goto next_insn
643
644 next_insn:
645 GOTO_INSN (*pc++);
646
647 #endif
648
649 /* The first few instructions here are ordered according to their
650 frequency, in the hope that this will improve code locality a
651 little. */
652
653 insn_aload_0: // 0x2a
654 LOADA(0);
655 NEXT_INSN;
656
657 insn_iload: // 0x15
658 LOADI (get1u (pc++));
659 NEXT_INSN;
660
661 insn_iload_1: // 0x1b
662 LOADI (1);
663 NEXT_INSN;
664
665 insn_invokevirtual: // 0xb6
666 SAVE_PC;
667 {
668 int index = get2u (pc); pc += 2;
669
670 /* _Jv_ResolvePoolEntry returns immediately if the value already
671 * is resolved. If we want to clutter up the code here to gain
672 * a little performance, then we can check the corresponding bit
673 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
674 * don't think it is worth it. */
675
676 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
677
678 sp -= rmeth->stack_item_count;
679 NULLCHECK(sp[0]);
680
681 if (rmeth->vtable_index == -1)
682 {
683 // final methods do not appear in the vtable,
684 // if it does not appear in the superclass.
685 fun = (void (*) (...)) rmeth->method->ncode;
686 }
687 else
688 {
689 jobject rcv = sp[0].o;
690 _Jv_VTable *table = *(_Jv_VTable**)rcv;
691 fun = (void (*) (...))table->method[rmeth->vtable_index];
692 }
693 }
694 goto perform_invoke;
695
696 perform_invoke:
697 {
698 /* here goes the magic again... */
699 ffi_cif *cif = &rmeth->cif;
700 ffi_raw *raw = (ffi_raw*) sp;
701
702 jdouble rvalue;
703
704 #if FFI_NATIVE_RAW_API
705 /* We assume that this is only implemented if it's correct */
706 /* to use it here. On a 64 bit machine, it never is. */
707 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
708 #else
709 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
710 #endif
711
712 int rtype = cif->rtype->type;
713
714 /* the likelyhood of object, int, or void return is very high,
715 * so those are checked before the switch */
716 if (rtype == FFI_TYPE_POINTER)
717 {
718 PUSHA (*(jobject*)&rvalue);
719 }
720 else if (rtype == FFI_TYPE_SINT32)
721 {
722 PUSHI (*(jint*)&rvalue);
723 }
724 else if (rtype == FFI_TYPE_VOID)
725 {
726 /* skip */
727 }
728 else switch (rtype)
729 {
730 case FFI_TYPE_SINT8:
731 {
732 jbyte value = (*(jint*)&rvalue) & 0xff;
733 PUSHI (value);
734 }
735 break;
736
737 case FFI_TYPE_SINT16:
738 {
739 jshort value = (*(jint*)&rvalue) & 0xffff;
740 PUSHI (value);
741 }
742 break;
743
744 case FFI_TYPE_UINT16:
745 {
746 jint value = (*(jint*)&rvalue) & 0xffff;
747 PUSHI (value);
748 }
749 break;
750
751 case FFI_TYPE_FLOAT:
752 PUSHF (*(jfloat*)&rvalue);
753 break;
754
755 case FFI_TYPE_DOUBLE:
756 PUSHD (rvalue);
757 break;
758
759 case FFI_TYPE_SINT64:
760 PUSHL (*(jlong*)&rvalue);
761 break;
762
763 default:
764 throw_internal_error ("unknown return type in invokeXXX");
765 }
766
767 }
768 NEXT_INSN;
769
770
771 insn_nop:
772 NEXT_INSN;
773
774 insn_aconst_null:
775 PUSHA (NULL);
776 NEXT_INSN;
777
778 insn_iconst_m1:
779 PUSHI (-1);
780 NEXT_INSN;
781
782 insn_iconst_0:
783 PUSHI (0);
784 NEXT_INSN;
785
786 insn_iconst_1:
787 PUSHI (1);
788 NEXT_INSN;
789
790 insn_iconst_2:
791 PUSHI (2);
792 NEXT_INSN;
793
794 insn_iconst_3:
795 PUSHI (3);
796 NEXT_INSN;
797
798 insn_iconst_4:
799 PUSHI (4);
800 NEXT_INSN;
801
802 insn_iconst_5:
803 PUSHI (5);
804 NEXT_INSN;
805
806 insn_lconst_0:
807 PUSHL (0);
808 NEXT_INSN;
809
810 insn_lconst_1:
811 PUSHL (1);
812 NEXT_INSN;
813
814 insn_fconst_0:
815 PUSHF (0);
816 NEXT_INSN;
817
818 insn_fconst_1:
819 PUSHF (1);
820 NEXT_INSN;
821
822 insn_fconst_2:
823 PUSHF (2);
824 NEXT_INSN;
825
826 insn_dconst_0:
827 PUSHD (0);
828 NEXT_INSN;
829
830 insn_dconst_1:
831 PUSHD (1);
832 NEXT_INSN;
833
834 insn_bipush:
835 PUSHI (get1s(pc++));
836 NEXT_INSN;
837
838 insn_sipush:
839 PUSHI (get2s(pc)); pc += 2;
840 NEXT_INSN;
841
842 insn_ldc:
843 {
844 int index = get1u (pc++);
845 PUSHA(pool_data[index].o);
846 }
847 NEXT_INSN;
848
849 insn_ldc_w:
850 {
851 int index = get2u (pc); pc += 2;
852 PUSHA(pool_data[index].o);
853 }
854 NEXT_INSN;
855
856 insn_ldc2_w:
857 {
858 int index = get2u (pc); pc += 2;
859 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
860 sp += 2;
861 }
862 NEXT_INSN;
863
864 insn_lload:
865 LOADL (get1u (pc++));
866 NEXT_INSN;
867
868 insn_fload:
869 LOADF (get1u (pc++));
870 NEXT_INSN;
871
872 insn_dload:
873 LOADD (get1u (pc++));
874 NEXT_INSN;
875
876 insn_aload:
877 LOADA (get1u (pc++));
878 NEXT_INSN;
879
880 insn_iload_0:
881 LOADI (0);
882 NEXT_INSN;
883
884 insn_iload_2:
885 LOADI (2);
886 NEXT_INSN;
887
888 insn_iload_3:
889 LOADI (3);
890 NEXT_INSN;
891
892 insn_lload_0:
893 LOADL (0);
894 NEXT_INSN;
895
896 insn_lload_1:
897 LOADL (1);
898 NEXT_INSN;
899
900 insn_lload_2:
901 LOADL (2);
902 NEXT_INSN;
903
904 insn_lload_3:
905 LOADL (3);
906 NEXT_INSN;
907
908 insn_fload_0:
909 LOADF (0);
910 NEXT_INSN;
911
912 insn_fload_1:
913 LOADF (1);
914 NEXT_INSN;
915
916 insn_fload_2:
917 LOADF (2);
918 NEXT_INSN;
919
920 insn_fload_3:
921 LOADF (3);
922 NEXT_INSN;
923
924 insn_dload_0:
925 LOADD (0);
926 NEXT_INSN;
927
928 insn_dload_1:
929 LOADD (1);
930 NEXT_INSN;
931
932 insn_dload_2:
933 LOADD (2);
934 NEXT_INSN;
935
936 insn_dload_3:
937 LOADD (3);
938 NEXT_INSN;
939
940 insn_aload_1:
941 LOADA(1);
942 NEXT_INSN;
943
944 insn_aload_2:
945 LOADA(2);
946 NEXT_INSN;
947
948 insn_aload_3:
949 LOADA(3);
950 NEXT_INSN;
951
952 insn_iaload:
953 SAVE_PC;
954 {
955 jint index = POPI();
956 jintArray arr = (jintArray) POPA();
957 NULLCHECK (arr);
958 if (index < 0 || index >= arr->length)
959 {
960 _Jv_ThrowBadArrayIndex (index);
961 }
962 PUSHI( elements(arr)[index] );
963 }
964 NEXT_INSN;
965
966 insn_laload:
967 SAVE_PC;
968 {
969 jint index = POPI();
970 jlongArray arr = (jlongArray) POPA();
971 NULLCHECK (arr);
972 if (index < 0 || index >= arr->length)
973 {
974 _Jv_ThrowBadArrayIndex (index);
975 }
976 PUSHL( elements(arr)[index] );
977 }
978 NEXT_INSN;
979
980 insn_faload:
981 SAVE_PC;
982 {
983 jint index = POPI();
984 jfloatArray arr = (jfloatArray) POPA();
985 NULLCHECK (arr);
986 if (index < 0 || index >= arr->length)
987 {
988 _Jv_ThrowBadArrayIndex (index);
989 }
990 PUSHF( elements(arr)[index] );
991 }
992 NEXT_INSN;
993
994 insn_daload:
995 SAVE_PC;
996 {
997 jint index = POPI();
998 jdoubleArray arr = (jdoubleArray) POPA();
999 NULLCHECK (arr);
1000 if (index < 0 || index >= arr->length)
1001 {
1002 _Jv_ThrowBadArrayIndex (index);
1003 }
1004 PUSHD( elements(arr)[index] );
1005 }
1006 NEXT_INSN;
1007
1008 insn_aaload:
1009 SAVE_PC;
1010 {
1011 jint index = POPI();
1012 jobjectArray arr = (jobjectArray) POPA();
1013 NULLCHECK (arr);
1014 if (index < 0 || index >= arr->length)
1015 {
1016 _Jv_ThrowBadArrayIndex (index);
1017 }
1018 PUSHA( elements(arr)[index] );
1019 }
1020 NEXT_INSN;
1021
1022 insn_baload:
1023 SAVE_PC;
1024 {
1025 jint index = POPI();
1026 jbyteArray arr = (jbyteArray) POPA();
1027 NULLCHECK (arr);
1028 if (index < 0 || index >= arr->length)
1029 {
1030 _Jv_ThrowBadArrayIndex (index);
1031 }
1032 PUSHI( elements(arr)[index] );
1033 }
1034 NEXT_INSN;
1035
1036 insn_caload:
1037 SAVE_PC;
1038 {
1039 jint index = POPI();
1040 jcharArray arr = (jcharArray) POPA();
1041 NULLCHECK (arr);
1042 if (index < 0 || index >= arr->length)
1043 {
1044 _Jv_ThrowBadArrayIndex (index);
1045 }
1046 PUSHI( elements(arr)[index] );
1047 }
1048 NEXT_INSN;
1049
1050 insn_saload:
1051 SAVE_PC;
1052 {
1053 jint index = POPI();
1054 jshortArray arr = (jshortArray) POPA();
1055 NULLCHECK (arr);
1056 if (index < 0 || index >= arr->length)
1057 {
1058 _Jv_ThrowBadArrayIndex (index);
1059 }
1060 PUSHI( elements(arr)[index] );
1061 }
1062 NEXT_INSN;
1063
1064 insn_istore:
1065 STOREI (get1u (pc++));
1066 NEXT_INSN;
1067
1068 insn_lstore:
1069 STOREL (get1u (pc++));
1070 NEXT_INSN;
1071
1072 insn_fstore:
1073 STOREF (get1u (pc++));
1074 NEXT_INSN;
1075
1076 insn_dstore:
1077 STORED (get1u (pc++));
1078 NEXT_INSN;
1079
1080 insn_astore:
1081 STOREA (get1u (pc++));
1082 NEXT_INSN;
1083
1084 insn_istore_0:
1085 STOREI (0);
1086 NEXT_INSN;
1087
1088 insn_istore_1:
1089 STOREI (1);
1090 NEXT_INSN;
1091
1092 insn_istore_2:
1093 STOREI (2);
1094 NEXT_INSN;
1095
1096 insn_istore_3:
1097 STOREI (3);
1098 NEXT_INSN;
1099
1100 insn_lstore_0:
1101 STOREL (0);
1102 NEXT_INSN;
1103
1104 insn_lstore_1:
1105 STOREL (1);
1106 NEXT_INSN;
1107
1108 insn_lstore_2:
1109 STOREL (2);
1110 NEXT_INSN;
1111
1112 insn_lstore_3:
1113 STOREL (3);
1114 NEXT_INSN;
1115
1116 insn_fstore_0:
1117 STOREF (0);
1118 NEXT_INSN;
1119
1120 insn_fstore_1:
1121 STOREF (1);
1122 NEXT_INSN;
1123
1124 insn_fstore_2:
1125 STOREF (2);
1126 NEXT_INSN;
1127
1128 insn_fstore_3:
1129 STOREF (3);
1130 NEXT_INSN;
1131
1132 insn_dstore_0:
1133 STORED (0);
1134 NEXT_INSN;
1135
1136 insn_dstore_1:
1137 STORED (1);
1138 NEXT_INSN;
1139
1140 insn_dstore_2:
1141 STORED (2);
1142 NEXT_INSN;
1143
1144 insn_dstore_3:
1145 STORED (3);
1146 NEXT_INSN;
1147
1148 insn_astore_0:
1149 STOREA(0);
1150 NEXT_INSN;
1151
1152 insn_astore_1:
1153 STOREA(1);
1154 NEXT_INSN;
1155
1156 insn_astore_2:
1157 STOREA(2);
1158 NEXT_INSN;
1159
1160 insn_astore_3:
1161 STOREA(3);
1162 NEXT_INSN;
1163
1164 insn_iastore:
1165 SAVE_PC;
1166 {
1167 jint value = POPI();
1168 jint index = POPI();
1169 jintArray arr = (jintArray) POPA();
1170 NULLCHECK (arr);
1171 if (index < 0 || index >= arr->length)
1172 {
1173 _Jv_ThrowBadArrayIndex (index);
1174 }
1175 elements(arr)[index] = value;
1176 }
1177 NEXT_INSN;
1178
1179 insn_lastore:
1180 SAVE_PC;
1181 {
1182 jlong value = POPL();
1183 jint index = POPI();
1184 jlongArray arr = (jlongArray) POPA();
1185 NULLCHECK (arr);
1186 if (index < 0 || index >= arr->length)
1187 {
1188 _Jv_ThrowBadArrayIndex (index);
1189 }
1190 elements(arr)[index] = value;
1191 }
1192 NEXT_INSN;
1193
1194 insn_fastore:
1195 SAVE_PC;
1196 {
1197 jfloat value = POPF();
1198 jint index = POPI();
1199 jfloatArray arr = (jfloatArray) POPA();
1200 NULLCHECK (arr);
1201 if (index < 0 || index >= arr->length)
1202 {
1203 _Jv_ThrowBadArrayIndex (index);
1204 }
1205 elements(arr)[index] = value;
1206 }
1207 NEXT_INSN;
1208
1209 insn_dastore:
1210 SAVE_PC;
1211 {
1212 jdouble value = POPD();
1213 jint index = POPI();
1214 jdoubleArray arr = (jdoubleArray) POPA();
1215 NULLCHECK (arr);
1216 if (index < 0 || index >= arr->length)
1217 {
1218 _Jv_ThrowBadArrayIndex (index);
1219 }
1220 elements(arr)[index] = value;
1221 }
1222 NEXT_INSN;
1223
1224 insn_aastore:
1225 SAVE_PC;
1226 {
1227 jobject value = POPA();
1228 jint index = POPI();
1229 jobjectArray arr = (jobjectArray) POPA();
1230 NULLCHECK (arr);
1231 if (index < 0 || index >= arr->length)
1232 {
1233 _Jv_ThrowBadArrayIndex (index);
1234 }
1235 _Jv_CheckArrayStore (arr, value);
1236 elements(arr)[index] = value;
1237 }
1238 NEXT_INSN;
1239
1240 insn_bastore:
1241 SAVE_PC;
1242 {
1243 jbyte value = (jbyte) POPI();
1244 jint index = POPI();
1245 jbyteArray arr = (jbyteArray) POPA();
1246 NULLCHECK (arr);
1247 if (index < 0 || index >= arr->length)
1248 {
1249 _Jv_ThrowBadArrayIndex (index);
1250 }
1251 elements(arr)[index] = value;
1252 }
1253 NEXT_INSN;
1254
1255 insn_castore:
1256 SAVE_PC;
1257 {
1258 jchar value = (jchar) POPI();
1259 jint index = POPI();
1260 jcharArray arr = (jcharArray) POPA();
1261 NULLCHECK (arr);
1262 if (index < 0 || index >= arr->length)
1263 {
1264 _Jv_ThrowBadArrayIndex (index);
1265 }
1266 elements(arr)[index] = value;
1267 }
1268 NEXT_INSN;
1269
1270 insn_sastore:
1271 SAVE_PC;
1272 {
1273 jshort value = (jshort) POPI();
1274 jint index = POPI();
1275 jshortArray arr = (jshortArray) POPA();
1276 NULLCHECK (arr);
1277 if (index < 0 || index >= arr->length)
1278 {
1279 _Jv_ThrowBadArrayIndex (index);
1280 }
1281 elements(arr)[index] = value;
1282 }
1283 NEXT_INSN;
1284
1285 insn_pop:
1286 sp -= 1;
1287 NEXT_INSN;
1288
1289 insn_pop2:
1290 sp -= 2;
1291 NEXT_INSN;
1292
1293 insn_dup:
1294 sp[0] = sp[-1];
1295 sp += 1;
1296 NEXT_INSN;
1297
1298 insn_dup_x1:
1299 dupx (sp, 1, 1); sp+=1;
1300 NEXT_INSN;
1301
1302 insn_dup_x2:
1303 dupx (sp, 1, 2); sp+=1;
1304 NEXT_INSN;
1305
1306 insn_dup2:
1307 sp[0] = sp[-2];
1308 sp[1] = sp[-1];
1309 sp += 2;
1310 NEXT_INSN;
1311
1312 insn_dup2_x1:
1313 dupx (sp, 2, 1); sp+=2;
1314 NEXT_INSN;
1315
1316 insn_dup2_x2:
1317 dupx (sp, 2, 2); sp+=2;
1318 NEXT_INSN;
1319
1320 insn_swap:
1321 {
1322 jobject tmp1 = POPA();
1323 jobject tmp2 = POPA();
1324 PUSHA (tmp1);
1325 PUSHA (tmp2);
1326 }
1327 NEXT_INSN;
1328
1329 insn_iadd:
1330 BINOPI(+);
1331 NEXT_INSN;
1332
1333 insn_ladd:
1334 BINOPL(+);
1335 NEXT_INSN;
1336
1337 insn_fadd:
1338 BINOPF(+);
1339 NEXT_INSN;
1340
1341 insn_dadd:
1342 BINOPD(+);
1343 NEXT_INSN;
1344
1345 insn_isub:
1346 BINOPI(-);
1347 NEXT_INSN;
1348
1349 insn_lsub:
1350 BINOPL(-);
1351 NEXT_INSN;
1352
1353 insn_fsub:
1354 BINOPF(-);
1355 NEXT_INSN;
1356
1357 insn_dsub:
1358 BINOPD(-);
1359 NEXT_INSN;
1360
1361 insn_imul:
1362 BINOPI(*);
1363 NEXT_INSN;
1364
1365 insn_lmul:
1366 BINOPL(*);
1367 NEXT_INSN;
1368
1369 insn_fmul:
1370 BINOPF(*);
1371 NEXT_INSN;
1372
1373 insn_dmul:
1374 BINOPD(*);
1375 NEXT_INSN;
1376
1377 insn_idiv:
1378 SAVE_PC;
1379 {
1380 jint value2 = POPI();
1381 jint value1 = POPI();
1382 jint res = _Jv_divI (value1, value2);
1383 PUSHI (res);
1384 }
1385 NEXT_INSN;
1386
1387 insn_ldiv:
1388 SAVE_PC;
1389 {
1390 jlong value2 = POPL();
1391 jlong value1 = POPL();
1392 jlong res = _Jv_divJ (value1, value2);
1393 PUSHL (res);
1394 }
1395 NEXT_INSN;
1396
1397 insn_fdiv:
1398 SAVE_PC;
1399 {
1400 jfloat value2 = POPF();
1401 jfloat value1 = POPF();
1402 jfloat res = value1 / value2;
1403 PUSHF (res);
1404 }
1405 NEXT_INSN;
1406
1407 insn_ddiv:
1408 SAVE_PC;
1409 {
1410 jdouble value2 = POPD();
1411 jdouble value1 = POPD();
1412 jdouble res = value1 / value2;
1413 PUSHD (res);
1414 }
1415 NEXT_INSN;
1416
1417 insn_irem:
1418 SAVE_PC;
1419 {
1420 jint value2 = POPI();
1421 jint value1 = POPI();
1422 jint res = _Jv_remI (value1, value2);
1423 PUSHI (res);
1424 }
1425 NEXT_INSN;
1426
1427 insn_lrem:
1428 SAVE_PC;
1429 {
1430 jlong value2 = POPL();
1431 jlong value1 = POPL();
1432 jlong res = _Jv_remJ (value1, value2);
1433 PUSHL (res);
1434 }
1435 NEXT_INSN;
1436
1437 insn_frem:
1438 SAVE_PC;
1439 {
1440 jfloat value2 = POPF();
1441 jfloat value1 = POPF();
1442 jfloat res = __ieee754_fmod (value1, value2);
1443 PUSHF (res);
1444 }
1445 NEXT_INSN;
1446
1447 insn_drem:
1448 SAVE_PC;
1449 {
1450 jdouble value2 = POPD();
1451 jdouble value1 = POPD();
1452 jdouble res = __ieee754_fmod (value1, value2);
1453 PUSHD (res);
1454 }
1455 NEXT_INSN;
1456
1457 insn_ineg:
1458 {
1459 jint value = POPI();
1460 PUSHI (value * -1);
1461 }
1462 NEXT_INSN;
1463
1464 insn_lneg:
1465 {
1466 jlong value = POPL();
1467 PUSHL (value * -1);
1468 }
1469 NEXT_INSN;
1470
1471 insn_fneg:
1472 {
1473 jfloat value = POPF();
1474 PUSHF (value * -1);
1475 }
1476 NEXT_INSN;
1477
1478 insn_dneg:
1479 {
1480 jdouble value = POPD();
1481 PUSHD (value * -1);
1482 }
1483 NEXT_INSN;
1484
1485 insn_ishl:
1486 {
1487 jint shift = (POPI() & 0x1f);
1488 jint value = POPI();
1489 PUSHI (value << shift);
1490 }
1491 NEXT_INSN;
1492
1493 insn_lshl:
1494 {
1495 jint shift = (POPI() & 0x3f);
1496 jlong value = POPL();
1497 PUSHL (value << shift);
1498 }
1499 NEXT_INSN;
1500
1501 insn_ishr:
1502 {
1503 jint shift = (POPI() & 0x1f);
1504 jint value = POPI();
1505 PUSHI (value >> shift);
1506 }
1507 NEXT_INSN;
1508
1509 insn_lshr:
1510 {
1511 jint shift = (POPI() & 0x3f);
1512 jlong value = POPL();
1513 PUSHL (value >> shift);
1514 }
1515 NEXT_INSN;
1516
1517 insn_iushr:
1518 {
1519 jint shift = (POPI() & 0x1f);
1520 unsigned long value = POPI();
1521 PUSHI ((jint) (value >> shift));
1522 }
1523 NEXT_INSN;
1524
1525 insn_lushr:
1526 {
1527 jint shift = (POPI() & 0x3f);
1528 UINT64 value = (UINT64) POPL();
1529 PUSHL ((value >> shift));
1530 }
1531 NEXT_INSN;
1532
1533 insn_iand:
1534 BINOPI (&);
1535 NEXT_INSN;
1536
1537 insn_land:
1538 BINOPL (&);
1539 NEXT_INSN;
1540
1541 insn_ior:
1542 BINOPI (|);
1543 NEXT_INSN;
1544
1545 insn_lor:
1546 BINOPL (|);
1547 NEXT_INSN;
1548
1549 insn_ixor:
1550 BINOPI (^);
1551 NEXT_INSN;
1552
1553 insn_lxor:
1554 BINOPL (^);
1555 NEXT_INSN;
1556
1557 insn_iinc:
1558 {
1559 jint index = get1u (pc++);
1560 jint amount = get1s (pc++);
1561 locals[index].i += amount;
1562 }
1563 NEXT_INSN;
1564
1565 insn_i2l:
1566 {jlong value = POPI(); PUSHL (value);}
1567 NEXT_INSN;
1568
1569 insn_i2f:
1570 {jfloat value = POPI(); PUSHF (value);}
1571 NEXT_INSN;
1572
1573 insn_i2d:
1574 {jdouble value = POPI(); PUSHD (value);}
1575 NEXT_INSN;
1576
1577 insn_l2i:
1578 {jint value = POPL(); PUSHI (value);}
1579 NEXT_INSN;
1580
1581 insn_l2f:
1582 {jfloat value = POPL(); PUSHF (value);}
1583 NEXT_INSN;
1584
1585 insn_l2d:
1586 {jdouble value = POPL(); PUSHD (value);}
1587 NEXT_INSN;
1588
1589 insn_f2i:
1590 { jint value = (jint)POPF (); PUSHI(value); }
1591 NEXT_INSN;
1592
1593 insn_f2l:
1594 { jlong value = (jlong)POPF (); PUSHL(value); }
1595 NEXT_INSN;
1596
1597 insn_f2d:
1598 { jdouble value = POPF (); PUSHD(value); }
1599 NEXT_INSN;
1600
1601 insn_d2i:
1602 { jint value = (jint)POPD (); PUSHI(value); }
1603 NEXT_INSN;
1604
1605 insn_d2l:
1606 { jlong value = (jlong)POPD (); PUSHL(value); }
1607 NEXT_INSN;
1608
1609 insn_d2f:
1610 { jfloat value = POPD (); PUSHF(value); }
1611 NEXT_INSN;
1612
1613 insn_i2b:
1614 { jbyte value = POPI (); PUSHI(value); }
1615 NEXT_INSN;
1616
1617 insn_i2c:
1618 { jchar value = POPI (); PUSHI(value); }
1619 NEXT_INSN;
1620
1621 insn_i2s:
1622 { jshort value = POPI (); PUSHI(value); }
1623 NEXT_INSN;
1624
1625 insn_lcmp:
1626 {
1627 jlong value2 = POPL ();
1628 jlong value1 = POPL ();
1629 if (value1 > value2)
1630 { PUSHI (1); }
1631 else if (value1 == value2)
1632 { PUSHI (0); }
1633 else
1634 { PUSHI (-1); }
1635 }
1636 NEXT_INSN;
1637
1638 insn_fcmpl:
1639 insn_fcmpg:
1640 {
1641 jfloat value2 = POPF ();
1642 jfloat value1 = POPF ();
1643 if (value1 > value2)
1644 PUSHI (1);
1645 else if (value1 == value2)
1646 PUSHI (0);
1647 else if (value1 < value2)
1648 PUSHI (-1);
1649 else if ((*(pc-1)) == op_fcmpg)
1650 PUSHI (1);
1651 else
1652 PUSHI (-1);
1653 }
1654 NEXT_INSN;
1655
1656 insn_dcmpl:
1657 insn_dcmpg:
1658 {
1659 jdouble value2 = POPD ();
1660 jdouble value1 = POPD ();
1661 if (value1 > value2)
1662 PUSHI (1);
1663 else if (value1 == value2)
1664 PUSHI (0);
1665 else if (value1 < value2)
1666 PUSHI (-1);
1667 else if ((*(pc-1)) == op_dcmpg)
1668 PUSHI (1);
1669 else
1670 PUSHI (-1);
1671 }
1672 NEXT_INSN;
1673
1674 insn_ifeq:
1675 {
1676 jint offset = get2s (pc);
1677 if (POPI() == 0)
1678 pc = pc-1+offset;
1679 else
1680 pc = pc+2;
1681 }
1682 NEXT_INSN;
1683
1684 insn_ifne:
1685 {
1686 jint offset = get2s (pc);
1687 if (POPI() != 0)
1688 pc = pc-1+offset;
1689 else
1690 pc = pc+2;
1691 }
1692 NEXT_INSN;
1693
1694 insn_iflt:
1695 {
1696 jint offset = get2s (pc);
1697 if (POPI() < 0)
1698 pc = pc-1+offset;
1699 else
1700 pc = pc+2;
1701 }
1702 NEXT_INSN;
1703
1704 insn_ifge:
1705 {
1706 jint offset = get2s (pc);
1707 if (POPI() >= 0)
1708 pc = pc-1+offset;
1709 else
1710 pc = pc+2;
1711 }
1712 NEXT_INSN;
1713
1714 insn_ifgt:
1715 {
1716 jint offset = get2s (pc);
1717 if (POPI() > 0)
1718 pc = pc-1+offset;
1719 else
1720 pc = pc+2;
1721 }
1722 NEXT_INSN;
1723
1724 insn_ifle:
1725 {
1726 jint offset = get2s (pc);
1727 if (POPI() <= 0)
1728 pc = pc-1+offset;
1729 else
1730 pc = pc+2;
1731 }
1732 NEXT_INSN;
1733
1734 insn_if_icmpeq:
1735 {
1736 jint offset = get2s (pc);
1737 jint value2 = POPI();
1738 jint value1 = POPI();
1739 if (value1 == value2)
1740 pc = pc-1+offset;
1741 else
1742 pc = pc+2;
1743 }
1744 NEXT_INSN;
1745
1746 insn_if_icmpne:
1747 {
1748 jint offset = get2s (pc);
1749 jint value2 = POPI();
1750 jint value1 = POPI();
1751 if (value1 != value2)
1752 pc = pc-1+offset;
1753 else
1754 pc = pc+2;
1755 }
1756 NEXT_INSN;
1757
1758 insn_if_icmplt:
1759 {
1760 jint offset = get2s (pc);
1761 jint value2 = POPI();
1762 jint value1 = POPI();
1763 if (value1 < value2)
1764 pc = pc-1+offset;
1765 else
1766 pc = pc+2;
1767 }
1768 NEXT_INSN;
1769
1770 insn_if_icmpge:
1771 {
1772 jint offset = get2s (pc);
1773 jint value2 = POPI();
1774 jint value1 = POPI();
1775 if (value1 >= value2)
1776 pc = pc-1+offset;
1777 else
1778 pc = pc+2;
1779 }
1780 NEXT_INSN;
1781
1782 insn_if_icmpgt:
1783 {
1784 jint offset = get2s (pc);
1785 jint value2 = POPI();
1786 jint value1 = POPI();
1787 if (value1 > value2)
1788 pc = pc-1+offset;
1789 else
1790 pc = pc+2;
1791 }
1792 NEXT_INSN;
1793
1794 insn_if_icmple:
1795 {
1796 jint offset = get2s (pc);
1797 jint value2 = POPI();
1798 jint value1 = POPI();
1799 if (value1 <= value2)
1800 pc = pc-1+offset;
1801 else
1802 pc = pc+2;
1803 }
1804 NEXT_INSN;
1805
1806 insn_if_acmpeq:
1807 {
1808 jint offset = get2s (pc);
1809 jobject value2 = POPA();
1810 jobject value1 = POPA();
1811 if (value1 == value2)
1812 pc = pc-1+offset;
1813 else
1814 pc = pc+2;
1815 }
1816 NEXT_INSN;
1817
1818 insn_if_acmpne:
1819 {
1820 jint offset = get2s (pc);
1821 jobject value2 = POPA();
1822 jobject value1 = POPA();
1823 if (value1 != value2)
1824 pc = pc-1+offset;
1825 else
1826 pc = pc+2;
1827 }
1828 NEXT_INSN;
1829
1830 insn_goto:
1831 {
1832 jint offset = get2s (pc);
1833 pc = pc-1+offset;
1834 }
1835 NEXT_INSN;
1836
1837 insn_jsr:
1838 {
1839 unsigned char *base_pc = pc-1;
1840 jint offset = get2s (pc); pc += 2;
1841 PUSHA ((jobject)pc);
1842 pc = base_pc+offset;
1843 }
1844 NEXT_INSN;
1845
1846 insn_ret:
1847 {
1848 jint index = get1u (pc);
1849 pc = (unsigned char*) PEEKA (index);
1850 }
1851 NEXT_INSN;
1852
1853 insn_tableswitch:
1854 {
1855 unsigned char *base_pc = pc-1;
1856 int index = POPI();
1857
1858 unsigned char* base = bytecode ();
1859 while ((pc-base) % 4 != 0)
1860 pc++;
1861
1862 jint def = get4 (pc);
1863 jint low = get4 (pc+4);
1864 jint high = get4 (pc+8);
1865
1866 if (index < low || index > high)
1867 pc = base_pc + def;
1868 else
1869 pc = base_pc + get4 (pc+4*(index-low+3));
1870 }
1871 NEXT_INSN;
1872
1873 insn_lookupswitch:
1874 {
1875 unsigned char *base_pc = pc-1;
1876 int index = POPI();
1877
1878 unsigned char* base = bytecode ();
1879 while ((pc-base) % 4 != 0)
1880 pc++;
1881
1882 jint def = get4 (pc);
1883 jint npairs = get4 (pc+4);
1884
1885 int max = npairs-1;
1886 int min = 0;
1887
1888 // simple binary search...
1889 while (min < max)
1890 {
1891 int half = (min+max)/2;
1892 int match = get4 (pc+ 4*(2 + 2*half));
1893
1894 if (index == match)
1895 min = max = half;
1896
1897 else if (index < match)
1898 max = half-1;
1899
1900 else
1901 min = half+1;
1902 }
1903
1904 if (index == get4 (pc+ 4*(2 + 2*min)))
1905 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1906 else
1907 pc = base_pc + def;
1908 }
1909 NEXT_INSN;
1910
1911 /* on return, just save the sp and return to caller */
1912 insn_ireturn:
1913 insn_lreturn:
1914 insn_freturn:
1915 insn_dreturn:
1916 insn_areturn:
1917 insn_return:
1918 inv->sp = sp;
1919 return;
1920
1921 insn_getstatic:
1922 SAVE_PC;
1923 {
1924 jint fieldref_index = get2u (pc); pc += 2;
1925 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1926 _Jv_Field *field = pool_data[fieldref_index].field;
1927
1928 if ((field->flags & Modifier::STATIC) == 0)
1929 throw_incompatible_class_change_error
1930 (JvNewStringLatin1 ("field no longer static"));
1931
1932 jclass type = field->type;
1933
1934 if (type->isPrimitive ())
1935 {
1936 switch (type->size_in_bytes)
1937 {
1938 case 1:
1939 PUSHI (*(jbyte*) (field->u.addr));
1940
1941 case 2:
1942 if (type == JvPrimClass (char))
1943 PUSHI(*(jchar*) (field->u.addr));
1944 else
1945 PUSHI(*(jshort*) (field->u.addr));
1946 break;
1947
1948 case 4:
1949 PUSHI(*(jint*) (field->u.addr));
1950 break;
1951
1952 case 8:
1953 PUSHL(*(jlong*) (field->u.addr));
1954 break;
1955 }
1956 }
1957 else
1958 {
1959 PUSHA(*(jobject*) (field->u.addr));
1960 }
1961 }
1962 NEXT_INSN;
1963
1964 insn_getfield:
1965 SAVE_PC;
1966 {
1967 jint fieldref_index = get2u (pc); pc += 2;
1968 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1969 _Jv_Field *field = pool_data[fieldref_index].field;
1970
1971 if ((field->flags & Modifier::STATIC) != 0)
1972 throw_incompatible_class_change_error
1973 (JvNewStringLatin1 ("field is static"));
1974
1975 jclass type = field->type;
1976 jint field_offset = field->u.boffset;
1977 if (field_offset > 0xffff)
1978 JvThrow (new java::lang::VirtualMachineError);
1979
1980 jobject obj = POPA();
1981 NULLCHECK(obj);
1982
1983 if (type->isPrimitive ())
1984 {
1985 switch (type->size_in_bytes)
1986 {
1987 case 1:
1988 PUSHI (*(jbyte*) ((char*)obj + field_offset));
1989 break;
1990
1991 case 2:
1992 if (type == JvPrimClass (char))
1993 PUSHI (*(jchar*) ((char*)obj + field_offset));
1994 else
1995 PUSHI (*(jshort*) ((char*)obj + field_offset));
1996 break;
1997
1998 case 4:
1999 PUSHI (*(jint*) ((char*)obj + field_offset));
2000 break;
2001
2002 case 8:
2003 PUSHL(*(jlong*) ((char*)obj + field_offset));
2004 break;
2005 }
2006 }
2007 else
2008 {
2009 PUSHA(*(jobject*) ((char*)obj + field_offset));
2010 }
2011 }
2012 NEXT_INSN;
2013
2014 insn_putstatic:
2015 SAVE_PC;
2016 {
2017 jint fieldref_index = get2u (pc); pc += 2;
2018 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2019 _Jv_Field *field = pool_data[fieldref_index].field;
2020
2021 jclass type = field->type;
2022
2023 // ResolvePoolEntry cannot check this
2024 if ((field->flags & Modifier::STATIC) == 0)
2025 throw_incompatible_class_change_error
2026 (JvNewStringLatin1 ("field no longer static"));
2027
2028 if (type->isPrimitive ())
2029 {
2030 switch (type->size_in_bytes)
2031 {
2032 case 1:
2033 {
2034 jint value = POPI();
2035 *(jbyte*) (field->u.addr) = value;
2036 break;
2037 }
2038
2039 case 2:
2040 {
2041 jint value = POPI();
2042 *(jchar*) (field->u.addr) = value;
2043 break;
2044 }
2045
2046 case 4:
2047 {
2048 jint value = POPI();
2049 *(jint*) (field->u.addr) = value;
2050 break;
2051 }
2052
2053 case 8:
2054 {
2055 jlong value = POPL();
2056 *(jlong*) (field->u.addr) = value;
2057 break;
2058 }
2059 }
2060 }
2061 else
2062 {
2063 jobject value = POPA();
2064 *(jobject*) (field->u.addr) = value;
2065 }
2066 }
2067 NEXT_INSN;
2068
2069
2070 insn_putfield:
2071 SAVE_PC;
2072 {
2073 jint fieldref_index = get2u (pc); pc += 2;
2074 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2075 _Jv_Field *field = pool_data[fieldref_index].field;
2076
2077 jclass type = field->type;
2078
2079 if ((field->flags & Modifier::STATIC) != 0)
2080 throw_incompatible_class_change_error
2081 (JvNewStringLatin1 ("field is static"));
2082
2083 jint field_offset = field->u.boffset;
2084 if (field_offset > 0xffff)
2085 JvThrow (new java::lang::VirtualMachineError);
2086
2087 if (type->isPrimitive ())
2088 {
2089 switch (type->size_in_bytes)
2090 {
2091 case 1:
2092 {
2093 jint value = POPI();
2094 jobject obj = POPA();
2095 NULLCHECK(obj);
2096 *(jbyte*) ((char*)obj + field_offset) = value;
2097 break;
2098 }
2099
2100 case 2:
2101 {
2102 jint value = POPI();
2103 jobject obj = POPA();
2104 NULLCHECK(obj);
2105 *(jchar*) ((char*)obj + field_offset) = value;
2106 break;
2107 }
2108
2109 case 4:
2110 {
2111 jint value = POPI();
2112 jobject obj = POPA();
2113 NULLCHECK(obj);
2114 *(jint*) ((char*)obj + field_offset) = value;
2115 break;
2116 }
2117
2118 case 8:
2119 {
2120 jlong value = POPL();
2121 jobject obj = POPA();
2122 NULLCHECK(obj);
2123 *(jlong*) ((char*)obj + field_offset) = value;
2124 break;
2125 }
2126 }
2127 }
2128 else
2129 {
2130 jobject value = POPA();
2131 jobject obj = POPA();
2132 NULLCHECK(obj);
2133 *(jobject*) ((char*)obj + field_offset) = value;
2134 }
2135 }
2136 NEXT_INSN;
2137
2138 insn_invokespecial:
2139 SAVE_PC;
2140 {
2141 int index = get2u (pc); pc += 2;
2142
2143 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2144
2145 sp -= rmeth->stack_item_count;
2146
2147 NULLCHECK(sp[0]);
2148
2149 fun = (void (*) (...))rmeth->method->ncode;
2150 }
2151 goto perform_invoke;
2152
2153 insn_invokestatic:
2154 SAVE_PC;
2155 {
2156 int index = get2u (pc); pc += 2;
2157
2158 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2159
2160 sp -= rmeth->stack_item_count;
2161
2162 _Jv_InitClass (rmeth->klass);
2163 fun = (void (*) (...))rmeth->method->ncode;
2164 }
2165 goto perform_invoke;
2166
2167 insn_invokeinterface:
2168 SAVE_PC;
2169 {
2170 int index = get2u (pc); pc += 2;
2171
2172 // invokeinterface has two unused bytes...
2173 pc += 2;
2174
2175 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2176
2177 sp -= rmeth->stack_item_count;
2178 NULLCHECK(sp[0]);
2179
2180 jobject rcv = sp[0].o;
2181
2182 fun = (void (*) (...))
2183 _Jv_LookupInterfaceMethod (rcv->getClass (),
2184 rmeth->method->name,
2185 rmeth->method->signature);
2186 }
2187 goto perform_invoke;
2188
2189
2190 insn_new:
2191 SAVE_PC;
2192 {
2193 int index = get2u (pc); pc += 2;
2194 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2195 _Jv_InitClass (klass);
2196 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2197 PUSHA (res);
2198 }
2199 NEXT_INSN;
2200
2201 insn_newarray:
2202 SAVE_PC;
2203 {
2204 int atype = get1u (pc++);
2205 int size = POPI();
2206 jobject result = _Jv_NewArray (atype, size);
2207 PUSHA (result);
2208 }
2209 NEXT_INSN;
2210
2211 insn_anewarray:
2212 SAVE_PC;
2213 {
2214 int index = get2u (pc); pc += 2;
2215 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2216 int size = POPI();
2217 _Jv_InitClass (klass);
2218 jobject result = _Jv_NewObjectArray (size, klass, 0);
2219 PUSHA (result);
2220 }
2221 NEXT_INSN;
2222
2223 insn_arraylength:
2224 SAVE_PC;
2225 {
2226 __JArray *arr = (__JArray*)POPA();
2227 PUSHI (arr->length);
2228 }
2229 NEXT_INSN;
2230
2231 insn_athrow:
2232 SAVE_PC;
2233 {
2234 jobject value = POPA();
2235 JvThrow (value);
2236 }
2237 NEXT_INSN;
2238
2239 insn_checkcast:
2240 SAVE_PC;
2241 {
2242 jobject value = POPA();
2243 jint index = get2u (pc); pc += 2;
2244 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2245
2246 if (value != NULL && ! to->isInstance (value))
2247 {
2248 JvThrow (new java::lang::ClassCastException
2249 (to->getName()));
2250 }
2251
2252 PUSHA (value);
2253 }
2254 NEXT_INSN;
2255
2256 insn_instanceof:
2257 SAVE_PC;
2258 {
2259 jobject value = POPA();
2260 jint index = get2u (pc); pc += 2;
2261 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2262 PUSHI (to->isInstance (value));
2263 }
2264 NEXT_INSN;
2265
2266 insn_monitorenter:
2267 SAVE_PC;
2268 {
2269 jobject value = POPA();
2270 NULLCHECK(value);
2271 _Jv_MonitorEnter (value);
2272 }
2273 NEXT_INSN;
2274
2275 insn_monitorexit:
2276 SAVE_PC;
2277 {
2278 jobject value = POPA();
2279 NULLCHECK(value);
2280 _Jv_MonitorExit (value);
2281 }
2282 NEXT_INSN;
2283
2284 insn_ifnull:
2285 {
2286 unsigned char* base_pc = pc-1;
2287 jint offset = get2s (pc); pc += 2;
2288 jobject val = POPA();
2289 if (val == NULL)
2290 pc = base_pc+offset;
2291 }
2292 NEXT_INSN;
2293
2294 insn_ifnonnull:
2295 {
2296 unsigned char* base_pc = pc-1;
2297 jint offset = get2s (pc); pc += 2;
2298 jobject val = POPA();
2299 if (val != NULL)
2300 pc = base_pc+offset;
2301 }
2302 NEXT_INSN;
2303
2304 insn_wide:
2305 SAVE_PC;
2306 {
2307 jint the_mod_op = get1u (pc++);
2308 jint wide = get2u (pc); pc += 2;
2309
2310 switch (the_mod_op)
2311 {
2312 case op_istore:
2313 STOREI (wide);
2314 NEXT_INSN;
2315
2316 case op_fstore:
2317 STOREF (wide);
2318 NEXT_INSN;
2319
2320 case op_astore:
2321 STOREA (wide);
2322 NEXT_INSN;
2323
2324 case op_lload:
2325 LOADL (wide);
2326 NEXT_INSN;
2327
2328 case op_dload:
2329 LOADD (wide);
2330 NEXT_INSN;
2331
2332 case op_iload:
2333 LOADI (wide);
2334 NEXT_INSN;
2335
2336 case op_aload:
2337 LOADA (wide);
2338 NEXT_INSN;
2339
2340 case op_lstore:
2341 STOREL (wide);
2342 NEXT_INSN;
2343
2344 case op_dstore:
2345 STORED (wide);
2346 NEXT_INSN;
2347
2348 case op_ret:
2349 pc = (unsigned char*) PEEKA (wide);
2350 NEXT_INSN;
2351
2352 case op_iinc:
2353 {
2354 jint amount = get2s (pc); pc += 2;
2355 jint value = PEEKI (wide);
2356 POKEI (wide, value+amount);
2357 }
2358 NEXT_INSN;
2359
2360 default:
2361 throw_internal_error ("illegal bytecode modified by wide");
2362 }
2363
2364 }
2365
2366 insn_multianewarray:
2367 SAVE_PC;
2368 {
2369 int kind_index = get2u (pc); pc += 2;
2370 int dim = get1u (pc); pc += 1;
2371
2372 jclass type
2373 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2374 _Jv_InitClass (type);
2375 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2376
2377 for (int i = dim - 1; i >= 0; i--)
2378 {
2379 sizes[i] = POPI ();
2380 }
2381
2382 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2383
2384 PUSHA (res);
2385 }
2386 NEXT_INSN;
2387
2388 insn_goto_w:
2389 {
2390 unsigned char* base_pc = pc-1;
2391 int offset = get4 (pc); pc += 4;
2392 pc = base_pc+offset;
2393 }
2394 NEXT_INSN;
2395
2396 insn_jsr_w:
2397 {
2398 unsigned char* base_pc = pc-1;
2399 int offset = get4 (pc); pc += 4;
2400 PUSHA((jobject)pc);
2401 pc = base_pc+offset;
2402 }
2403 NEXT_INSN;
2404 }
2405
2406
2407 static void
2408 throw_internal_error (char *msg)
2409 {
2410 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2411 }
2412
2413 static void
2414 throw_incompatible_class_change_error (jstring msg)
2415 {
2416 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2417 }
2418
2419 #ifndef HANDLE_SEGV
2420 static java::lang::NullPointerException *null_pointer_exc;
2421 static void
2422 throw_null_pointer_exception ()
2423 {
2424 if (null_pointer_exc == NULL)
2425 null_pointer_exc = new java::lang::NullPointerException;
2426
2427 JvThrow (null_pointer_exc);
2428 }
2429 #endif
2430
2431 #endif // INTERPRETER