OSDN Git Service

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