OSDN Git Service

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