Mark as release
[official-gcc.git] / libjava / interpret-run.cc
blob26cc4a616ddc62c53ddb41c916607989b2a829ae
1 // interpret-run.cc - Code to interpret bytecode
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 /* This file is meant only to be included in interpret.cc, it should not be
12 * compiled directly. */
14 using namespace java::lang::reflect;
16 // FRAME_DESC registers this particular invocation as the top-most
17 // interpreter frame. This lets the stack tracing code (for
18 // Throwable) print information about the method being interpreted
19 // rather than about the interpreter itself. FRAME_DESC has a
20 // destructor so it cleans up automatically when the interpreter
21 // returns.
22 java::lang::Thread *thread = java::lang::Thread::currentThread();
23 _Jv_InterpFrame frame_desc (meth, thread);
25 _Jv_word stack[meth->max_stack];
26 _Jv_word *sp = stack;
28 _Jv_word locals[meth->max_locals];
30 #define INSN_LABEL(op) &&insn_##op
32 static const void *const insn_target[] =
34 INSN_LABEL(nop),
35 INSN_LABEL(aconst_null),
36 INSN_LABEL(iconst_m1),
37 INSN_LABEL(iconst_0),
38 INSN_LABEL(iconst_1),
39 INSN_LABEL(iconst_2),
40 INSN_LABEL(iconst_3),
41 INSN_LABEL(iconst_4),
42 INSN_LABEL(iconst_5),
43 INSN_LABEL(lconst_0),
44 INSN_LABEL(lconst_1),
45 INSN_LABEL(fconst_0),
46 INSN_LABEL(fconst_1),
47 INSN_LABEL(fconst_2),
48 INSN_LABEL(dconst_0),
49 INSN_LABEL(dconst_1),
50 INSN_LABEL(bipush),
51 INSN_LABEL(sipush),
52 INSN_LABEL(ldc),
53 INSN_LABEL(ldc_w),
54 INSN_LABEL(ldc2_w),
55 INSN_LABEL(iload),
56 INSN_LABEL(lload),
57 INSN_LABEL(fload),
58 INSN_LABEL(dload),
59 INSN_LABEL(aload),
60 INSN_LABEL(iload_0),
61 INSN_LABEL(iload_1),
62 INSN_LABEL(iload_2),
63 INSN_LABEL(iload_3),
64 INSN_LABEL(lload_0),
65 INSN_LABEL(lload_1),
66 INSN_LABEL(lload_2),
67 INSN_LABEL(lload_3),
68 INSN_LABEL(fload_0),
69 INSN_LABEL(fload_1),
70 INSN_LABEL(fload_2),
71 INSN_LABEL(fload_3),
72 INSN_LABEL(dload_0),
73 INSN_LABEL(dload_1),
74 INSN_LABEL(dload_2),
75 INSN_LABEL(dload_3),
76 INSN_LABEL(aload_0),
77 INSN_LABEL(aload_1),
78 INSN_LABEL(aload_2),
79 INSN_LABEL(aload_3),
80 INSN_LABEL(iaload),
81 INSN_LABEL(laload),
82 INSN_LABEL(faload),
83 INSN_LABEL(daload),
84 INSN_LABEL(aaload),
85 INSN_LABEL(baload),
86 INSN_LABEL(caload),
87 INSN_LABEL(saload),
88 INSN_LABEL(istore),
89 INSN_LABEL(lstore),
90 INSN_LABEL(fstore),
91 INSN_LABEL(dstore),
92 INSN_LABEL(astore),
93 INSN_LABEL(istore_0),
94 INSN_LABEL(istore_1),
95 INSN_LABEL(istore_2),
96 INSN_LABEL(istore_3),
97 INSN_LABEL(lstore_0),
98 INSN_LABEL(lstore_1),
99 INSN_LABEL(lstore_2),
100 INSN_LABEL(lstore_3),
101 INSN_LABEL(fstore_0),
102 INSN_LABEL(fstore_1),
103 INSN_LABEL(fstore_2),
104 INSN_LABEL(fstore_3),
105 INSN_LABEL(dstore_0),
106 INSN_LABEL(dstore_1),
107 INSN_LABEL(dstore_2),
108 INSN_LABEL(dstore_3),
109 INSN_LABEL(astore_0),
110 INSN_LABEL(astore_1),
111 INSN_LABEL(astore_2),
112 INSN_LABEL(astore_3),
113 INSN_LABEL(iastore),
114 INSN_LABEL(lastore),
115 INSN_LABEL(fastore),
116 INSN_LABEL(dastore),
117 INSN_LABEL(aastore),
118 INSN_LABEL(bastore),
119 INSN_LABEL(castore),
120 INSN_LABEL(sastore),
121 INSN_LABEL(pop),
122 INSN_LABEL(pop2),
123 INSN_LABEL(dup),
124 INSN_LABEL(dup_x1),
125 INSN_LABEL(dup_x2),
126 INSN_LABEL(dup2),
127 INSN_LABEL(dup2_x1),
128 INSN_LABEL(dup2_x2),
129 INSN_LABEL(swap),
130 INSN_LABEL(iadd),
131 INSN_LABEL(ladd),
132 INSN_LABEL(fadd),
133 INSN_LABEL(dadd),
134 INSN_LABEL(isub),
135 INSN_LABEL(lsub),
136 INSN_LABEL(fsub),
137 INSN_LABEL(dsub),
138 INSN_LABEL(imul),
139 INSN_LABEL(lmul),
140 INSN_LABEL(fmul),
141 INSN_LABEL(dmul),
142 INSN_LABEL(idiv),
143 INSN_LABEL(ldiv),
144 INSN_LABEL(fdiv),
145 INSN_LABEL(ddiv),
146 INSN_LABEL(irem),
147 INSN_LABEL(lrem),
148 INSN_LABEL(frem),
149 INSN_LABEL(drem),
150 INSN_LABEL(ineg),
151 INSN_LABEL(lneg),
152 INSN_LABEL(fneg),
153 INSN_LABEL(dneg),
154 INSN_LABEL(ishl),
155 INSN_LABEL(lshl),
156 INSN_LABEL(ishr),
157 INSN_LABEL(lshr),
158 INSN_LABEL(iushr),
159 INSN_LABEL(lushr),
160 INSN_LABEL(iand),
161 INSN_LABEL(land),
162 INSN_LABEL(ior),
163 INSN_LABEL(lor),
164 INSN_LABEL(ixor),
165 INSN_LABEL(lxor),
166 INSN_LABEL(iinc),
167 INSN_LABEL(i2l),
168 INSN_LABEL(i2f),
169 INSN_LABEL(i2d),
170 INSN_LABEL(l2i),
171 INSN_LABEL(l2f),
172 INSN_LABEL(l2d),
173 INSN_LABEL(f2i),
174 INSN_LABEL(f2l),
175 INSN_LABEL(f2d),
176 INSN_LABEL(d2i),
177 INSN_LABEL(d2l),
178 INSN_LABEL(d2f),
179 INSN_LABEL(i2b),
180 INSN_LABEL(i2c),
181 INSN_LABEL(i2s),
182 INSN_LABEL(lcmp),
183 INSN_LABEL(fcmpl),
184 INSN_LABEL(fcmpg),
185 INSN_LABEL(dcmpl),
186 INSN_LABEL(dcmpg),
187 INSN_LABEL(ifeq),
188 INSN_LABEL(ifne),
189 INSN_LABEL(iflt),
190 INSN_LABEL(ifge),
191 INSN_LABEL(ifgt),
192 INSN_LABEL(ifle),
193 INSN_LABEL(if_icmpeq),
194 INSN_LABEL(if_icmpne),
195 INSN_LABEL(if_icmplt),
196 INSN_LABEL(if_icmpge),
197 INSN_LABEL(if_icmpgt),
198 INSN_LABEL(if_icmple),
199 INSN_LABEL(if_acmpeq),
200 INSN_LABEL(if_acmpne),
201 INSN_LABEL(goto),
202 INSN_LABEL(jsr),
203 INSN_LABEL(ret),
204 INSN_LABEL(tableswitch),
205 INSN_LABEL(lookupswitch),
206 INSN_LABEL(ireturn),
207 INSN_LABEL(lreturn),
208 INSN_LABEL(freturn),
209 INSN_LABEL(dreturn),
210 INSN_LABEL(areturn),
211 INSN_LABEL(return),
212 INSN_LABEL(getstatic),
213 INSN_LABEL(putstatic),
214 INSN_LABEL(getfield),
215 INSN_LABEL(putfield),
216 INSN_LABEL(invokevirtual),
217 INSN_LABEL(invokespecial),
218 INSN_LABEL(invokestatic),
219 INSN_LABEL(invokeinterface),
220 INSN_LABEL (breakpoint),
221 INSN_LABEL(new),
222 INSN_LABEL(newarray),
223 INSN_LABEL(anewarray),
224 INSN_LABEL(arraylength),
225 INSN_LABEL(athrow),
226 INSN_LABEL(checkcast),
227 INSN_LABEL(instanceof),
228 INSN_LABEL(monitorenter),
229 INSN_LABEL(monitorexit),
230 #ifdef DIRECT_THREADED
231 0, // wide
232 #else
233 INSN_LABEL(wide),
234 #endif
235 INSN_LABEL(multianewarray),
236 INSN_LABEL(ifnull),
237 INSN_LABEL(ifnonnull),
238 INSN_LABEL(goto_w),
239 INSN_LABEL(jsr_w),
240 #ifdef DIRECT_THREADED
241 INSN_LABEL (ldc_class)
242 #else
244 #endif
247 pc_t pc;
249 #ifdef DIRECT_THREADED
251 #define NEXT_INSN goto *((pc++)->insn)
252 #define INTVAL() ((pc++)->int_val)
253 #define AVAL() ((pc++)->datum)
255 #define GET1S() INTVAL ()
256 #define GET2S() INTVAL ()
257 #define GET1U() INTVAL ()
258 #define GET2U() INTVAL ()
259 #define AVAL1U() AVAL ()
260 #define AVAL2U() AVAL ()
261 #define AVAL2UP() AVAL ()
262 #define SKIP_GOTO ++pc
263 #define GOTO_VAL() (insn_slot *) pc->datum
264 #define PCVAL(unionval) unionval.p
265 #define AMPAMP(label) &&label
267 // Compile if we must. NOTE: Double-check locking.
268 if (meth->prepared == NULL)
270 _Jv_MutexLock (&compile_mutex);
271 if (meth->prepared == NULL)
272 meth->compile (insn_target);
273 _Jv_MutexUnlock (&compile_mutex);
276 // If we're only compiling, stop here
277 if (args == NULL)
278 return;
280 pc = (insn_slot *) meth->prepared;
282 #else
284 #define NEXT_INSN goto *(insn_target[*pc++])
286 #define GET1S() get1s (pc++)
287 #define GET2S() (pc += 2, get2s (pc- 2))
288 #define GET1U() get1u (pc++)
289 #define GET2U() (pc += 2, get2u (pc - 2))
290 // Note that these could be more efficient when not handling 'ldc
291 // class'.
292 #define AVAL1U() \
293 ({ int index = get1u (pc++); \
294 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
295 #define AVAL2U() \
296 ({ int index = get2u (pc); pc += 2; \
297 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
298 // Note that we don't need to resolve the pool entry here as class
299 // constants are never wide.
300 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
301 #define SKIP_GOTO pc += 2
302 #define GOTO_VAL() pc - 1 + get2s (pc)
303 #define PCVAL(unionval) unionval.i
304 #define AMPAMP(label) NULL
306 pc = meth->bytecode ();
308 #endif /* DIRECT_THREADED */
310 #define TAKE_GOTO pc = GOTO_VAL ()
312 /* Go straight at it! the ffi raw format matches the internal
313 stack representation exactly. At least, that's the idea.
315 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
317 _Jv_word *pool_data = meth->defining_class->constants.data;
319 /* These three are temporaries for common code used by several
320 instructions. */
321 void (*fun)();
322 _Jv_ResolvedMethod* rmeth;
323 int tmpval;
327 // We keep nop around. It is used if we're interpreting the
328 // bytecodes and not doing direct threading.
329 insn_nop:
330 NEXT_INSN;
332 /* The first few instructions here are ordered according to their
333 frequency, in the hope that this will improve code locality a
334 little. */
336 insn_aload_0: // 0x2a
337 LOADA (0);
338 NEXT_INSN;
340 insn_iload: // 0x15
341 LOADI (GET1U ());
342 NEXT_INSN;
344 insn_iload_1: // 0x1b
345 LOADI (1);
346 NEXT_INSN;
348 insn_invokevirtual: // 0xb6
350 SAVE_PC();
351 int index = GET2U ();
353 /* _Jv_Linker::resolve_pool_entry returns immediately if the
354 * value already is resolved. If we want to clutter up the
355 * code here to gain a little performance, then we can check
356 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
357 * directly. For now, I don't think it is worth it. */
359 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
360 index)).rmethod;
362 sp -= rmeth->stack_item_count;
364 if (rmeth->method->accflags & Modifier::FINAL)
366 // We can't rely on NULLCHECK working if the method is final.
367 if (! sp[0].o)
368 throw_null_pointer_exception ();
370 // Final methods might not appear in the vtable.
371 fun = (void (*)()) rmeth->method->ncode;
373 else
375 NULLCHECK (sp[0].o);
376 jobject rcv = sp[0].o;
377 _Jv_VTable *table = *(_Jv_VTable**) rcv;
378 fun = (void (*)()) table->get_method (rmeth->method->index);
381 #ifdef DIRECT_THREADED
382 // Rewrite instruction so that we use a faster pre-resolved
383 // method.
384 pc[-2].insn = &&invokevirtual_resolved;
385 pc[-1].datum = rmeth;
386 #endif /* DIRECT_THREADED */
388 goto perform_invoke;
390 #ifdef DIRECT_THREADED
391 invokevirtual_resolved:
393 SAVE_PC();
394 rmeth = (_Jv_ResolvedMethod *) AVAL ();
395 sp -= rmeth->stack_item_count;
397 if (rmeth->method->accflags & Modifier::FINAL)
399 // We can't rely on NULLCHECK working if the method is final.
400 if (! sp[0].o)
401 throw_null_pointer_exception ();
403 // Final methods might not appear in the vtable.
404 fun = (void (*)()) rmeth->method->ncode;
406 else
408 jobject rcv = sp[0].o;
409 _Jv_VTable *table = *(_Jv_VTable**) rcv;
410 fun = (void (*)()) table->get_method (rmeth->method->index);
413 goto perform_invoke;
414 #endif /* DIRECT_THREADED */
416 perform_invoke:
418 /* here goes the magic again... */
419 ffi_cif *cif = &rmeth->cif;
420 ffi_raw *raw = (ffi_raw*) sp;
422 _Jv_value rvalue;
424 #if FFI_NATIVE_RAW_API
425 /* We assume that this is only implemented if it's correct */
426 /* to use it here. On a 64 bit machine, it never is. */
427 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
428 #else
429 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
430 #endif
432 int rtype = cif->rtype->type;
434 /* the likelyhood of object, int, or void return is very high,
435 * so those are checked before the switch */
436 if (rtype == FFI_TYPE_POINTER)
438 PUSHA (rvalue.object_value);
440 else if (rtype == FFI_TYPE_SINT32)
442 PUSHI (rvalue.int_value);
444 else if (rtype == FFI_TYPE_VOID)
446 /* skip */
448 else
450 switch (rtype)
452 case FFI_TYPE_SINT8:
453 PUSHI ((jbyte)(rvalue.int_value & 0xff));
454 break;
456 case FFI_TYPE_SINT16:
457 PUSHI ((jshort)(rvalue.int_value & 0xffff));
458 break;
460 case FFI_TYPE_UINT16:
461 PUSHI (rvalue.int_value & 0xffff);
462 break;
464 case FFI_TYPE_FLOAT:
465 PUSHF (rvalue.float_value);
466 break;
468 case FFI_TYPE_DOUBLE:
469 PUSHD (rvalue.double_value);
470 break;
472 case FFI_TYPE_SINT64:
473 PUSHL (rvalue.long_value);
474 break;
476 default:
477 throw_internal_error ("unknown return type in invokeXXX");
481 NEXT_INSN;
483 insn_aconst_null:
484 PUSHA (NULL);
485 NEXT_INSN;
487 insn_iconst_m1:
488 PUSHI (-1);
489 NEXT_INSN;
491 insn_iconst_0:
492 PUSHI (0);
493 NEXT_INSN;
495 insn_iconst_1:
496 PUSHI (1);
497 NEXT_INSN;
499 insn_iconst_2:
500 PUSHI (2);
501 NEXT_INSN;
503 insn_iconst_3:
504 PUSHI (3);
505 NEXT_INSN;
507 insn_iconst_4:
508 PUSHI (4);
509 NEXT_INSN;
511 insn_iconst_5:
512 PUSHI (5);
513 NEXT_INSN;
515 insn_lconst_0:
516 PUSHL (0);
517 NEXT_INSN;
519 insn_lconst_1:
520 PUSHL (1);
521 NEXT_INSN;
523 insn_fconst_0:
524 PUSHF (0);
525 NEXT_INSN;
527 insn_fconst_1:
528 PUSHF (1);
529 NEXT_INSN;
531 insn_fconst_2:
532 PUSHF (2);
533 NEXT_INSN;
535 insn_dconst_0:
536 PUSHD (0);
537 NEXT_INSN;
539 insn_dconst_1:
540 PUSHD (1);
541 NEXT_INSN;
543 insn_bipush:
544 // For direct threaded, bipush and sipush are the same.
545 #ifndef DIRECT_THREADED
546 PUSHI (GET1S ());
547 NEXT_INSN;
548 #endif /* DIRECT_THREADED */
549 insn_sipush:
550 PUSHI (GET2S ());
551 NEXT_INSN;
553 insn_ldc:
554 // For direct threaded, ldc and ldc_w are the same.
555 #ifndef DIRECT_THREADED
556 PUSHA ((jobject) AVAL1U ());
557 NEXT_INSN;
558 #endif /* DIRECT_THREADED */
559 insn_ldc_w:
560 PUSHA ((jobject) AVAL2U ());
561 NEXT_INSN;
563 #ifdef DIRECT_THREADED
564 // For direct threaded we have a separate 'ldc class' operation.
565 insn_ldc_class:
567 SAVE_PC();
568 // We could rewrite the instruction at this point.
569 int index = INTVAL ();
570 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
571 index)).o;
572 PUSHA (k);
574 NEXT_INSN;
575 #endif /* DIRECT_THREADED */
577 insn_ldc2_w:
579 void *where = AVAL2UP ();
580 memcpy (sp, where, 2*sizeof (_Jv_word));
581 sp += 2;
583 NEXT_INSN;
585 insn_lload:
586 LOADL (GET1U ());
587 NEXT_INSN;
589 insn_fload:
590 LOADF (GET1U ());
591 NEXT_INSN;
593 insn_dload:
594 LOADD (GET1U ());
595 NEXT_INSN;
597 insn_aload:
598 LOADA (GET1U ());
599 NEXT_INSN;
601 insn_iload_0:
602 LOADI (0);
603 NEXT_INSN;
605 insn_iload_2:
606 LOADI (2);
607 NEXT_INSN;
609 insn_iload_3:
610 LOADI (3);
611 NEXT_INSN;
613 insn_lload_0:
614 LOADL (0);
615 NEXT_INSN;
617 insn_lload_1:
618 LOADL (1);
619 NEXT_INSN;
621 insn_lload_2:
622 LOADL (2);
623 NEXT_INSN;
625 insn_lload_3:
626 LOADL (3);
627 NEXT_INSN;
629 insn_fload_0:
630 LOADF (0);
631 NEXT_INSN;
633 insn_fload_1:
634 LOADF (1);
635 NEXT_INSN;
637 insn_fload_2:
638 LOADF (2);
639 NEXT_INSN;
641 insn_fload_3:
642 LOADF (3);
643 NEXT_INSN;
645 insn_dload_0:
646 LOADD (0);
647 NEXT_INSN;
649 insn_dload_1:
650 LOADD (1);
651 NEXT_INSN;
653 insn_dload_2:
654 LOADD (2);
655 NEXT_INSN;
657 insn_dload_3:
658 LOADD (3);
659 NEXT_INSN;
661 insn_aload_1:
662 LOADA(1);
663 NEXT_INSN;
665 insn_aload_2:
666 LOADA(2);
667 NEXT_INSN;
669 insn_aload_3:
670 LOADA(3);
671 NEXT_INSN;
673 insn_iaload:
675 jint index = POPI();
676 jintArray arr = (jintArray) POPA();
677 NULLARRAYCHECK (arr);
678 ARRAYBOUNDSCHECK (arr, index);
679 PUSHI( elements(arr)[index] );
681 NEXT_INSN;
683 insn_laload:
685 jint index = POPI();
686 jlongArray arr = (jlongArray) POPA();
687 NULLARRAYCHECK (arr);
688 ARRAYBOUNDSCHECK (arr, index);
689 PUSHL( elements(arr)[index] );
691 NEXT_INSN;
693 insn_faload:
695 jint index = POPI();
696 jfloatArray arr = (jfloatArray) POPA();
697 NULLARRAYCHECK (arr);
698 ARRAYBOUNDSCHECK (arr, index);
699 PUSHF( elements(arr)[index] );
701 NEXT_INSN;
703 insn_daload:
705 jint index = POPI();
706 jdoubleArray arr = (jdoubleArray) POPA();
707 NULLARRAYCHECK (arr);
708 ARRAYBOUNDSCHECK (arr, index);
709 PUSHD( elements(arr)[index] );
711 NEXT_INSN;
713 insn_aaload:
715 jint index = POPI();
716 jobjectArray arr = (jobjectArray) POPA();
717 NULLARRAYCHECK (arr);
718 ARRAYBOUNDSCHECK (arr, index);
719 PUSHA( elements(arr)[index] );
721 NEXT_INSN;
723 insn_baload:
725 jint index = POPI();
726 jbyteArray arr = (jbyteArray) POPA();
727 NULLARRAYCHECK (arr);
728 ARRAYBOUNDSCHECK (arr, index);
729 PUSHI( elements(arr)[index] );
731 NEXT_INSN;
733 insn_caload:
735 jint index = POPI();
736 jcharArray arr = (jcharArray) POPA();
737 NULLARRAYCHECK (arr);
738 ARRAYBOUNDSCHECK (arr, index);
739 PUSHI( elements(arr)[index] );
741 NEXT_INSN;
743 insn_saload:
745 jint index = POPI();
746 jshortArray arr = (jshortArray) POPA();
747 NULLARRAYCHECK (arr);
748 ARRAYBOUNDSCHECK (arr, index);
749 PUSHI( elements(arr)[index] );
751 NEXT_INSN;
753 insn_istore:
754 STOREI (GET1U ());
755 NEXT_INSN;
757 insn_lstore:
758 STOREL (GET1U ());
759 NEXT_INSN;
761 insn_fstore:
762 STOREF (GET1U ());
763 NEXT_INSN;
765 insn_dstore:
766 STORED (GET1U ());
767 NEXT_INSN;
769 insn_astore:
770 STOREA (GET1U ());
771 NEXT_INSN;
773 insn_istore_0:
774 STOREI (0);
775 NEXT_INSN;
777 insn_istore_1:
778 STOREI (1);
779 NEXT_INSN;
781 insn_istore_2:
782 STOREI (2);
783 NEXT_INSN;
785 insn_istore_3:
786 STOREI (3);
787 NEXT_INSN;
789 insn_lstore_0:
790 STOREL (0);
791 NEXT_INSN;
793 insn_lstore_1:
794 STOREL (1);
795 NEXT_INSN;
797 insn_lstore_2:
798 STOREL (2);
799 NEXT_INSN;
801 insn_lstore_3:
802 STOREL (3);
803 NEXT_INSN;
805 insn_fstore_0:
806 STOREF (0);
807 NEXT_INSN;
809 insn_fstore_1:
810 STOREF (1);
811 NEXT_INSN;
813 insn_fstore_2:
814 STOREF (2);
815 NEXT_INSN;
817 insn_fstore_3:
818 STOREF (3);
819 NEXT_INSN;
821 insn_dstore_0:
822 STORED (0);
823 NEXT_INSN;
825 insn_dstore_1:
826 STORED (1);
827 NEXT_INSN;
829 insn_dstore_2:
830 STORED (2);
831 NEXT_INSN;
833 insn_dstore_3:
834 STORED (3);
835 NEXT_INSN;
837 insn_astore_0:
838 STOREA(0);
839 NEXT_INSN;
841 insn_astore_1:
842 STOREA(1);
843 NEXT_INSN;
845 insn_astore_2:
846 STOREA(2);
847 NEXT_INSN;
849 insn_astore_3:
850 STOREA(3);
851 NEXT_INSN;
853 insn_iastore:
855 jint value = POPI();
856 jint index = POPI();
857 jintArray arr = (jintArray) POPA();
858 NULLARRAYCHECK (arr);
859 ARRAYBOUNDSCHECK (arr, index);
860 elements(arr)[index] = value;
862 NEXT_INSN;
864 insn_lastore:
866 jlong value = POPL();
867 jint index = POPI();
868 jlongArray arr = (jlongArray) POPA();
869 NULLARRAYCHECK (arr);
870 ARRAYBOUNDSCHECK (arr, index);
871 elements(arr)[index] = value;
873 NEXT_INSN;
875 insn_fastore:
877 jfloat value = POPF();
878 jint index = POPI();
879 jfloatArray arr = (jfloatArray) POPA();
880 NULLARRAYCHECK (arr);
881 ARRAYBOUNDSCHECK (arr, index);
882 elements(arr)[index] = value;
884 NEXT_INSN;
886 insn_dastore:
888 jdouble value = POPD();
889 jint index = POPI();
890 jdoubleArray arr = (jdoubleArray) POPA();
891 NULLARRAYCHECK (arr);
892 ARRAYBOUNDSCHECK (arr, index);
893 elements(arr)[index] = value;
895 NEXT_INSN;
897 insn_aastore:
899 jobject value = POPA();
900 jint index = POPI();
901 jobjectArray arr = (jobjectArray) POPA();
902 NULLARRAYCHECK (arr);
903 ARRAYBOUNDSCHECK (arr, index);
904 _Jv_CheckArrayStore (arr, value);
905 elements(arr)[index] = value;
907 NEXT_INSN;
909 insn_bastore:
911 jbyte value = (jbyte) POPI();
912 jint index = POPI();
913 jbyteArray arr = (jbyteArray) POPA();
914 NULLARRAYCHECK (arr);
915 ARRAYBOUNDSCHECK (arr, index);
916 elements(arr)[index] = value;
918 NEXT_INSN;
920 insn_castore:
922 jchar value = (jchar) POPI();
923 jint index = POPI();
924 jcharArray arr = (jcharArray) POPA();
925 NULLARRAYCHECK (arr);
926 ARRAYBOUNDSCHECK (arr, index);
927 elements(arr)[index] = value;
929 NEXT_INSN;
931 insn_sastore:
933 jshort value = (jshort) POPI();
934 jint index = POPI();
935 jshortArray arr = (jshortArray) POPA();
936 NULLARRAYCHECK (arr);
937 ARRAYBOUNDSCHECK (arr, index);
938 elements(arr)[index] = value;
940 NEXT_INSN;
942 insn_pop:
943 sp -= 1;
944 NEXT_INSN;
946 insn_pop2:
947 sp -= 2;
948 NEXT_INSN;
950 insn_dup:
951 sp[0] = sp[-1];
952 sp += 1;
953 NEXT_INSN;
955 insn_dup_x1:
956 dupx (sp, 1, 1); sp+=1;
957 NEXT_INSN;
959 insn_dup_x2:
960 dupx (sp, 1, 2); sp+=1;
961 NEXT_INSN;
963 insn_dup2:
964 sp[0] = sp[-2];
965 sp[1] = sp[-1];
966 sp += 2;
967 NEXT_INSN;
969 insn_dup2_x1:
970 dupx (sp, 2, 1); sp+=2;
971 NEXT_INSN;
973 insn_dup2_x2:
974 dupx (sp, 2, 2); sp+=2;
975 NEXT_INSN;
977 insn_swap:
979 jobject tmp1 = POPA();
980 jobject tmp2 = POPA();
981 PUSHA (tmp1);
982 PUSHA (tmp2);
984 NEXT_INSN;
986 insn_iadd:
987 BINOPI(+);
988 NEXT_INSN;
990 insn_ladd:
991 BINOPL(+);
992 NEXT_INSN;
994 insn_fadd:
995 BINOPF(+);
996 NEXT_INSN;
998 insn_dadd:
999 BINOPD(+);
1000 NEXT_INSN;
1002 insn_isub:
1003 BINOPI(-);
1004 NEXT_INSN;
1006 insn_lsub:
1007 BINOPL(-);
1008 NEXT_INSN;
1010 insn_fsub:
1011 BINOPF(-);
1012 NEXT_INSN;
1014 insn_dsub:
1015 BINOPD(-);
1016 NEXT_INSN;
1018 insn_imul:
1019 BINOPI(*);
1020 NEXT_INSN;
1022 insn_lmul:
1023 BINOPL(*);
1024 NEXT_INSN;
1026 insn_fmul:
1027 BINOPF(*);
1028 NEXT_INSN;
1030 insn_dmul:
1031 BINOPD(*);
1032 NEXT_INSN;
1034 insn_idiv:
1036 SAVE_PC();
1037 jint value2 = POPI();
1038 jint value1 = POPI();
1039 jint res = _Jv_divI (value1, value2);
1040 PUSHI (res);
1042 NEXT_INSN;
1044 insn_ldiv:
1046 SAVE_PC();
1047 jlong value2 = POPL();
1048 jlong value1 = POPL();
1049 jlong res = _Jv_divJ (value1, value2);
1050 PUSHL (res);
1052 NEXT_INSN;
1054 insn_fdiv:
1056 jfloat value2 = POPF();
1057 jfloat value1 = POPF();
1058 jfloat res = value1 / value2;
1059 PUSHF (res);
1061 NEXT_INSN;
1063 insn_ddiv:
1065 jdouble value2 = POPD();
1066 jdouble value1 = POPD();
1067 jdouble res = value1 / value2;
1068 PUSHD (res);
1070 NEXT_INSN;
1072 insn_irem:
1074 SAVE_PC();
1075 jint value2 = POPI();
1076 jint value1 = POPI();
1077 jint res = _Jv_remI (value1, value2);
1078 PUSHI (res);
1080 NEXT_INSN;
1082 insn_lrem:
1084 SAVE_PC();
1085 jlong value2 = POPL();
1086 jlong value1 = POPL();
1087 jlong res = _Jv_remJ (value1, value2);
1088 PUSHL (res);
1090 NEXT_INSN;
1092 insn_frem:
1094 jfloat value2 = POPF();
1095 jfloat value1 = POPF();
1096 jfloat res = __ieee754_fmod (value1, value2);
1097 PUSHF (res);
1099 NEXT_INSN;
1101 insn_drem:
1103 jdouble value2 = POPD();
1104 jdouble value1 = POPD();
1105 jdouble res = __ieee754_fmod (value1, value2);
1106 PUSHD (res);
1108 NEXT_INSN;
1110 insn_ineg:
1112 jint value = POPI();
1113 PUSHI (value * -1);
1115 NEXT_INSN;
1117 insn_lneg:
1119 jlong value = POPL();
1120 PUSHL (value * -1);
1122 NEXT_INSN;
1124 insn_fneg:
1126 jfloat value = POPF();
1127 PUSHF (value * -1);
1129 NEXT_INSN;
1131 insn_dneg:
1133 jdouble value = POPD();
1134 PUSHD (value * -1);
1136 NEXT_INSN;
1138 insn_ishl:
1140 jint shift = (POPI() & 0x1f);
1141 jint value = POPI();
1142 PUSHI (value << shift);
1144 NEXT_INSN;
1146 insn_lshl:
1148 jint shift = (POPI() & 0x3f);
1149 jlong value = POPL();
1150 PUSHL (value << shift);
1152 NEXT_INSN;
1154 insn_ishr:
1156 jint shift = (POPI() & 0x1f);
1157 jint value = POPI();
1158 PUSHI (value >> shift);
1160 NEXT_INSN;
1162 insn_lshr:
1164 jint shift = (POPI() & 0x3f);
1165 jlong value = POPL();
1166 PUSHL (value >> shift);
1168 NEXT_INSN;
1170 insn_iushr:
1172 jint shift = (POPI() & 0x1f);
1173 _Jv_uint value = (_Jv_uint) POPI();
1174 PUSHI ((jint) (value >> shift));
1176 NEXT_INSN;
1178 insn_lushr:
1180 jint shift = (POPI() & 0x3f);
1181 _Jv_ulong value = (_Jv_ulong) POPL();
1182 PUSHL ((jlong) (value >> shift));
1184 NEXT_INSN;
1186 insn_iand:
1187 BINOPI (&);
1188 NEXT_INSN;
1190 insn_land:
1191 BINOPL (&);
1192 NEXT_INSN;
1194 insn_ior:
1195 BINOPI (|);
1196 NEXT_INSN;
1198 insn_lor:
1199 BINOPL (|);
1200 NEXT_INSN;
1202 insn_ixor:
1203 BINOPI (^);
1204 NEXT_INSN;
1206 insn_lxor:
1207 BINOPL (^);
1208 NEXT_INSN;
1210 insn_iinc:
1212 jint index = GET1U ();
1213 jint amount = GET1S ();
1214 locals[index].i += amount;
1216 NEXT_INSN;
1218 insn_i2l:
1219 {jlong value = POPI(); PUSHL (value);}
1220 NEXT_INSN;
1222 insn_i2f:
1223 {jfloat value = POPI(); PUSHF (value);}
1224 NEXT_INSN;
1226 insn_i2d:
1227 {jdouble value = POPI(); PUSHD (value);}
1228 NEXT_INSN;
1230 insn_l2i:
1231 {jint value = POPL(); PUSHI (value);}
1232 NEXT_INSN;
1234 insn_l2f:
1235 {jfloat value = POPL(); PUSHF (value);}
1236 NEXT_INSN;
1238 insn_l2d:
1239 {jdouble value = POPL(); PUSHD (value);}
1240 NEXT_INSN;
1242 insn_f2i:
1244 using namespace java::lang;
1245 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1246 PUSHI(value);
1248 NEXT_INSN;
1250 insn_f2l:
1252 using namespace java::lang;
1253 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1254 PUSHL(value);
1256 NEXT_INSN;
1258 insn_f2d:
1259 { jdouble value = POPF (); PUSHD(value); }
1260 NEXT_INSN;
1262 insn_d2i:
1264 using namespace java::lang;
1265 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1266 PUSHI(value);
1268 NEXT_INSN;
1270 insn_d2l:
1272 using namespace java::lang;
1273 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1274 PUSHL(value);
1276 NEXT_INSN;
1278 insn_d2f:
1279 { jfloat value = POPD (); PUSHF(value); }
1280 NEXT_INSN;
1282 insn_i2b:
1283 { jbyte value = POPI (); PUSHI(value); }
1284 NEXT_INSN;
1286 insn_i2c:
1287 { jchar value = POPI (); PUSHI(value); }
1288 NEXT_INSN;
1290 insn_i2s:
1291 { jshort value = POPI (); PUSHI(value); }
1292 NEXT_INSN;
1294 insn_lcmp:
1296 jlong value2 = POPL ();
1297 jlong value1 = POPL ();
1298 if (value1 > value2)
1299 { PUSHI (1); }
1300 else if (value1 == value2)
1301 { PUSHI (0); }
1302 else
1303 { PUSHI (-1); }
1305 NEXT_INSN;
1307 insn_fcmpl:
1308 tmpval = -1;
1309 goto fcmp;
1311 insn_fcmpg:
1312 tmpval = 1;
1314 fcmp:
1316 jfloat value2 = POPF ();
1317 jfloat value1 = POPF ();
1318 if (value1 > value2)
1319 PUSHI (1);
1320 else if (value1 == value2)
1321 PUSHI (0);
1322 else if (value1 < value2)
1323 PUSHI (-1);
1324 else
1325 PUSHI (tmpval);
1327 NEXT_INSN;
1329 insn_dcmpl:
1330 tmpval = -1;
1331 goto dcmp;
1333 insn_dcmpg:
1334 tmpval = 1;
1336 dcmp:
1338 jdouble value2 = POPD ();
1339 jdouble value1 = POPD ();
1340 if (value1 > value2)
1341 PUSHI (1);
1342 else if (value1 == value2)
1343 PUSHI (0);
1344 else if (value1 < value2)
1345 PUSHI (-1);
1346 else
1347 PUSHI (tmpval);
1349 NEXT_INSN;
1351 insn_ifeq:
1353 if (POPI() == 0)
1354 TAKE_GOTO;
1355 else
1356 SKIP_GOTO;
1358 NEXT_INSN;
1360 insn_ifne:
1362 if (POPI() != 0)
1363 TAKE_GOTO;
1364 else
1365 SKIP_GOTO;
1367 NEXT_INSN;
1369 insn_iflt:
1371 if (POPI() < 0)
1372 TAKE_GOTO;
1373 else
1374 SKIP_GOTO;
1376 NEXT_INSN;
1378 insn_ifge:
1380 if (POPI() >= 0)
1381 TAKE_GOTO;
1382 else
1383 SKIP_GOTO;
1385 NEXT_INSN;
1387 insn_ifgt:
1389 if (POPI() > 0)
1390 TAKE_GOTO;
1391 else
1392 SKIP_GOTO;
1394 NEXT_INSN;
1396 insn_ifle:
1398 if (POPI() <= 0)
1399 TAKE_GOTO;
1400 else
1401 SKIP_GOTO;
1403 NEXT_INSN;
1405 insn_if_icmpeq:
1407 jint value2 = POPI();
1408 jint value1 = POPI();
1409 if (value1 == value2)
1410 TAKE_GOTO;
1411 else
1412 SKIP_GOTO;
1414 NEXT_INSN;
1416 insn_if_icmpne:
1418 jint value2 = POPI();
1419 jint value1 = POPI();
1420 if (value1 != value2)
1421 TAKE_GOTO;
1422 else
1423 SKIP_GOTO;
1425 NEXT_INSN;
1427 insn_if_icmplt:
1429 jint value2 = POPI();
1430 jint value1 = POPI();
1431 if (value1 < value2)
1432 TAKE_GOTO;
1433 else
1434 SKIP_GOTO;
1436 NEXT_INSN;
1438 insn_if_icmpge:
1440 jint value2 = POPI();
1441 jint value1 = POPI();
1442 if (value1 >= value2)
1443 TAKE_GOTO;
1444 else
1445 SKIP_GOTO;
1447 NEXT_INSN;
1449 insn_if_icmpgt:
1451 jint value2 = POPI();
1452 jint value1 = POPI();
1453 if (value1 > value2)
1454 TAKE_GOTO;
1455 else
1456 SKIP_GOTO;
1458 NEXT_INSN;
1460 insn_if_icmple:
1462 jint value2 = POPI();
1463 jint value1 = POPI();
1464 if (value1 <= value2)
1465 TAKE_GOTO;
1466 else
1467 SKIP_GOTO;
1469 NEXT_INSN;
1471 insn_if_acmpeq:
1473 jobject value2 = POPA();
1474 jobject value1 = POPA();
1475 if (value1 == value2)
1476 TAKE_GOTO;
1477 else
1478 SKIP_GOTO;
1480 NEXT_INSN;
1482 insn_if_acmpne:
1484 jobject value2 = POPA();
1485 jobject value1 = POPA();
1486 if (value1 != value2)
1487 TAKE_GOTO;
1488 else
1489 SKIP_GOTO;
1491 NEXT_INSN;
1493 insn_goto_w:
1494 #ifndef DIRECT_THREADED
1495 // For direct threaded, goto and goto_w are the same.
1496 pc = pc - 1 + get4 (pc);
1497 NEXT_INSN;
1498 #endif /* DIRECT_THREADED */
1499 insn_goto:
1500 TAKE_GOTO;
1501 NEXT_INSN;
1503 insn_jsr_w:
1504 #ifndef DIRECT_THREADED
1505 // For direct threaded, jsr and jsr_w are the same.
1507 pc_t next = pc - 1 + get4 (pc);
1508 pc += 4;
1509 PUSHA ((jobject) pc);
1510 pc = next;
1512 NEXT_INSN;
1513 #endif /* DIRECT_THREADED */
1514 insn_jsr:
1516 pc_t next = GOTO_VAL();
1517 SKIP_GOTO;
1518 PUSHA ((jobject) pc);
1519 pc = next;
1521 NEXT_INSN;
1523 insn_ret:
1525 jint index = GET1U ();
1526 pc = (pc_t) PEEKA (index);
1528 NEXT_INSN;
1530 insn_tableswitch:
1532 #ifdef DIRECT_THREADED
1533 void *def = (pc++)->datum;
1535 int index = POPI();
1537 jint low = INTVAL ();
1538 jint high = INTVAL ();
1540 if (index < low || index > high)
1541 pc = (insn_slot *) def;
1542 else
1543 pc = (insn_slot *) ((pc + index - low)->datum);
1544 #else
1545 pc_t base_pc = pc - 1;
1546 int index = POPI ();
1548 pc_t base = (pc_t) meth->bytecode ();
1549 while ((pc - base) % 4 != 0)
1550 ++pc;
1552 jint def = get4 (pc);
1553 jint low = get4 (pc + 4);
1554 jint high = get4 (pc + 8);
1555 if (index < low || index > high)
1556 pc = base_pc + def;
1557 else
1558 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1559 #endif /* DIRECT_THREADED */
1561 NEXT_INSN;
1563 insn_lookupswitch:
1565 #ifdef DIRECT_THREADED
1566 void *def = (pc++)->insn;
1568 int index = POPI();
1570 jint npairs = INTVAL ();
1572 int max = npairs - 1;
1573 int min = 0;
1575 // Simple binary search...
1576 while (min < max)
1578 int half = (min + max) / 2;
1579 int match = pc[2 * half].int_val;
1581 if (index == match)
1583 // Found it.
1584 pc = (insn_slot *) pc[2 * half + 1].datum;
1585 NEXT_INSN;
1587 else if (index < match)
1588 // We can use HALF - 1 here because we check again on
1589 // loop exit.
1590 max = half - 1;
1591 else
1592 // We can use HALF + 1 here because we check again on
1593 // loop exit.
1594 min = half + 1;
1596 if (index == pc[2 * min].int_val)
1597 pc = (insn_slot *) pc[2 * min + 1].datum;
1598 else
1599 pc = (insn_slot *) def;
1600 #else
1601 unsigned char *base_pc = pc-1;
1602 int index = POPI();
1604 unsigned char* base = meth->bytecode ();
1605 while ((pc-base) % 4 != 0)
1606 ++pc;
1608 jint def = get4 (pc);
1609 jint npairs = get4 (pc+4);
1611 int max = npairs-1;
1612 int min = 0;
1614 // Simple binary search...
1615 while (min < max)
1617 int half = (min+max)/2;
1618 int match = get4 (pc+ 4*(2 + 2*half));
1620 if (index == match)
1621 min = max = half;
1622 else if (index < match)
1623 // We can use HALF - 1 here because we check again on
1624 // loop exit.
1625 max = half - 1;
1626 else
1627 // We can use HALF + 1 here because we check again on
1628 // loop exit.
1629 min = half + 1;
1632 if (index == get4 (pc+ 4*(2 + 2*min)))
1633 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1634 else
1635 pc = base_pc + def;
1636 #endif /* DIRECT_THREADED */
1638 NEXT_INSN;
1640 insn_areturn:
1641 *(jobject *) retp = POPA ();
1642 return;
1644 insn_lreturn:
1645 *(jlong *) retp = POPL ();
1646 return;
1648 insn_freturn:
1649 *(jfloat *) retp = POPF ();
1650 return;
1652 insn_dreturn:
1653 *(jdouble *) retp = POPD ();
1654 return;
1656 insn_ireturn:
1657 *(jint *) retp = POPI ();
1658 return;
1660 insn_return:
1661 return;
1663 insn_getstatic:
1665 jint fieldref_index = GET2U ();
1666 SAVE_PC(); // Constant pool resolution could throw.
1667 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1668 _Jv_Field *field = pool_data[fieldref_index].field;
1670 if ((field->flags & Modifier::STATIC) == 0)
1671 throw_incompatible_class_change_error
1672 (JvNewStringLatin1 ("field no longer static"));
1674 jclass type = field->type;
1676 // We rewrite the instruction once we discover what it refers
1677 // to.
1678 void *newinsn = NULL;
1679 if (type->isPrimitive ())
1681 switch (type->size_in_bytes)
1683 case 1:
1684 PUSHI (*field->u.byte_addr);
1685 newinsn = AMPAMP (getstatic_resolved_1);
1686 break;
1688 case 2:
1689 if (type == JvPrimClass (char))
1691 PUSHI (*field->u.char_addr);
1692 newinsn = AMPAMP (getstatic_resolved_char);
1694 else
1696 PUSHI (*field->u.short_addr);
1697 newinsn = AMPAMP (getstatic_resolved_short);
1699 break;
1701 case 4:
1702 PUSHI(*field->u.int_addr);
1703 newinsn = AMPAMP (getstatic_resolved_4);
1704 break;
1706 case 8:
1707 PUSHL(*field->u.long_addr);
1708 newinsn = AMPAMP (getstatic_resolved_8);
1709 break;
1712 else
1714 PUSHA(*field->u.object_addr);
1715 newinsn = AMPAMP (getstatic_resolved_obj);
1718 #ifdef DIRECT_THREADED
1719 pc[-2].insn = newinsn;
1720 pc[-1].datum = field->u.addr;
1721 #endif /* DIRECT_THREADED */
1723 NEXT_INSN;
1725 #ifdef DIRECT_THREADED
1726 getstatic_resolved_1:
1727 PUSHI (*(jbyte *) AVAL ());
1728 NEXT_INSN;
1730 getstatic_resolved_char:
1731 PUSHI (*(jchar *) AVAL ());
1732 NEXT_INSN;
1734 getstatic_resolved_short:
1735 PUSHI (*(jshort *) AVAL ());
1736 NEXT_INSN;
1738 getstatic_resolved_4:
1739 PUSHI (*(jint *) AVAL ());
1740 NEXT_INSN;
1742 getstatic_resolved_8:
1743 PUSHL (*(jlong *) AVAL ());
1744 NEXT_INSN;
1746 getstatic_resolved_obj:
1747 PUSHA (*(jobject *) AVAL ());
1748 NEXT_INSN;
1749 #endif /* DIRECT_THREADED */
1751 insn_getfield:
1753 SAVE_PC();
1754 jint fieldref_index = GET2U ();
1755 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1756 _Jv_Field *field = pool_data[fieldref_index].field;
1758 if ((field->flags & Modifier::STATIC) != 0)
1759 throw_incompatible_class_change_error
1760 (JvNewStringLatin1 ("field is static"));
1762 jclass type = field->type;
1763 jint field_offset = field->u.boffset;
1765 jobject obj = POPA();
1766 NULLCHECK(obj);
1768 void *newinsn = NULL;
1769 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1770 if (type->isPrimitive ())
1772 switch (type->size_in_bytes)
1774 case 1:
1775 PUSHI (val->byte_value);
1776 newinsn = AMPAMP (getfield_resolved_1);
1777 break;
1779 case 2:
1780 if (type == JvPrimClass (char))
1782 PUSHI (val->char_value);
1783 newinsn = AMPAMP (getfield_resolved_char);
1785 else
1787 PUSHI (val->short_value);
1788 newinsn = AMPAMP (getfield_resolved_short);
1790 break;
1792 case 4:
1793 PUSHI (val->int_value);
1794 newinsn = AMPAMP (getfield_resolved_4);
1795 break;
1797 case 8:
1798 PUSHL (val->long_value);
1799 newinsn = AMPAMP (getfield_resolved_8);
1800 break;
1803 else
1805 PUSHA (val->object_value);
1806 newinsn = AMPAMP (getfield_resolved_obj);
1809 #ifdef DIRECT_THREADED
1810 pc[-2].insn = newinsn;
1811 pc[-1].int_val = field_offset;
1812 #endif /* DIRECT_THREADED */
1814 NEXT_INSN;
1816 #ifdef DIRECT_THREADED
1817 getfield_resolved_1:
1819 char *obj = (char *) POPA ();
1820 NULLCHECK (obj);
1821 PUSHI (*(jbyte *) (obj + INTVAL ()));
1823 NEXT_INSN;
1825 getfield_resolved_char:
1827 char *obj = (char *) POPA ();
1828 NULLCHECK (obj);
1829 PUSHI (*(jchar *) (obj + INTVAL ()));
1831 NEXT_INSN;
1833 getfield_resolved_short:
1835 char *obj = (char *) POPA ();
1836 NULLCHECK (obj);
1837 PUSHI (*(jshort *) (obj + INTVAL ()));
1839 NEXT_INSN;
1841 getfield_resolved_4:
1843 char *obj = (char *) POPA ();
1844 NULLCHECK (obj);
1845 PUSHI (*(jint *) (obj + INTVAL ()));
1847 NEXT_INSN;
1849 getfield_resolved_8:
1851 char *obj = (char *) POPA ();
1852 NULLCHECK (obj);
1853 PUSHL (*(jlong *) (obj + INTVAL ()));
1855 NEXT_INSN;
1857 getfield_resolved_obj:
1859 char *obj = (char *) POPA ();
1860 NULLCHECK (obj);
1861 PUSHA (*(jobject *) (obj + INTVAL ()));
1863 NEXT_INSN;
1864 #endif /* DIRECT_THREADED */
1866 insn_putstatic:
1868 SAVE_PC();
1869 jint fieldref_index = GET2U ();
1870 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1871 _Jv_Field *field = pool_data[fieldref_index].field;
1873 jclass type = field->type;
1875 // ResolvePoolEntry cannot check this
1876 if ((field->flags & Modifier::STATIC) == 0)
1877 throw_incompatible_class_change_error
1878 (JvNewStringLatin1 ("field no longer static"));
1880 void *newinsn = NULL;
1881 if (type->isPrimitive ())
1883 switch (type->size_in_bytes)
1885 case 1:
1887 jint value = POPI();
1888 *field->u.byte_addr = value;
1889 newinsn = AMPAMP (putstatic_resolved_1);
1890 break;
1893 case 2:
1895 jint value = POPI();
1896 *field->u.char_addr = value;
1897 newinsn = AMPAMP (putstatic_resolved_2);
1898 break;
1901 case 4:
1903 jint value = POPI();
1904 *field->u.int_addr = value;
1905 newinsn = AMPAMP (putstatic_resolved_4);
1906 break;
1909 case 8:
1911 jlong value = POPL();
1912 *field->u.long_addr = value;
1913 newinsn = AMPAMP (putstatic_resolved_8);
1914 break;
1918 else
1920 jobject value = POPA();
1921 *field->u.object_addr = value;
1922 newinsn = AMPAMP (putstatic_resolved_obj);
1925 #ifdef DIRECT_THREADED
1926 pc[-2].insn = newinsn;
1927 pc[-1].datum = field->u.addr;
1928 #endif /* DIRECT_THREADED */
1930 NEXT_INSN;
1932 #ifdef DIRECT_THREADED
1933 putstatic_resolved_1:
1934 *(jbyte *) AVAL () = POPI ();
1935 NEXT_INSN;
1937 putstatic_resolved_2:
1938 *(jchar *) AVAL () = POPI ();
1939 NEXT_INSN;
1941 putstatic_resolved_4:
1942 *(jint *) AVAL () = POPI ();
1943 NEXT_INSN;
1945 putstatic_resolved_8:
1946 *(jlong *) AVAL () = POPL ();
1947 NEXT_INSN;
1949 putstatic_resolved_obj:
1950 *(jobject *) AVAL () = POPA ();
1951 NEXT_INSN;
1952 #endif /* DIRECT_THREADED */
1954 insn_putfield:
1956 SAVE_PC();
1957 jint fieldref_index = GET2U ();
1958 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1959 _Jv_Field *field = pool_data[fieldref_index].field;
1961 jclass type = field->type;
1963 if ((field->flags & Modifier::STATIC) != 0)
1964 throw_incompatible_class_change_error
1965 (JvNewStringLatin1 ("field is static"));
1967 jint field_offset = field->u.boffset;
1969 void *newinsn = NULL;
1970 if (type->isPrimitive ())
1972 switch (type->size_in_bytes)
1974 case 1:
1976 jint value = POPI();
1977 jobject obj = POPA();
1978 NULLCHECK(obj);
1979 *(jbyte*) ((char*)obj + field_offset) = value;
1980 newinsn = AMPAMP (putfield_resolved_1);
1981 break;
1984 case 2:
1986 jint value = POPI();
1987 jobject obj = POPA();
1988 NULLCHECK(obj);
1989 *(jchar*) ((char*)obj + field_offset) = value;
1990 newinsn = AMPAMP (putfield_resolved_2);
1991 break;
1994 case 4:
1996 jint value = POPI();
1997 jobject obj = POPA();
1998 NULLCHECK(obj);
1999 *(jint*) ((char*)obj + field_offset) = value;
2000 newinsn = AMPAMP (putfield_resolved_4);
2001 break;
2004 case 8:
2006 jlong value = POPL();
2007 jobject obj = POPA();
2008 NULLCHECK(obj);
2009 *(jlong*) ((char*)obj + field_offset) = value;
2010 newinsn = AMPAMP (putfield_resolved_8);
2011 break;
2015 else
2017 jobject value = POPA();
2018 jobject obj = POPA();
2019 NULLCHECK(obj);
2020 *(jobject*) ((char*)obj + field_offset) = value;
2021 newinsn = AMPAMP (putfield_resolved_obj);
2024 #ifdef DIRECT_THREADED
2025 pc[-2].insn = newinsn;
2026 pc[-1].int_val = field_offset;
2027 #endif /* DIRECT_THREADED */
2029 NEXT_INSN;
2031 #ifdef DIRECT_THREADED
2032 putfield_resolved_1:
2034 jint val = POPI ();
2035 char *obj = (char *) POPA ();
2036 NULLCHECK (obj);
2037 *(jbyte *) (obj + INTVAL ()) = val;
2039 NEXT_INSN;
2041 putfield_resolved_2:
2043 jint val = POPI ();
2044 char *obj = (char *) POPA ();
2045 NULLCHECK (obj);
2046 *(jchar *) (obj + INTVAL ()) = val;
2048 NEXT_INSN;
2050 putfield_resolved_4:
2052 jint val = POPI ();
2053 char *obj = (char *) POPA ();
2054 NULLCHECK (obj);
2055 *(jint *) (obj + INTVAL ()) = val;
2057 NEXT_INSN;
2059 putfield_resolved_8:
2061 jlong val = POPL ();
2062 char *obj = (char *) POPA ();
2063 NULLCHECK (obj);
2064 *(jlong *) (obj + INTVAL ()) = val;
2066 NEXT_INSN;
2068 putfield_resolved_obj:
2070 jobject val = POPA ();
2071 char *obj = (char *) POPA ();
2072 NULLCHECK (obj);
2073 *(jobject *) (obj + INTVAL ()) = val;
2075 NEXT_INSN;
2076 #endif /* DIRECT_THREADED */
2078 insn_invokespecial:
2080 SAVE_PC();
2081 int index = GET2U ();
2083 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2084 index)).rmethod;
2086 sp -= rmeth->stack_item_count;
2088 // We don't use NULLCHECK here because we can't rely on that
2089 // working for <init>. So instead we do an explicit test.
2090 if (! sp[0].o)
2092 SAVE_PC();
2093 throw_null_pointer_exception ();
2096 fun = (void (*)()) rmeth->method->ncode;
2098 #ifdef DIRECT_THREADED
2099 // Rewrite instruction so that we use a faster pre-resolved
2100 // method.
2101 pc[-2].insn = &&invokespecial_resolved;
2102 pc[-1].datum = rmeth;
2103 #endif /* DIRECT_THREADED */
2105 goto perform_invoke;
2107 #ifdef DIRECT_THREADED
2108 invokespecial_resolved:
2110 SAVE_PC();
2111 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2112 sp -= rmeth->stack_item_count;
2113 // We don't use NULLCHECK here because we can't rely on that
2114 // working for <init>. So instead we do an explicit test.
2115 if (! sp[0].o)
2117 throw_null_pointer_exception ();
2119 fun = (void (*)()) rmeth->method->ncode;
2121 goto perform_invoke;
2122 #endif /* DIRECT_THREADED */
2124 insn_invokestatic:
2126 SAVE_PC();
2127 int index = GET2U ();
2129 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2130 index)).rmethod;
2132 sp -= rmeth->stack_item_count;
2134 fun = (void (*)()) rmeth->method->ncode;
2136 #ifdef DIRECT_THREADED
2137 // Rewrite instruction so that we use a faster pre-resolved
2138 // method.
2139 pc[-2].insn = &&invokestatic_resolved;
2140 pc[-1].datum = rmeth;
2141 #endif /* DIRECT_THREADED */
2143 goto perform_invoke;
2145 #ifdef DIRECT_THREADED
2146 invokestatic_resolved:
2148 SAVE_PC();
2149 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2150 sp -= rmeth->stack_item_count;
2151 fun = (void (*)()) rmeth->method->ncode;
2153 goto perform_invoke;
2154 #endif /* DIRECT_THREADED */
2156 insn_invokeinterface:
2158 SAVE_PC();
2159 int index = GET2U ();
2161 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2162 index)).rmethod;
2164 sp -= rmeth->stack_item_count;
2166 jobject rcv = sp[0].o;
2168 NULLCHECK (rcv);
2170 fun = (void (*)())
2171 _Jv_LookupInterfaceMethod (rcv->getClass (),
2172 rmeth->method->name,
2173 rmeth->method->signature);
2175 #ifdef DIRECT_THREADED
2176 // Rewrite instruction so that we use a faster pre-resolved
2177 // method.
2178 pc[-2].insn = &&invokeinterface_resolved;
2179 pc[-1].datum = rmeth;
2180 #else
2181 // Skip dummy bytes.
2182 pc += 2;
2183 #endif /* DIRECT_THREADED */
2185 goto perform_invoke;
2187 #ifdef DIRECT_THREADED
2188 invokeinterface_resolved:
2190 SAVE_PC();
2191 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2192 sp -= rmeth->stack_item_count;
2193 jobject rcv = sp[0].o;
2194 NULLCHECK (rcv);
2195 fun = (void (*)())
2196 _Jv_LookupInterfaceMethod (rcv->getClass (),
2197 rmeth->method->name,
2198 rmeth->method->signature);
2200 goto perform_invoke;
2201 #endif /* DIRECT_THREADED */
2203 insn_new:
2205 SAVE_PC();
2206 int index = GET2U ();
2207 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2208 index)).clazz;
2209 /* VM spec, section 3.11.5 */
2210 if ((klass->getModifiers() & Modifier::ABSTRACT)
2211 || klass->isInterface())
2212 throw new java::lang::InstantiationException;
2213 jobject res = _Jv_AllocObject (klass);
2214 PUSHA (res);
2216 #ifdef DIRECT_THREADED
2217 pc[-2].insn = &&new_resolved;
2218 pc[-1].datum = klass;
2219 #endif /* DIRECT_THREADED */
2221 NEXT_INSN;
2223 #ifdef DIRECT_THREADED
2224 new_resolved:
2226 jclass klass = (jclass) AVAL ();
2227 jobject res = _Jv_AllocObject (klass);
2228 PUSHA (res);
2230 NEXT_INSN;
2231 #endif /* DIRECT_THREADED */
2233 insn_newarray:
2235 int atype = GET1U ();
2236 int size = POPI();
2237 jobject result = _Jv_NewArray (atype, size);
2238 PUSHA (result);
2240 NEXT_INSN;
2242 insn_anewarray:
2244 SAVE_PC();
2245 int index = GET2U ();
2246 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2247 index)).clazz;
2248 int size = POPI();
2249 jobject result = _Jv_NewObjectArray (size, klass, 0);
2250 PUSHA (result);
2252 #ifdef DIRECT_THREADED
2253 pc[-2].insn = &&anewarray_resolved;
2254 pc[-1].datum = klass;
2255 #endif /* DIRECT_THREADED */
2257 NEXT_INSN;
2259 #ifdef DIRECT_THREADED
2260 anewarray_resolved:
2262 jclass klass = (jclass) AVAL ();
2263 int size = POPI ();
2264 jobject result = _Jv_NewObjectArray (size, klass, 0);
2265 PUSHA (result);
2267 NEXT_INSN;
2268 #endif /* DIRECT_THREADED */
2270 insn_arraylength:
2272 __JArray *arr = (__JArray*)POPA();
2273 NULLARRAYCHECK (arr);
2274 PUSHI (arr->length);
2276 NEXT_INSN;
2278 insn_athrow:
2280 jobject value = POPA();
2281 throw static_cast<jthrowable>(value);
2283 NEXT_INSN;
2285 insn_checkcast:
2287 SAVE_PC();
2288 jobject value = POPA();
2289 jint index = GET2U ();
2290 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2291 index)).clazz;
2293 value = (jobject) _Jv_CheckCast (to, value);
2295 PUSHA (value);
2297 #ifdef DIRECT_THREADED
2298 pc[-2].insn = &&checkcast_resolved;
2299 pc[-1].datum = to;
2300 #endif /* DIRECT_THREADED */
2302 NEXT_INSN;
2304 #ifdef DIRECT_THREADED
2305 checkcast_resolved:
2307 SAVE_PC();
2308 jobject value = POPA ();
2309 jclass to = (jclass) AVAL ();
2310 value = (jobject) _Jv_CheckCast (to, value);
2311 PUSHA (value);
2313 NEXT_INSN;
2314 #endif /* DIRECT_THREADED */
2316 insn_instanceof:
2318 SAVE_PC();
2319 jobject value = POPA();
2320 jint index = GET2U ();
2321 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2322 index)).clazz;
2323 PUSHI (to->isInstance (value));
2325 #ifdef DIRECT_THREADED
2326 pc[-2].insn = &&instanceof_resolved;
2327 pc[-1].datum = to;
2328 #endif /* DIRECT_THREADED */
2330 NEXT_INSN;
2332 #ifdef DIRECT_THREADED
2333 instanceof_resolved:
2335 jobject value = POPA ();
2336 jclass to = (jclass) AVAL ();
2337 PUSHI (to->isInstance (value));
2339 NEXT_INSN;
2340 #endif /* DIRECT_THREADED */
2342 insn_monitorenter:
2344 jobject value = POPA();
2345 NULLCHECK(value);
2346 _Jv_MonitorEnter (value);
2348 NEXT_INSN;
2350 insn_monitorexit:
2352 jobject value = POPA();
2353 NULLCHECK(value);
2354 _Jv_MonitorExit (value);
2356 NEXT_INSN;
2358 insn_ifnull:
2360 jobject val = POPA();
2361 if (val == NULL)
2362 TAKE_GOTO;
2363 else
2364 SKIP_GOTO;
2366 NEXT_INSN;
2368 insn_ifnonnull:
2370 jobject val = POPA();
2371 if (val != NULL)
2372 TAKE_GOTO;
2373 else
2374 SKIP_GOTO;
2376 NEXT_INSN;
2378 insn_multianewarray:
2380 SAVE_PC();
2381 int kind_index = GET2U ();
2382 int dim = GET1U ();
2384 jclass type
2385 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2386 kind_index)).clazz;
2387 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2389 for (int i = dim - 1; i >= 0; i--)
2391 sizes[i] = POPI ();
2394 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2396 PUSHA (res);
2398 NEXT_INSN;
2400 #ifndef DIRECT_THREADED
2401 insn_wide:
2403 jint the_mod_op = get1u (pc++);
2404 jint wide = get2u (pc); pc += 2;
2406 switch (the_mod_op)
2408 case op_istore:
2409 STOREI (wide);
2410 NEXT_INSN;
2412 case op_fstore:
2413 STOREF (wide);
2414 NEXT_INSN;
2416 case op_astore:
2417 STOREA (wide);
2418 NEXT_INSN;
2420 case op_lload:
2421 LOADL (wide);
2422 NEXT_INSN;
2424 case op_dload:
2425 LOADD (wide);
2426 NEXT_INSN;
2428 case op_iload:
2429 LOADI (wide);
2430 NEXT_INSN;
2432 case op_fload:
2433 LOADF (wide);
2434 NEXT_INSN;
2436 case op_aload:
2437 LOADA (wide);
2438 NEXT_INSN;
2440 case op_lstore:
2441 STOREL (wide);
2442 NEXT_INSN;
2444 case op_dstore:
2445 STORED (wide);
2446 NEXT_INSN;
2448 case op_ret:
2449 pc = (unsigned char*) PEEKA (wide);
2450 NEXT_INSN;
2452 case op_iinc:
2454 jint amount = get2s (pc); pc += 2;
2455 jint value = PEEKI (wide);
2456 POKEI (wide, value+amount);
2458 NEXT_INSN;
2460 default:
2461 throw_internal_error ("illegal bytecode modified by wide");
2465 #endif /* DIRECT_THREADED */
2467 insn_breakpoint:
2469 // nothing just yet
2472 catch (java::lang::Throwable *ex)
2474 #ifdef DIRECT_THREADED
2475 void *logical_pc = (void *) ((insn_slot *) pc - 1);
2476 #else
2477 int logical_pc = pc - 1 - meth->bytecode ();
2478 #endif
2479 _Jv_InterpException *exc = meth->exceptions ();
2480 jclass exc_class = ex->getClass ();
2482 for (int i = 0; i < meth->exc_count; i++)
2484 if (PCVAL (exc[i].start_pc) <= logical_pc
2485 && logical_pc < PCVAL (exc[i].end_pc))
2487 #ifdef DIRECT_THREADED
2488 jclass handler = (jclass) exc[i].handler_type.p;
2489 #else
2490 jclass handler = NULL;
2491 if (exc[i].handler_type.i != 0)
2492 handler = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2493 exc[i].handler_type.i)).clazz;
2494 #endif /* DIRECT_THREADED */
2496 if (handler == NULL || handler->isAssignableFrom (exc_class))
2499 #ifdef DIRECT_THREADED
2500 pc = (insn_slot *) exc[i].handler_pc.p;
2501 #else
2502 pc = meth->bytecode () + exc[i].handler_pc.i;
2503 #endif /* DIRECT_THREADED */
2504 sp = stack;
2505 sp++->o = ex; // Push exception.
2506 NEXT_INSN;
2511 // No handler, so re-throw.
2512 throw ex;