source: trunk/src/gcc/libjava/interpret.cc@ 1533

Last change on this file since 1533 was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • 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.