OSDN Git Service

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