source: trunk/src/gcc/libjava/interpret.cc@ 1479

Last change on this file since 1479 was 1392, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 64.0 KB
Line 
1// interpret.cc - Code for the interpreter
2
3/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11/* Author: Kresten Krab Thorup <[email protected]> */
12
13#include <config.h>
14
15// Define this to get the direct-threaded interpreter. If undefined,
16// we revert to a basic bytecode interpreter. The former is faster
17// but uses more memory.
18#define DIRECT_THREADED
19
20#pragma implementation "java-interp.h"
21
22#include <jvm.h>
23#include <java-cpool.h>
24#include <java-interp.h>
25#include <java/lang/System.h>
26#include <java/lang/String.h>
27#include <java/lang/Integer.h>
28#include <java/lang/Long.h>
29#include <java/lang/StringBuffer.h>
30#include <java/lang/Class.h>
31#include <java/lang/reflect/Modifier.h>
32#include <java/lang/ClassCastException.h>
33#include <java/lang/VirtualMachineError.h>
34#include <java/lang/InternalError.h>
35#include <java/lang/NullPointerException.h>
36#include <java/lang/ArithmeticException.h>
37#include <java/lang/IncompatibleClassChangeError.h>
38#include <java/lang/Thread.h>
39#include <java-insns.h>
40#include <java-signal.h>
41
42#ifdef INTERPRETER
43
44#include <stdlib.h>
45
46using namespace gcj;
47
48static void throw_internal_error (char *msg)
49 __attribute__ ((__noreturn__));
50static void throw_incompatible_class_change_error (jstring msg)
51 __attribute__ ((__noreturn__));
52#ifndef HANDLE_SEGV
53static void throw_null_pointer_exception ()
54 __attribute__ ((__noreturn__));
55#endif
56
57extern "C" double __ieee754_fmod (double,double);
58
59// This represents a single slot in the "compiled" form of the
60// bytecode.
61union insn_slot
62{
63 // Address of code.
64 void *insn;
65 // An integer value used by an instruction.
66 jint int_val;
67 // A pointer value used by an instruction.
68 void *datum;
69};
70
71// The type of the PC depends on whether we're doing direct threading
72// or a more ordinary bytecode interpreter.
73#ifdef DIRECT_THREADED
74typedef insn_slot *pc_t;
75#else
76typedef unsigned char *pc_t;
77#endif
78
79static inline void dupx (_Jv_word *sp, int n, int x)
80{
81 // first "slide" n+x elements n to the right
82 int top = n-1;
83 for (int i = 0; i < n+x; i++)
84 {
85 sp[(top-i)] = sp[(top-i)-n];
86 }
87
88 // next, copy the n top elements, n+x down
89 for (int i = 0; i < n; i++)
90 {
91 sp[top-(n+x)-i] = sp[top-i];
92 }
93
94};
95
96// Used to convert from floating types to integral types.
97template<typename TO, typename FROM>
98static inline TO
99convert (FROM val, TO min, TO max)
100{
101 TO ret;
102 if (val >= (FROM) max)
103 ret = max;
104 else if (val <= (FROM) min)
105 ret = min;
106 else if (val != val)
107 ret = 0;
108 else
109 ret = (TO) val;
110 return ret;
111}
112
113#define PUSHA(V) (sp++)->o = (V)
114#define PUSHI(V) (sp++)->i = (V)
115#define PUSHF(V) (sp++)->f = (V)
116#if SIZEOF_VOID_P == 8
117# define PUSHL(V) (sp->l = (V), sp += 2)
118# define PUSHD(V) (sp->d = (V), sp += 2)
119#else
120# define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
121 (sp++)->ia[0] = w2.ia[0]; \
122 (sp++)->ia[0] = w2.ia[1]; } while (0)
123# define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
124 (sp++)->ia[0] = w2.ia[0]; \
125 (sp++)->ia[0] = w2.ia[1]; } while (0)
126#endif
127
128#define POPA() ((--sp)->o)
129#define POPI() ((jint) (--sp)->i) // cast since it may be promoted
130#define POPF() ((jfloat) (--sp)->f)
131#if SIZEOF_VOID_P == 8
132# define POPL() (sp -= 2, (jlong) sp->l)
133# define POPD() (sp -= 2, (jdouble) sp->d)
134#else
135# define POPL() ({ _Jv_word2 w2; \
136 w2.ia[1] = (--sp)->ia[0]; \
137 w2.ia[0] = (--sp)->ia[0]; w2.l; })
138# define POPD() ({ _Jv_word2 w2; \
139 w2.ia[1] = (--sp)->ia[0]; \
140 w2.ia[0] = (--sp)->ia[0]; w2.d; })
141#endif
142
143#define LOADA(I) (sp++)->o = locals[I].o
144#define LOADI(I) (sp++)->i = locals[I].i
145#define LOADF(I) (sp++)->f = locals[I].f
146#if SIZEOF_VOID_P == 8
147# define LOADL(I) (sp->l = locals[I].l, sp += 2)
148# define LOADD(I) (sp->d = locals[I].d, sp += 2)
149#else
150# define LOADL(I) do { jint __idx = (I); \
151 (sp++)->ia[0] = locals[__idx].ia[0]; \
152 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
153 } while (0)
154# define LOADD(I) LOADL(I)
155#endif
156
157#define STOREA(I) locals[I].o = (--sp)->o
158#define STOREI(I) locals[I].i = (--sp)->i
159#define STOREF(I) locals[I].f = (--sp)->f
160#if SIZEOF_VOID_P == 8
161# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
162# define STORED(I) (sp -= 2, locals[I].d = sp->d)
163#else
164# define STOREL(I) do { jint __idx = (I); \
165 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
166 locals[__idx].ia[0] = (--sp)->ia[0]; \
167 } while (0)
168# define STORED(I) STOREL(I)
169#endif
170
171#define PEEKI(I) (locals+(I))->i
172#define PEEKA(I) (locals+(I))->o
173
174#define POKEI(I,V) ((locals+(I))->i = (V))
175
176
177#define BINOPI(OP) { \
178 jint value2 = POPI(); \
179 jint value1 = POPI(); \
180 PUSHI(value1 OP value2); \
181}
182
183#define BINOPF(OP) { \
184 jfloat value2 = POPF(); \
185 jfloat value1 = POPF(); \
186 PUSHF(value1 OP value2); \
187}
188
189#define BINOPL(OP) { \
190 jlong value2 = POPL(); \
191 jlong value1 = POPL(); \
192 PUSHL(value1 OP value2); \
193}
194
195#define BINOPD(OP) { \
196 jdouble value2 = POPD(); \
197 jdouble value1 = POPD(); \
198 PUSHD(value1 OP value2); \
199}
200
201static inline jint get1s(unsigned char* loc) {
202 return *(signed char*)loc;
203}
204
205static inline jint get1u(unsigned char* loc) {
206 return *loc;
207}
208
209static inline jint get2s(unsigned char* loc) {
210 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
211}
212
213static inline jint get2u(unsigned char* loc) {
214 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
215}
216
217static jint get4(unsigned char* loc) {
218 return (((jint)(loc[0])) << 24)
219 | (((jint)(loc[1])) << 16)
220 | (((jint)(loc[2])) << 8)
221 | (((jint)(loc[3])) << 0);
222}
223
224
225#ifdef HANDLE_SEGV
226#define NULLCHECK(X)
227#define NULLARRAYCHECK(X)
228#else
229#define NULLCHECK(X) \
230 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
231#define NULLARRAYCHECK(X) \
232 do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
233#endif
234
235#define ARRAYBOUNDSCHECK(array, index) \
236 do \
237 { \
238 if (((unsigned) index) >= (unsigned) (array->length)) \
239 _Jv_ThrowBadArrayIndex (index); \
240 } \
241 while (0)
242
243void _Jv_InterpMethod::run_normal (ffi_cif *,
244 void* ret,
245 ffi_raw * args,
246 void* __this)
247{
248 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
249 _this->run (ret, args);
250}
251
252void _Jv_InterpMethod::run_synch_object (ffi_cif *,
253 void* ret,
254 ffi_raw * args,
255 void* __this)
256{
257 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
258
259 jobject rcv = (jobject) args[0].ptr;
260 JvSynchronize mutex (rcv);
261
262 _this->run (ret, args);
263}
264
265void _Jv_InterpMethod::run_synch_class (ffi_cif *,
266 void* ret,
267 ffi_raw * args,
268 void* __this)
269{
270 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
271
272 jclass sync = _this->defining_class;
273 JvSynchronize mutex (sync);
274
275 _this->run (ret, args);
276}
277
278#ifdef DIRECT_THREADED
279// "Compile" a method by turning it from bytecode to direct-threaded
280// code.
281void
282_Jv_InterpMethod::compile (const void * const *insn_targets)
283{
284 insn_slot *insns = NULL;
285 int next = 0;
286 unsigned char *codestart = bytecode ();
287 unsigned char *end = codestart + code_length;
288 _Jv_word *pool_data = defining_class->constants.data;
289
290#define SET_ONE(Field, Value) \
291 do \
292 { \
293 if (first_pass) \
294 ++next; \
295 else \
296 insns[next++].Field = Value; \
297 } \
298 while (0)
299
300#define SET_INSN(Value) SET_ONE (insn, (void *) Value)
301#define SET_INT(Value) SET_ONE (int_val, Value)
302#define SET_DATUM(Value) SET_ONE (datum, Value)
303
304 // Map from bytecode PC to slot in INSNS.
305 int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
306 for (int i = 0; i < code_length; ++i)
307 pc_mapping[i] = -1;
308
309 for (int i = 0; i < 2; ++i)
310 {
311 jboolean first_pass = i == 0;
312
313 if (! first_pass)
314 {
315 insns = (insn_slot *) _Jv_AllocBytes (sizeof (insn_slot) * next);
316 next = 0;
317 }
318
319 unsigned char *pc = codestart;
320 while (pc < end)
321 {
322 int base_pc_val = pc - codestart;
323 if (first_pass)
324 pc_mapping[base_pc_val] = next;
325
326 java_opcode opcode = (java_opcode) *pc++;
327 // Just elide NOPs.
328 if (opcode == op_nop)
329 continue;
330 SET_INSN (insn_targets[opcode]);
331
332 switch (opcode)
333 {
334 case op_nop:
335 case op_aconst_null:
336 case op_iconst_m1:
337 case op_iconst_0:
338 case op_iconst_1:
339 case op_iconst_2:
340 case op_iconst_3:
341 case op_iconst_4:
342 case op_iconst_5:
343 case op_lconst_0:
344 case op_lconst_1:
345 case op_fconst_0:
346 case op_fconst_1:
347 case op_fconst_2:
348 case op_dconst_0:
349 case op_dconst_1:
350 case op_iload_0:
351 case op_iload_1:
352 case op_iload_2:
353 case op_iload_3:
354 case op_lload_0:
355 case op_lload_1:
356 case op_lload_2:
357 case op_lload_3:
358 case op_fload_0:
359 case op_fload_1:
360 case op_fload_2:
361 case op_fload_3:
362 case op_dload_0:
363 case op_dload_1:
364 case op_dload_2:
365 case op_dload_3:
366 case op_aload_0:
367 case op_aload_1:
368 case op_aload_2:
369 case op_aload_3:
370 case op_iaload:
371 case op_laload:
372 case op_faload:
373 case op_daload:
374 case op_aaload:
375 case op_baload:
376 case op_caload:
377 case op_saload:
378 case op_istore_0:
379 case op_istore_1:
380 case op_istore_2:
381 case op_istore_3:
382 case op_lstore_0:
383 case op_lstore_1:
384 case op_lstore_2:
385 case op_lstore_3:
386 case op_fstore_0:
387 case op_fstore_1:
388 case op_fstore_2:
389 case op_fstore_3:
390 case op_dstore_0:
391 case op_dstore_1:
392 case op_dstore_2:
393 case op_dstore_3:
394 case op_astore_0:
395 case op_astore_1:
396 case op_astore_2:
397 case op_astore_3:
398 case op_iastore:
399 case op_lastore:
400 case op_fastore:
401 case op_dastore:
402 case op_aastore:
403 case op_bastore:
404 case op_castore:
405 case op_sastore:
406 case op_pop:
407 case op_pop2:
408 case op_dup:
409 case op_dup_x1:
410 case op_dup_x2:
411 case op_dup2:
412 case op_dup2_x1:
413 case op_dup2_x2:
414 case op_swap:
415 case op_iadd:
416 case op_isub:
417 case op_imul:
418 case op_idiv:
419 case op_irem:
420 case op_ishl:
421 case op_ishr:
422 case op_iushr:
423 case op_iand:
424 case op_ior:
425 case op_ixor:
426 case op_ladd:
427 case op_lsub:
428 case op_lmul:
429 case op_ldiv:
430 case op_lrem:
431 case op_lshl:
432 case op_lshr:
433 case op_lushr:
434 case op_land:
435 case op_lor:
436 case op_lxor:
437 case op_fadd:
438 case op_fsub:
439 case op_fmul:
440 case op_fdiv:
441 case op_frem:
442 case op_dadd:
443 case op_dsub:
444 case op_dmul:
445 case op_ddiv:
446 case op_drem:
447 case op_ineg:
448 case op_i2b:
449 case op_i2c:
450 case op_i2s:
451 case op_lneg:
452 case op_fneg:
453 case op_dneg:
454 case op_i2l:
455 case op_i2f:
456 case op_i2d:
457 case op_l2i:
458 case op_l2f:
459 case op_l2d:
460 case op_f2i:
461 case op_f2l:
462 case op_f2d:
463 case op_d2i:
464 case op_d2l:
465 case op_d2f:
466 case op_lcmp:
467 case op_fcmpl:
468 case op_fcmpg:
469 case op_dcmpl:
470 case op_dcmpg:
471 case op_monitorenter:
472 case op_monitorexit:
473 case op_ireturn:
474 case op_lreturn:
475 case op_freturn:
476 case op_dreturn:
477 case op_areturn:
478 case op_return:
479 case op_athrow:
480 case op_arraylength:
481 // No argument, nothing else to do.
482 break;
483
484 case op_bipush:
485 SET_INT (get1s (pc));
486 ++pc;
487 break;
488
489 case op_ldc:
490 {
491 int index = get1u (pc);
492 ++pc;
493 SET_DATUM (pool_data[index].o);
494 }
495 break;
496
497 case op_ret:
498 case op_iload:
499 case op_lload:
500 case op_fload:
501 case op_dload:
502 case op_aload:
503 case op_istore:
504 case op_lstore:
505 case op_fstore:
506 case op_dstore:
507 case op_astore:
508 case op_newarray:
509 SET_INT (get1u (pc));
510 ++pc;
511 break;
512
513 case op_iinc:
514 SET_INT (get1u (pc));
515 SET_INT (get1s (pc + 1));
516 pc += 2;
517 break;
518
519 case op_ldc_w:
520 {
521 int index = get2u (pc);
522 pc += 2;
523 SET_DATUM (pool_data[index].o);
524 }
525 break;
526
527 case op_ldc2_w:
528 {
529 int index = get2u (pc);
530 pc += 2;
531 SET_DATUM (&pool_data[index]);
532 }
533 break;
534
535 case op_sipush:
536 SET_INT (get2s (pc));
537 pc += 2;
538 break;
539
540 case op_new:
541 case op_getstatic:
542 case op_getfield:
543 case op_putfield:
544 case op_putstatic:
545 case op_anewarray:
546 case op_instanceof:
547 case op_checkcast:
548 case op_invokespecial:
549 case op_invokestatic:
550 case op_invokevirtual:
551 SET_INT (get2u (pc));
552 pc += 2;
553 break;
554
555 case op_multianewarray:
556 SET_INT (get2u (pc));
557 SET_INT (get1u (pc + 2));
558 pc += 3;
559 break;
560
561 case op_jsr:
562 case op_ifeq:
563 case op_ifne:
564 case op_iflt:
565 case op_ifge:
566 case op_ifgt:
567 case op_ifle:
568 case op_if_icmpeq:
569 case op_if_icmpne:
570 case op_if_icmplt:
571 case op_if_icmpge:
572 case op_if_icmpgt:
573 case op_if_icmple:
574 case op_if_acmpeq:
575 case op_if_acmpne:
576 case op_ifnull:
577 case op_ifnonnull:
578 case op_goto:
579 {
580 int offset = get2s (pc);
581 pc += 2;
582
583 int new_pc = base_pc_val + offset;
584
585 bool orig_was_goto = opcode == op_goto;
586
587 // Thread jumps. We limit the loop count; this lets
588 // us avoid infinite loops if the bytecode contains
589 // such. `10' is arbitrary.
590 int count = 10;
591 while (codestart[new_pc] == op_goto && count-- > 0)
592 new_pc += get2s (&codestart[new_pc + 1]);
593
594 // If the jump takes us to a `return' instruction and
595 // the original branch was an unconditional goto, then
596 // we hoist the return.
597 opcode = (java_opcode) codestart[new_pc];
598 if (orig_was_goto
599 && (opcode == op_ireturn || opcode == op_lreturn
600 || opcode == op_freturn || opcode == op_dreturn
601 || opcode == op_areturn || opcode == op_return))
602 {
603 --next;
604 SET_INSN (insn_targets[opcode]);
605 }
606 else
607 SET_DATUM (&insns[pc_mapping[new_pc]]);
608 }
609 break;
610
611 case op_tableswitch:
612 {
613 while ((pc - codestart) % 4 != 0)
614 ++pc;
615
616 jint def = get4 (pc);
617 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
618 pc += 4;
619
620 int low = get4 (pc);
621 SET_INT (low);
622 pc += 4;
623 int high = get4 (pc);
624 SET_INT (high);
625 pc += 4;
626
627 for (int i = low; i <= high; ++i)
628 {
629 SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
630 pc += 4;
631 }
632 }
633 break;
634
635 case op_lookupswitch:
636 {
637 while ((pc - codestart) % 4 != 0)
638 ++pc;
639
640 jint def = get4 (pc);
641 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
642 pc += 4;
643
644 jint npairs = get4 (pc);
645 pc += 4;
646 SET_INT (npairs);
647
648 while (npairs-- > 0)
649 {
650 jint match = get4 (pc);
651 jint offset = get4 (pc + 4);
652 SET_INT (match);
653 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
654 pc += 8;
655 }
656 }
657 break;
658
659 case op_invokeinterface:
660 {
661 jint index = get2u (pc);
662 pc += 2;
663 // We ignore the next two bytes.
664 pc += 2;
665 SET_INT (index);
666 }
667 break;
668
669 case op_wide:
670 {
671 opcode = (java_opcode) get1u (pc);
672 pc += 1;
673 jint val = get2u (pc);
674 pc += 2;
675
676 // We implement narrow and wide instructions using the
677 // same code in the interpreter. So we rewrite the
678 // instruction slot here.
679 if (! first_pass)
680 insns[next - 1].insn = (void *) insn_targets[opcode];
681 SET_INT (val);
682
683 if (opcode == op_iinc)
684 {
685 SET_INT (get2s (pc));
686 pc += 2;
687 }
688 }
689 break;
690
691 case op_jsr_w:
692 case op_goto_w:
693 {
694 jint offset = get4 (pc);
695 pc += 4;
696 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
697 }
698 break;
699
700 // Some "can't happen" cases that we include for
701 // error-checking purposes.
702 case op_putfield_1:
703 case op_putfield_2:
704 case op_putfield_4:
705 case op_putfield_8:
706 case op_putfield_a:
707 case op_putstatic_1:
708 case op_putstatic_2:
709 case op_putstatic_4:
710 case op_putstatic_8:
711 case op_putstatic_a:
712 case op_getfield_1:
713 case op_getfield_2s:
714 case op_getfield_2u:
715 case op_getfield_4:
716 case op_getfield_8:
717 case op_getfield_a:
718 case op_getstatic_1:
719 case op_getstatic_2s:
720 case op_getstatic_2u:
721 case op_getstatic_4:
722 case op_getstatic_8:
723 case op_getstatic_a:
724 default:
725 // Fail somehow.
726 break;
727 }
728 }
729 }
730
731 // Now update exceptions.
732 _Jv_InterpException *exc = exceptions ();
733 for (int i = 0; i < exc_count; ++i)
734 {
735 exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
736 exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
737 exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
738 jclass handler = (_Jv_ResolvePoolEntry (defining_class,
739 exc[i].handler_type.i)).clazz;
740 exc[i].handler_type.p = handler;
741 }
742
743 prepared = insns;
744}
745#endif /* DIRECT_THREADED */
746
747// This function exists so that the stack-tracing code can find the
748// boundaries of the interpreter.
749void
750_Jv_StartOfInterpreter (void)
751{
752}
753
754void
755_Jv_InterpMethod::run (void *retp, ffi_raw *args)
756{
757 using namespace java::lang::reflect;
758
759 // FRAME_DESC registers this particular invocation as the top-most
760 // interpreter frame. This lets the stack tracing code (for
761 // Throwable) print information about the method being interpreted
762 // rather than about the interpreter itself. FRAME_DESC has a
763 // destructor so it cleans up automatically when the interpreter
764 // returns.
765 java::lang::Thread *thread = java::lang::Thread::currentThread();
766 _Jv_MethodChain frame_desc (this,
767 (_Jv_MethodChain **) &thread->interp_frame);
768
769 _Jv_word stack[max_stack];
770 _Jv_word *sp = stack;
771
772 _Jv_word locals[max_locals];
773
774 /* Go straight at it! the ffi raw format matches the internal
775 stack representation exactly. At least, that's the idea.
776 */
777 memcpy ((void*) locals, (void*) args, args_raw_size);
778
779 _Jv_word *pool_data = defining_class->constants.data;
780
781 /* These three are temporaries for common code used by several
782 instructions. */
783 void (*fun)();
784 _Jv_ResolvedMethod* rmeth;
785 int tmpval;
786
787#define INSN_LABEL(op) &&insn_##op
788
789 static const void *const insn_target[] =
790 {
791 INSN_LABEL(nop),
792 INSN_LABEL(aconst_null),
793 INSN_LABEL(iconst_m1),
794 INSN_LABEL(iconst_0),
795 INSN_LABEL(iconst_1),
796 INSN_LABEL(iconst_2),
797 INSN_LABEL(iconst_3),
798 INSN_LABEL(iconst_4),
799 INSN_LABEL(iconst_5),
800 INSN_LABEL(lconst_0),
801 INSN_LABEL(lconst_1),
802 INSN_LABEL(fconst_0),
803 INSN_LABEL(fconst_1),
804 INSN_LABEL(fconst_2),
805 INSN_LABEL(dconst_0),
806 INSN_LABEL(dconst_1),
807 INSN_LABEL(bipush),
808 INSN_LABEL(sipush),
809 INSN_LABEL(ldc),
810 INSN_LABEL(ldc_w),
811 INSN_LABEL(ldc2_w),
812 INSN_LABEL(iload),
813 INSN_LABEL(lload),
814 INSN_LABEL(fload),
815 INSN_LABEL(dload),
816 INSN_LABEL(aload),
817 INSN_LABEL(iload_0),
818 INSN_LABEL(iload_1),
819 INSN_LABEL(iload_2),
820 INSN_LABEL(iload_3),
821 INSN_LABEL(lload_0),
822 INSN_LABEL(lload_1),
823 INSN_LABEL(lload_2),
824 INSN_LABEL(lload_3),
825 INSN_LABEL(fload_0),
826 INSN_LABEL(fload_1),
827 INSN_LABEL(fload_2),
828 INSN_LABEL(fload_3),
829 INSN_LABEL(dload_0),
830 INSN_LABEL(dload_1),
831 INSN_LABEL(dload_2),
832 INSN_LABEL(dload_3),
833 INSN_LABEL(aload_0),
834 INSN_LABEL(aload_1),
835 INSN_LABEL(aload_2),
836 INSN_LABEL(aload_3),
837 INSN_LABEL(iaload),
838 INSN_LABEL(laload),
839 INSN_LABEL(faload),
840 INSN_LABEL(daload),
841 INSN_LABEL(aaload),
842 INSN_LABEL(baload),
843 INSN_LABEL(caload),
844 INSN_LABEL(saload),
845 INSN_LABEL(istore),
846 INSN_LABEL(lstore),
847 INSN_LABEL(fstore),
848 INSN_LABEL(dstore),
849 INSN_LABEL(astore),
850 INSN_LABEL(istore_0),
851 INSN_LABEL(istore_1),
852 INSN_LABEL(istore_2),
853 INSN_LABEL(istore_3),
854 INSN_LABEL(lstore_0),
855 INSN_LABEL(lstore_1),
856 INSN_LABEL(lstore_2),
857 INSN_LABEL(lstore_3),
858 INSN_LABEL(fstore_0),
859 INSN_LABEL(fstore_1),
860 INSN_LABEL(fstore_2),
861 INSN_LABEL(fstore_3),
862 INSN_LABEL(dstore_0),
863 INSN_LABEL(dstore_1),
864 INSN_LABEL(dstore_2),
865 INSN_LABEL(dstore_3),
866 INSN_LABEL(astore_0),
867 INSN_LABEL(astore_1),
868 INSN_LABEL(astore_2),
869 INSN_LABEL(astore_3),
870 INSN_LABEL(iastore),
871 INSN_LABEL(lastore),
872 INSN_LABEL(fastore),
873 INSN_LABEL(dastore),
874 INSN_LABEL(aastore),
875 INSN_LABEL(bastore),
876 INSN_LABEL(castore),
877 INSN_LABEL(sastore),
878 INSN_LABEL(pop),
879 INSN_LABEL(pop2),
880 INSN_LABEL(dup),
881 INSN_LABEL(dup_x1),
882 INSN_LABEL(dup_x2),
883 INSN_LABEL(dup2),
884 INSN_LABEL(dup2_x1),
885 INSN_LABEL(dup2_x2),
886 INSN_LABEL(swap),
887 INSN_LABEL(iadd),
888 INSN_LABEL(ladd),
889 INSN_LABEL(fadd),
890 INSN_LABEL(dadd),
891 INSN_LABEL(isub),
892 INSN_LABEL(lsub),
893 INSN_LABEL(fsub),
894 INSN_LABEL(dsub),
895 INSN_LABEL(imul),
896 INSN_LABEL(lmul),
897 INSN_LABEL(fmul),
898 INSN_LABEL(dmul),
899 INSN_LABEL(idiv),
900 INSN_LABEL(ldiv),
901 INSN_LABEL(fdiv),
902 INSN_LABEL(ddiv),
903 INSN_LABEL(irem),
904 INSN_LABEL(lrem),
905 INSN_LABEL(frem),
906 INSN_LABEL(drem),
907 INSN_LABEL(ineg),
908 INSN_LABEL(lneg),
909 INSN_LABEL(fneg),
910 INSN_LABEL(dneg),
911 INSN_LABEL(ishl),
912 INSN_LABEL(lshl),
913 INSN_LABEL(ishr),
914 INSN_LABEL(lshr),
915 INSN_LABEL(iushr),
916 INSN_LABEL(lushr),
917 INSN_LABEL(iand),
918 INSN_LABEL(land),
919 INSN_LABEL(ior),
920 INSN_LABEL(lor),
921 INSN_LABEL(ixor),
922 INSN_LABEL(lxor),
923 INSN_LABEL(iinc),
924 INSN_LABEL(i2l),
925 INSN_LABEL(i2f),
926 INSN_LABEL(i2d),
927 INSN_LABEL(l2i),
928 INSN_LABEL(l2f),
929 INSN_LABEL(l2d),
930 INSN_LABEL(f2i),
931 INSN_LABEL(f2l),
932 INSN_LABEL(f2d),
933 INSN_LABEL(d2i),
934 INSN_LABEL(d2l),
935 INSN_LABEL(d2f),
936 INSN_LABEL(i2b),
937 INSN_LABEL(i2c),
938 INSN_LABEL(i2s),
939 INSN_LABEL(lcmp),
940 INSN_LABEL(fcmpl),
941 INSN_LABEL(fcmpg),
942 INSN_LABEL(dcmpl),
943 INSN_LABEL(dcmpg),
944 INSN_LABEL(ifeq),
945 INSN_LABEL(ifne),
946 INSN_LABEL(iflt),
947 INSN_LABEL(ifge),
948 INSN_LABEL(ifgt),
949 INSN_LABEL(ifle),
950 INSN_LABEL(if_icmpeq),
951 INSN_LABEL(if_icmpne),
952 INSN_LABEL(if_icmplt),
953 INSN_LABEL(if_icmpge),
954 INSN_LABEL(if_icmpgt),
955 INSN_LABEL(if_icmple),
956 INSN_LABEL(if_acmpeq),
957 INSN_LABEL(if_acmpne),
958 INSN_LABEL(goto),
959 INSN_LABEL(jsr),
960 INSN_LABEL(ret),
961 INSN_LABEL(tableswitch),
962 INSN_LABEL(lookupswitch),
963 INSN_LABEL(ireturn),
964 INSN_LABEL(lreturn),
965 INSN_LABEL(freturn),
966 INSN_LABEL(dreturn),
967 INSN_LABEL(areturn),
968 INSN_LABEL(return),
969 INSN_LABEL(getstatic),
970 INSN_LABEL(putstatic),
971 INSN_LABEL(getfield),
972 INSN_LABEL(putfield),
973 INSN_LABEL(invokevirtual),
974 INSN_LABEL(invokespecial),
975 INSN_LABEL(invokestatic),
976 INSN_LABEL(invokeinterface),
977 0, /* Unused. */
978 INSN_LABEL(new),
979 INSN_LABEL(newarray),
980 INSN_LABEL(anewarray),
981 INSN_LABEL(arraylength),
982 INSN_LABEL(athrow),
983 INSN_LABEL(checkcast),
984 INSN_LABEL(instanceof),
985 INSN_LABEL(monitorenter),
986 INSN_LABEL(monitorexit),
987#ifdef DIRECT_THREADED
988 0, // wide
989#else
990 INSN_LABEL(wide),
991#endif
992 INSN_LABEL(multianewarray),
993 INSN_LABEL(ifnull),
994 INSN_LABEL(ifnonnull),
995 INSN_LABEL(goto_w),
996 INSN_LABEL(jsr_w),
997 0
998 };
999
1000 pc_t pc;
1001
1002#ifdef DIRECT_THREADED
1003
1004#define NEXT_INSN goto *((pc++)->insn)
1005#define INTVAL() ((pc++)->int_val)
1006#define AVAL() ((pc++)->datum)
1007
1008#define GET1S() INTVAL ()
1009#define GET2S() INTVAL ()
1010#define GET1U() INTVAL ()
1011#define GET2U() INTVAL ()
1012#define AVAL1U() AVAL ()
1013#define AVAL2U() AVAL ()
1014#define AVAL2UP() AVAL ()
1015#define SKIP_GOTO ++pc
1016#define GOTO_VAL() (insn_slot *) pc->datum
1017#define PCVAL(unionval) unionval.p
1018#define AMPAMP(label) &&label
1019
1020 // Compile if we must.
1021 if (prepared == NULL)
1022 compile (insn_target);
1023 pc = (insn_slot *) prepared;
1024
1025#else
1026
1027#define NEXT_INSN goto *(insn_target[*pc++])
1028
1029#define GET1S() get1s (pc++)
1030#define GET2S() (pc += 2, get2s (pc- 2))
1031#define GET1U() get1u (pc++)
1032#define GET2U() (pc += 2, get2u (pc - 2))
1033#define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1034#define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1035#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1036#define SKIP_GOTO pc += 2
1037#define GOTO_VAL() pc - 1 + get2s (pc)
1038#define PCVAL(unionval) unionval.i
1039#define AMPAMP(label) NULL
1040
1041 pc = bytecode ();
1042
1043#endif /* DIRECT_THREADED */
1044
1045#define TAKE_GOTO pc = GOTO_VAL ()
1046
1047 try
1048 {
1049 // We keep nop around. It is used if we're interpreting the
1050 // bytecodes and not doing direct threading.
1051 insn_nop:
1052 NEXT_INSN;
1053
1054 /* The first few instructions here are ordered according to their
1055 frequency, in the hope that this will improve code locality a
1056 little. */
1057
1058 insn_aload_0: // 0x2a
1059 LOADA (0);
1060 NEXT_INSN;
1061
1062 insn_iload: // 0x15
1063 LOADI (GET1U ());
1064 NEXT_INSN;
1065
1066 insn_iload_1: // 0x1b
1067 LOADI (1);
1068 NEXT_INSN;
1069
1070 insn_invokevirtual: // 0xb6
1071 {
1072 int index = GET2U ();
1073
1074 /* _Jv_ResolvePoolEntry returns immediately if the value already
1075 * is resolved. If we want to clutter up the code here to gain
1076 * a little performance, then we can check the corresponding bit
1077 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
1078 * don't think it is worth it. */
1079
1080 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
1081
1082 sp -= rmeth->stack_item_count;
1083 // We don't use NULLCHECK here because we can't rely on that
1084 // working if the method is final. So instead we do an
1085 // explicit test.
1086 if (! sp[0].o)
1087 throw new java::lang::NullPointerException;
1088
1089 if (rmeth->vtable_index == -1)
1090 {
1091 // final methods do not appear in the vtable,
1092 // if it does not appear in the superclass.
1093 fun = (void (*)()) rmeth->method->ncode;
1094 }
1095 else
1096 {
1097 jobject rcv = sp[0].o;
1098 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1099 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1100 }
1101
1102#ifdef DIRECT_THREADED
1103 // Rewrite instruction so that we use a faster pre-resolved
1104 // method.
1105 pc[-2].insn = &&invokevirtual_resolved;
1106 pc[-1].datum = rmeth;
1107#endif /* DIRECT_THREADED */
1108 }
1109 goto perform_invoke;
1110
1111#ifdef DIRECT_THREADED
1112 invokevirtual_resolved:
1113 {
1114 rmeth = (_Jv_ResolvedMethod *) AVAL ();
1115 sp -= rmeth->stack_item_count;
1116 // We don't use NULLCHECK here because we can't rely on that
1117 // working if the method is final. So instead we do an
1118 // explicit test.
1119 if (! sp[0].o)
1120 throw new java::lang::NullPointerException;
1121
1122 if (rmeth->vtable_index == -1)
1123 {
1124 // final methods do not appear in the vtable,
1125 // if it does not appear in the superclass.
1126 fun = (void (*)()) rmeth->method->ncode;
1127 }
1128 else
1129 {
1130 jobject rcv = sp[0].o;
1131 _Jv_VTable *table = *(_Jv_VTable**) rcv;
1132 fun = (void (*)()) table->get_method (rmeth->vtable_index);
1133 }
1134 }
1135 goto perform_invoke;
1136#endif /* DIRECT_THREADED */
1137
1138 perform_invoke:
1139 {
1140 /* here goes the magic again... */
1141 ffi_cif *cif = &rmeth->cif;
1142 ffi_raw *raw = (ffi_raw*) sp;
1143
1144 jdouble rvalue;
1145
1146#if FFI_NATIVE_RAW_API
1147 /* We assume that this is only implemented if it's correct */
1148 /* to use it here. On a 64 bit machine, it never is. */
1149 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
1150#else
1151 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
1152#endif
1153
1154 int rtype = cif->rtype->type;
1155
1156 /* the likelyhood of object, int, or void return is very high,
1157 * so those are checked before the switch */
1158 if (rtype == FFI_TYPE_POINTER)
1159 {
1160 PUSHA (*(jobject*)&rvalue);
1161 }
1162 else if (rtype == FFI_TYPE_SINT32)
1163 {
1164 PUSHI (*(jint*)&rvalue);
1165 }
1166 else if (rtype == FFI_TYPE_VOID)
1167 {
1168 /* skip */
1169 }
1170 else
1171 {
1172 switch (rtype)
1173 {
1174 case FFI_TYPE_SINT8:
1175 {
1176 jbyte value = (*(jint*)&rvalue) & 0xff;
1177 PUSHI (value);
1178 }
1179 break;
1180
1181 case FFI_TYPE_SINT16:
1182 {
1183 jshort value = (*(jint*)&rvalue) & 0xffff;
1184 PUSHI (value);
1185 }
1186 break;
1187
1188 case FFI_TYPE_UINT16:
1189 {
1190 jint value = (*(jint*)&rvalue) & 0xffff;
1191 PUSHI (value);
1192 }
1193 break;
1194
1195 case FFI_TYPE_FLOAT:
1196 PUSHF (*(jfloat*)&rvalue);
1197 break;
1198
1199 case FFI_TYPE_DOUBLE:
1200 PUSHD (rvalue);
1201 break;
1202
1203 case FFI_TYPE_SINT64:
1204 PUSHL (*(jlong*)&rvalue);
1205 break;
1206
1207 default:
1208 throw_internal_error ("unknown return type in invokeXXX");
1209 }
1210 }
1211 }
1212 NEXT_INSN;
1213
1214 insn_aconst_null:
1215 PUSHA (NULL);
1216 NEXT_INSN;
1217
1218 insn_iconst_m1:
1219 PUSHI (-1);
1220 NEXT_INSN;
1221
1222 insn_iconst_0:
1223 PUSHI (0);
1224 NEXT_INSN;
1225
1226 insn_iconst_1:
1227 PUSHI (1);
1228 NEXT_INSN;
1229
1230 insn_iconst_2:
1231 PUSHI (2);
1232 NEXT_INSN;
1233
1234 insn_iconst_3:
1235 PUSHI (3);
1236 NEXT_INSN;
1237
1238 insn_iconst_4:
1239 PUSHI (4);
1240 NEXT_INSN;
1241
1242 insn_iconst_5:
1243 PUSHI (5);
1244 NEXT_INSN;
1245
1246 insn_lconst_0:
1247 PUSHL (0);
1248 NEXT_INSN;
1249
1250 insn_lconst_1:
1251 PUSHL (1);
1252 NEXT_INSN;
1253
1254 insn_fconst_0:
1255 PUSHF (0);
1256 NEXT_INSN;
1257
1258 insn_fconst_1:
1259 PUSHF (1);
1260 NEXT_INSN;
1261
1262 insn_fconst_2:
1263 PUSHF (2);
1264 NEXT_INSN;
1265
1266 insn_dconst_0:
1267 PUSHD (0);
1268 NEXT_INSN;
1269
1270 insn_dconst_1:
1271 PUSHD (1);
1272 NEXT_INSN;
1273
1274 insn_bipush:
1275 // For direct threaded, bipush and sipush are the same.
1276#ifndef DIRECT_THREADED
1277 PUSHI (GET1S ());
1278 NEXT_INSN;
1279#endif /* DIRECT_THREADED */
1280 insn_sipush:
1281 PUSHI (GET2S ());
1282 NEXT_INSN;
1283
1284 insn_ldc:
1285 // For direct threaded, ldc and ldc_w are the same.
1286#ifndef DIRECT_THREADED
1287 PUSHA ((jobject) AVAL1U ());
1288 NEXT_INSN;
1289#endif /* DIRECT_THREADED */
1290 insn_ldc_w:
1291 PUSHA ((jobject) AVAL2U ());
1292 NEXT_INSN;
1293
1294 insn_ldc2_w:
1295 {
1296 void *where = AVAL2UP ();
1297 memcpy (sp, where, 2*sizeof (_Jv_word));
1298 sp += 2;
1299 }
1300 NEXT_INSN;
1301
1302 insn_lload:
1303 LOADL (GET1U ());
1304 NEXT_INSN;
1305
1306 insn_fload:
1307 LOADF (GET1U ());
1308 NEXT_INSN;
1309
1310 insn_dload:
1311 LOADD (GET1U ());
1312 NEXT_INSN;
1313
1314 insn_aload:
1315 LOADA (GET1U ());
1316 NEXT_INSN;
1317
1318 insn_iload_0:
1319 LOADI (0);
1320 NEXT_INSN;
1321
1322 insn_iload_2:
1323 LOADI (2);
1324 NEXT_INSN;
1325
1326 insn_iload_3:
1327 LOADI (3);
1328 NEXT_INSN;
1329
1330 insn_lload_0:
1331 LOADL (0);
1332 NEXT_INSN;
1333
1334 insn_lload_1:
1335 LOADL (1);
1336 NEXT_INSN;
1337
1338 insn_lload_2:
1339 LOADL (2);
1340 NEXT_INSN;
1341
1342 insn_lload_3:
1343 LOADL (3);
1344 NEXT_INSN;
1345
1346 insn_fload_0:
1347 LOADF (0);
1348 NEXT_INSN;
1349
1350 insn_fload_1:
1351 LOADF (1);
1352 NEXT_INSN;
1353
1354 insn_fload_2:
1355 LOADF (2);
1356 NEXT_INSN;
1357
1358 insn_fload_3:
1359 LOADF (3);
1360 NEXT_INSN;
1361
1362 insn_dload_0:
1363 LOADD (0);
1364 NEXT_INSN;
1365
1366 insn_dload_1:
1367 LOADD (1);
1368 NEXT_INSN;
1369
1370 insn_dload_2:
1371 LOADD (2);
1372 NEXT_INSN;
1373
1374 insn_dload_3:
1375 LOADD (3);
1376 NEXT_INSN;
1377
1378 insn_aload_1:
1379 LOADA(1);
1380 NEXT_INSN;
1381
1382 insn_aload_2:
1383 LOADA(2);
1384 NEXT_INSN;
1385
1386 insn_aload_3:
1387 LOADA(3);
1388 NEXT_INSN;
1389
1390 insn_iaload:
1391 {
1392 jint index = POPI();
1393 jintArray arr = (jintArray) POPA();
1394 NULLARRAYCHECK (arr);
1395 ARRAYBOUNDSCHECK (arr, index);
1396 PUSHI( elements(arr)[index] );
1397 }
1398 NEXT_INSN;
1399
1400 insn_laload:
1401 {
1402 jint index = POPI();
1403 jlongArray arr = (jlongArray) POPA();
1404 NULLARRAYCHECK (arr);
1405 ARRAYBOUNDSCHECK (arr, index);
1406 PUSHL( elements(arr)[index] );
1407 }
1408 NEXT_INSN;
1409
1410 insn_faload:
1411 {
1412 jint index = POPI();
1413 jfloatArray arr = (jfloatArray) POPA();
1414 NULLARRAYCHECK (arr);
1415 ARRAYBOUNDSCHECK (arr, index);
1416 PUSHF( elements(arr)[index] );
1417 }
1418 NEXT_INSN;
1419
1420 insn_daload:
1421 {
1422 jint index = POPI();
1423 jdoubleArray arr = (jdoubleArray) POPA();
1424 NULLARRAYCHECK (arr);
1425 ARRAYBOUNDSCHECK (arr, index);
1426 PUSHD( elements(arr)[index] );
1427 }
1428 NEXT_INSN;
1429
1430 insn_aaload:
1431 {
1432 jint index = POPI();
1433 jobjectArray arr = (jobjectArray) POPA();
1434 NULLARRAYCHECK (arr);
1435 ARRAYBOUNDSCHECK (arr, index);
1436 PUSHA( elements(arr)[index] );
1437 }
1438 NEXT_INSN;
1439
1440 insn_baload:
1441 {
1442 jint index = POPI();
1443 jbyteArray arr = (jbyteArray) POPA();
1444 NULLARRAYCHECK (arr);
1445 ARRAYBOUNDSCHECK (arr, index);
1446 PUSHI( elements(arr)[index] );
1447 }
1448 NEXT_INSN;
1449
1450 insn_caload:
1451 {
1452 jint index = POPI();
1453 jcharArray arr = (jcharArray) POPA();
1454 NULLARRAYCHECK (arr);
1455 ARRAYBOUNDSCHECK (arr, index);
1456 PUSHI( elements(arr)[index] );
1457 }
1458 NEXT_INSN;
1459
1460 insn_saload:
1461 {
1462 jint index = POPI();
1463 jshortArray arr = (jshortArray) POPA();
1464 NULLARRAYCHECK (arr);
1465 ARRAYBOUNDSCHECK (arr, index);
1466 PUSHI( elements(arr)[index] );
1467 }
1468 NEXT_INSN;
1469
1470 insn_istore:
1471 STOREI (GET1U ());
1472 NEXT_INSN;
1473
1474 insn_lstore:
1475 STOREL (GET1U ());
1476 NEXT_INSN;
1477
1478 insn_fstore:
1479 STOREF (GET1U ());
1480 NEXT_INSN;
1481
1482 insn_dstore:
1483 STORED (GET1U ());
1484 NEXT_INSN;
1485