OSDN Git Service

2005-07-26 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 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 #include <platform.h>
15
16 #pragma implementation "java-interp.h"
17
18 #include <jvm.h>
19 #include <java-cpool.h>
20 #include <java-interp.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/Long.h>
25 #include <java/lang/StringBuffer.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/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/lang/InstantiationException.h>
34 #include <java/lang/Thread.h>
35 #include <java-insns.h>
36 #include <java-signal.h>
37 #include <java/lang/ClassFormatError.h>
38 #include <execution.h>
39 #include <java/lang/reflect/Modifier.h>
40
41 #ifdef INTERPRETER
42
43 // Execution engine for interpreted code.
44 _Jv_InterpreterEngine _Jv_soleInterpreterEngine;
45
46 #include <stdlib.h>
47
48 using namespace gcj;
49
50 static void throw_internal_error (char *msg)
51   __attribute__ ((__noreturn__));
52 static void throw_incompatible_class_change_error (jstring msg)
53   __attribute__ ((__noreturn__));
54 #ifndef HANDLE_SEGV
55 static void throw_null_pointer_exception ()
56   __attribute__ ((__noreturn__));
57 #endif
58
59 static void throw_class_format_error (jstring msg)
60         __attribute__ ((__noreturn__));
61 static void throw_class_format_error (char *msg)
62         __attribute__ ((__noreturn__));
63
64 #ifdef DIRECT_THREADED
65 // Lock to ensure that methods are not compiled concurrently.
66 // We could use a finer-grained lock here, however it is not safe to use
67 // the Class monitor as user code in another thread could hold it.
68 static _Jv_Mutex_t compile_mutex;
69
70 void
71 _Jv_InitInterpreter()
72 {
73   _Jv_MutexInit (&compile_mutex);
74 }
75 #else
76 void _Jv_InitInterpreter() {}
77 #endif
78
79 extern "C" double __ieee754_fmod (double,double);
80
81 static inline void dupx (_Jv_word *sp, int n, int x)
82 {
83   // first "slide" n+x elements n to the right
84   int top = n-1;
85   for (int i = 0; i < n+x; i++)
86     {
87       sp[(top-i)] = sp[(top-i)-n];
88     }
89   
90   // next, copy the n top elements, n+x down
91   for (int i = 0; i < n; i++)
92     {
93       sp[top-(n+x)-i] = sp[top-i];
94     }
95 }
96
97 // Used to convert from floating types to integral types.
98 template<typename TO, typename FROM>
99 static inline TO
100 convert (FROM val, TO min, TO max)
101 {
102   TO ret;
103   if (val >= (FROM) max)
104     ret = max;
105   else if (val <= (FROM) min)
106     ret = min;
107   else if (val != val)
108     ret = 0;
109   else
110     ret = (TO) val;
111   return ret;
112 }
113
114 #define PUSHA(V)  (sp++)->o = (V)
115 #define PUSHI(V)  (sp++)->i = (V)
116 #define PUSHF(V)  (sp++)->f = (V)
117 #if SIZEOF_VOID_P == 8
118 # define PUSHL(V)   (sp->l = (V), sp += 2)
119 # define PUSHD(V)   (sp->d = (V), sp += 2)
120 #else
121 # define PUSHL(V)  do { _Jv_word2 w2; w2.l=(V); \
122                         (sp++)->ia[0] = w2.ia[0]; \
123                         (sp++)->ia[0] = w2.ia[1]; } while (0)
124 # define PUSHD(V)  do { _Jv_word2 w2; w2.d=(V); \
125                         (sp++)->ia[0] = w2.ia[0]; \
126                         (sp++)->ia[0] = w2.ia[1]; } while (0)
127 #endif
128
129 #define POPA()    ((--sp)->o)
130 #define POPI()    ((jint) (--sp)->i) // cast since it may be promoted
131 #define POPF()    ((jfloat) (--sp)->f)
132 #if SIZEOF_VOID_P == 8
133 # define POPL()   (sp -= 2, (jlong) sp->l)
134 # define POPD()   (sp -= 2, (jdouble) sp->d)
135 #else
136 # define POPL()    ({ _Jv_word2 w2; \
137                      w2.ia[1] = (--sp)->ia[0]; \
138                      w2.ia[0] = (--sp)->ia[0]; w2.l; })
139 # define POPD()    ({ _Jv_word2 w2; \
140                      w2.ia[1] = (--sp)->ia[0]; \
141                      w2.ia[0] = (--sp)->ia[0]; w2.d; })
142 #endif
143
144 #define LOADA(I)  (sp++)->o = locals[I].o
145 #define LOADI(I)  (sp++)->i = locals[I].i
146 #define LOADF(I)  (sp++)->f = locals[I].f
147 #if SIZEOF_VOID_P == 8
148 # define LOADL(I)  (sp->l = locals[I].l, sp += 2)
149 # define LOADD(I)  (sp->d = locals[I].d, sp += 2)
150 #else
151 # define LOADL(I)  do { jint __idx = (I); \
152                         (sp++)->ia[0] = locals[__idx].ia[0]; \
153                         (sp++)->ia[0] = locals[__idx+1].ia[0]; \
154                    } while (0)
155 # define LOADD(I)  LOADL(I)
156 #endif
157
158 #define STOREA(I) locals[I].o = (--sp)->o
159 #define STOREI(I) locals[I].i = (--sp)->i
160 #define STOREF(I) locals[I].f = (--sp)->f
161 #if SIZEOF_VOID_P == 8
162 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
163 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
164 #else
165 # define STOREL(I) do { jint __idx = (I); \
166                        locals[__idx+1].ia[0] = (--sp)->ia[0]; \
167                        locals[__idx].ia[0] = (--sp)->ia[0]; \
168                    } while (0)
169 # define STORED(I) STOREL(I)
170 #endif
171
172 #define PEEKI(I)  (locals+(I))->i
173 #define PEEKA(I)  (locals+(I))->o
174
175 #define POKEI(I,V)  ((locals+(I))->i = (V))
176
177
178 #define BINOPI(OP) { \
179    jint value2 = POPI(); \
180    jint value1 = POPI(); \
181    PUSHI(value1 OP value2); \
182 }
183
184 #define BINOPF(OP) { \
185    jfloat value2 = POPF(); \
186    jfloat value1 = POPF(); \
187    PUSHF(value1 OP value2); \
188 }
189
190 #define BINOPL(OP) { \
191    jlong value2 = POPL(); \
192    jlong value1 = POPL(); \
193    PUSHL(value1 OP value2); \
194 }
195
196 #define BINOPD(OP) { \
197    jdouble value2 = POPD(); \
198    jdouble value1 = POPD(); \
199    PUSHD(value1 OP value2); \
200 }
201
202 static inline jint get1s(unsigned char* loc) {
203   return *(signed char*)loc;
204 }
205
206 static inline jint get1u(unsigned char* loc) {
207   return *loc;
208 }
209
210 static inline jint get2s(unsigned char* loc) {
211   return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
212 }
213
214 static inline jint get2u(unsigned char* loc) {
215   return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
216 }
217
218 static jint get4(unsigned char* loc) {
219   return (((jint)(loc[0])) << 24) 
220        | (((jint)(loc[1])) << 16) 
221        | (((jint)(loc[2])) << 8) 
222        | (((jint)(loc[3])) << 0);
223 }
224
225 #define SAVE_PC() frame_desc.pc = pc
226
227 #ifdef HANDLE_SEGV
228 #define NULLCHECK(X) SAVE_PC()
229 #define NULLARRAYCHECK(X) SAVE_PC()
230 #else
231 #define NULLCHECK(X) \
232   do { SAVE_PC(); if ((X)==NULL) throw_null_pointer_exception (); } while (0)
233 #define NULLARRAYCHECK(X) \
234   do { SAVE_PC(); if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
235 #endif
236
237 #define ARRAYBOUNDSCHECK(array, index)                                        \
238   do                                                                          \
239     {                                                                         \
240       if (((unsigned) index) >= (unsigned) (array->length))                   \
241         _Jv_ThrowBadArrayIndex (index);                                       \
242     }                                                                         \
243   while (0)
244
245 void
246 _Jv_InterpMethod::run_normal (ffi_cif *,
247                               void* ret,
248                               ffi_raw * args,
249                               void* __this)
250 {
251   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
252   run (ret, args, _this);
253 }
254
255 void
256 _Jv_InterpMethod::run_synch_object (ffi_cif *,
257                                     void* ret,
258                                     ffi_raw * args,
259                                     void* __this)
260 {
261   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
262
263   jobject rcv = (jobject) args[0].ptr;
264   JvSynchronize mutex (rcv);
265
266   run (ret, args, _this);
267 }
268
269 void
270 _Jv_InterpMethod::run_class (ffi_cif *,
271                              void* ret,
272                              ffi_raw * args,
273                              void* __this)
274 {
275   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
276   _Jv_InitClass (_this->defining_class);
277   run (ret, args, _this);
278 }
279
280 void
281 _Jv_InterpMethod::run_synch_class (ffi_cif *,
282                                    void* ret,
283                                    ffi_raw * args,
284                                    void* __this)
285 {
286   _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
287
288   jclass sync = _this->defining_class;
289   _Jv_InitClass (sync);
290   JvSynchronize mutex (sync);
291
292   run (ret, args, _this);
293 }
294
295 #ifdef DIRECT_THREADED
296 // "Compile" a method by turning it from bytecode to direct-threaded
297 // code.
298 void
299 _Jv_InterpMethod::compile (const void * const *insn_targets)
300 {
301   insn_slot *insns = NULL;
302   int next = 0;
303   unsigned char *codestart = bytecode ();
304   unsigned char *end = codestart + code_length;
305   _Jv_word *pool_data = defining_class->constants.data;
306
307 #define SET_ONE(Field, Value)                                                 \
308   do                                                                          \
309     {                                                                         \
310       if (first_pass)                                                         \
311         ++next;                                                               \
312       else                                                                    \
313         insns[next++].Field = Value;                                          \
314     }                                                                         \
315   while (0)
316
317 #define SET_INSN(Value) SET_ONE (insn, (void *) Value)
318 #define SET_INT(Value) SET_ONE (int_val, Value)
319 #define SET_DATUM(Value) SET_ONE (datum, Value)
320
321   // Map from bytecode PC to slot in INSNS.
322   int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
323   for (int i = 0; i < code_length; ++i)
324     pc_mapping[i] = -1;
325
326   for (int i = 0; i < 2; ++i)
327     {
328       jboolean first_pass = i == 0;
329
330       if (! first_pass)
331         {
332           insns = (insn_slot *) _Jv_AllocBytes (sizeof (insn_slot) * next);
333           next = 0;
334         }
335
336       unsigned char *pc = codestart;
337       while (pc < end)
338         {
339           int base_pc_val = pc - codestart;
340           if (first_pass)
341             pc_mapping[base_pc_val] = next;
342
343           java_opcode opcode = (java_opcode) *pc++;
344           // Just elide NOPs.
345           if (opcode == op_nop)
346             continue;
347           SET_INSN (insn_targets[opcode]);
348
349           switch (opcode)
350             {
351             case op_nop:
352             case op_aconst_null:
353             case op_iconst_m1:
354             case op_iconst_0:
355             case op_iconst_1:
356             case op_iconst_2:
357             case op_iconst_3:
358             case op_iconst_4:
359             case op_iconst_5:
360             case op_lconst_0:
361             case op_lconst_1:
362             case op_fconst_0:
363             case op_fconst_1:
364             case op_fconst_2:
365             case op_dconst_0:
366             case op_dconst_1:
367             case op_iload_0:
368             case op_iload_1:
369             case op_iload_2:
370             case op_iload_3:
371             case op_lload_0:
372             case op_lload_1:
373             case op_lload_2:
374             case op_lload_3:
375             case op_fload_0:
376             case op_fload_1:
377             case op_fload_2:
378             case op_fload_3:
379             case op_dload_0:
380             case op_dload_1:
381             case op_dload_2:
382             case op_dload_3:
383             case op_aload_0:
384             case op_aload_1:
385             case op_aload_2:
386             case op_aload_3:
387             case op_iaload:
388             case op_laload:
389             case op_faload:
390             case op_daload:
391             case op_aaload:
392             case op_baload:
393             case op_caload:
394             case op_saload:
395             case op_istore_0:
396             case op_istore_1:
397             case op_istore_2:
398             case op_istore_3:
399             case op_lstore_0:
400             case op_lstore_1:
401             case op_lstore_2:
402             case op_lstore_3:
403             case op_fstore_0:
404             case op_fstore_1:
405             case op_fstore_2:
406             case op_fstore_3:
407             case op_dstore_0:
408             case op_dstore_1:
409             case op_dstore_2:
410             case op_dstore_3:
411             case op_astore_0:
412             case op_astore_1:
413             case op_astore_2:
414             case op_astore_3:
415             case op_iastore:
416             case op_lastore:
417             case op_fastore:
418             case op_dastore:
419             case op_aastore:
420             case op_bastore:
421             case op_castore:
422             case op_sastore:
423             case op_pop:
424             case op_pop2:
425             case op_dup:
426             case op_dup_x1:
427             case op_dup_x2:
428             case op_dup2:
429             case op_dup2_x1:
430             case op_dup2_x2:
431             case op_swap:
432             case op_iadd:
433             case op_isub:
434             case op_imul:
435             case op_idiv:
436             case op_irem:
437             case op_ishl:
438             case op_ishr:
439             case op_iushr:
440             case op_iand:
441             case op_ior:
442             case op_ixor:
443             case op_ladd:
444             case op_lsub:
445             case op_lmul:
446             case op_ldiv:
447             case op_lrem:
448             case op_lshl:
449             case op_lshr:
450             case op_lushr:
451             case op_land:
452             case op_lor:
453             case op_lxor:
454             case op_fadd:
455             case op_fsub:
456             case op_fmul:
457             case op_fdiv:
458             case op_frem:
459             case op_dadd:
460             case op_dsub:
461             case op_dmul:
462             case op_ddiv:
463             case op_drem:
464             case op_ineg:
465             case op_i2b:
466             case op_i2c:
467             case op_i2s:
468             case op_lneg:
469             case op_fneg:
470             case op_dneg:
471             case op_i2l:
472             case op_i2f:
473             case op_i2d:
474             case op_l2i:
475             case op_l2f:
476             case op_l2d:
477             case op_f2i:
478             case op_f2l:
479             case op_f2d:
480             case op_d2i:
481             case op_d2l:
482             case op_d2f:
483             case op_lcmp:
484             case op_fcmpl:
485             case op_fcmpg:
486             case op_dcmpl:
487             case op_dcmpg:
488             case op_monitorenter:
489             case op_monitorexit:
490             case op_ireturn:
491             case op_lreturn:
492             case op_freturn:
493             case op_dreturn:
494             case op_areturn:
495             case op_return:
496             case op_athrow:
497             case op_arraylength:
498               // No argument, nothing else to do.
499               break;
500
501             case op_bipush:
502               SET_INT (get1s (pc));
503               ++pc;
504               break;
505
506             case op_ldc:
507               {
508                 int index = get1u (pc);
509                 ++pc;
510                 SET_DATUM (pool_data[index].o);
511               }
512               break;
513
514             case op_ret:
515             case op_iload:
516             case op_lload:
517             case op_fload:
518             case op_dload:
519             case op_aload:
520             case op_istore:
521             case op_lstore:
522             case op_fstore:
523             case op_dstore:
524             case op_astore:
525             case op_newarray:
526               SET_INT (get1u (pc));
527               ++pc;
528               break;
529
530             case op_iinc:
531               SET_INT (get1u (pc));
532               SET_INT (get1s (pc + 1));
533               pc += 2;
534               break;
535
536             case op_ldc_w:
537               {
538                 int index = get2u (pc);
539                 pc += 2;
540                 SET_DATUM (pool_data[index].o);
541               }
542               break;
543
544             case op_ldc2_w:
545               {
546                 int index = get2u (pc);
547                 pc += 2;
548                 SET_DATUM (&pool_data[index]);
549               }
550               break;
551
552             case op_sipush:
553               SET_INT (get2s (pc));
554               pc += 2;
555               break;
556
557             case op_new:
558             case op_getstatic:
559             case op_getfield:
560             case op_putfield:
561             case op_putstatic:
562             case op_anewarray:
563             case op_instanceof:
564             case op_checkcast:
565             case op_invokespecial:
566             case op_invokestatic:
567             case op_invokevirtual:
568               SET_INT (get2u (pc));
569               pc += 2;
570               break;
571
572             case op_multianewarray:
573               SET_INT (get2u (pc));
574               SET_INT (get1u (pc + 2));
575               pc += 3;
576               break;
577
578             case op_jsr:
579             case op_ifeq:
580             case op_ifne:
581             case op_iflt:
582             case op_ifge:
583             case op_ifgt:
584             case op_ifle:
585             case op_if_icmpeq:
586             case op_if_icmpne:
587             case op_if_icmplt:
588             case op_if_icmpge:
589             case op_if_icmpgt:
590             case op_if_icmple:
591             case op_if_acmpeq:
592             case op_if_acmpne:
593             case op_ifnull:
594             case op_ifnonnull:
595             case op_goto:
596               {
597                 int offset = get2s (pc);
598                 pc += 2;
599
600                 int new_pc = base_pc_val + offset;
601
602                 bool orig_was_goto = opcode == op_goto;
603
604                 // Thread jumps.  We limit the loop count; this lets
605                 // us avoid infinite loops if the bytecode contains
606                 // such.  `10' is arbitrary.
607                 int count = 10;
608                 while (codestart[new_pc] == op_goto && count-- > 0)
609                   new_pc += get2s (&codestart[new_pc + 1]);
610
611                 // If the jump takes us to a `return' instruction and
612                 // the original branch was an unconditional goto, then
613                 // we hoist the return.
614                 opcode = (java_opcode) codestart[new_pc];
615                 if (orig_was_goto
616                     && (opcode == op_ireturn || opcode == op_lreturn
617                         || opcode == op_freturn || opcode == op_dreturn
618                         || opcode == op_areturn || opcode == op_return))
619                   {
620                     --next;
621                     SET_INSN (insn_targets[opcode]);
622                   }
623                 else
624                   SET_DATUM (&insns[pc_mapping[new_pc]]);
625               }
626               break;
627
628             case op_tableswitch:
629               {
630                 while ((pc - codestart) % 4 != 0)
631                   ++pc;
632
633                 jint def = get4 (pc);
634                 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
635                 pc += 4;
636
637                 int low = get4 (pc);
638                 SET_INT (low);
639                 pc += 4;
640                 int high = get4 (pc);
641                 SET_INT (high);
642                 pc += 4;
643
644                 for (int i = low; i <= high; ++i)
645                   {
646                     SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
647                     pc += 4;
648                   }
649               }
650               break;
651
652             case op_lookupswitch:
653               {
654                 while ((pc - codestart) % 4 != 0)
655                   ++pc;
656
657                 jint def = get4 (pc);
658                 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
659                 pc += 4;
660
661                 jint npairs = get4 (pc);
662                 pc += 4;
663                 SET_INT (npairs);
664
665                 while (npairs-- > 0)
666                   {
667                     jint match = get4 (pc);
668                     jint offset = get4 (pc + 4);
669                     SET_INT (match);
670                     SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
671                     pc += 8;
672                   }
673               }
674               break;
675
676             case op_invokeinterface:
677               {
678                 jint index = get2u (pc);
679                 pc += 2;
680                 // We ignore the next two bytes.
681                 pc += 2;
682                 SET_INT (index);
683               }
684               break;
685
686             case op_wide:
687               {
688                 opcode = (java_opcode) get1u (pc);
689                 pc += 1;
690                 jint val = get2u (pc);
691                 pc += 2;
692
693                 // We implement narrow and wide instructions using the
694                 // same code in the interpreter.  So we rewrite the
695                 // instruction slot here.
696                 if (! first_pass)
697                   insns[next - 1].insn = (void *) insn_targets[opcode];
698                 SET_INT (val);
699
700                 if (opcode == op_iinc)
701                   {
702                     SET_INT (get2s (pc));
703                     pc += 2;
704                   }
705               }
706               break;
707
708             case op_jsr_w:
709             case op_goto_w:
710               {
711                 jint offset = get4 (pc);
712                 pc += 4;
713                 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
714               }
715               break;
716
717             // Some "can't happen" cases that we include for
718             // error-checking purposes.
719             case op_putfield_1:
720             case op_putfield_2:
721             case op_putfield_4:
722             case op_putfield_8:
723             case op_putfield_a:
724             case op_putstatic_1:
725             case op_putstatic_2:
726             case op_putstatic_4:
727             case op_putstatic_8:
728             case op_putstatic_a:
729             case op_getfield_1:
730             case op_getfield_2s:
731             case op_getfield_2u:
732             case op_getfield_4:
733             case op_getfield_8:
734             case op_getfield_a:
735             case op_getstatic_1:
736             case op_getstatic_2s:
737             case op_getstatic_2u:
738             case op_getstatic_4:
739             case op_getstatic_8:
740             case op_getstatic_a:
741             default:
742               // Fail somehow.
743               break;
744             }
745         }
746     }
747
748   // Now update exceptions.
749   _Jv_InterpException *exc = exceptions ();
750   for (int i = 0; i < exc_count; ++i)
751     {
752       exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
753       exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
754       exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
755       jclass handler
756         = (_Jv_Linker::resolve_pool_entry (defining_class,
757                                              exc[i].handler_type.i)).clazz;
758       exc[i].handler_type.p = handler;
759     }
760
761   // Translate entries in the LineNumberTable from bytecode PC's to direct
762   // threaded interpreter instruction values.
763   for (int i = 0; i < line_table_len; i++)
764     {
765       int byte_pc = line_table[i].bytecode_pc;
766       // It isn't worth throwing an exception if this table is
767       // corrupted, but at the same time we don't want a crash.
768       if (byte_pc < 0 || byte_pc >= code_length)
769         byte_pc = 0;
770       line_table[i].pc = &insns[pc_mapping[byte_pc]];
771     }  
772
773   prepared = insns;
774 }
775 #endif /* DIRECT_THREADED */
776
777 void
778 _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
779 {
780   using namespace java::lang::reflect;
781
782   // FRAME_DESC registers this particular invocation as the top-most
783   // interpreter frame.  This lets the stack tracing code (for
784   // Throwable) print information about the method being interpreted
785   // rather than about the interpreter itself.  FRAME_DESC has a
786   // destructor so it cleans up automatically when the interpreter
787   // returns.
788   java::lang::Thread *thread = java::lang::Thread::currentThread();
789   _Jv_InterpFrame frame_desc (meth,
790                               (_Jv_InterpFrame **) &thread->interp_frame);
791
792   _Jv_word stack[meth->max_stack];
793   _Jv_word *sp = stack;
794
795   _Jv_word locals[meth->max_locals];
796
797   /* Go straight at it!  the ffi raw format matches the internal
798      stack representation exactly.  At least, that's the idea.
799   */
800   memcpy ((void*) locals, (void*) args, meth->args_raw_size);
801
802   _Jv_word *pool_data = meth->defining_class->constants.data;
803
804   /* These three are temporaries for common code used by several
805      instructions.  */
806   void (*fun)();
807   _Jv_ResolvedMethod* rmeth;
808   int tmpval;
809
810 #define INSN_LABEL(op) &&insn_##op
811
812   static const void *const insn_target[] = 
813   {
814     INSN_LABEL(nop),
815     INSN_LABEL(aconst_null),
816     INSN_LABEL(iconst_m1),
817     INSN_LABEL(iconst_0),
818     INSN_LABEL(iconst_1),
819     INSN_LABEL(iconst_2),
820     INSN_LABEL(iconst_3),
821     INSN_LABEL(iconst_4),
822     INSN_LABEL(iconst_5),
823     INSN_LABEL(lconst_0),
824     INSN_LABEL(lconst_1),
825     INSN_LABEL(fconst_0),
826     INSN_LABEL(fconst_1),
827     INSN_LABEL(fconst_2),
828     INSN_LABEL(dconst_0),
829     INSN_LABEL(dconst_1),
830     INSN_LABEL(bipush),
831     INSN_LABEL(sipush),
832     INSN_LABEL(ldc),
833     INSN_LABEL(ldc_w),
834     INSN_LABEL(ldc2_w),
835     INSN_LABEL(iload),
836     INSN_LABEL(lload),
837     INSN_LABEL(fload),
838     INSN_LABEL(dload),
839     INSN_LABEL(aload),
840     INSN_LABEL(iload_0),
841     INSN_LABEL(iload_1),
842     INSN_LABEL(iload_2),
843     INSN_LABEL(iload_3),
844     INSN_LABEL(lload_0),
845     INSN_LABEL(lload_1),
846     INSN_LABEL(lload_2),
847     INSN_LABEL(lload_3),
848     INSN_LABEL(fload_0),
849     INSN_LABEL(fload_1),
850     INSN_LABEL(fload_2),
851     INSN_LABEL(fload_3),
852     INSN_LABEL(dload_0),
853     INSN_LABEL(dload_1),
854     INSN_LABEL(dload_2),
855     INSN_LABEL(dload_3),
856     INSN_LABEL(aload_0),
857     INSN_LABEL(aload_1),
858     INSN_LABEL(aload_2),
859     INSN_LABEL(aload_3),
860     INSN_LABEL(iaload),
861     INSN_LABEL(laload),
862     INSN_LABEL(faload),
863     INSN_LABEL(daload),
864     INSN_LABEL(aaload),
865     INSN_LABEL(baload),
866     INSN_LABEL(caload),
867     INSN_LABEL(saload),
868     INSN_LABEL(istore),
869     INSN_LABEL(lstore),
870     INSN_LABEL(fstore),
871     INSN_LABEL(dstore),
872     INSN_LABEL(astore),
873     INSN_LABEL(istore_0),
874     INSN_LABEL(istore_1),
875     INSN_LABEL(istore_2),
876     INSN_LABEL(istore_3),
877     INSN_LABEL(lstore_0),
878     INSN_LABEL(lstore_1),
879     INSN_LABEL(lstore_2),
880     INSN_LABEL(lstore_3),
881     INSN_LABEL(fstore_0),
882     INSN_LABEL(fstore_1),
883     INSN_LABEL(fstore_2),
884     INSN_LABEL(fstore_3),
885     INSN_LABEL(dstore_0),
886     INSN_LABEL(dstore_1),
887     INSN_LABEL(dstore_2),
888     INSN_LABEL(dstore_3),
889     INSN_LABEL(astore_0),
890     INSN_LABEL(astore_1),
891     INSN_LABEL(astore_2),
892     INSN_LABEL(astore_3),
893     INSN_LABEL(iastore),
894     INSN_LABEL(lastore),
895     INSN_LABEL(fastore),
896     INSN_LABEL(dastore),
897     INSN_LABEL(aastore),
898     INSN_LABEL(bastore),
899     INSN_LABEL(castore),
900     INSN_LABEL(sastore),
901     INSN_LABEL(pop),
902     INSN_LABEL(pop2),
903     INSN_LABEL(dup),
904     INSN_LABEL(dup_x1),
905     INSN_LABEL(dup_x2),
906     INSN_LABEL(dup2),
907     INSN_LABEL(dup2_x1),
908     INSN_LABEL(dup2_x2),
909     INSN_LABEL(swap),
910     INSN_LABEL(iadd),
911     INSN_LABEL(ladd),
912     INSN_LABEL(fadd),
913     INSN_LABEL(dadd),
914     INSN_LABEL(isub),
915     INSN_LABEL(lsub),
916     INSN_LABEL(fsub),
917     INSN_LABEL(dsub),
918     INSN_LABEL(imul),
919     INSN_LABEL(lmul),
920     INSN_LABEL(fmul),
921     INSN_LABEL(dmul),
922     INSN_LABEL(idiv),
923     INSN_LABEL(ldiv),
924     INSN_LABEL(fdiv),
925     INSN_LABEL(ddiv),
926     INSN_LABEL(irem),
927     INSN_LABEL(lrem),
928     INSN_LABEL(frem),
929     INSN_LABEL(drem),
930     INSN_LABEL(ineg),
931     INSN_LABEL(lneg),
932     INSN_LABEL(fneg),
933     INSN_LABEL(dneg),
934     INSN_LABEL(ishl),
935     INSN_LABEL(lshl),
936     INSN_LABEL(ishr),
937     INSN_LABEL(lshr),
938     INSN_LABEL(iushr),
939     INSN_LABEL(lushr),
940     INSN_LABEL(iand),
941     INSN_LABEL(land),
942     INSN_LABEL(ior),
943     INSN_LABEL(lor),
944     INSN_LABEL(ixor),
945     INSN_LABEL(lxor),
946     INSN_LABEL(iinc),
947     INSN_LABEL(i2l),
948     INSN_LABEL(i2f),
949     INSN_LABEL(i2d),
950     INSN_LABEL(l2i),
951     INSN_LABEL(l2f),
952     INSN_LABEL(l2d),
953     INSN_LABEL(f2i),
954     INSN_LABEL(f2l),
955     INSN_LABEL(f2d),
956     INSN_LABEL(d2i),
957     INSN_LABEL(d2l),
958     INSN_LABEL(d2f),
959     INSN_LABEL(i2b),
960     INSN_LABEL(i2c),
961     INSN_LABEL(i2s),
962     INSN_LABEL(lcmp),
963     INSN_LABEL(fcmpl),
964     INSN_LABEL(fcmpg),
965     INSN_LABEL(dcmpl),
966     INSN_LABEL(dcmpg),
967     INSN_LABEL(ifeq),
968     INSN_LABEL(ifne),
969     INSN_LABEL(iflt),
970     INSN_LABEL(ifge),
971     INSN_LABEL(ifgt),
972     INSN_LABEL(ifle),
973     INSN_LABEL(if_icmpeq),
974     INSN_LABEL(if_icmpne),
975     INSN_LABEL(if_icmplt),
976     INSN_LABEL(if_icmpge),
977     INSN_LABEL(if_icmpgt),
978     INSN_LABEL(if_icmple),
979     INSN_LABEL(if_acmpeq),
980     INSN_LABEL(if_acmpne),
981     INSN_LABEL(goto), 
982     INSN_LABEL(jsr),
983     INSN_LABEL(ret),
984     INSN_LABEL(tableswitch),
985     INSN_LABEL(lookupswitch),
986     INSN_LABEL(ireturn),
987     INSN_LABEL(lreturn),
988     INSN_LABEL(freturn),
989     INSN_LABEL(dreturn),
990     INSN_LABEL(areturn),
991     INSN_LABEL(return),
992     INSN_LABEL(getstatic),
993     INSN_LABEL(putstatic),
994     INSN_LABEL(getfield),
995     INSN_LABEL(putfield),
996     INSN_LABEL(invokevirtual),
997     INSN_LABEL(invokespecial),
998     INSN_LABEL(invokestatic),
999     INSN_LABEL(invokeinterface),
1000     0, /* Unused.  */
1001     INSN_LABEL(new),
1002     INSN_LABEL(newarray),
1003     INSN_LABEL(anewarray),
1004     INSN_LABEL(arraylength),
1005     INSN_LABEL(athrow),
1006     INSN_LABEL(checkcast),
1007     INSN_LABEL(instanceof),
1008     INSN_LABEL(monitorenter),
1009     INSN_LABEL(monitorexit),
1010 #ifdef DIRECT_THREADED
1011     0, // wide
1012 #else
1013     INSN_LABEL(wide),
1014 #endif
1015     INSN_LABEL(multianewarray),
1016     INSN_LABEL(ifnull),
1017     INSN_LABEL(ifnonnull),
1018     INSN_LABEL(goto_w),
1019     INSN_LABEL(jsr_w),
1020     0
1021   };
1022
1023   pc_t pc;
1024
1025 #ifdef DIRECT_THREADED
1026
1027 #define NEXT_INSN goto *((pc++)->insn)
1028 #define INTVAL() ((pc++)->int_val)
1029 #define AVAL() ((pc++)->datum)
1030
1031 #define GET1S() INTVAL ()
1032 #define GET2S() INTVAL ()
1033 #define GET1U() INTVAL ()
1034 #define GET2U() INTVAL ()
1035 #define AVAL1U() AVAL ()
1036 #define AVAL2U() AVAL ()
1037 #define AVAL2UP() AVAL ()
1038 #define SKIP_GOTO ++pc
1039 #define GOTO_VAL() (insn_slot *) pc->datum
1040 #define PCVAL(unionval) unionval.p
1041 #define AMPAMP(label) &&label
1042
1043   // Compile if we must. NOTE: Double-check locking.
1044   if (meth->prepared == NULL)
1045     {
1046       _Jv_MutexLock (&compile_mutex);
1047       if (meth->prepared == NULL)
1048         meth->compile (insn_target);
1049       _Jv_MutexUnlock (&compile_mutex);
1050     }
1051   pc = (insn_slot *) meth->prepared;
1052
1053 #else
1054
1055 #define NEXT_INSN goto *(insn_target[*pc++])
1056
1057 #define GET1S() get1s (pc++)
1058 #define GET2S() (pc += 2, get2s (pc- 2))
1059 #define GET1U() get1u (pc++)
1060 #define GET2U() (pc += 2, get2u (pc - 2))
1061 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1062 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1063 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1064 #define SKIP_GOTO pc += 2
1065 #define GOTO_VAL() pc - 1 + get2s (pc)
1066 #define PCVAL(unionval) unionval.i
1067 #define AMPAMP(label) NULL
1068
1069   pc = bytecode ();
1070
1071 #endif /* DIRECT_THREADED */
1072
1073 #define TAKE_GOTO pc = GOTO_VAL ()
1074
1075   try
1076     {
1077       // We keep nop around.  It is used if we're interpreting the
1078       // bytecodes and not doing direct threading.
1079     insn_nop:
1080       NEXT_INSN;
1081
1082       /* The first few instructions here are ordered according to their
1083          frequency, in the hope that this will improve code locality a
1084          little.  */
1085
1086     insn_aload_0:               // 0x2a
1087       LOADA (0);
1088       NEXT_INSN;
1089
1090     insn_iload:         // 0x15
1091       LOADI (GET1U ());
1092       NEXT_INSN;
1093
1094     insn_iload_1:               // 0x1b
1095       LOADI (1);
1096       NEXT_INSN;
1097
1098     insn_invokevirtual: // 0xb6
1099       {
1100         int index = GET2U ();
1101
1102         /* _Jv_Linker::resolve_pool_entry returns immediately if the
1103          * value already is resolved.  If we want to clutter up the
1104          * code here to gain a little performance, then we can check
1105          * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
1106          * directly.  For now, I don't think it is worth it.  */
1107
1108         SAVE_PC();
1109         rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
1110                                                    index)).rmethod;
1111
1112         sp -= rmeth->stack_item_count;
1113         // We don't use NULLCHECK here because we can't rely on that
1114         // working if the method is final.  So instead we do an
1115         // explicit test.
1116         if (! sp[0].o)
1117           {
1118             //printf("invokevirtual pc = %p/%i\n", pc, meth->get_pc_val(pc));
1119             throw new java::lang::NullPointerException;
1120           }
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 #ifdef DIRECT_THREADED
1136         // Rewrite instruction so that we use a faster pre-resolved
1137         // method.
1138         pc[-2].insn = &&invokevirtual_resolved;
1139         pc[-1].datum = rmeth;
1140 #endif /* DIRECT_THREADED */
1141       }
1142       goto perform_invoke;
1143
1144 #ifdef DIRECT_THREADED
1145     invokevirtual_resolved:
1146       {
1147         rmeth = (_Jv_ResolvedMethod *) AVAL ();
1148         sp -= rmeth->stack_item_count;
1149         // We don't use NULLCHECK here because we can't rely on that
1150         // working if the method is final.  So instead we do an
1151         // explicit test.
1152         if (! sp[0].o)
1153           {
1154             SAVE_PC();
1155             throw new java::lang::NullPointerException;
1156           }
1157
1158         if (rmeth->vtable_index == -1)
1159           {
1160             // final methods do not appear in the vtable,
1161             // if it does not appear in the superclass.
1162             fun = (void (*)()) rmeth->method->ncode;
1163           }
1164         else
1165           {
1166             jobject rcv = sp[0].o;
1167             _Jv_VTable *table = *(_Jv_VTable**) rcv;
1168             fun = (void (*)()) table->get_method (rmeth->vtable_index);
1169           }
1170       }
1171       goto perform_invoke;
1172 #endif /* DIRECT_THREADED */
1173
1174     perform_invoke:
1175       {
1176         SAVE_PC();
1177         
1178         /* here goes the magic again... */
1179         ffi_cif *cif = &rmeth->cif;
1180         ffi_raw *raw = (ffi_raw*) sp;
1181
1182         _Jv_value rvalue;
1183
1184 #if FFI_NATIVE_RAW_API
1185         /* We assume that this is only implemented if it's correct      */
1186         /* to use it here.  On a 64 bit machine, it never is.           */
1187         ffi_raw_call (cif, fun, (void*)&rvalue, raw);
1188 #else
1189         ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
1190 #endif
1191
1192         int rtype = cif->rtype->type;
1193
1194         /* the likelyhood of object, int, or void return is very high,
1195          * so those are checked before the switch */
1196         if (rtype == FFI_TYPE_POINTER)
1197           {
1198             PUSHA (rvalue.object_value);
1199           }
1200         else if (rtype == FFI_TYPE_SINT32)
1201           {
1202             PUSHI (rvalue.int_value);
1203           }
1204         else if (rtype == FFI_TYPE_VOID)
1205           {
1206             /* skip */
1207           }
1208         else
1209           {
1210             switch (rtype)
1211               {
1212               case FFI_TYPE_SINT8:
1213                 PUSHI ((jbyte)(rvalue.int_value & 0xff));
1214                 break;
1215
1216               case FFI_TYPE_SINT16:
1217                 PUSHI ((jshort)(rvalue.int_value & 0xffff));
1218                 break;
1219
1220               case FFI_TYPE_UINT16:
1221                 PUSHI (rvalue.int_value & 0xffff);
1222                 break;
1223
1224               case FFI_TYPE_FLOAT:
1225                 PUSHF (rvalue.float_value);
1226                 break;
1227
1228               case FFI_TYPE_DOUBLE:
1229                 PUSHD (rvalue.double_value);
1230                 break;
1231
1232               case FFI_TYPE_SINT64:
1233                 PUSHL (rvalue.long_value);
1234                 break;
1235
1236               default:
1237                 throw_internal_error ("unknown return type in invokeXXX");
1238               }
1239           }
1240       }
1241       NEXT_INSN;
1242
1243     insn_aconst_null:
1244       PUSHA (NULL);
1245       NEXT_INSN;
1246
1247     insn_iconst_m1:
1248       PUSHI (-1);
1249       NEXT_INSN;
1250
1251     insn_iconst_0:
1252       PUSHI (0);
1253       NEXT_INSN;
1254
1255     insn_iconst_1:
1256       PUSHI (1);
1257       NEXT_INSN;
1258
1259     insn_iconst_2:
1260       PUSHI (2);
1261       NEXT_INSN;
1262
1263     insn_iconst_3:
1264       PUSHI (3);
1265       NEXT_INSN;
1266
1267     insn_iconst_4:
1268       PUSHI (4);
1269       NEXT_INSN;
1270
1271     insn_iconst_5:
1272       PUSHI (5);
1273       NEXT_INSN;
1274
1275     insn_lconst_0:
1276       PUSHL (0);
1277       NEXT_INSN;
1278
1279     insn_lconst_1:
1280       PUSHL (1);
1281       NEXT_INSN;
1282
1283     insn_fconst_0:
1284       PUSHF (0);
1285       NEXT_INSN;
1286
1287     insn_fconst_1:
1288       PUSHF (1);
1289       NEXT_INSN;
1290
1291     insn_fconst_2:
1292       PUSHF (2);
1293       NEXT_INSN;
1294
1295     insn_dconst_0:
1296       PUSHD (0);
1297       NEXT_INSN;
1298
1299     insn_dconst_1:
1300       PUSHD (1);
1301       NEXT_INSN;
1302
1303     insn_bipush:
1304       // For direct threaded, bipush and sipush are the same.
1305 #ifndef DIRECT_THREADED
1306       PUSHI (GET1S ());
1307       NEXT_INSN;
1308 #endif /* DIRECT_THREADED */
1309     insn_sipush:
1310       PUSHI (GET2S ());
1311       NEXT_INSN;
1312
1313     insn_ldc:
1314       // For direct threaded, ldc and ldc_w are the same.
1315 #ifndef DIRECT_THREADED
1316       PUSHA ((jobject) AVAL1U ());
1317       NEXT_INSN;
1318 #endif /* DIRECT_THREADED */
1319     insn_ldc_w:
1320       PUSHA ((jobject) AVAL2U ());
1321       NEXT_INSN;
1322
1323     insn_ldc2_w:
1324       {
1325         void *where = AVAL2UP ();
1326         memcpy (sp, where, 2*sizeof (_Jv_word));
1327         sp += 2;
1328       }
1329       NEXT_INSN;
1330
1331     insn_lload:
1332       LOADL (GET1U ());
1333       NEXT_INSN;
1334
1335     insn_fload:
1336       LOADF (GET1U ());
1337       NEXT_INSN;
1338
1339     insn_dload:
1340       LOADD (GET1U ());
1341       NEXT_INSN;
1342
1343     insn_aload:
1344       LOADA (GET1U ());
1345       NEXT_INSN;
1346
1347     insn_iload_0:
1348       LOADI (0);
1349       NEXT_INSN;
1350
1351     insn_iload_2:
1352       LOADI (2);
1353       NEXT_INSN;
1354
1355     insn_iload_3:
1356       LOADI (3);
1357       NEXT_INSN;
1358
1359     insn_lload_0:
1360       LOADL (0);
1361       NEXT_INSN;
1362
1363     insn_lload_1:
1364       LOADL (1);
1365       NEXT_INSN;
1366
1367     insn_lload_2:
1368       LOADL (2);
1369       NEXT_INSN;
1370
1371     insn_lload_3:
1372       LOADL (3);
1373       NEXT_INSN;
1374
1375     insn_fload_0:
1376       LOADF (0);
1377       NEXT_INSN;
1378
1379     insn_fload_1:
1380       LOADF (1);
1381       NEXT_INSN;
1382
1383     insn_fload_2:
1384       LOADF (2);
1385       NEXT_INSN;
1386
1387     insn_fload_3:
1388       LOADF (3);
1389       NEXT_INSN;
1390
1391     insn_dload_0:
1392       LOADD (0);
1393       NEXT_INSN;
1394
1395     insn_dload_1:
1396       LOADD (1);
1397       NEXT_INSN;
1398
1399     insn_dload_2:
1400       LOADD (2);
1401       NEXT_INSN;
1402
1403     insn_dload_3:
1404       LOADD (3);
1405       NEXT_INSN;
1406
1407     insn_aload_1:
1408       LOADA(1);
1409       NEXT_INSN;
1410
1411     insn_aload_2:
1412       LOADA(2);
1413       NEXT_INSN;
1414
1415     insn_aload_3:
1416       LOADA(3);
1417       NEXT_INSN;
1418
1419     insn_iaload:
1420       {
1421         jint index = POPI();
1422         jintArray arr = (jintArray) POPA();
1423         NULLARRAYCHECK (arr);
1424         ARRAYBOUNDSCHECK (arr, index);
1425         PUSHI( elements(arr)[index] );
1426       }
1427       NEXT_INSN;
1428
1429     insn_laload:
1430       {
1431         jint index = POPI();
1432         jlongArray arr = (jlongArray) POPA();
1433         NULLARRAYCHECK (arr);
1434         ARRAYBOUNDSCHECK (arr, index);
1435         PUSHL( elements(arr)[index] );
1436       }
1437       NEXT_INSN;
1438
1439     insn_faload:
1440       {
1441         jint index = POPI();
1442         jfloatArray arr = (jfloatArray) POPA();
1443         NULLARRAYCHECK (arr);
1444         ARRAYBOUNDSCHECK (arr, index);
1445         PUSHF( elements(arr)[index] );
1446       }
1447       NEXT_INSN;
1448
1449     insn_daload:
1450       {
1451         jint index = POPI();
1452         jdoubleArray arr = (jdoubleArray) POPA();
1453         NULLARRAYCHECK (arr);
1454         ARRAYBOUNDSCHECK (arr, index);
1455         PUSHD( elements(arr)[index] );
1456       }
1457       NEXT_INSN;
1458
1459     insn_aaload:
1460       {
1461         jint index = POPI();
1462         jobjectArray arr = (jobjectArray) POPA();
1463         NULLARRAYCHECK (arr);
1464         ARRAYBOUNDSCHECK (arr, index);
1465         PUSHA( elements(arr)[index] );
1466       }
1467       NEXT_INSN;
1468
1469     insn_baload:
1470       {
1471         jint index = POPI();
1472         jbyteArray arr = (jbyteArray) POPA();
1473         NULLARRAYCHECK (arr);
1474         ARRAYBOUNDSCHECK (arr, index);
1475         PUSHI( elements(arr)[index] );
1476       }
1477       NEXT_INSN;
1478
1479     insn_caload:
1480       {
1481         jint index = POPI();
1482         jcharArray arr = (jcharArray) POPA();
1483         NULLARRAYCHECK (arr);
1484         ARRAYBOUNDSCHECK (arr, index);
1485         PUSHI( elements(arr)[index] );
1486       }
1487       NEXT_INSN;
1488
1489     insn_saload:
1490       {
1491         jint index = POPI();
1492         jshortArray arr = (jshortArray) POPA();
1493         NULLARRAYCHECK (arr);
1494         ARRAYBOUNDSCHECK (arr, index);
1495         PUSHI( elements(arr)[index] );
1496       }
1497       NEXT_INSN;
1498
1499     insn_istore:
1500       STOREI (GET1U ());
1501       NEXT_INSN;
1502
1503     insn_lstore:
1504       STOREL (GET1U ());
1505       NEXT_INSN;
1506
1507     insn_fstore:
1508       STOREF (GET1U ());
1509       NEXT_INSN;
1510
1511     insn_dstore:
1512       STORED (GET1U ());
1513       NEXT_INSN;
1514
1515     insn_astore:
1516       STOREA (GET1U ());
1517       NEXT_INSN;
1518
1519     insn_istore_0:
1520       STOREI (0);
1521       NEXT_INSN;
1522
1523     insn_istore_1:
1524       STOREI (1);
1525       NEXT_INSN;
1526
1527     insn_istore_2:
1528       STOREI (2);
1529       NEXT_INSN;
1530
1531     insn_istore_3:
1532       STOREI (3);
1533       NEXT_INSN;
1534
1535     insn_lstore_0:
1536       STOREL (0);
1537       NEXT_INSN;
1538
1539     insn_lstore_1:
1540       STOREL (1);
1541       NEXT_INSN;
1542
1543     insn_lstore_2:
1544       STOREL (2);
1545       NEXT_INSN;
1546
1547     insn_lstore_3:
1548       STOREL (3);
1549       NEXT_INSN;
1550
1551     insn_fstore_0:
1552       STOREF (0);
1553       NEXT_INSN;
1554
1555     insn_fstore_1:
1556       STOREF (1);
1557       NEXT_INSN;
1558
1559     insn_fstore_2:
1560       STOREF (2);
1561       NEXT_INSN;
1562
1563     insn_fstore_3:
1564       STOREF (3);
1565       NEXT_INSN;
1566
1567     insn_dstore_0:
1568       STORED (0);
1569       NEXT_INSN;
1570
1571     insn_dstore_1:
1572       STORED (1);
1573       NEXT_INSN;
1574
1575     insn_dstore_2:
1576       STORED (2);
1577       NEXT_INSN;
1578
1579     insn_dstore_3:
1580       STORED (3);
1581       NEXT_INSN;
1582
1583     insn_astore_0:
1584       STOREA(0);
1585       NEXT_INSN;
1586
1587     insn_astore_1:
1588       STOREA(1);
1589       NEXT_INSN;
1590
1591     insn_astore_2:
1592       STOREA(2);
1593       NEXT_INSN;
1594
1595     insn_astore_3:
1596       STOREA(3);
1597       NEXT_INSN;
1598
1599     insn_iastore:
1600       {
1601         jint value = POPI();
1602         jint index  = POPI();
1603         jintArray arr = (jintArray) POPA();
1604         NULLARRAYCHECK (arr);
1605         ARRAYBOUNDSCHECK (arr, index);
1606         elements(arr)[index] = value;
1607       }
1608       NEXT_INSN;
1609
1610     insn_lastore:
1611       {
1612         jlong value = POPL();
1613         jint index  = POPI();
1614         jlongArray arr = (jlongArray) POPA();
1615         NULLARRAYCHECK (arr);
1616         ARRAYBOUNDSCHECK (arr, index);
1617         elements(arr)[index] = value;
1618       }
1619       NEXT_INSN;
1620
1621     insn_fastore:
1622       {
1623         jfloat value = POPF();
1624         jint index  = POPI();
1625         jfloatArray arr = (jfloatArray) POPA();
1626         NULLARRAYCHECK (arr);
1627         ARRAYBOUNDSCHECK (arr, index);
1628         elements(arr)[index] = value;
1629       }
1630       NEXT_INSN;
1631
1632     insn_dastore:
1633       {
1634         jdouble value = POPD();
1635         jint index  = POPI();
1636         jdoubleArray arr = (jdoubleArray) POPA();
1637         NULLARRAYCHECK (arr);
1638         ARRAYBOUNDSCHECK (arr, index);
1639         elements(arr)[index] = value;
1640       }
1641       NEXT_INSN;
1642
1643     insn_aastore:
1644       {
1645         jobject value = POPA();
1646         jint index  = POPI();
1647         jobjectArray arr = (jobjectArray) POPA();
1648         NULLARRAYCHECK (arr);
1649         ARRAYBOUNDSCHECK (arr, index);
1650         _Jv_CheckArrayStore (arr, value);
1651         elements(arr)[index] = value;
1652       }
1653       NEXT_INSN;
1654
1655     insn_bastore:
1656       {
1657         jbyte value = (jbyte) POPI();
1658         jint index  = POPI();
1659         jbyteArray arr = (jbyteArray) POPA();
1660         NULLARRAYCHECK (arr);
1661         ARRAYBOUNDSCHECK (arr, index);
1662         elements(arr)[index] = value;
1663       }
1664       NEXT_INSN;
1665
1666     insn_castore:
1667       {
1668         jchar value = (jchar) POPI();
1669         jint index  = POPI();
1670         jcharArray arr = (jcharArray) POPA();
1671         NULLARRAYCHECK (arr);
1672         ARRAYBOUNDSCHECK (arr, index);
1673         elements(arr)[index] = value;
1674       }
1675       NEXT_INSN;
1676
1677     insn_sastore:
1678       {
1679         jshort value = (jshort) POPI();
1680         jint index  = POPI();
1681         jshortArray arr = (jshortArray) POPA();
1682         NULLARRAYCHECK (arr);
1683         ARRAYBOUNDSCHECK (arr, index);
1684         elements(arr)[index] = value;
1685       }
1686       NEXT_INSN;
1687
1688     insn_pop:
1689       sp -= 1;
1690       NEXT_INSN;
1691
1692     insn_pop2:
1693       sp -= 2;
1694       NEXT_INSN;
1695
1696     insn_dup:
1697       sp[0] = sp[-1];
1698       sp += 1;
1699       NEXT_INSN;
1700
1701     insn_dup_x1:
1702       dupx (sp, 1, 1); sp+=1;
1703       NEXT_INSN;
1704
1705     insn_dup_x2:
1706       dupx (sp, 1, 2); sp+=1;
1707       NEXT_INSN;
1708
1709     insn_dup2:
1710       sp[0] = sp[-2];
1711       sp[1] = sp[-1];
1712       sp += 2;
1713       NEXT_INSN;
1714
1715     insn_dup2_x1:
1716       dupx (sp, 2, 1); sp+=2;
1717       NEXT_INSN;
1718
1719     insn_dup2_x2:
1720       dupx (sp, 2, 2); sp+=2;
1721       NEXT_INSN;
1722
1723     insn_swap:
1724       {
1725         jobject tmp1 = POPA();
1726         jobject tmp2 = POPA();
1727         PUSHA (tmp1);
1728         PUSHA (tmp2);
1729       }
1730       NEXT_INSN;
1731
1732     insn_iadd:
1733       BINOPI(+);
1734       NEXT_INSN;
1735
1736     insn_ladd:
1737       BINOPL(+);
1738       NEXT_INSN;
1739
1740     insn_fadd:
1741       BINOPF(+);
1742       NEXT_INSN;
1743
1744     insn_dadd:
1745       BINOPD(+);
1746       NEXT_INSN;
1747
1748     insn_isub:
1749       BINOPI(-);
1750       NEXT_INSN;
1751
1752     insn_lsub:
1753       BINOPL(-);
1754       NEXT_INSN;
1755
1756     insn_fsub:
1757       BINOPF(-);
1758       NEXT_INSN;
1759
1760     insn_dsub:
1761       BINOPD(-);
1762       NEXT_INSN;
1763
1764     insn_imul:
1765       BINOPI(*);
1766       NEXT_INSN;
1767
1768     insn_lmul:
1769       BINOPL(*);
1770       NEXT_INSN;
1771
1772     insn_fmul:
1773       BINOPF(*);
1774       NEXT_INSN;
1775
1776     insn_dmul:
1777       BINOPD(*);
1778       NEXT_INSN;
1779
1780     insn_idiv:
1781       {
1782         jint value2 = POPI();
1783         jint value1 = POPI();
1784         jint res = _Jv_divI (value1, value2);
1785         PUSHI (res);
1786       }
1787       NEXT_INSN;
1788
1789     insn_ldiv:
1790       {
1791         jlong value2 = POPL();
1792         jlong value1 = POPL();
1793         jlong res = _Jv_divJ (value1, value2);
1794         PUSHL (res);
1795       }
1796       NEXT_INSN;
1797
1798     insn_fdiv:
1799       {
1800         jfloat value2 = POPF();
1801         jfloat value1 = POPF();
1802         jfloat res = value1 / value2;
1803         PUSHF (res);
1804       }
1805       NEXT_INSN;
1806
1807     insn_ddiv:
1808       {
1809         jdouble value2 = POPD();
1810         jdouble value1 = POPD();
1811         jdouble res = value1 / value2;
1812         PUSHD (res);
1813       }
1814       NEXT_INSN;
1815
1816     insn_irem:
1817       {
1818         jint value2 = POPI();
1819         jint value1 =  POPI();
1820         jint res = _Jv_remI (value1, value2);
1821         PUSHI (res);
1822       }
1823       NEXT_INSN;
1824
1825     insn_lrem:
1826       {
1827         jlong value2 = POPL();
1828         jlong value1 = POPL();
1829         jlong res = _Jv_remJ (value1, value2);
1830         PUSHL (res);
1831       }
1832       NEXT_INSN;
1833
1834     insn_frem:
1835       {
1836         jfloat value2 = POPF();
1837         jfloat value1 = POPF();
1838         jfloat res    = __ieee754_fmod (value1, value2);
1839         PUSHF (res);
1840       }
1841       NEXT_INSN;
1842
1843     insn_drem:
1844       {
1845         jdouble value2 = POPD();
1846         jdouble value1 = POPD();
1847         jdouble res    = __ieee754_fmod (value1, value2);
1848         PUSHD (res);
1849       }
1850       NEXT_INSN;
1851
1852     insn_ineg:
1853       {
1854         jint value = POPI();
1855         PUSHI (value * -1);
1856       }
1857       NEXT_INSN;
1858
1859     insn_lneg:
1860       {
1861         jlong value = POPL();
1862         PUSHL (value * -1);
1863       }
1864       NEXT_INSN;
1865
1866     insn_fneg:
1867       {
1868         jfloat value = POPF();
1869         PUSHF (value * -1);
1870       }
1871       NEXT_INSN;
1872
1873     insn_dneg:
1874       {
1875         jdouble value = POPD();
1876         PUSHD (value * -1);
1877       }
1878       NEXT_INSN;
1879
1880     insn_ishl:
1881       {
1882         jint shift = (POPI() & 0x1f);
1883         jint value = POPI();
1884         PUSHI (value << shift);
1885       }
1886       NEXT_INSN;
1887
1888     insn_lshl:
1889       {
1890         jint shift = (POPI() & 0x3f);
1891         jlong value = POPL();
1892         PUSHL (value << shift);
1893       }
1894       NEXT_INSN;
1895
1896     insn_ishr:
1897       {
1898         jint shift = (POPI() & 0x1f);
1899         jint value = POPI();
1900         PUSHI (value >> shift);
1901       }
1902       NEXT_INSN;
1903
1904     insn_lshr:
1905       {
1906         jint shift = (POPI() & 0x3f);
1907         jlong value = POPL();
1908         PUSHL (value >> shift);
1909       }
1910       NEXT_INSN;
1911
1912     insn_iushr:
1913       {
1914         jint shift = (POPI() & 0x1f);
1915         _Jv_uint value = (_Jv_uint) POPI();
1916         PUSHI ((jint) (value >> shift));
1917       }
1918       NEXT_INSN;
1919
1920     insn_lushr:
1921       {
1922         jint shift = (POPI() & 0x3f);
1923         _Jv_ulong value = (_Jv_ulong) POPL();
1924         PUSHL ((jlong) (value >> shift));
1925       }
1926       NEXT_INSN;
1927
1928     insn_iand:
1929       BINOPI (&);
1930       NEXT_INSN;
1931
1932     insn_land:
1933       BINOPL (&);
1934       NEXT_INSN;
1935
1936     insn_ior:
1937       BINOPI (|);
1938       NEXT_INSN;
1939
1940     insn_lor:
1941       BINOPL (|);
1942       NEXT_INSN;
1943
1944     insn_ixor:
1945       BINOPI (^);
1946       NEXT_INSN;
1947
1948     insn_lxor:
1949       BINOPL (^);
1950       NEXT_INSN;
1951
1952     insn_iinc:
1953       {
1954         jint index  = GET1U ();
1955         jint amount = GET1S ();
1956         locals[index].i += amount;
1957       }
1958       NEXT_INSN;
1959
1960     insn_i2l:
1961       {jlong value = POPI(); PUSHL (value);}
1962       NEXT_INSN;
1963
1964     insn_i2f:
1965       {jfloat value = POPI(); PUSHF (value);}
1966       NEXT_INSN;
1967
1968     insn_i2d:
1969       {jdouble value = POPI(); PUSHD (value);}
1970       NEXT_INSN;
1971
1972     insn_l2i:
1973       {jint value = POPL(); PUSHI (value);}
1974       NEXT_INSN;
1975
1976     insn_l2f:
1977       {jfloat value = POPL(); PUSHF (value);}
1978       NEXT_INSN;
1979
1980     insn_l2d:
1981       {jdouble value = POPL(); PUSHD (value);}
1982       NEXT_INSN;
1983
1984     insn_f2i:
1985       {
1986         using namespace java::lang;
1987         jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1988         PUSHI(value);
1989       }
1990       NEXT_INSN;
1991
1992     insn_f2l:
1993       {
1994         using namespace java::lang;
1995         jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1996         PUSHL(value);
1997       }
1998       NEXT_INSN;
1999
2000     insn_f2d:
2001       { jdouble value = POPF (); PUSHD(value); }
2002       NEXT_INSN;
2003
2004     insn_d2i:
2005       {
2006         using namespace java::lang;
2007         jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
2008         PUSHI(value);
2009       }
2010       NEXT_INSN;
2011
2012     insn_d2l:
2013       {
2014         using namespace java::lang;
2015         jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
2016         PUSHL(value);
2017       }
2018       NEXT_INSN;
2019
2020     insn_d2f:
2021       { jfloat value = POPD (); PUSHF(value); }
2022       NEXT_INSN;
2023
2024     insn_i2b:
2025       { jbyte value = POPI (); PUSHI(value); }
2026       NEXT_INSN;
2027
2028     insn_i2c:
2029       { jchar value = POPI (); PUSHI(value); }
2030       NEXT_INSN;
2031
2032     insn_i2s:
2033       { jshort value = POPI (); PUSHI(value); }
2034       NEXT_INSN;
2035
2036     insn_lcmp:
2037       {
2038         jlong value2 = POPL ();
2039         jlong value1 = POPL ();
2040         if (value1 > value2)
2041           { PUSHI (1); }
2042         else if (value1 == value2)
2043           { PUSHI (0); }
2044         else
2045           { PUSHI (-1); }
2046       }
2047       NEXT_INSN;
2048
2049     insn_fcmpl:
2050       tmpval = -1;
2051       goto fcmp;
2052
2053     insn_fcmpg:
2054       tmpval = 1;
2055
2056     fcmp:
2057       {
2058         jfloat value2 = POPF ();
2059         jfloat value1 = POPF ();
2060         if (value1 > value2)
2061           PUSHI (1);
2062         else if (value1 == value2)
2063           PUSHI (0);
2064         else if (value1 < value2)
2065           PUSHI (-1);
2066         else
2067           PUSHI (tmpval);
2068       }
2069       NEXT_INSN;
2070
2071     insn_dcmpl:
2072       tmpval = -1;
2073       goto dcmp;
2074
2075     insn_dcmpg:
2076       tmpval = 1;
2077
2078     dcmp:
2079       {
2080         jdouble value2 = POPD ();
2081         jdouble value1 = POPD ();
2082         if (value1 > value2)
2083           PUSHI (1);
2084         else if (value1 == value2)
2085           PUSHI (0);
2086         else if (value1 < value2)
2087           PUSHI (-1);
2088         else
2089           PUSHI (tmpval);
2090       }
2091       NEXT_INSN;
2092
2093     insn_ifeq:
2094       {
2095         if (POPI() == 0)
2096           TAKE_GOTO;
2097         else
2098           SKIP_GOTO;
2099       }
2100       NEXT_INSN;
2101
2102     insn_ifne:
2103       {
2104         if (POPI() != 0)
2105           TAKE_GOTO;
2106         else
2107           SKIP_GOTO;
2108       }
2109       NEXT_INSN;
2110
2111     insn_iflt:
2112       {
2113         if (POPI() < 0)
2114           TAKE_GOTO;
2115         else
2116           SKIP_GOTO;
2117       }
2118       NEXT_INSN;
2119
2120     insn_ifge:
2121       {
2122         if (POPI() >= 0)
2123           TAKE_GOTO;
2124         else
2125           SKIP_GOTO;
2126       }
2127       NEXT_INSN;
2128
2129     insn_ifgt:
2130       {
2131         if (POPI() > 0)
2132           TAKE_GOTO;
2133         else
2134           SKIP_GOTO;
2135       }
2136       NEXT_INSN;
2137
2138     insn_ifle:
2139       {
2140         if (POPI() <= 0)
2141           TAKE_GOTO;
2142         else
2143           SKIP_GOTO;
2144       }
2145       NEXT_INSN;
2146
2147     insn_if_icmpeq:
2148       {
2149         jint value2 = POPI();
2150         jint value1 = POPI();
2151         if (value1 == value2)
2152           TAKE_GOTO;
2153         else
2154           SKIP_GOTO;
2155       }
2156       NEXT_INSN;
2157
2158     insn_if_icmpne:
2159       {
2160         jint value2 = POPI();
2161         jint value1 = POPI();
2162         if (value1 != value2)
2163           TAKE_GOTO;
2164         else
2165           SKIP_GOTO;
2166       }
2167       NEXT_INSN;
2168
2169     insn_if_icmplt:
2170       {
2171         jint value2 = POPI();
2172         jint value1 = POPI();
2173         if (value1 < value2)
2174           TAKE_GOTO;
2175         else
2176           SKIP_GOTO;
2177       }
2178       NEXT_INSN;
2179
2180     insn_if_icmpge:
2181       {
2182         jint value2 = POPI();
2183         jint value1 = POPI();
2184         if (value1 >= value2)
2185           TAKE_GOTO;
2186         else
2187           SKIP_GOTO;
2188       }
2189       NEXT_INSN;
2190
2191     insn_if_icmpgt:
2192       {
2193         jint value2 = POPI();
2194         jint value1 = POPI();
2195         if (value1 > value2)
2196           TAKE_GOTO;
2197         else
2198           SKIP_GOTO;
2199       }
2200       NEXT_INSN;
2201
2202     insn_if_icmple:
2203       {
2204         jint value2 = POPI();
2205         jint value1 = POPI();
2206         if (value1 <= value2)
2207           TAKE_GOTO;
2208         else
2209           SKIP_GOTO;
2210       }
2211       NEXT_INSN;
2212
2213     insn_if_acmpeq:
2214       {
2215         jobject value2 = POPA();
2216         jobject value1 = POPA();
2217         if (value1 == value2)
2218           TAKE_GOTO;
2219         else
2220           SKIP_GOTO;
2221       }
2222       NEXT_INSN;
2223
2224     insn_if_acmpne:
2225       {
2226         jobject value2 = POPA();
2227         jobject value1 = POPA();
2228         if (value1 != value2)
2229           TAKE_GOTO;
2230         else
2231           SKIP_GOTO;
2232       }
2233       NEXT_INSN;
2234
2235     insn_goto_w:
2236 #ifndef DIRECT_THREADED
2237       // For direct threaded, goto and goto_w are the same.
2238       pc = pc - 1 + get4 (pc);
2239       NEXT_INSN;
2240 #endif /* DIRECT_THREADED */
2241     insn_goto:
2242       TAKE_GOTO;
2243       NEXT_INSN;
2244
2245     insn_jsr_w:
2246 #ifndef DIRECT_THREADED
2247       // For direct threaded, jsr and jsr_w are the same.
2248       {
2249         pc_t next = pc - 1 + get4 (pc);
2250         pc += 4;
2251         PUSHA ((jobject) pc);
2252         pc = next;
2253       }
2254       NEXT_INSN;
2255 #endif /* DIRECT_THREADED */
2256     insn_jsr:
2257       {
2258         pc_t next = GOTO_VAL();
2259         SKIP_GOTO;
2260         PUSHA ((jobject) pc);
2261         pc = next;
2262       }
2263       NEXT_INSN;
2264
2265     insn_ret:
2266       {
2267         jint index = GET1U ();
2268         pc = (pc_t) PEEKA (index);
2269       }
2270       NEXT_INSN;
2271
2272     insn_tableswitch:
2273       {
2274 #ifdef DIRECT_THREADED
2275         void *def = (pc++)->datum;
2276
2277         int index = POPI();
2278
2279         jint low = INTVAL ();
2280         jint high = INTVAL ();
2281
2282         if (index < low || index > high)
2283           pc = (insn_slot *) def;
2284         else
2285           pc = (insn_slot *) ((pc + index - low)->datum);
2286 #else
2287         pc_t base_pc = pc - 1;
2288         int index = POPI ();
2289
2290         pc_t base = (pc_t) bytecode ();
2291         while ((pc - base) % 4 != 0)
2292           ++pc;
2293
2294         jint def = get4 (pc);
2295         jint low = get4 (pc + 4);
2296         jint high = get4 (pc + 8);
2297         if (index < low || index > high)
2298           pc = base_pc + def;
2299         else
2300           pc = base_pc + get4 (pc + 4 * (index - low + 3));
2301 #endif /* DIRECT_THREADED */
2302       }
2303       NEXT_INSN;
2304
2305     insn_lookupswitch:
2306       {
2307 #ifdef DIRECT_THREADED
2308         void *def = (pc++)->insn;
2309
2310         int index = POPI();
2311
2312         jint npairs = INTVAL ();
2313
2314         int max = npairs - 1;
2315         int min = 0;
2316
2317         // Simple binary search...
2318         while (min < max)
2319           {
2320             int half = (min + max) / 2;
2321             int match = pc[2 * half].int_val;
2322
2323             if (index == match)
2324               {
2325                 // Found it.
2326                 pc = (insn_slot *) pc[2 * half + 1].datum;
2327                 NEXT_INSN;
2328               }
2329             else if (index < match)
2330               // We can use HALF - 1 here because we check again on
2331               // loop exit.
2332               max = half - 1;
2333             else
2334               // We can use HALF + 1 here because we check again on
2335               // loop exit.
2336               min = half + 1;
2337           }
2338         if (index == pc[2 * min].int_val)
2339           pc = (insn_slot *) pc[2 * min + 1].datum;
2340         else
2341           pc = (insn_slot *) def;
2342 #else
2343         unsigned char *base_pc = pc-1;
2344         int index = POPI();
2345
2346         unsigned char* base = bytecode ();
2347         while ((pc-base) % 4 != 0)
2348           ++pc;
2349
2350         jint def     = get4 (pc);
2351         jint npairs  = get4 (pc+4);
2352
2353         int max = npairs-1;
2354         int min = 0;
2355
2356         // Simple binary search...
2357         while (min < max)
2358           {
2359             int half = (min+max)/2;
2360             int match = get4 (pc+ 4*(2 + 2*half));
2361
2362             if (index == match)
2363               min = max = half;
2364             else if (index < match)
2365               // We can use HALF - 1 here because we check again on
2366               // loop exit.
2367               max = half - 1;
2368             else
2369               // We can use HALF + 1 here because we check again on
2370               // loop exit.
2371               min = half + 1;
2372           }
2373
2374         if (index == get4 (pc+ 4*(2 + 2*min)))
2375           pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
2376         else
2377           pc = base_pc + def;    
2378 #endif /* DIRECT_THREADED */
2379       }
2380       NEXT_INSN;
2381
2382     insn_areturn:
2383       *(jobject *) retp = POPA ();
2384       return;
2385
2386     insn_lreturn:
2387       *(jlong *) retp = POPL ();
2388       return;
2389
2390     insn_freturn:
2391       *(jfloat *) retp = POPF ();
2392       return;
2393
2394     insn_dreturn:
2395       *(jdouble *) retp = POPD ();
2396       return;
2397
2398     insn_ireturn:
2399       *(jint *) retp = POPI ();
2400       return;
2401
2402     insn_return:
2403       return;
2404
2405     insn_getstatic:
2406       {
2407         jint fieldref_index = GET2U ();
2408         SAVE_PC(); // Constant pool resolution could throw.
2409         _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2410         _Jv_Field *field = pool_data[fieldref_index].field;
2411
2412         if ((field->flags & Modifier::STATIC) == 0)
2413           throw_incompatible_class_change_error 
2414             (JvNewStringLatin1 ("field no longer static"));
2415
2416         jclass type = field->type;
2417
2418         // We rewrite the instruction once we discover what it refers
2419         // to.
2420         void *newinsn = NULL;
2421         if (type->isPrimitive ())
2422           {
2423             switch (type->size_in_bytes)
2424               {
2425               case 1:
2426                 PUSHI (*field->u.byte_addr);
2427                 newinsn = AMPAMP (getstatic_resolved_1);
2428                 break;
2429
2430               case 2:
2431                 if (type == JvPrimClass (char))
2432                   {
2433                     PUSHI (*field->u.char_addr);
2434                     newinsn = AMPAMP (getstatic_resolved_char);
2435                   }
2436                 else
2437                   {
2438                     PUSHI (*field->u.short_addr);
2439                     newinsn = AMPAMP (getstatic_resolved_short);
2440                   }
2441                 break;
2442
2443               case 4:
2444                 PUSHI(*field->u.int_addr);
2445                 newinsn = AMPAMP (getstatic_resolved_4);
2446                 break;
2447
2448               case 8:
2449                 PUSHL(*field->u.long_addr);
2450                 newinsn = AMPAMP (getstatic_resolved_8);
2451                 break;
2452               }
2453           }
2454         else
2455           {
2456             PUSHA(*field->u.object_addr);
2457             newinsn = AMPAMP (getstatic_resolved_obj);
2458           }
2459
2460 #ifdef DIRECT_THREADED
2461         pc[-2].insn = newinsn;
2462         pc[-1].datum = field->u.addr;
2463 #endif /* DIRECT_THREADED */
2464       }
2465       NEXT_INSN;
2466
2467 #ifdef DIRECT_THREADED
2468     getstatic_resolved_1:
2469       PUSHI (*(jbyte *) AVAL ());
2470       NEXT_INSN;
2471
2472     getstatic_resolved_char:
2473       PUSHI (*(jchar *) AVAL ());
2474       NEXT_INSN;
2475
2476     getstatic_resolved_short:
2477       PUSHI (*(jshort *) AVAL ());
2478       NEXT_INSN;
2479
2480     getstatic_resolved_4:
2481       PUSHI (*(jint *) AVAL ());
2482       NEXT_INSN;
2483
2484     getstatic_resolved_8:
2485       PUSHL (*(jlong *) AVAL ());
2486       NEXT_INSN;
2487
2488     getstatic_resolved_obj:
2489       PUSHA (*(jobject *) AVAL ());
2490       NEXT_INSN;
2491 #endif /* DIRECT_THREADED */
2492
2493     insn_getfield:
2494       {
2495         jint fieldref_index = GET2U ();
2496         _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2497         _Jv_Field *field = pool_data[fieldref_index].field;
2498
2499         if ((field->flags & Modifier::STATIC) != 0)
2500           throw_incompatible_class_change_error 
2501             (JvNewStringLatin1 ("field is static"));
2502
2503         jclass type = field->type;
2504         jint field_offset = field->u.boffset;
2505         if (field_offset > 0xffff)
2506           throw new java::lang::VirtualMachineError;
2507
2508         jobject obj   = POPA();
2509         NULLCHECK(obj);
2510
2511         void *newinsn = NULL;
2512         _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
2513         if (type->isPrimitive ())
2514           {
2515             switch (type->size_in_bytes)
2516               {
2517               case 1:
2518                 PUSHI (val->byte_value);
2519                 newinsn = AMPAMP (getfield_resolved_1);
2520                 break;
2521
2522               case 2:
2523                 if (type == JvPrimClass (char))
2524                   {
2525                     PUSHI (val->char_value);
2526                     newinsn = AMPAMP (getfield_resolved_char);
2527                   }
2528                 else
2529                   {
2530                     PUSHI (val->short_value);
2531                     newinsn = AMPAMP (getfield_resolved_short);
2532                   }
2533                 break;
2534
2535               case 4:
2536                 PUSHI (val->int_value);
2537                 newinsn = AMPAMP (getfield_resolved_4);
2538                 break;
2539
2540               case 8:
2541                 PUSHL (val->long_value);
2542                 newinsn = AMPAMP (getfield_resolved_8);
2543                 break;
2544               }
2545           }
2546         else
2547           {
2548             PUSHA (val->object_value);
2549             newinsn = AMPAMP (getfield_resolved_obj);
2550           }
2551
2552 #ifdef DIRECT_THREADED
2553         pc[-2].insn = newinsn;
2554         pc[-1].int_val = field_offset;
2555 #endif /* DIRECT_THREADED */
2556       }
2557       NEXT_INSN;
2558
2559 #ifdef DIRECT_THREADED
2560     getfield_resolved_1:
2561       {
2562         char *obj = (char *) POPA ();
2563         NULLCHECK (obj);
2564         PUSHI (*(jbyte *) (obj + INTVAL ()));
2565       }
2566       NEXT_INSN;
2567
2568     getfield_resolved_char:
2569       {
2570         char *obj = (char *) POPA ();
2571         NULLCHECK (obj);
2572         PUSHI (*(jchar *) (obj + INTVAL ()));
2573       }
2574       NEXT_INSN;
2575
2576     getfield_resolved_short:
2577       {
2578         char *obj = (char *) POPA ();
2579         NULLCHECK (obj);
2580         PUSHI (*(jshort *) (obj + INTVAL ()));
2581       }
2582       NEXT_INSN;
2583
2584     getfield_resolved_4:
2585       {
2586         char *obj = (char *) POPA ();
2587         NULLCHECK (obj);
2588         PUSHI (*(jint *) (obj + INTVAL ()));
2589       }
2590       NEXT_INSN;
2591
2592     getfield_resolved_8:
2593       {
2594         char *obj = (char *) POPA ();
2595         NULLCHECK (obj);
2596         PUSHL (*(jlong *) (obj + INTVAL ()));
2597       }
2598       NEXT_INSN;
2599
2600     getfield_resolved_obj:
2601       {
2602         char *obj = (char *) POPA ();
2603         NULLCHECK (obj);
2604         PUSHA (*(jobject *) (obj + INTVAL ()));
2605       }
2606       NEXT_INSN;
2607 #endif /* DIRECT_THREADED */
2608
2609     insn_putstatic:
2610       {
2611         jint fieldref_index = GET2U ();
2612         _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2613         _Jv_Field *field = pool_data[fieldref_index].field;
2614
2615         jclass type = field->type;
2616
2617         // ResolvePoolEntry cannot check this
2618         if ((field->flags & Modifier::STATIC) == 0)
2619           throw_incompatible_class_change_error 
2620             (JvNewStringLatin1 ("field no longer static"));
2621
2622         void *newinsn = NULL;
2623         if (type->isPrimitive ())
2624           {
2625             switch (type->size_in_bytes) 
2626               {
2627               case 1:
2628                 {
2629                   jint value = POPI();
2630                   *field->u.byte_addr = value;
2631                   newinsn = AMPAMP (putstatic_resolved_1);
2632                   break;
2633                 }
2634
2635               case 2:
2636                 {
2637                   jint value = POPI();
2638                   *field->u.char_addr = value;
2639                   newinsn = AMPAMP (putstatic_resolved_2);
2640                   break;
2641                 }
2642
2643               case 4:
2644                 {
2645                   jint value = POPI();
2646                   *field->u.int_addr = value;
2647                   newinsn = AMPAMP (putstatic_resolved_4);
2648                   break;
2649                 }
2650
2651               case 8:
2652                 {
2653                   jlong value = POPL();
2654                   *field->u.long_addr = value;
2655                   newinsn = AMPAMP (putstatic_resolved_8);
2656                   break;
2657                 }
2658               }
2659           }
2660         else
2661           {
2662             jobject value = POPA();
2663             *field->u.object_addr = value;
2664             newinsn = AMPAMP (putstatic_resolved_obj);
2665           }
2666
2667 #ifdef DIRECT_THREADED
2668         pc[-2].insn = newinsn;
2669         pc[-1].datum = field->u.addr;
2670 #endif /* DIRECT_THREADED */
2671       }
2672       NEXT_INSN;
2673
2674 #ifdef DIRECT_THREADED
2675     putstatic_resolved_1:
2676       *(jbyte *) AVAL () = POPI ();
2677       NEXT_INSN;
2678
2679     putstatic_resolved_2:
2680       *(jchar *) AVAL () = POPI ();
2681       NEXT_INSN;
2682
2683     putstatic_resolved_4:
2684       *(jint *) AVAL () = POPI ();
2685       NEXT_INSN;
2686
2687     putstatic_resolved_8:
2688       *(jlong *) AVAL () = POPL ();
2689       NEXT_INSN;
2690
2691     putstatic_resolved_obj:
2692       *(jobject *) AVAL () = POPA ();
2693       NEXT_INSN;
2694 #endif /* DIRECT_THREADED */
2695
2696     insn_putfield:
2697       {
2698         jint fieldref_index = GET2U ();
2699         _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2700         _Jv_Field *field = pool_data[fieldref_index].field;
2701
2702         jclass type = field->type;
2703
2704         if ((field->flags & Modifier::STATIC) != 0)
2705           throw_incompatible_class_change_error 
2706             (JvNewStringLatin1 ("field is static"));
2707
2708         jint field_offset = field->u.boffset;
2709         if (field_offset > 0xffff)
2710           throw new java::lang::VirtualMachineError;
2711
2712         void *newinsn = NULL;
2713         if (type->isPrimitive ())
2714           {
2715             switch (type->size_in_bytes) 
2716               {
2717               case 1:
2718                 {
2719                   jint    value = POPI();
2720                   jobject obj   = POPA();
2721                   NULLCHECK(obj);
2722                   *(jbyte*) ((char*)obj + field_offset) = value;
2723                   newinsn = AMPAMP (putfield_resolved_1);
2724                   break;
2725                 }
2726
2727               case 2:
2728                 {
2729                   jint    value = POPI();
2730                   jobject obj   = POPA();
2731                   NULLCHECK(obj);
2732                   *(jchar*) ((char*)obj + field_offset) = value;
2733                   newinsn = AMPAMP (putfield_resolved_2);
2734                   break;
2735                 }
2736
2737               case 4:
2738                 {
2739                   jint    value = POPI();
2740                   jobject obj   = POPA();
2741                   NULLCHECK(obj);
2742                   *(jint*) ((char*)obj + field_offset) = value;
2743                   newinsn = AMPAMP (putfield_resolved_4);
2744                   break;
2745                 }
2746
2747               case 8:
2748                 {
2749                   jlong   value = POPL();
2750                   jobject obj   = POPA();
2751                   NULLCHECK(obj);
2752                   *(jlong*) ((char*)obj + field_offset) = value;
2753                   newinsn = AMPAMP (putfield_resolved_8);
2754                   break;
2755                 }
2756               }
2757           }
2758         else
2759           {
2760             jobject value = POPA();
2761             jobject obj   = POPA();
2762             NULLCHECK(obj);
2763             *(jobject*) ((char*)obj + field_offset) = value;
2764             newinsn = AMPAMP (putfield_resolved_obj);
2765           }
2766
2767 #ifdef DIRECT_THREADED
2768         pc[-2].insn = newinsn;
2769         pc[-1].int_val = field_offset;
2770 #endif /* DIRECT_THREADED */
2771       }
2772       NEXT_INSN;
2773
2774 #ifdef DIRECT_THREADED
2775     putfield_resolved_1:
2776       {
2777         jint val = POPI ();
2778         char *obj = (char *) POPA ();
2779         NULLCHECK (obj);
2780         *(jbyte *) (obj + INTVAL ()) = val;
2781       }
2782       NEXT_INSN;
2783
2784     putfield_resolved_2:
2785       {
2786         jint val = POPI ();
2787         char *obj = (char *) POPA ();
2788         NULLCHECK (obj);
2789         *(jchar *) (obj + INTVAL ()) = val;
2790       }
2791       NEXT_INSN;
2792
2793     putfield_resolved_4:
2794       {
2795         jint val = POPI ();
2796         char *obj = (char *) POPA ();
2797         NULLCHECK (obj);
2798         *(jint *) (obj + INTVAL ()) = val;
2799       }
2800       NEXT_INSN;
2801
2802     putfield_resolved_8:
2803       {
2804         jlong val = POPL ();
2805         char *obj = (char *) POPA ();
2806         NULLCHECK (obj);
2807         *(jlong *) (obj + INTVAL ()) = val;
2808       }
2809       NEXT_INSN;
2810
2811     putfield_resolved_obj:
2812       {
2813         jobject val = POPA ();
2814         char *obj = (char *) POPA ();
2815         NULLCHECK (obj);
2816         *(jobject *) (obj + INTVAL ()) = val;
2817       }
2818       NEXT_INSN;
2819 #endif /* DIRECT_THREADED */
2820
2821     insn_invokespecial:
2822       {
2823         int index = GET2U ();
2824
2825         rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2826                                                    index)).rmethod;
2827
2828         sp -= rmeth->stack_item_count;
2829
2830         // We don't use NULLCHECK here because we can't rely on that
2831         // working for <init>.  So instead we do an explicit test.
2832         if (! sp[0].o)
2833           {
2834             SAVE_PC();
2835             throw new java::lang::NullPointerException;
2836           }
2837
2838         fun = (void (*)()) rmeth->method->ncode;
2839
2840 #ifdef DIRECT_THREADED
2841         // Rewrite instruction so that we use a faster pre-resolved
2842         // method.
2843         pc[-2].insn = &&invokespecial_resolved;
2844         pc[-1].datum = rmeth;
2845 #endif /* DIRECT_THREADED */
2846       }
2847       goto perform_invoke;
2848
2849 #ifdef DIRECT_THREADED
2850     invokespecial_resolved:
2851       {
2852         rmeth = (_Jv_ResolvedMethod *) AVAL ();
2853         sp -= rmeth->stack_item_count;
2854         // We don't use NULLCHECK here because we can't rely on that
2855         // working for <init>.  So instead we do an explicit test.
2856         if (! sp[0].o)
2857           {
2858             SAVE_PC();
2859             throw new java::lang::NullPointerException;
2860           }
2861         fun = (void (*)()) rmeth->method->ncode;
2862       }
2863       goto perform_invoke;
2864 #endif /* DIRECT_THREADED */
2865
2866     insn_invokestatic:
2867       {
2868         int index = GET2U ();
2869
2870         rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2871                                                    index)).rmethod;
2872
2873         sp -= rmeth->stack_item_count;
2874
2875         fun = (void (*)()) rmeth->method->ncode;
2876
2877 #ifdef DIRECT_THREADED
2878         // Rewrite instruction so that we use a faster pre-resolved
2879         // method.
2880         pc[-2].insn = &&invokestatic_resolved;
2881         pc[-1].datum = rmeth;
2882 #endif /* DIRECT_THREADED */
2883       }
2884       goto perform_invoke;
2885
2886 #ifdef DIRECT_THREADED
2887     invokestatic_resolved:
2888       {
2889         rmeth = (_Jv_ResolvedMethod *) AVAL ();
2890         sp -= rmeth->stack_item_count;
2891         fun = (void (*)()) rmeth->method->ncode;
2892       }
2893       goto perform_invoke;
2894 #endif /* DIRECT_THREADED */
2895
2896     insn_invokeinterface:
2897       {
2898         int index = GET2U ();
2899
2900         rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2901                                                    index)).rmethod;
2902
2903         sp -= rmeth->stack_item_count;
2904
2905         jobject rcv = sp[0].o;
2906
2907         NULLCHECK (rcv);
2908
2909         fun = (void (*)())
2910           _Jv_LookupInterfaceMethod (rcv->getClass (),
2911                                      rmeth->method->name,
2912                                      rmeth->method->signature);
2913
2914 #ifdef DIRECT_THREADED
2915         // Rewrite instruction so that we use a faster pre-resolved
2916         // method.
2917         pc[-2].insn = &&invokeinterface_resolved;
2918         pc[-1].datum = rmeth;
2919 #else
2920         // Skip dummy bytes.
2921         pc += 2;
2922 #endif /* DIRECT_THREADED */
2923       }
2924       goto perform_invoke;
2925
2926 #ifdef DIRECT_THREADED
2927     invokeinterface_resolved:
2928       {
2929         rmeth = (_Jv_ResolvedMethod *) AVAL ();
2930         sp -= rmeth->stack_item_count;
2931         jobject rcv = sp[0].o;
2932         NULLCHECK (rcv);
2933         fun = (void (*)())
2934           _Jv_LookupInterfaceMethod (rcv->getClass (),
2935                                      rmeth->method->name,
2936                                      rmeth->method->signature);
2937       }
2938       goto perform_invoke;
2939 #endif /* DIRECT_THREADED */
2940
2941     insn_new:
2942       {
2943         int index = GET2U ();
2944         jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2945                                                           index)).clazz;
2946         /* VM spec, section 3.11.5 */
2947         if ((klass->getModifiers() & Modifier::ABSTRACT)
2948             || klass->isInterface())
2949           throw new java::lang::InstantiationException;
2950         jobject res = _Jv_AllocObject (klass);
2951         PUSHA (res);
2952
2953 #ifdef DIRECT_THREADED
2954         pc[-2].insn = &&new_resolved;
2955         pc[-1].datum = klass;
2956 #endif /* DIRECT_THREADED */
2957       }
2958       NEXT_INSN;
2959
2960 #ifdef DIRECT_THREADED
2961     new_resolved:
2962       {
2963         jclass klass = (jclass) AVAL ();
2964         jobject res = _Jv_AllocObject (klass);
2965         PUSHA (res);
2966       }
2967       NEXT_INSN;
2968 #endif /* DIRECT_THREADED */
2969
2970     insn_newarray:
2971       {
2972         int atype = GET1U ();
2973         int size  = POPI();
2974         jobject result = _Jv_NewArray (atype, size);
2975         PUSHA (result);
2976       }
2977       NEXT_INSN;
2978
2979     insn_anewarray:
2980       {
2981         int index = GET2U ();
2982         jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2983                                                           index)).clazz;
2984         int size  = POPI();
2985         jobject result = _Jv_NewObjectArray (size, klass, 0);
2986         PUSHA (result);
2987
2988 #ifdef DIRECT_THREADED
2989         pc[-2].insn = &&anewarray_resolved;
2990         pc[-1].datum = klass;
2991 #endif /* DIRECT_THREADED */
2992       }
2993       NEXT_INSN;
2994
2995 #ifdef DIRECT_THREADED
2996     anewarray_resolved:
2997       {
2998         jclass klass = (jclass) AVAL ();
2999         int size = POPI ();
3000         jobject result = _Jv_NewObjectArray (size, klass, 0);
3001         PUSHA (result);
3002       }
3003       NEXT_INSN;
3004 #endif /* DIRECT_THREADED */
3005
3006     insn_arraylength:
3007       {
3008         __JArray *arr = (__JArray*)POPA();
3009         NULLARRAYCHECK (arr);
3010         PUSHI (arr->length);
3011       }
3012       NEXT_INSN;
3013
3014     insn_athrow:
3015       {
3016         jobject value = POPA();
3017         throw static_cast<jthrowable>(value);
3018       }
3019       NEXT_INSN;
3020
3021     insn_checkcast:
3022       {
3023         SAVE_PC();
3024         jobject value = POPA();
3025         jint index = GET2U ();
3026         jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
3027                                                        index)).clazz;
3028
3029         value = (jobject) _Jv_CheckCast (to, value);
3030
3031         PUSHA (value);
3032
3033 #ifdef DIRECT_THREADED
3034         pc[-2].insn = &&checkcast_resolved;
3035         pc[-1].datum = to;
3036 #endif /* DIRECT_THREADED */
3037       }
3038       NEXT_INSN;
3039
3040 #ifdef DIRECT_THREADED
3041     checkcast_resolved:
3042       {
3043         SAVE_PC();
3044         jobject value = POPA ();
3045         jclass to = (jclass) AVAL ();
3046         value = (jobject) _Jv_CheckCast (to, value);
3047         PUSHA (value);
3048       }
3049       NEXT_INSN;
3050 #endif /* DIRECT_THREADED */
3051
3052     insn_instanceof:
3053       {
3054         SAVE_PC();
3055         jobject value = POPA();
3056         jint index = GET2U ();
3057         jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
3058                                                        index)).clazz;
3059         PUSHI (to->isInstance (value));
3060
3061 #ifdef DIRECT_THREADED
3062         pc[-2].insn = &&instanceof_resolved;
3063         pc[-1].datum = to;
3064 #endif /* DIRECT_THREADED */
3065       }
3066       NEXT_INSN;
3067
3068 #ifdef DIRECT_THREADED
3069     instanceof_resolved:
3070       {
3071         jobject value = POPA ();
3072         jclass to = (jclass) AVAL ();
3073         PUSHI (to->isInstance (value));
3074       }
3075       NEXT_INSN;
3076 #endif /* DIRECT_THREADED */
3077
3078     insn_monitorenter:
3079       {
3080         jobject value = POPA();
3081         NULLCHECK(value);
3082         _Jv_MonitorEnter (value);
3083       }
3084       NEXT_INSN;
3085
3086     insn_monitorexit:
3087       {
3088         jobject value = POPA();
3089         NULLCHECK(value);
3090         _Jv_MonitorExit (value);
3091       }
3092       NEXT_INSN;
3093
3094     insn_ifnull:
3095       {
3096         jobject val = POPA();
3097         if (val == NULL)
3098           TAKE_GOTO;
3099         else
3100           SKIP_GOTO;
3101       }
3102       NEXT_INSN;
3103
3104     insn_ifnonnull:
3105       {
3106         jobject val = POPA();
3107         if (val != NULL)
3108           TAKE_GOTO;
3109         else
3110           SKIP_GOTO;
3111       }
3112       NEXT_INSN;
3113
3114     insn_multianewarray:
3115       {
3116         int kind_index = GET2U ();
3117         int dim        = GET1U ();
3118
3119         jclass type    
3120           = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
3121                                                kind_index)).clazz;
3122         jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
3123
3124         for (int i = dim - 1; i >= 0; i--)
3125           {
3126             sizes[i] = POPI ();
3127           }
3128
3129         jobject res    = _Jv_NewMultiArray (type,dim, sizes);
3130
3131         PUSHA (res);
3132       }
3133       NEXT_INSN;
3134
3135 #ifndef DIRECT_THREADED
3136     insn_wide:
3137       {
3138         jint the_mod_op = get1u (pc++);
3139         jint wide       = get2u (pc); pc += 2;
3140
3141         switch (the_mod_op)
3142           {
3143           case op_istore:
3144             STOREI (wide);
3145             NEXT_INSN;
3146
3147           case op_fstore:
3148             STOREF (wide);
3149             NEXT_INSN;
3150
3151           case op_astore:
3152             STOREA (wide);
3153             NEXT_INSN;
3154
3155           case op_lload:
3156             LOADL (wide);
3157             NEXT_INSN;
3158
3159           case op_dload:
3160             LOADD (wide);
3161             NEXT_INSN;
3162
3163           case op_iload:
3164             LOADI (wide);
3165             NEXT_INSN;
3166
3167           case op_fload:
3168             LOADF (wide);
3169             NEXT_INSN;
3170
3171           case op_aload:
3172             LOADA (wide);
3173             NEXT_INSN;
3174
3175           case op_lstore:
3176             STOREL (wide);
3177             NEXT_INSN;
3178
3179           case op_dstore:
3180             STORED (wide);
3181             NEXT_INSN;
3182
3183           case op_ret:
3184             pc = (unsigned char*) PEEKA (wide);
3185             NEXT_INSN;
3186
3187           case op_iinc:
3188             {
3189               jint amount = get2s (pc); pc += 2;
3190               jint value = PEEKI (wide);
3191               POKEI (wide, value+amount);
3192             }
3193             NEXT_INSN;
3194
3195           default:
3196             throw_internal_error ("illegal bytecode modified by wide");
3197           }
3198
3199       }
3200 #endif /* DIRECT_THREADED */
3201     }
3202   catch (java::lang::Throwable *ex)
3203     {
3204 #ifdef DIRECT_THREADED
3205       void *logical_pc = (void *) ((insn_slot *) pc - 1);
3206 #else
3207       int logical_pc = pc - 1 - bytecode ();
3208 #endif
3209       _Jv_InterpException *exc = meth->exceptions ();
3210       jclass exc_class = ex->getClass ();
3211
3212       for (int i = 0; i < meth->exc_count; i++)
3213         {
3214           if (PCVAL (exc[i].start_pc) <= logical_pc
3215               && logical_pc < PCVAL (exc[i].end_pc))
3216             {
3217 #ifdef DIRECT_THREADED
3218               jclass handler = (jclass) exc[i].handler_type.p;
3219 #else
3220               jclass handler = NULL;
3221               if (exc[i].handler_type.i != 0)
3222                 handler = (_Jv_Linker::resolve_pool_entry (defining_class,
3223                                                              exc[i].handler_type.i)).clazz;
3224 #endif /* DIRECT_THREADED */
3225
3226               if (handler == NULL || handler->isAssignableFrom (exc_class))
3227                 {
3228 #ifdef DIRECT_THREADED
3229                   pc = (insn_slot *) exc[i].handler_pc.p;
3230 #else
3231                   pc = bytecode () + exc[i].handler_pc.i;
3232 #endif /* DIRECT_THREADED */
3233                   sp = stack;
3234                   sp++->o = ex; // Push exception.
3235                   NEXT_INSN;
3236                 }
3237             }
3238         }
3239
3240       // No handler, so re-throw.
3241       throw ex;
3242     }
3243 }
3244
3245 static void
3246 throw_internal_error (char *msg)
3247 {
3248   throw new java::lang::InternalError (JvNewStringLatin1 (msg));
3249 }
3250
3251 static void 
3252 throw_incompatible_class_change_error (jstring msg)
3253 {
3254   throw new java::lang::IncompatibleClassChangeError (msg);
3255 }
3256
3257 #ifndef HANDLE_SEGV
3258 static java::lang::NullPointerException *null_pointer_exc;
3259 static void 
3260 throw_null_pointer_exception ()
3261 {
3262   if (null_pointer_exc == NULL)
3263     null_pointer_exc = new java::lang::NullPointerException;
3264
3265   throw null_pointer_exc;
3266 }
3267 #endif
3268
3269 /* Look up source code line number for given bytecode (or direct threaded
3270    interpreter) PC. */
3271 int
3272 _Jv_InterpMethod::get_source_line(pc_t mpc)
3273 {
3274   int line = line_table_len > 0 ? line_table[0].line : -1;
3275   for (int i = 1; i < line_table_len; i++)
3276     if (line_table[i].pc > mpc)
3277       break;
3278     else
3279       line = line_table[i].line;
3280
3281   return line;
3282 }
3283
3284 /** Do static initialization for fields with a constant initializer */
3285 void
3286 _Jv_InitField (jobject obj, jclass klass, int index)
3287 {
3288   using namespace java::lang::reflect;
3289
3290   if (obj != 0 && klass == 0)
3291     klass = obj->getClass ();
3292
3293   if (!_Jv_IsInterpretedClass (klass))
3294     return;
3295
3296   _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
3297
3298   _Jv_Field * field = (&klass->fields[0]) + index;
3299
3300   if (index > klass->field_count)
3301     throw_internal_error ("field out of range");
3302
3303   int init = iclass->field_initializers[index];
3304   if (init == 0)
3305     return;
3306
3307   _Jv_Constants *pool = &klass->constants;
3308   int tag = pool->tags[init];
3309
3310   if (! field->isResolved ())
3311     throw_internal_error ("initializing unresolved field");
3312
3313   if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
3314     throw_internal_error ("initializing non-static field with no object");
3315
3316   void *addr = 0;
3317
3318   if ((field->flags & Modifier::STATIC) != 0)
3319     addr = (void*) field->u.addr;
3320   else
3321     addr = (void*) (((char*)obj) + field->u.boffset);
3322
3323   switch (tag)
3324     {
3325     case JV_CONSTANT_String:
3326       {
3327         jstring str;
3328         str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
3329         pool->data[init].string = str;
3330         pool->tags[init] = JV_CONSTANT_ResolvedString;
3331       }
3332       /* fall through */
3333
3334     case JV_CONSTANT_ResolvedString:
3335       if (! (field->type == &java::lang::String::class$
3336              || field->type == &java::lang::Class::class$))
3337         throw_class_format_error ("string initialiser to non-string field");
3338
3339       *(jstring*)addr = pool->data[init].string;
3340       break;
3341
3342     case JV_CONSTANT_Integer:
3343       {
3344         int value = pool->data[init].i;
3345
3346         if (field->type == JvPrimClass (boolean))
3347           *(jboolean*)addr = (jboolean)value;
3348         
3349         else if (field->type == JvPrimClass (byte))
3350           *(jbyte*)addr = (jbyte)value;
3351         
3352         else if (field->type == JvPrimClass (char))
3353           *(jchar*)addr = (jchar)value;
3354
3355         else if (field->type == JvPrimClass (short))
3356           *(jshort*)addr = (jshort)value;
3357         
3358         else if (field->type == JvPrimClass (int))
3359           *(jint*)addr = (jint)value;
3360
3361         else
3362           throw_class_format_error ("erroneous field initializer");
3363       }  
3364       break;
3365
3366     case JV_CONSTANT_Long:
3367       if (field->type != JvPrimClass (long))
3368         throw_class_format_error ("erroneous field initializer");
3369
3370       *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
3371       break;
3372
3373     case JV_CONSTANT_Float:
3374       if (field->type != JvPrimClass (float))
3375         throw_class_format_error ("erroneous field initializer");
3376
3377       *(jfloat*)addr = pool->data[init].f;
3378       break;
3379
3380     case JV_CONSTANT_Double:
3381       if (field->type != JvPrimClass (double))
3382         throw_class_format_error ("erroneous field initializer");
3383
3384       *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
3385       break;
3386
3387     default:
3388       throw_class_format_error ("erroneous field initializer");
3389     }
3390 }
3391
3392 inline static unsigned char*
3393 skip_one_type (unsigned char* ptr)
3394 {
3395   int ch = *ptr++;
3396
3397   while (ch == '[')
3398     { 
3399       ch = *ptr++;
3400     }
3401   
3402   if (ch == 'L')
3403     {
3404       do { ch = *ptr++; } while (ch != ';');
3405     }
3406
3407   return ptr;
3408 }
3409
3410 static ffi_type*
3411 get_ffi_type_from_signature (unsigned char* ptr)
3412 {
3413   switch (*ptr) 
3414     {
3415     case 'L':
3416     case '[':
3417       return &ffi_type_pointer;
3418       break;
3419
3420     case 'Z':
3421       // On some platforms a bool is a byte, on others an int.
3422       if (sizeof (jboolean) == sizeof (jbyte))
3423         return &ffi_type_sint8;
3424       else
3425         {
3426           JvAssert (sizeof (jbyte) == sizeof (jint));
3427           return &ffi_type_sint32;
3428         }
3429       break;
3430
3431     case 'B':
3432       return &ffi_type_sint8;
3433       break;
3434       
3435     case 'C':
3436       return &ffi_type_uint16;
3437       break;
3438           
3439     case 'S': 
3440       return &ffi_type_sint16;
3441       break;
3442           
3443     case 'I':
3444       return &ffi_type_sint32;
3445       break;
3446           
3447     case 'J':
3448       return &ffi_type_sint64;
3449       break;
3450           
3451     case 'F':
3452       return &ffi_type_float;
3453       break;
3454           
3455     case 'D':
3456       return &ffi_type_double;
3457       break;
3458
3459     case 'V':
3460       return &ffi_type_void;
3461       break;
3462     }
3463
3464   throw_internal_error ("unknown type in signature");
3465 }
3466
3467 /* this function yields the number of actual arguments, that is, if the
3468  * function is non-static, then one is added to the number of elements
3469  * found in the signature */
3470
3471 int 
3472 _Jv_count_arguments (_Jv_Utf8Const *signature,
3473                      jboolean staticp)
3474 {
3475   unsigned char *ptr = (unsigned char*) signature->chars();
3476   int arg_count = staticp ? 0 : 1;
3477
3478   /* first, count number of arguments */
3479
3480   // skip '('
3481   ptr++;
3482
3483   // count args
3484   while (*ptr != ')')
3485     {
3486       ptr = skip_one_type (ptr);
3487       arg_count += 1;
3488     }
3489
3490   return arg_count;
3491 }
3492
3493 /* This beast will build a cif, given the signature.  Memory for
3494  * the cif itself and for the argument types must be allocated by the
3495  * caller.
3496  */
3497
3498 static int 
3499 init_cif (_Jv_Utf8Const* signature,
3500           int arg_count,
3501           jboolean staticp,
3502           ffi_cif *cif,
3503           ffi_type **arg_types,
3504           ffi_type **rtype_p)
3505 {
3506   unsigned char *ptr = (unsigned char*) signature->chars();
3507
3508   int arg_index = 0;            // arg number
3509   int item_count = 0;           // stack-item count
3510
3511   // setup receiver
3512   if (!staticp)
3513     {
3514       arg_types[arg_index++] = &ffi_type_pointer;
3515       item_count += 1;
3516     }
3517
3518   // skip '('
3519   ptr++;
3520
3521   // assign arg types
3522   while (*ptr != ')')
3523     {
3524       arg_types[arg_index++] = get_ffi_type_from_signature (ptr);
3525
3526       if (*ptr == 'J' || *ptr == 'D')
3527         item_count += 2;
3528       else
3529         item_count += 1;
3530
3531       ptr = skip_one_type (ptr);
3532     }
3533
3534   // skip ')'
3535   ptr++;
3536   ffi_type *rtype = get_ffi_type_from_signature (ptr);
3537
3538   ptr = skip_one_type (ptr);
3539   if (ptr != (unsigned char*)signature->chars() + signature->len())
3540     throw_internal_error ("did not find end of signature");
3541
3542   if (ffi_prep_cif (cif, FFI_DEFAULT_ABI,
3543                     arg_count, rtype, arg_types) != FFI_OK)
3544     throw_internal_error ("ffi_prep_cif failed");
3545
3546   if (rtype_p != NULL)
3547     *rtype_p = rtype;
3548
3549   return item_count;
3550 }
3551
3552 #if FFI_NATIVE_RAW_API
3553 #   define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure
3554 #   define FFI_RAW_SIZE ffi_raw_size
3555 #else
3556 #   define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure
3557 #   define FFI_RAW_SIZE ffi_java_raw_size
3558 #endif
3559
3560 /* we put this one here, and not in interpret.cc because it
3561  * calls the utility routines _Jv_count_arguments 
3562  * which are static to this module.  The following struct defines the
3563  * layout we use for the stubs, it's only used in the ncode method. */
3564
3565 typedef struct {
3566   ffi_raw_closure  closure;
3567   ffi_cif   cif;
3568   ffi_type *arg_types[0];
3569 } ncode_closure;
3570
3571 typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
3572
3573 void *
3574 _Jv_InterpMethod::ncode ()
3575 {
3576   using namespace java::lang::reflect;
3577
3578   if (self->ncode != 0)
3579     return self->ncode;
3580
3581   jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
3582   int arg_count = _Jv_count_arguments (self->signature, staticp);
3583
3584   ncode_closure *closure =
3585     (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
3586                                         + arg_count * sizeof (ffi_type*));
3587
3588   init_cif (self->signature,
3589             arg_count,
3590             staticp,
3591             &closure->cif,
3592             &closure->arg_types[0],
3593             NULL);
3594
3595   ffi_closure_fun fun;
3596
3597   args_raw_size = FFI_RAW_SIZE (&closure->cif);
3598
3599   JvAssert ((self->accflags & Modifier::NATIVE) == 0);
3600
3601   if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
3602     {
3603       if (staticp)
3604         fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
3605       else
3606         fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
3607     }
3608   else
3609     {
3610       if (staticp)
3611         fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
3612       else
3613         fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
3614     }
3615
3616   FFI_PREP_RAW_CLOSURE (&closure->closure,
3617                         &closure->cif, 
3618                         fun,
3619                         (void*)this);
3620
3621   self->ncode = (void*)closure;
3622   return self->ncode;
3623 }
3624
3625 void *
3626 _Jv_JNIMethod::ncode ()
3627 {
3628   using namespace java::lang::reflect;
3629
3630   if (self->ncode != 0)
3631     return self->ncode;
3632
3633   jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
3634   int arg_count = _Jv_count_arguments (self->signature, staticp);
3635
3636   ncode_closure *closure =
3637     (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
3638                                     + arg_count * sizeof (ffi_type*));
3639
3640   ffi_type *rtype;
3641   init_cif (self->signature,
3642             arg_count,
3643             staticp,
3644             &closure->cif,
3645             &closure->arg_types[0],
3646             &rtype);
3647
3648   ffi_closure_fun fun;
3649
3650   args_raw_size = FFI_RAW_SIZE (&closure->cif);
3651
3652   // Initialize the argument types and CIF that represent the actual
3653   // underlying JNI function.
3654   int extra_args = 1;
3655   if ((self->accflags & Modifier::STATIC))
3656     ++extra_args;
3657   jni_arg_types = (ffi_type **) _Jv_AllocBytes ((extra_args + arg_count)
3658                                                 * sizeof (ffi_type *));
3659   int offset = 0;
3660   jni_arg_types[offset++] = &ffi_type_pointer;
3661   if ((self->accflags & Modifier::STATIC))
3662     jni_arg_types[offset++] = &ffi_type_pointer;
3663   memcpy (&jni_arg_types[offset], &closure->arg_types[0],
3664           arg_count * sizeof (ffi_type *));
3665
3666   if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi,
3667                     extra_args + arg_count, rtype,
3668                     jni_arg_types) != FFI_OK)
3669     throw_internal_error ("ffi_prep_cif failed for JNI function");
3670
3671   JvAssert ((self->accflags & Modifier::NATIVE) != 0);
3672
3673   // FIXME: for now we assume that all native methods for
3674   // interpreted code use JNI.
3675   fun = (ffi_closure_fun) &_Jv_JNIMethod::call;
3676
3677   FFI_PREP_RAW_CLOSURE (&closure->closure,
3678                         &closure->cif, 
3679                         fun,
3680                         (void*) this);
3681
3682   self->ncode = (void *) closure;
3683   return self->ncode;
3684 }
3685
3686 static void
3687 throw_class_format_error (jstring msg)
3688 {
3689   throw (msg
3690          ? new java::lang::ClassFormatError (msg)
3691          : new java::lang::ClassFormatError);
3692 }
3693
3694 static void
3695 throw_class_format_error (char *msg)
3696 {
3697   throw_class_format_error (JvNewStringLatin1 (msg));
3698 }
3699
3700 \f
3701
3702 void
3703 _Jv_InterpreterEngine::do_verify (jclass klass)
3704 {
3705   _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
3706   for (int i = 0; i < klass->method_count; i++)
3707     {
3708       using namespace java::lang::reflect;
3709       _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
3710       _Jv_ushort accflags = klass->methods[i].accflags;
3711       if ((accflags & (Modifier::NATIVE | Modifier::ABSTRACT)) == 0)
3712         {
3713           _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
3714           _Jv_VerifyMethod (im);
3715         }
3716     }
3717 }
3718
3719 void
3720 _Jv_InterpreterEngine::do_create_ncode (jclass klass)
3721 {
3722   _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
3723   for (int i = 0; i < klass->method_count; i++)
3724     {
3725       // Just skip abstract methods.  This is particularly important
3726       // because we don't resize the interpreted_methods array when
3727       // miranda methods are added to it.
3728       if ((klass->methods[i].accflags
3729            & java::lang::reflect::Modifier::ABSTRACT)
3730           != 0)
3731         continue;
3732
3733       _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
3734
3735       if ((klass->methods[i].accflags & java::lang::reflect::Modifier::NATIVE)
3736           != 0)
3737         {
3738           // You might think we could use a virtual `ncode' method in
3739           // the _Jv_MethodBase and unify the native and non-native
3740           // cases.  Well, we can't, because we don't allocate these
3741           // objects using `new', and thus they don't get a vtable.
3742           _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth);
3743           klass->methods[i].ncode = jnim->ncode ();
3744         }
3745       else if (imeth != 0)              // it could be abstract
3746         {
3747           _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
3748           klass->methods[i].ncode = im->ncode ();
3749         }
3750     }
3751 }
3752
3753 void
3754 _Jv_InterpreterEngine::do_allocate_static_fields (jclass klass,
3755                                                   int static_size)
3756 {
3757   _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
3758
3759   char *static_data = (char *) _Jv_AllocBytes (static_size);
3760
3761   for (int i = 0; i < klass->field_count; i++)
3762     {
3763       _Jv_Field *field = &klass->fields[i];
3764
3765       if ((field->flags & java::lang::reflect::Modifier::STATIC) != 0)
3766         {
3767           field->u.addr  = static_data + field->u.boffset;
3768               
3769           if (iclass->field_initializers[i] != 0)
3770             {
3771               _Jv_Linker::resolve_field (field, klass->loader);
3772               _Jv_InitField (0, klass, i);
3773             }
3774         }
3775     }
3776
3777   // Now we don't need the field_initializers anymore, so let the
3778   // collector get rid of it.
3779   iclass->field_initializers = 0;
3780 }
3781
3782 _Jv_ResolvedMethod *
3783 _Jv_InterpreterEngine::do_resolve_method (_Jv_Method *method, jclass klass,
3784                                           jboolean staticp, jint vtable_index)
3785 {
3786   int arg_count = _Jv_count_arguments (method->signature, staticp);
3787
3788   _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*)
3789     _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod)
3790                     + arg_count*sizeof (ffi_type*));
3791
3792   result->stack_item_count
3793     = init_cif (method->signature,
3794                 arg_count,
3795                 staticp,
3796                 &result->cif,
3797                 &result->arg_types[0],
3798                 NULL);
3799
3800   result->vtable_index        = vtable_index;
3801   result->method              = method;
3802   result->klass               = klass;
3803
3804   return result;
3805 }
3806
3807 void
3808 _Jv_InterpreterEngine::do_post_miranda_hook (jclass klass)
3809 {
3810   _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
3811   for (int i = 0; i < klass->method_count; i++)
3812     {
3813       // Just skip abstract methods.  This is particularly important
3814       // because we don't resize the interpreted_methods array when
3815       // miranda methods are added to it.
3816       if ((klass->methods[i].accflags
3817            & java::lang::reflect::Modifier::ABSTRACT)
3818           != 0)
3819         continue;
3820       // Miranda method additions mean that the `methods' array moves.
3821       // We cache a pointer into this array, so we have to update.
3822       iclass->interpreted_methods[i]->self = &klass->methods[i];
3823     }
3824 }
3825
3826 #endif // INTERPRETER