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