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