1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003 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
_Jv_InitInterpreter()64 _Jv_InitInterpreter()
65 {
66 _Jv_MutexInit (&compile_mutex);
67 }
68 #else
_Jv_InitInterpreter()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
dupx(_Jv_word * sp,int n,int x)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
convert(FROM val,TO min,TO max)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
get1s(unsigned char * loc)216 static inline jint get1s(unsigned char* loc) {
217 return *(signed char*)loc;
218 }
219
get1u(unsigned char * loc)220 static inline jint get1u(unsigned char* loc) {
221 return *loc;
222 }
223
get2s(unsigned char * loc)224 static inline jint get2s(unsigned char* loc) {
225 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
226 }
227
get2u(unsigned char * loc)228 static inline jint get2u(unsigned char* loc) {
229 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
230 }
231
get4(unsigned char * loc)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
run_normal(ffi_cif *,void * ret,ffi_raw * args,void * __this)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
run_synch_object(ffi_cif *,void * ret,ffi_raw * args,void * __this)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
run_class(ffi_cif *,void * ret,ffi_raw * args,void * __this)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
run_synch_class(ffi_cif *,void * ret,ffi_raw * args,void * __this)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
compile(const void * const * insn_targets)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
_Jv_StartOfInterpreter(void)780 _Jv_StartOfInterpreter (void)
781 {
782 }
783
784 void
run(void * retp,ffi_raw * args)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 jdouble 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 (*(jobject*)&rvalue);
1196 }
1197 else if (rtype == FFI_TYPE_SINT32)
1198 {
1199 PUSHI (*(jint*)&rvalue);
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 {
1211 jbyte value = (*(jint*)&rvalue) & 0xff;
1212 PUSHI (value);
1213 }
1214 break;
1215
1216 case FFI_TYPE_SINT16:
1217 {
1218 jshort value = (*(jint*)&rvalue) & 0xffff;
1219 PUSHI (value);
1220 }
1221 break;
1222
1223 case FFI_TYPE_UINT16:
1224 {
1225 jint value = (*(jint*)&rvalue) & 0xffff;
1226 PUSHI (value);
1227 }
1228 break;
1229
1230 case FFI_TYPE_FLOAT:
1231 PUSHF (*(jfloat*)&rvalue);
1232 break;
1233
1234 case FFI_TYPE_DOUBLE:
1235 PUSHD (rvalue);
1236 break;
1237
1238 case FFI_TYPE_SINT64:
1239 PUSHL (*(jlong*)&rvalue);
1240 break;
1241
1242 default:
1243 throw_internal_error ("unknown return type in invokeXXX");
1244 }
1245 }
1246 }
1247 NEXT_INSN;
1248
1249 insn_aconst_null:
1250 PUSHA (NULL);
1251 NEXT_INSN;
1252
1253 insn_iconst_m1:
1254 PUSHI (-1);
1255 NEXT_INSN;
1256
1257 insn_iconst_0:
1258 PUSHI (0);
1259 NEXT_INSN;
1260
1261 insn_iconst_1:
1262 PUSHI (1);
1263 NEXT_INSN;
1264
1265 insn_iconst_2:
1266 PUSHI (2);
1267 NEXT_INSN;
1268
1269 insn_iconst_3:
1270 PUSHI (3);
1271 NEXT_INSN;
1272
1273 insn_iconst_4:
1274 PUSHI (4);
1275 NEXT_INSN;
1276
1277 insn_iconst_5:
1278 PUSHI (5);
1279 NEXT_INSN;
1280
1281 insn_lconst_0:
1282 PUSHL (0);
1283 NEXT_INSN;
1284
1285 insn_lconst_1:
1286 PUSHL (1);
1287 NEXT_INSN;
1288
1289 insn_fconst_0:
1290 PUSHF (0);
1291 NEXT_INSN;
1292
1293 insn_fconst_1:
1294 PUSHF (1);
1295 NEXT_INSN;
1296
1297 insn_fconst_2:
1298 PUSHF (2);
1299 NEXT_INSN;
1300
1301 insn_dconst_0:
1302 PUSHD (0);
1303 NEXT_INSN;
1304
1305 insn_dconst_1:
1306 PUSHD (1);
1307 NEXT_INSN;
1308
1309 insn_bipush:
1310 // For direct threaded, bipush and sipush are the same.
1311 #ifndef DIRECT_THREADED
1312 PUSHI (GET1S ());
1313 NEXT_INSN;
1314 #endif /* DIRECT_THREADED */
1315 insn_sipush:
1316 PUSHI (GET2S ());
1317 NEXT_INSN;
1318
1319 insn_ldc:
1320 // For direct threaded, ldc and ldc_w are the same.
1321 #ifndef DIRECT_THREADED
1322 PUSHA ((jobject) AVAL1U ());
1323 NEXT_INSN;
1324 #endif /* DIRECT_THREADED */
1325 insn_ldc_w:
1326 PUSHA ((jobject) AVAL2U ());
1327 NEXT_INSN;
1328
1329 insn_ldc2_w:
1330 {
1331 void *where = AVAL2UP ();
1332 memcpy (sp, where, 2*sizeof (_Jv_word));
1333 sp += 2;
1334 }
1335 NEXT_INSN;
1336
1337 insn_lload:
1338 LOADL (GET1U ());
1339 NEXT_INSN;
1340
1341 insn_fload:
1342 LOADF (GET1U ());
1343 NEXT_INSN;
1344
1345 insn_dload:
1346 LOADD (GET1U ());
1347 NEXT_INSN;
1348
1349 insn_aload:
1350 LOADA (GET1U ());
1351 NEXT_INSN;
1352
1353 insn_iload_0:
1354 LOADI (0);
1355 NEXT_INSN;
1356
1357 insn_iload_2:
1358 LOADI (2);
1359 NEXT_INSN;
1360
1361 insn_iload_3:
1362 LOADI (3);
1363 NEXT_INSN;
1364
1365 insn_lload_0:
1366 LOADL (0);
1367 NEXT_INSN;
1368
1369 insn_lload_1:
1370 LOADL (1);
1371 NEXT_INSN;
1372
1373 insn_lload_2:
1374 LOADL (2);
1375 NEXT_INSN;
1376
1377 insn_lload_3:
1378 LOADL (3);
1379 NEXT_INSN;
1380
1381 insn_fload_0:
1382 LOADF (0);
1383 NEXT_INSN;
1384
1385 insn_fload_1:
1386 LOADF (1);
1387 NEXT_INSN;
1388
1389 insn_fload_2:
1390 LOADF (2);
1391 NEXT_INSN;
1392
1393 insn_fload_3:
1394 LOADF (3);
1395 NEXT_INSN;
1396
1397 insn_dload_0:
1398 LOADD (0);
1399 NEXT_INSN;
1400
1401 insn_dload_1:
1402 LOADD (1);
1403 NEXT_INSN;
1404
1405 insn_dload_2:
1406 LOADD (2);
1407 NEXT_INSN;
1408
1409 insn_dload_3:
1410 LOADD (3);
1411 NEXT_INSN;
1412
1413 insn_aload_1:
1414 LOADA(1);
1415 NEXT_INSN;
1416
1417 insn_aload_2:
1418 LOADA(2);
1419 NEXT_INSN;
1420
1421 insn_aload_3:
1422 LOADA(3);
1423 NEXT_INSN;
1424
1425 insn_iaload:
1426 {
1427 jint index = POPI();
1428 jintArray arr = (jintArray) POPA();
1429 NULLARRAYCHECK (arr);
1430 ARRAYBOUNDSCHECK (arr, index);
1431 PUSHI( elements(arr)[index] );
1432 }
1433 NEXT_INSN;
1434
1435 insn_laload:
1436 {
1437 jint index = POPI();
1438 jlongArray arr = (jlongArray) POPA();
1439 NULLARRAYCHECK (arr);
1440 ARRAYBOUNDSCHECK (arr, index);
1441 PUSHL( elements(arr)[index] );
1442 }
1443 NEXT_INSN;
1444
1445 insn_faload:
1446 {
1447 jint index = POPI();
1448 jfloatArray arr = (jfloatArray) POPA();
1449 NULLARRAYCHECK (arr);
1450 ARRAYBOUNDSCHECK (arr, index);
1451 PUSHF( elements(arr)[index] );
1452 }
1453 NEXT_INSN;
1454
1455 insn_daload:
1456 {
1457 jint index = POPI();
1458 jdoubleArray arr = (jdoubleArray) POPA();
1459 NULLARRAYCHECK (arr);
1460 ARRAYBOUNDSCHECK (arr, index);
1461 PUSHD( elements(arr)[index] );
1462 }
1463 NEXT_INSN;
1464
1465 insn_aaload:
1466 {
1467 jint index = POPI();
1468 jobjectArray arr = (jobjectArray) POPA();
1469 NULLARRAYCHECK (arr);
1470 ARRAYBOUNDSCHECK (arr, index);
1471 PUSHA( elements(arr)[index] );
1472 }
1473 NEXT_INSN;
1474
1475 insn_baload:
1476 {
1477 jint index = POPI();
1478 jbyteArray arr = (jbyteArray) POPA();
1479 NULLARRAYCHECK (arr);
1480 ARRAYBOUNDSCHECK (arr, index);
1481 PUSHI( elements(arr)[index] );
1482 }
1483 NEXT_INSN;
1484
1485 insn_caload:
1486 {
1487 jint index = POPI();
1488 jcharArray arr = (jcharArray) POPA();
1489 NULLARRAYCHECK (arr);
1490 ARRAYBOUNDSCHECK (arr, index);
1491 PUSHI( elements(arr)[index] );
1492 }
1493 NEXT_INSN;
1494
1495 insn_saload:
1496 {
1497 jint index = POPI();
1498 jshortArray arr = (jshortArray) POPA();
1499 NULLARRAYCHECK (arr);
1500 ARRAYBOUNDSCHECK (arr, index);
1501 PUSHI( elements(arr)[index] );
1502 }
1503 NEXT_INSN;
1504
1505 insn_istore:
1506 STOREI (GET1U ());
1507 NEXT_INSN;
1508
1509 insn_lstore:
1510 STOREL (GET1U ());
1511 NEXT_INSN;
1512
1513 insn_fstore:
1514 STOREF (GET1U ());
1515 NEXT_INSN;
1516
1517 insn_dstore:
1518 STORED (GET1U ());
1519 NEXT_INSN;
1520
1521 insn_astore:
1522 STOREA (GET1U ());
1523 NEXT_INSN;
1524
1525 insn_istore_0:
1526 STOREI (0);
1527 NEXT_INSN;
1528
1529 insn_istore_1:
1530 STOREI (1);
1531 NEXT_INSN;
1532
1533 insn_istore_2:
1534 STOREI (2);
1535 NEXT_INSN;
1536
1537 insn_istore_3:
1538 STOREI (3);
1539 NEXT_INSN;
1540
1541 insn_lstore_0:
1542 STOREL (0);
1543 NEXT_INSN;
1544
1545 insn_lstore_1:
1546 STOREL (1);
1547 NEXT_INSN;
1548
1549 insn_lstore_2:
1550 STOREL (2);
1551 NEXT_INSN;
1552
1553 insn_lstore_3:
1554 STOREL (3);
1555 NEXT_INSN;
1556
1557 insn_fstore_0:
1558 STOREF (0);
1559 NEXT_INSN;
1560
1561 insn_fstore_1:
1562 STOREF (1);
1563 NEXT_INSN;
1564
1565 insn_fstore_2:
1566 STOREF (2);
1567 NEXT_INSN;
1568
1569 insn_fstore_3:
1570 STOREF (3);
1571 NEXT_INSN;
1572
1573 insn_dstore_0:
1574 STORED (0);
1575 NEXT_INSN;
1576
1577 insn_dstore_1:
1578 STORED (1);
1579 NEXT_INSN;
1580
1581 insn_dstore_2:
1582 STORED (2);
1583 NEXT_INSN;
1584
1585 insn_dstore_3:
1586 STORED (3);
1587 NEXT_INSN;
1588
1589 insn_astore_0:
1590 STOREA(0);
1591 NEXT_INSN;
1592
1593 insn_astore_1:
1594 STOREA(1);
1595 NEXT_INSN;
1596
1597 insn_astore_2:
1598 STOREA(2);
1599 NEXT_INSN;
1600
1601 insn_astore_3:
1602 STOREA(3);
1603 NEXT_INSN;
1604
1605 insn_iastore:
1606 {
1607 jint value = POPI();
1608 jint index = POPI();
1609 jintArray arr = (jintArray) POPA();
1610 NULLARRAYCHECK (arr);
1611 ARRAYBOUNDSCHECK (arr, index);
1612 elements(arr)[index] = value;
1613 }
1614 NEXT_INSN;
1615
1616 insn_lastore:
1617 {
1618 jlong value = POPL();
1619 jint index = POPI();
1620 jlongArray arr = (jlongArray) POPA();
1621 NULLARRAYCHECK (arr);
1622 ARRAYBOUNDSCHECK (arr, index);
1623 elements(arr)[index] = value;
1624 }
1625 NEXT_INSN;
1626
1627 insn_fastore:
1628 {
1629 jfloat value = POPF();
1630 jint index = POPI();
1631 jfloatArray arr = (jfloatArray) POPA();
1632 NULLARRAYCHECK (arr);
1633 ARRAYBOUNDSCHECK (arr, index);
1634 elements(arr)[index] = value;
1635 }
1636 NEXT_INSN;
1637
1638 insn_dastore:
1639 {
1640 jdouble value = POPD();
1641 jint index = POPI();
1642 jdoubleArray arr = (jdoubleArray) POPA();
1643 NULLARRAYCHECK (arr);
1644 ARRAYBOUNDSCHECK (arr, index);
1645 elements(arr)[index] = value;
1646 }
1647 NEXT_INSN;
1648
1649 insn_aastore:
1650 {
1651 jobject value = POPA();
1652 jint index = POPI();
1653 jobjectArray arr = (jobjectArray) POPA();
1654 NULLARRAYCHECK (arr);
1655 ARRAYBOUNDSCHECK (arr, index);
1656 _Jv_CheckArrayStore (arr, value);
1657 elements(arr)[index] = value;
1658 }
1659 NEXT_INSN;
1660
1661 insn_bastore:
1662 {
1663 jbyte value = (jbyte) POPI();
1664 jint index = POPI();
1665 jbyteArray arr = (jbyteArray) POPA();
1666 NULLARRAYCHECK (arr);
1667 ARRAYBOUNDSCHECK (arr, index);
1668 elements(arr)[index] = value;
1669 }
1670 NEXT_INSN;
1671
1672 insn_castore:
1673 {
1674 jchar value = (jchar) POPI();
1675 jint index = POPI();
1676 jcharArray arr = (jcharArray) POPA();
1677 NULLARRAYCHECK (arr);
1678 ARRAYBOUNDSCHECK (arr, index);
1679 elements(arr)[index] = value;
1680 }
1681 NEXT_INSN;
1682
1683 insn_sastore:
1684 {
1685 jshort value = (jshort) POPI();
1686 jint index = POPI();
1687 jshortArray arr = (jshortArray) POPA();
1688 NULLARRAYCHECK (arr);
1689 ARRAYBOUNDSCHECK (arr, index);
1690 elements(arr)[index] = value;
1691 }
1692 NEXT_INSN;
1693
1694 insn_pop:
1695 sp -= 1;
1696 NEXT_INSN;
1697
1698 insn_pop2:
1699 sp -= 2;
1700 NEXT_INSN;
1701
1702 insn_dup:
1703 sp[0] = sp[-1];
1704 sp += 1;
1705 NEXT_INSN;
1706
1707 insn_dup_x1:
1708 dupx (sp, 1, 1); sp+=1;
1709 NEXT_INSN;
1710
1711 insn_dup_x2:
1712 dupx (sp, 1, 2); sp+=1;
1713 NEXT_INSN;
1714
1715 insn_dup2:
1716 sp[0] = sp[-2];
1717 sp[1] = sp[-1];
1718 sp += 2;
1719 NEXT_INSN;
1720
1721 insn_dup2_x1:
1722 dupx (sp, 2, 1); sp+=2;
1723 NEXT_INSN;
1724
1725 insn_dup2_x2:
1726 dupx (sp, 2, 2); sp+=2;
1727 NEXT_INSN;
1728
1729 insn_swap:
1730 {
1731 jobject tmp1 = POPA();
1732 jobject tmp2 = POPA();
1733 PUSHA (tmp1);
1734 PUSHA (tmp2);
1735 }
1736 NEXT_INSN;
1737
1738 insn_iadd:
1739 BINOPI(+);
1740 NEXT_INSN;
1741
1742 insn_ladd:
1743 BINOPL(+);
1744 NEXT_INSN;
1745
1746 insn_fadd:
1747 BINOPF(+);
1748 NEXT_INSN;
1749
1750 insn_dadd:
1751 BINOPD(+);
1752 NEXT_INSN;
1753
1754 insn_isub:
1755 BINOPI(-);
1756 NEXT_INSN;
1757
1758 insn_lsub:
1759 BINOPL(-);
1760 NEXT_INSN;
1761
1762 insn_fsub:
1763 BINOPF(-);
1764 NEXT_INSN;
1765
1766 insn_dsub:
1767 BINOPD(-);
1768 NEXT_INSN;
1769
1770 insn_imul:
1771 BINOPI(*);
1772 NEXT_INSN;
1773
1774 insn_lmul:
1775 BINOPL(*);
1776 NEXT_INSN;
1777
1778 insn_fmul:
1779 BINOPF(*);
1780 NEXT_INSN;
1781
1782 insn_dmul:
1783 BINOPD(*);
1784 NEXT_INSN;
1785
1786 insn_idiv:
1787 {
1788 jint value2 = POPI();
1789 jint value1 = POPI();
1790 jint res = _Jv_divI (value1, value2);
1791 PUSHI (res);
1792 }
1793 NEXT_INSN;
1794
1795 insn_ldiv:
1796 {
1797 jlong value2 = POPL();
1798 jlong value1 = POPL();
1799 jlong res = _Jv_divJ (value1, value2);
1800 PUSHL (res);
1801 }
1802 NEXT_INSN;
1803
1804 insn_fdiv:
1805 {
1806 jfloat value2 = POPF();
1807 jfloat value1 = POPF();
1808 jfloat res = value1 / value2;
1809 PUSHF (res);
1810 }
1811 NEXT_INSN;
1812
1813 insn_ddiv:
1814 {
1815 jdouble value2 = POPD();
1816 jdouble value1 = POPD();
1817 jdouble res = value1 / value2;
1818 PUSHD (res);
1819 }
1820 NEXT_INSN;
1821
1822 insn_irem:
1823 {
1824 jint value2 = POPI();
1825 jint value1 = POPI();
1826 jint res = _Jv_remI (value1, value2);
1827 PUSHI (res);
1828 }
1829 NEXT_INSN;
1830
1831 insn_lrem:
1832 {
1833 jlong value2 = POPL();
1834 jlong value1 = POPL();
1835 jlong res = _Jv_remJ (value1, value2);
1836 PUSHL (res);
1837 }
1838 NEXT_INSN;
1839
1840 insn_frem:
1841 {
1842 jfloat value2 = POPF();
1843 jfloat value1 = POPF();
1844 jfloat res = __ieee754_fmod (value1, value2);
1845 PUSHF (res);
1846 }
1847 NEXT_INSN;
1848
1849 insn_drem:
1850 {
1851 jdouble value2 = POPD();
1852 jdouble value1 = POPD();
1853 jdouble res = __ieee754_fmod (value1, value2);
1854 PUSHD (res);
1855 }
1856 NEXT_INSN;
1857
1858 insn_ineg:
1859 {
1860 jint value = POPI();
1861 PUSHI (value * -1);
1862 }
1863 NEXT_INSN;
1864
1865 insn_lneg:
1866 {
1867 jlong value = POPL();
1868 PUSHL (value * -1);
1869 }
1870 NEXT_INSN;
1871
1872 insn_fneg:
1873 {
1874 jfloat value = POPF();
1875 PUSHF (value * -1);
1876 }
1877 NEXT_INSN;
1878
1879 insn_dneg:
1880 {
1881 jdouble value = POPD();
1882 PUSHD (value * -1);
1883 }
1884 NEXT_INSN;
1885
1886 insn_ishl:
1887 {
1888 jint shift = (POPI() & 0x1f);
1889 jint value = POPI();
1890 PUSHI (value << shift);
1891 }
1892 NEXT_INSN;
1893
1894 insn_lshl:
1895 {
1896 jint shift = (POPI() & 0x3f);
1897 jlong value = POPL();
1898 PUSHL (value << shift);
1899 }
1900 NEXT_INSN;
1901
1902 insn_ishr:
1903 {
1904 jint shift = (POPI() & 0x1f);
1905 jint value = POPI();
1906 PUSHI (value >> shift);
1907 }
1908 NEXT_INSN;
1909
1910 insn_lshr:
1911 {
1912 jint shift = (POPI() & 0x3f);
1913 jlong value = POPL();
1914 PUSHL (value >> shift);
1915 }
1916 NEXT_INSN;
1917
1918 insn_iushr:
1919 {
1920 jint shift = (POPI() & 0x1f);
1921 _Jv_uint value = (_Jv_uint) POPI();
1922 PUSHI ((jint) (value >> shift));
1923 }
1924 NEXT_INSN;
1925
1926 insn_lushr:
1927 {
1928 jint shift = (POPI() & 0x3f);
1929 _Jv_ulong value = (_Jv_ulong) POPL();
1930 PUSHL ((jlong) (value >> shift));
1931 }
1932 NEXT_INSN;
1933
1934 insn_iand:
1935 BINOPI (&);
1936 NEXT_INSN;
1937
1938 insn_land:
1939 BINOPL (&);
1940 NEXT_INSN;
1941
1942 insn_ior:
1943 BINOPI (|);
1944 NEXT_INSN;
1945
1946 insn_lor:
1947 BINOPL (|);
1948 NEXT_INSN;
1949
1950 insn_ixor:
1951 BINOPI (^);
1952 NEXT_INSN;
1953
1954 insn_lxor:
1955 BINOPL (^);
1956 NEXT_INSN;
1957
1958 insn_iinc:
1959 {
1960 jint index = GET1U ();
1961 jint amount = GET1S ();
1962 locals[index].i += amount;
1963 }
1964 NEXT_INSN;
1965
1966 insn_i2l:
1967 {jlong value = POPI(); PUSHL (value);}
1968 NEXT_INSN;
1969
1970 insn_i2f:
1971 {jfloat value = POPI(); PUSHF (value);}
1972 NEXT_INSN;
1973
1974 insn_i2d:
1975 {jdouble value = POPI(); PUSHD (value);}
1976 NEXT_INSN;
1977
1978 insn_l2i:
1979 {jint value = POPL(); PUSHI (value);}
1980 NEXT_INSN;
1981
1982 insn_l2f:
1983 {jfloat value = POPL(); PUSHF (value);}
1984 NEXT_INSN;
1985
1986 insn_l2d:
1987 {jdouble value = POPL(); PUSHD (value);}
1988 NEXT_INSN;
1989
1990 insn_f2i:
1991 {
1992 using namespace java::lang;
1993 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1994 PUSHI(value);
1995 }
1996 NEXT_INSN;
1997
1998 insn_f2l:
1999 {
2000 using namespace java::lang;
2001 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
2002 PUSHL(value);
2003 }
2004 NEXT_INSN;
2005
2006 insn_f2d:
2007 { jdouble value = POPF (); PUSHD(value); }
2008 NEXT_INSN;
2009
2010 insn_d2i:
2011 {
2012 using namespace java::lang;
2013 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
2014 PUSHI(value);
2015 }
2016 NEXT_INSN;
2017
2018 insn_d2l:
2019 {
2020 using namespace java::lang;
2021 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
2022 PUSHL(value);
2023 }
2024 NEXT_INSN;
2025
2026 insn_d2f:
2027 { jfloat value = POPD (); PUSHF(value); }
2028 NEXT_INSN;
2029
2030 insn_i2b:
2031 { jbyte value = POPI (); PUSHI(value); }
2032 NEXT_INSN;
2033
2034 insn_i2c:
2035 { jchar value = POPI (); PUSHI(value); }
2036 NEXT_INSN;
2037
2038 insn_i2s:
2039 { jshort value = POPI (); PUSHI(value); }
2040 NEXT_INSN;
2041
2042 insn_lcmp:
2043 {
2044 jlong value2 = POPL ();
2045 jlong value1 = POPL ();
2046 if (value1 > value2)
2047 { PUSHI (1); }
2048 else if (value1 == value2)
2049 { PUSHI (0); }
2050 else
2051 { PUSHI (-1); }
2052 }
2053 NEXT_INSN;
2054
2055 insn_fcmpl:
2056 tmpval = -1;
2057 goto fcmp;
2058
2059 insn_fcmpg:
2060 tmpval = 1;
2061
2062 fcmp:
2063 {
2064 jfloat value2 = POPF ();
2065 jfloat value1 = POPF ();
2066 if (value1 > value2)
2067 PUSHI (1);
2068 else if (value1 == value2)
2069 PUSHI (0);
2070 else if (value1 < value2)
2071 PUSHI (-1);
2072 else
2073 PUSHI (tmpval);
2074 }
2075 NEXT_INSN;
2076
2077 insn_dcmpl:
2078 tmpval = 1;
2079 goto dcmp;
2080
2081 insn_dcmpg:
2082 tmpval = -1;
2083
2084 dcmp:
2085 {
2086 jdouble value2 = POPD ();
2087 jdouble value1 = POPD ();
2088 if (value1 > value2)
2089 PUSHI (1);
2090 else if (value1 == value2)
2091 PUSHI (0);
2092 else if (value1 < value2)
2093 PUSHI (-1);
2094 else
2095 PUSHI (tmpval);
2096 }
2097 NEXT_INSN;
2098
2099 insn_ifeq:
2100 {
2101 if (POPI() == 0)
2102 TAKE_GOTO;
2103 else
2104 SKIP_GOTO;
2105 }
2106 NEXT_INSN;
2107
2108 insn_ifne:
2109 {
2110 if (POPI() != 0)
2111 TAKE_GOTO;
2112 else
2113 SKIP_GOTO;
2114 }
2115 NEXT_INSN;
2116
2117 insn_iflt:
2118 {
2119 if (POPI() < 0)
2120 TAKE_GOTO;
2121 else
2122 SKIP_GOTO;
2123 }
2124 NEXT_INSN;
2125
2126 insn_ifge:
2127 {
2128 if (POPI() >= 0)
2129 TAKE_GOTO;
2130 else
2131 SKIP_GOTO;
2132 }
2133 NEXT_INSN;
2134
2135 insn_ifgt:
2136 {
2137 if (POPI() > 0)
2138 TAKE_GOTO;
2139 else
2140 SKIP_GOTO;
2141 }
2142 NEXT_INSN;
2143
2144 insn_ifle:
2145 {
2146 if (POPI() <= 0)
2147 TAKE_GOTO;
2148 else
2149 SKIP_GOTO;
2150 }
2151 NEXT_INSN;
2152
2153 insn_if_icmpeq:
2154 {
2155 jint value2 = POPI();
2156 jint value1 = POPI();
2157 if (value1 == value2)
2158 TAKE_GOTO;
2159 else
2160 SKIP_GOTO;
2161 }
2162 NEXT_INSN;
2163
2164 insn_if_icmpne:
2165 {
2166 jint value2 = POPI();
2167 jint value1 = POPI();
2168 if (value1 != value2)
2169 TAKE_GOTO;
2170 else
2171 SKIP_GOTO;
2172 }
2173 NEXT_INSN;
2174
2175 insn_if_icmplt:
2176 {
2177 jint value2 = POPI();
2178 jint value1 = POPI();
2179 if (value1 < value2)
2180 TAKE_GOTO;
2181 else
2182 SKIP_GOTO;
2183 }
2184 NEXT_INSN;
2185
2186 insn_if_icmpge:
2187 {
2188 jint value2 = POPI();
2189 jint value1 = POPI();
2190 if (value1 >= value2)
2191 TAKE_GOTO;
2192 else
2193 SKIP_GOTO;
2194 }
2195 NEXT_INSN;
2196
2197 insn_if_icmpgt:
2198 {
2199 jint value2 = POPI();
2200 jint value1 = POPI();
2201 if (value1 > value2)
2202 TAKE_GOTO;
2203 else
2204 SKIP_GOTO;
2205 }
2206 NEXT_INSN;
2207
2208 insn_if_icmple:
2209 {
2210 jint value2 = POPI();
2211 jint value1 = POPI();
2212 if (value1 <= value2)
2213 TAKE_GOTO;
2214 else
2215 SKIP_GOTO;
2216 }
2217 NEXT_INSN;
2218
2219 insn_if_acmpeq:
2220 {
2221 jobject value2 = POPA();
2222 jobject value1 = POPA();
2223 if (value1 == value2)
2224 TAKE_GOTO;
2225 else
2226 SKIP_GOTO;
2227 }
2228 NEXT_INSN;
2229
2230 insn_if_acmpne:
2231 {
2232 jobject value2 = POPA();
2233 jobject value1 = POPA();
2234 if (value1 != value2)
2235 TAKE_GOTO;
2236 else
2237 SKIP_GOTO;
2238 }
2239 NEXT_INSN;
2240
2241 insn_goto_w:
2242 #ifndef DIRECT_THREADED
2243 // For direct threaded, goto and goto_w are the same.
2244 pc = pc - 1 + get4 (pc);
2245 NEXT_INSN;
2246 #endif /* DIRECT_THREADED */
2247 insn_goto:
2248 TAKE_GOTO;
2249 NEXT_INSN;
2250
2251 insn_jsr_w:
2252 #ifndef DIRECT_THREADED
2253 // For direct threaded, jsr and jsr_w are the same.
2254 {
2255 pc_t next = pc - 1 + get4 (pc);
2256 pc += 4;
2257 PUSHA ((jobject) pc);
2258 pc = next;
2259 }
2260 NEXT_INSN;
2261 #endif /* DIRECT_THREADED */
2262 insn_jsr:
2263 {
2264 pc_t next = GOTO_VAL();
2265 SKIP_GOTO;
2266 PUSHA ((jobject) pc);
2267 pc = next;
2268 }
2269 NEXT_INSN;
2270
2271 insn_ret:
2272 {
2273 jint index = GET1U ();
2274 pc = (pc_t) PEEKA (index);
2275 }
2276 NEXT_INSN;
2277
2278 insn_tableswitch:
2279 {
2280 #ifdef DIRECT_THREADED
2281 void *def = (pc++)->datum;
2282
2283 int index = POPI();
2284
2285 jint low = INTVAL ();
2286 jint high = INTVAL ();
2287
2288 if (index < low || index > high)
2289 pc = (insn_slot *) def;
2290 else
2291 pc = (insn_slot *) ((pc + index - low)->datum);
2292 #else
2293 pc_t base_pc = pc - 1;
2294 int index = POPI ();
2295
2296 pc_t base = (pc_t) bytecode ();
2297 while ((pc - base) % 4 != 0)
2298 ++pc;
2299
2300 jint def = get4 (pc);
2301 jint low = get4 (pc + 4);
2302 jint high = get4 (pc + 8);
2303 if (index < low || index > high)
2304 pc = base_pc + def;
2305 else
2306 pc = base_pc + get4 (pc + 4 * (index - low + 3));
2307 #endif /* DIRECT_THREADED */
2308 }
2309 NEXT_INSN;
2310
2311 insn_lookupswitch:
2312 {
2313 #ifdef DIRECT_THREADED
2314 void *def = (pc++)->insn;
2315
2316 int index = POPI();
2317
2318 jint npairs = INTVAL ();
2319
2320 int max = npairs - 1;
2321 int min = 0;
2322
2323 // Simple binary search...
2324 while (min < max)
2325 {
2326 int half = (min + max) / 2;
2327 int match = pc[2 * half].int_val;
2328
2329 if (index == match)
2330 {
2331 // Found it.
2332 pc = (insn_slot *) pc[2 * half + 1].datum;
2333 NEXT_INSN;
2334 }
2335 else if (index < match)
2336 // We can use HALF - 1 here because we check again on
2337 // loop exit.
2338 max = half - 1;
2339 else
2340 // We can use HALF + 1 here because we check again on
2341 // loop exit.
2342 min = half + 1;
2343 }
2344 if (index == pc[2 * min].int_val)
2345 pc = (insn_slot *) pc[2 * min + 1].datum;
2346 else
2347 pc = (insn_slot *) def;
2348 #else
2349 unsigned char *base_pc = pc-1;
2350 int index = POPI();
2351
2352 unsigned char* base = bytecode ();
2353 while ((pc-base) % 4 != 0)
2354 ++pc;
2355
2356 jint def = get4 (pc);
2357 jint npairs = get4 (pc+4);
2358
2359 int max = npairs-1;
2360 int min = 0;
2361
2362 // Simple binary search...
2363 while (min < max)
2364 {
2365 int half = (min+max)/2;
2366 int match = get4 (pc+ 4*(2 + 2*half));
2367
2368 if (index == match)
2369 min = max = half;
2370 else if (index < match)
2371 // We can use HALF - 1 here because we check again on
2372 // loop exit.
2373 max = half - 1;
2374 else
2375 // We can use HALF + 1 here because we check again on
2376 // loop exit.
2377 min = half + 1;
2378 }
2379
2380 if (index == get4 (pc+ 4*(2 + 2*min)))
2381 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
2382 else
2383 pc = base_pc + def;
2384 #endif /* DIRECT_THREADED */
2385 }
2386 NEXT_INSN;
2387
2388 insn_areturn:
2389 *(jobject *) retp = POPA ();
2390 return;
2391
2392 insn_lreturn:
2393 *(jlong *) retp = POPL ();
2394 return;
2395
2396 insn_freturn:
2397 *(jfloat *) retp = POPF ();
2398 return;
2399
2400 insn_dreturn:
2401 *(jdouble *) retp = POPD ();
2402 return;
2403
2404 insn_ireturn:
2405 *(jint *) retp = POPI ();
2406 return;
2407
2408 insn_return:
2409 return;
2410
2411 insn_getstatic:
2412 {
2413 jint fieldref_index = GET2U ();
2414 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2415 _Jv_Field *field = pool_data[fieldref_index].field;
2416
2417 if ((field->flags & Modifier::STATIC) == 0)
2418 throw_incompatible_class_change_error
2419 (JvNewStringLatin1 ("field no longer static"));
2420
2421 jclass type = field->type;
2422
2423 // We rewrite the instruction once we discover what it refers
2424 // to.
2425 void *newinsn = NULL;
2426 if (type->isPrimitive ())
2427 {
2428 switch (type->size_in_bytes)
2429 {
2430 case 1:
2431 PUSHI (*(jbyte*) (field->u.addr));
2432 newinsn = AMPAMP (getstatic_resolved_1);
2433 break;
2434
2435 case 2:
2436 if (type == JvPrimClass (char))
2437 {
2438 PUSHI(*(jchar*) (field->u.addr));
2439 newinsn = AMPAMP (getstatic_resolved_char);
2440 }
2441 else
2442 {
2443 PUSHI(*(jshort*) (field->u.addr));
2444 newinsn = AMPAMP (getstatic_resolved_short);
2445 }
2446 break;
2447
2448 case 4:
2449 PUSHI(*(jint*) (field->u.addr));
2450 newinsn = AMPAMP (getstatic_resolved_4);
2451 break;
2452
2453 case 8:
2454 PUSHL(*(jlong*) (field->u.addr));
2455 newinsn = AMPAMP (getstatic_resolved_8);
2456 break;
2457 }
2458 }
2459 else
2460 {
2461 PUSHA(*(jobject*) (field->u.addr));
2462 newinsn = AMPAMP (getstatic_resolved_obj);
2463 }
2464
2465 #ifdef DIRECT_THREADED
2466 pc[-2].insn = newinsn;
2467 pc[-1].datum = field->u.addr;
2468 #endif /* DIRECT_THREADED */
2469 }
2470 NEXT_INSN;
2471
2472 #ifdef DIRECT_THREADED
2473 getstatic_resolved_1:
2474 PUSHI (*(jbyte *) AVAL ());
2475 NEXT_INSN;
2476
2477 getstatic_resolved_char:
2478 PUSHI (*(jchar *) AVAL ());
2479 NEXT_INSN;
2480
2481 getstatic_resolved_short:
2482 PUSHI (*(jshort *) AVAL ());
2483 NEXT_INSN;
2484
2485 getstatic_resolved_4:
2486 PUSHI (*(jint *) AVAL ());
2487 NEXT_INSN;
2488
2489 getstatic_resolved_8:
2490 PUSHL (*(jlong *) AVAL ());
2491 NEXT_INSN;
2492
2493 getstatic_resolved_obj:
2494 PUSHA (*(jobject *) AVAL ());
2495 NEXT_INSN;
2496 #endif /* DIRECT_THREADED */
2497
2498 insn_getfield:
2499 {
2500 jint fieldref_index = GET2U ();
2501 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2502 _Jv_Field *field = pool_data[fieldref_index].field;
2503
2504 if ((field->flags & Modifier::STATIC) != 0)
2505 throw_incompatible_class_change_error
2506 (JvNewStringLatin1 ("field is static"));
2507
2508 jclass type = field->type;
2509 jint field_offset = field->u.boffset;
2510 if (field_offset > 0xffff)
2511 throw new java::lang::VirtualMachineError;
2512
2513 jobject obj = POPA();
2514 NULLCHECK(obj);
2515
2516 void *newinsn = NULL;
2517 if (type->isPrimitive ())
2518 {
2519 switch (type->size_in_bytes)
2520 {
2521 case 1:
2522 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2523 newinsn = AMPAMP (getfield_resolved_1);
2524 break;
2525
2526 case 2:
2527 if (type == JvPrimClass (char))
2528 {
2529 PUSHI (*(jchar*) ((char*)obj + field_offset));
2530 newinsn = AMPAMP (getfield_resolved_char);
2531 }
2532 else
2533 {
2534 PUSHI (*(jshort*) ((char*)obj + field_offset));
2535 newinsn = AMPAMP (getfield_resolved_short);
2536 }
2537 break;
2538
2539 case 4:
2540 PUSHI (*(jint*) ((char*)obj + field_offset));
2541 newinsn = AMPAMP (getfield_resolved_4);
2542 break;
2543
2544 case 8:
2545 PUSHL(*(jlong*) ((char*)obj + field_offset));
2546 newinsn = AMPAMP (getfield_resolved_8);
2547 break;
2548 }
2549 }
2550 else
2551 {
2552 PUSHA(*(jobject*) ((char*)obj + field_offset));
2553 newinsn = AMPAMP (getfield_resolved_obj);
2554 }
2555
2556 #ifdef DIRECT_THREADED
2557 pc[-2].insn = newinsn;
2558 pc[-1].int_val = field_offset;
2559 #endif /* DIRECT_THREADED */
2560 }
2561 NEXT_INSN;
2562
2563 #ifdef DIRECT_THREADED
2564 getfield_resolved_1:
2565 {
2566 char *obj = (char *) POPA ();
2567 NULLCHECK (obj);
2568 PUSHI (*(jbyte *) (obj + INTVAL ()));
2569 }
2570 NEXT_INSN;
2571
2572 getfield_resolved_char:
2573 {
2574 char *obj = (char *) POPA ();
2575 NULLCHECK (obj);
2576 PUSHI (*(jchar *) (obj + INTVAL ()));
2577 }
2578 NEXT_INSN;
2579
2580 getfield_resolved_short:
2581 {
2582 char *obj = (char *) POPA ();
2583 NULLCHECK (obj);
2584 PUSHI (*(jshort *) (obj + INTVAL ()));
2585 }
2586 NEXT_INSN;
2587
2588 getfield_resolved_4:
2589 {
2590 char *obj = (char *) POPA ();
2591 NULLCHECK (obj);
2592 PUSHI (*(jint *) (obj + INTVAL ()));
2593 }
2594 NEXT_INSN;
2595
2596 getfield_resolved_8:
2597 {
2598 char *obj = (char *) POPA ();
2599 NULLCHECK (obj);
2600 PUSHL (*(jlong *) (obj + INTVAL ()));
2601 }
2602 NEXT_INSN;
2603
2604 getfield_resolved_obj:
2605 {
2606 char *obj = (char *) POPA ();
2607 NULLCHECK (obj);
2608 PUSHA (*(jobject *) (obj + INTVAL ()));
2609 }
2610 NEXT_INSN;
2611 #endif /* DIRECT_THREADED */
2612
2613 insn_putstatic:
2614 {
2615 jint fieldref_index = GET2U ();
2616 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2617 _Jv_Field *field = pool_data[fieldref_index].field;
2618
2619 jclass type = field->type;
2620
2621 // ResolvePoolEntry cannot check this
2622 if ((field->flags & Modifier::STATIC) == 0)
2623 throw_incompatible_class_change_error
2624 (JvNewStringLatin1 ("field no longer static"));
2625
2626 void *newinsn = NULL;
2627 if (type->isPrimitive ())
2628 {
2629 switch (type->size_in_bytes)
2630 {
2631 case 1:
2632 {
2633 jint value = POPI();
2634 *(jbyte*) (field->u.addr) = value;
2635 newinsn = AMPAMP (putstatic_resolved_1);
2636 break;
2637 }
2638
2639 case 2:
2640 {
2641 jint value = POPI();
2642 *(jchar*) (field->u.addr) = value;
2643 newinsn = AMPAMP (putstatic_resolved_2);
2644 break;
2645 }
2646
2647 case 4:
2648 {
2649 jint value = POPI();
2650 *(jint*) (field->u.addr) = value;
2651 newinsn = AMPAMP (putstatic_resolved_4);
2652 break;
2653 }
2654
2655 case 8:
2656 {
2657 jlong value = POPL();
2658 *(jlong*) (field->u.addr) = value;
2659 newinsn = AMPAMP (putstatic_resolved_8);
2660 break;
2661 }
2662 }
2663 }
2664 else
2665 {
2666 jobject value = POPA();
2667 *(jobject*) (field->u.addr) = value;
2668 newinsn = AMPAMP (putstatic_resolved_obj);
2669 }
2670
2671 #ifdef DIRECT_THREADED
2672 pc[-2].insn = newinsn;
2673 pc[-1].datum = field->u.addr;
2674 #endif /* DIRECT_THREADED */
2675 }
2676 NEXT_INSN;
2677
2678 #ifdef DIRECT_THREADED
2679 putstatic_resolved_1:
2680 *(jbyte *) AVAL () = POPI ();
2681 NEXT_INSN;
2682
2683 putstatic_resolved_2:
2684 *(jchar *) AVAL () = POPI ();
2685 NEXT_INSN;
2686
2687 putstatic_resolved_4:
2688 *(jint *) AVAL () = POPI ();
2689 NEXT_INSN;
2690
2691 putstatic_resolved_8:
2692 *(jlong *) AVAL () = POPL ();
2693 NEXT_INSN;
2694
2695 putstatic_resolved_obj:
2696 *(jobject *) AVAL () = POPA ();
2697 NEXT_INSN;
2698 #endif /* DIRECT_THREADED */
2699
2700 insn_putfield:
2701 {
2702 jint fieldref_index = GET2U ();
2703 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2704 _Jv_Field *field = pool_data[fieldref_index].field;
2705
2706 jclass type = field->type;
2707
2708 if ((field->flags & Modifier::STATIC) != 0)
2709 throw_incompatible_class_change_error
2710 (JvNewStringLatin1 ("field is static"));
2711
2712 jint field_offset = field->u.boffset;
2713 if (field_offset > 0xffff)
2714 throw new java::lang::VirtualMachineError;
2715
2716 void *newinsn = NULL;
2717 if (type->isPrimitive ())
2718 {
2719 switch (type->size_in_bytes)
2720 {
2721 case 1:
2722 {
2723 jint value = POPI();
2724 jobject obj = POPA();
2725 NULLCHECK(obj);
2726 *(jbyte*) ((char*)obj + field_offset) = value;
2727 newinsn = AMPAMP (putfield_resolved_1);
2728 break;
2729 }
2730
2731 case 2:
2732 {
2733 jint value = POPI();
2734 jobject obj = POPA();
2735 NULLCHECK(obj);
2736 *(jchar*) ((char*)obj + field_offset) = value;
2737 newinsn = AMPAMP (putfield_resolved_2);
2738 break;
2739 }
2740
2741 case 4:
2742 {
2743 jint value = POPI();
2744 jobject obj = POPA();
2745 NULLCHECK(obj);
2746 *(jint*) ((char*)obj + field_offset) = value;
2747 newinsn = AMPAMP (putfield_resolved_4);
2748 break;
2749 }
2750
2751 case 8:
2752 {
2753 jlong value = POPL();
2754 jobject obj = POPA();
2755 NULLCHECK(obj);
2756 *(jlong*) ((char*)obj + field_offset) = value;
2757 newinsn = AMPAMP (putfield_resolved_8);
2758 break;
2759 }
2760 }
2761 }
2762 else
2763 {
2764 jobject value = POPA();
2765 jobject obj = POPA();
2766 NULLCHECK(obj);
2767 *(jobject*) ((char*)obj + field_offset) = value;
2768 newinsn = AMPAMP (putfield_resolved_obj);
2769 }
2770
2771 #ifdef DIRECT_THREADED
2772 pc[-2].insn = newinsn;
2773 pc[-1].int_val = field_offset;
2774 #endif /* DIRECT_THREADED */
2775 }
2776 NEXT_INSN;
2777
2778 #ifdef DIRECT_THREADED
2779 putfield_resolved_1:
2780 {
2781 jint val = POPI ();
2782 char *obj = (char *) POPA ();
2783 NULLCHECK (obj);
2784 *(jbyte *) (obj + INTVAL ()) = val;
2785 }
2786 NEXT_INSN;
2787
2788 putfield_resolved_2:
2789 {
2790 jint val = POPI ();
2791 char *obj = (char *) POPA ();
2792 NULLCHECK (obj);
2793 *(jchar *) (obj + INTVAL ()) = val;
2794 }
2795 NEXT_INSN;
2796
2797 putfield_resolved_4:
2798 {
2799 jint val = POPI ();
2800 char *obj = (char *) POPA ();
2801 NULLCHECK (obj);
2802 *(jint *) (obj + INTVAL ()) = val;
2803 }
2804 NEXT_INSN;
2805
2806 putfield_resolved_8:
2807 {
2808 jlong val = POPL ();
2809 char *obj = (char *) POPA ();
2810 NULLCHECK (obj);
2811 *(jlong *) (obj + INTVAL ()) = val;
2812 }
2813 NEXT_INSN;
2814
2815 putfield_resolved_obj:
2816 {
2817 jobject val = POPA ();
2818 char *obj = (char *) POPA ();
2819 NULLCHECK (obj);
2820 *(jobject *) (obj + INTVAL ()) = val;
2821 }
2822 NEXT_INSN;
2823 #endif /* DIRECT_THREADED */
2824
2825 insn_invokespecial:
2826 {
2827 int index = GET2U ();
2828
2829 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2830
2831 sp -= rmeth->stack_item_count;
2832
2833 // We don't use NULLCHECK here because we can't rely on that
2834 // working for <init>. So instead we do an explicit test.
2835 if (! sp[0].o)
2836 throw new java::lang::NullPointerException;
2837
2838 fun = (void (*)()) rmeth->method->ncode;
2839
2840 #ifdef DIRECT_THREADED
2841 // Rewrite instruction so that we use a faster pre-resolved
2842 // method.
2843 pc[-2].insn = &&invokespecial_resolved;
2844 pc[-1].datum = rmeth;
2845 #endif /* DIRECT_THREADED */
2846 }
2847 goto perform_invoke;
2848
2849 #ifdef DIRECT_THREADED
2850 invokespecial_resolved:
2851 {
2852 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2853 sp -= rmeth->stack_item_count;
2854 // We don't use NULLCHECK here because we can't rely on that
2855 // working for <init>. So instead we do an explicit test.
2856 if (! sp[0].o)
2857 throw new java::lang::NullPointerException;
2858 fun = (void (*)()) rmeth->method->ncode;
2859 }
2860 goto perform_invoke;
2861 #endif /* DIRECT_THREADED */
2862
2863 insn_invokestatic:
2864 {
2865 int index = GET2U ();
2866
2867 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2868
2869 sp -= rmeth->stack_item_count;
2870
2871 fun = (void (*)()) rmeth->method->ncode;
2872
2873 #ifdef DIRECT_THREADED
2874 // Rewrite instruction so that we use a faster pre-resolved
2875 // method.
2876 pc[-2].insn = &&invokestatic_resolved;
2877 pc[-1].datum = rmeth;
2878 #endif /* DIRECT_THREADED */
2879 }
2880 goto perform_invoke;
2881
2882 #ifdef DIRECT_THREADED
2883 invokestatic_resolved:
2884 {
2885 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2886 sp -= rmeth->stack_item_count;
2887 fun = (void (*)()) rmeth->method->ncode;
2888 }
2889 goto perform_invoke;
2890 #endif /* DIRECT_THREADED */
2891
2892 insn_invokeinterface:
2893 {
2894 int index = GET2U ();
2895
2896 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2897
2898 sp -= rmeth->stack_item_count;
2899
2900 jobject rcv = sp[0].o;
2901
2902 NULLCHECK (rcv);
2903
2904 fun = (void (*)())
2905 _Jv_LookupInterfaceMethod (rcv->getClass (),
2906 rmeth->method->name,
2907 rmeth->method->signature);
2908
2909 #ifdef DIRECT_THREADED
2910 // Rewrite instruction so that we use a faster pre-resolved
2911 // method.
2912 pc[-2].insn = &&invokeinterface_resolved;
2913 pc[-1].datum = rmeth;
2914 #else
2915 // Skip dummy bytes.
2916 pc += 2;
2917 #endif /* DIRECT_THREADED */
2918 }
2919 goto perform_invoke;
2920
2921 #ifdef DIRECT_THREADED
2922 invokeinterface_resolved:
2923 {
2924 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2925 sp -= rmeth->stack_item_count;
2926 jobject rcv = sp[0].o;
2927 NULLCHECK (rcv);
2928 fun = (void (*)())
2929 _Jv_LookupInterfaceMethod (rcv->getClass (),
2930 rmeth->method->name,
2931 rmeth->method->signature);
2932 }
2933 goto perform_invoke;
2934 #endif /* DIRECT_THREADED */
2935
2936 insn_new:
2937 {
2938 int index = GET2U ();
2939 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2940 // We initialize here because otherwise `size_in_bytes' may
2941 // not be set correctly, leading us to pass `0' as the size.
2942 // FIXME: fix in the allocator? There is a PR for this.
2943 _Jv_InitClass (klass);
2944 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2945 PUSHA (res);
2946
2947 #ifdef DIRECT_THREADED
2948 pc[-2].insn = &&new_resolved;
2949 pc[-1].datum = klass;
2950 #endif /* DIRECT_THREADED */
2951 }
2952 NEXT_INSN;
2953
2954 #ifdef DIRECT_THREADED
2955 new_resolved:
2956 {
2957 jclass klass = (jclass) AVAL ();
2958 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2959 PUSHA (res);
2960 }
2961 NEXT_INSN;
2962 #endif /* DIRECT_THREADED */
2963
2964 insn_newarray:
2965 {
2966 int atype = GET1U ();
2967 int size = POPI();
2968 jobject result = _Jv_NewArray (atype, size);
2969 PUSHA (result);
2970 }
2971 NEXT_INSN;
2972
2973 insn_anewarray:
2974 {
2975 int index = GET2U ();
2976 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2977 int size = POPI();
2978 jobject result = _Jv_NewObjectArray (size, klass, 0);
2979 PUSHA (result);
2980
2981 #ifdef DIRECT_THREADED
2982 pc[-2].insn = &&anewarray_resolved;
2983 pc[-1].datum = klass;
2984 #endif /* DIRECT_THREADED */
2985 }
2986 NEXT_INSN;
2987
2988 #ifdef DIRECT_THREADED
2989 anewarray_resolved:
2990 {
2991 jclass klass = (jclass) AVAL ();
2992 int size = POPI ();
2993 jobject result = _Jv_NewObjectArray (size, klass, 0);
2994 PUSHA (result);
2995 }
2996 NEXT_INSN;
2997 #endif /* DIRECT_THREADED */
2998
2999 insn_arraylength:
3000 {
3001 __JArray *arr = (__JArray*)POPA();
3002 NULLARRAYCHECK (arr);
3003 PUSHI (arr->length);
3004 }
3005 NEXT_INSN;
3006
3007 insn_athrow:
3008 {
3009 jobject value = POPA();
3010 throw static_cast<jthrowable>(value);
3011 }
3012 NEXT_INSN;
3013
3014 insn_checkcast:
3015 {
3016 jobject value = POPA();
3017 jint index = GET2U ();
3018 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3019
3020 if (value != NULL && ! to->isInstance (value))
3021 throw new java::lang::ClassCastException (to->getName());
3022
3023 PUSHA (value);
3024
3025 #ifdef DIRECT_THREADED
3026 pc[-2].insn = &&checkcast_resolved;
3027 pc[-1].datum = to;
3028 #endif /* DIRECT_THREADED */
3029 }
3030 NEXT_INSN;
3031
3032 #ifdef DIRECT_THREADED
3033 checkcast_resolved:
3034 {
3035 jobject value = POPA ();
3036 jclass to = (jclass) AVAL ();
3037 if (value != NULL && ! to->isInstance (value))
3038 throw new java::lang::ClassCastException (to->getName());
3039 PUSHA (value);
3040 }
3041 NEXT_INSN;
3042 #endif /* DIRECT_THREADED */
3043
3044 insn_instanceof:
3045 {
3046 jobject value = POPA();
3047 jint index = GET2U ();
3048 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
3049 PUSHI (to->isInstance (value));
3050
3051 #ifdef DIRECT_THREADED
3052 pc[-2].insn = &&instanceof_resolved;
3053 pc[-1].datum = to;
3054 #endif /* DIRECT_THREADED */
3055 }
3056 NEXT_INSN;
3057
3058 #ifdef DIRECT_THREADED
3059 instanceof_resolved:
3060 {
3061 jobject value = POPA ();
3062 jclass to = (jclass) AVAL ();
3063 PUSHI (to->isInstance (value));
3064 }
3065 NEXT_INSN;
3066 #endif /* DIRECT_THREADED */
3067
3068 insn_monitorenter:
3069 {
3070 jobject value = POPA();
3071 NULLCHECK(value);
3072 _Jv_MonitorEnter (value);
3073 }
3074 NEXT_INSN;
3075
3076 insn_monitorexit:
3077 {
3078 jobject value = POPA();
3079 NULLCHECK(value);
3080 _Jv_MonitorExit (value);
3081 }
3082 NEXT_INSN;
3083
3084 insn_ifnull:
3085 {
3086 jobject val = POPA();
3087 if (val == NULL)
3088 TAKE_GOTO;
3089 else
3090 SKIP_GOTO;
3091 }
3092 NEXT_INSN;
3093
3094 insn_ifnonnull:
3095 {
3096 jobject val = POPA();
3097 if (val != NULL)
3098 TAKE_GOTO;
3099 else
3100 SKIP_GOTO;
3101 }
3102 NEXT_INSN;
3103
3104 insn_multianewarray:
3105 {
3106 int kind_index = GET2U ();
3107 int dim = GET1U ();
3108
3109 jclass type
3110 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
3111 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
3112
3113 for (int i = dim - 1; i >= 0; i--)
3114 {
3115 sizes[i] = POPI ();
3116 }
3117
3118 jobject res = _Jv_NewMultiArray (type,dim, sizes);
3119
3120 PUSHA (res);
3121 }
3122 NEXT_INSN;
3123
3124 #ifndef DIRECT_THREADED
3125 insn_wide:
3126 {
3127 jint the_mod_op = get1u (pc++);
3128 jint wide = get2u (pc); pc += 2;
3129
3130 switch (the_mod_op)
3131 {
3132 case op_istore:
3133 STOREI (wide);
3134 NEXT_INSN;
3135
3136 case op_fstore:
3137 STOREF (wide);
3138 NEXT_INSN;
3139
3140 case op_astore:
3141 STOREA (wide);
3142 NEXT_INSN;
3143
3144 case op_lload:
3145 LOADL (wide);
3146 NEXT_INSN;
3147
3148 case op_dload:
3149 LOADD (wide);
3150 NEXT_INSN;
3151
3152 case op_iload:
3153 LOADI (wide);
3154 NEXT_INSN;
3155
3156 case op_aload:
3157 LOADA (wide);
3158 NEXT_INSN;
3159
3160 case op_lstore:
3161 STOREL (wide);
3162 NEXT_INSN;
3163
3164 case op_dstore:
3165 STORED (wide);
3166 NEXT_INSN;
3167
3168 case op_ret:
3169 pc = (unsigned char*) PEEKA (wide);
3170 NEXT_INSN;
3171
3172 case op_iinc:
3173 {
3174 jint amount = get2s (pc); pc += 2;
3175 jint value = PEEKI (wide);
3176 POKEI (wide, value+amount);
3177 }
3178 NEXT_INSN;
3179
3180 default:
3181 throw_internal_error ("illegal bytecode modified by wide");
3182 }
3183
3184 }
3185 #endif /* DIRECT_THREADED */
3186 }
3187 catch (java::lang::Throwable *ex)
3188 {
3189 #ifdef DIRECT_THREADED
3190 void *logical_pc = (void *) ((insn_slot *) pc - 1);
3191 #else
3192 int logical_pc = pc - 1 - bytecode ();
3193 #endif
3194 _Jv_InterpException *exc = exceptions ();
3195 jclass exc_class = ex->getClass ();
3196
3197 for (int i = 0; i < exc_count; i++)
3198 {
3199 if (PCVAL (exc[i].start_pc) <= logical_pc
3200 && logical_pc < PCVAL (exc[i].end_pc))
3201 {
3202 #ifdef DIRECT_THREADED
3203 jclass handler = (jclass) exc[i].handler_type.p;
3204 #else
3205 jclass handler = NULL;
3206 if (exc[i].handler_type.i != 0)
3207 handler = (_Jv_ResolvePoolEntry (defining_class,
3208 exc[i].handler_type.i)).clazz;
3209 #endif /* DIRECT_THREADED */
3210
3211 if (handler == NULL || handler->isAssignableFrom (exc_class))
3212 {
3213 #ifdef DIRECT_THREADED
3214 pc = (insn_slot *) exc[i].handler_pc.p;
3215 #else
3216 pc = bytecode () + exc[i].handler_pc.i;
3217 #endif /* DIRECT_THREADED */
3218 sp = stack;
3219 sp++->o = ex; // Push exception.
3220 NEXT_INSN;
3221 }
3222 }
3223 }
3224
3225 // No handler, so re-throw.
3226 throw ex;
3227 }
3228 }
3229
3230 // This function exists so that the stack-tracing code can find the
3231 // boundaries of the interpreter.
3232 void
_Jv_EndOfInterpreter(void)3233 _Jv_EndOfInterpreter (void)
3234 {
3235 }
3236
3237 static void
throw_internal_error(char * msg)3238 throw_internal_error (char *msg)
3239 {
3240 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
3241 }
3242
3243 static void
throw_incompatible_class_change_error(jstring msg)3244 throw_incompatible_class_change_error (jstring msg)
3245 {
3246 throw new java::lang::IncompatibleClassChangeError (msg);
3247 }
3248
3249 #ifndef HANDLE_SEGV
3250 static java::lang::NullPointerException *null_pointer_exc;
3251 static void
throw_null_pointer_exception()3252 throw_null_pointer_exception ()
3253 {
3254 if (null_pointer_exc == NULL)
3255 null_pointer_exc = new java::lang::NullPointerException;
3256
3257 throw null_pointer_exc;
3258 }
3259 #endif
3260
3261 #endif // INTERPRETER
3262