source: vendor/gcc/3.3.4/libjava/interpret.cc

Last change on this file was 1391, checked in by bird, 21 years ago

GCC v3.3.3 sources.

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