* lower-subreg.c (resolve_clobber): Handle a subreg of a concatn.
[official-gcc.git] / libjava / interpret-run.cc
blob12d0b9a5683031f0f50db0d7bf700aefd3fe3ad2
1 // interpret-run.cc - Code to interpret bytecode
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 #ifdef DEBUG
252 #undef NEXT_INSN
253 #define NEXT_INSN \
254 do \
256 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
258 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
259 jmethodID method = meth->self; \
260 jlocation loc = meth->insn_index (pc); \
261 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
262 env, method, loc); \
264 goto *((pc++)->insn); \
266 while (0)
267 #else
268 #undef NEXT_INSN
269 #define NEXT_INSN goto *((pc++)->insn)
270 #endif
272 #define INTVAL() ((pc++)->int_val)
273 #define AVAL() ((pc++)->datum)
275 #define GET1S() INTVAL ()
276 #define GET2S() INTVAL ()
277 #define GET1U() INTVAL ()
278 #define GET2U() INTVAL ()
279 #define AVAL1U() AVAL ()
280 #define AVAL2U() AVAL ()
281 #define AVAL2UP() AVAL ()
282 #define SKIP_GOTO ++pc
283 #define GOTO_VAL() (insn_slot *) pc->datum
284 #define PCVAL(unionval) unionval.p
285 #define AMPAMP(label) &&label
287 // Compile if we must. NOTE: Double-check locking.
288 if (meth->prepared == NULL)
290 _Jv_MutexLock (&compile_mutex);
291 if (meth->prepared == NULL)
292 meth->compile (insn_target);
293 _Jv_MutexUnlock (&compile_mutex);
296 // If we're only compiling, stop here
297 if (args == NULL)
298 return;
300 pc = (insn_slot *) meth->prepared;
302 #else
304 #ifdef DEBUG
305 #define NEXT_INSN \
306 do \
308 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
310 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
311 jmethodID method = meth->self; \
312 jlocation loc = meth->insn_index (pc); \
313 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
314 env, method, loc); \
316 goto *(insn_target[*pc++])
317 #else
318 #define NEXT_INSN goto *(insn_target[*pc++])
319 #endif
321 #define GET1S() get1s (pc++)
322 #define GET2S() (pc += 2, get2s (pc- 2))
323 #define GET1U() get1u (pc++)
324 #define GET2U() (pc += 2, get2u (pc - 2))
325 // Note that these could be more efficient when not handling 'ldc
326 // class'.
327 #define AVAL1U() \
328 ({ int index = get1u (pc++); \
329 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
330 #define AVAL2U() \
331 ({ int index = get2u (pc); pc += 2; \
332 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
333 // Note that we don't need to resolve the pool entry here as class
334 // constants are never wide.
335 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
336 #define SKIP_GOTO pc += 2
337 #define GOTO_VAL() pc - 1 + get2s (pc)
338 #define PCVAL(unionval) unionval.i
339 #define AMPAMP(label) NULL
341 pc = meth->bytecode ();
343 #endif /* DIRECT_THREADED */
345 #define TAKE_GOTO pc = GOTO_VAL ()
347 /* Go straight at it! the ffi raw format matches the internal
348 stack representation exactly. At least, that's the idea.
350 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
352 _Jv_word *pool_data = meth->defining_class->constants.data;
354 /* These three are temporaries for common code used by several
355 instructions. */
356 void (*fun)();
357 _Jv_ResolvedMethod* rmeth;
358 int tmpval;
362 // We keep nop around. It is used if we're interpreting the
363 // bytecodes and not doing direct threading.
364 insn_nop:
365 NEXT_INSN;
367 /* The first few instructions here are ordered according to their
368 frequency, in the hope that this will improve code locality a
369 little. */
371 insn_aload_0: // 0x2a
372 LOADA (0);
373 NEXT_INSN;
375 insn_iload: // 0x15
376 LOADI (GET1U ());
377 NEXT_INSN;
379 insn_iload_1: // 0x1b
380 LOADI (1);
381 NEXT_INSN;
383 insn_invokevirtual: // 0xb6
385 SAVE_PC();
386 int index = GET2U ();
388 /* _Jv_Linker::resolve_pool_entry returns immediately if the
389 * value already is resolved. If we want to clutter up the
390 * code here to gain a little performance, then we can check
391 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
392 * directly. For now, I don't think it is worth it. */
394 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
395 index)).rmethod;
397 sp -= rmeth->stack_item_count;
399 if (rmeth->method->accflags & Modifier::FINAL)
401 // We can't rely on NULLCHECK working if the method is final.
402 if (! sp[0].o)
403 throw_null_pointer_exception ();
405 // Final methods might not appear in the vtable.
406 fun = (void (*)()) rmeth->method->ncode;
408 else
410 NULLCHECK (sp[0].o);
411 jobject rcv = sp[0].o;
412 _Jv_VTable *table = *(_Jv_VTable**) rcv;
413 fun = (void (*)()) table->get_method (rmeth->method->index);
416 #ifdef DIRECT_THREADED
417 // Rewrite instruction so that we use a faster pre-resolved
418 // method.
419 pc[-2].insn = &&invokevirtual_resolved;
420 pc[-1].datum = rmeth;
421 #endif /* DIRECT_THREADED */
423 goto perform_invoke;
425 #ifdef DIRECT_THREADED
426 invokevirtual_resolved:
428 SAVE_PC();
429 rmeth = (_Jv_ResolvedMethod *) AVAL ();
430 sp -= rmeth->stack_item_count;
432 if (rmeth->method->accflags & Modifier::FINAL)
434 // We can't rely on NULLCHECK working if the method is final.
435 if (! sp[0].o)
436 throw_null_pointer_exception ();
438 // Final methods might not appear in the vtable.
439 fun = (void (*)()) rmeth->method->ncode;
441 else
443 jobject rcv = sp[0].o;
444 _Jv_VTable *table = *(_Jv_VTable**) rcv;
445 fun = (void (*)()) table->get_method (rmeth->method->index);
448 goto perform_invoke;
449 #endif /* DIRECT_THREADED */
451 perform_invoke:
453 /* here goes the magic again... */
454 ffi_cif *cif = &rmeth->cif;
455 ffi_raw *raw = (ffi_raw*) sp;
457 _Jv_value rvalue;
459 #if FFI_NATIVE_RAW_API
460 /* We assume that this is only implemented if it's correct */
461 /* to use it here. On a 64 bit machine, it never is. */
462 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
463 #else
464 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
465 #endif
467 int rtype = cif->rtype->type;
469 /* the likelyhood of object, int, or void return is very high,
470 * so those are checked before the switch */
471 if (rtype == FFI_TYPE_POINTER)
473 PUSHA (rvalue.object_value);
475 else if (rtype == FFI_TYPE_SINT32)
477 PUSHI (rvalue.int_value);
479 else if (rtype == FFI_TYPE_VOID)
481 /* skip */
483 else
485 switch (rtype)
487 case FFI_TYPE_SINT8:
488 PUSHI ((jbyte)(rvalue.int_value & 0xff));
489 break;
491 case FFI_TYPE_SINT16:
492 PUSHI ((jshort)(rvalue.int_value & 0xffff));
493 break;
495 case FFI_TYPE_UINT16:
496 PUSHI (rvalue.int_value & 0xffff);
497 break;
499 case FFI_TYPE_FLOAT:
500 PUSHF (rvalue.float_value);
501 break;
503 case FFI_TYPE_DOUBLE:
504 PUSHD (rvalue.double_value);
505 break;
507 case FFI_TYPE_SINT64:
508 PUSHL (rvalue.long_value);
509 break;
511 default:
512 throw_internal_error ("unknown return type in invokeXXX");
516 NEXT_INSN;
518 insn_aconst_null:
519 PUSHA (NULL);
520 NEXT_INSN;
522 insn_iconst_m1:
523 PUSHI (-1);
524 NEXT_INSN;
526 insn_iconst_0:
527 PUSHI (0);
528 NEXT_INSN;
530 insn_iconst_1:
531 PUSHI (1);
532 NEXT_INSN;
534 insn_iconst_2:
535 PUSHI (2);
536 NEXT_INSN;
538 insn_iconst_3:
539 PUSHI (3);
540 NEXT_INSN;
542 insn_iconst_4:
543 PUSHI (4);
544 NEXT_INSN;
546 insn_iconst_5:
547 PUSHI (5);
548 NEXT_INSN;
550 insn_lconst_0:
551 PUSHL (0);
552 NEXT_INSN;
554 insn_lconst_1:
555 PUSHL (1);
556 NEXT_INSN;
558 insn_fconst_0:
559 PUSHF (0);
560 NEXT_INSN;
562 insn_fconst_1:
563 PUSHF (1);
564 NEXT_INSN;
566 insn_fconst_2:
567 PUSHF (2);
568 NEXT_INSN;
570 insn_dconst_0:
571 PUSHD (0);
572 NEXT_INSN;
574 insn_dconst_1:
575 PUSHD (1);
576 NEXT_INSN;
578 insn_bipush:
579 // For direct threaded, bipush and sipush are the same.
580 #ifndef DIRECT_THREADED
581 PUSHI (GET1S ());
582 NEXT_INSN;
583 #endif /* DIRECT_THREADED */
584 insn_sipush:
585 PUSHI (GET2S ());
586 NEXT_INSN;
588 insn_ldc:
589 // For direct threaded, ldc and ldc_w are the same.
590 #ifndef DIRECT_THREADED
591 PUSHA ((jobject) AVAL1U ());
592 NEXT_INSN;
593 #endif /* DIRECT_THREADED */
594 insn_ldc_w:
595 PUSHA ((jobject) AVAL2U ());
596 NEXT_INSN;
598 #ifdef DIRECT_THREADED
599 // For direct threaded we have a separate 'ldc class' operation.
600 insn_ldc_class:
602 SAVE_PC();
603 // We could rewrite the instruction at this point.
604 int index = INTVAL ();
605 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
606 index)).o;
607 PUSHA (k);
609 NEXT_INSN;
610 #endif /* DIRECT_THREADED */
612 insn_ldc2_w:
614 void *where = AVAL2UP ();
615 memcpy (sp, where, 2*sizeof (_Jv_word));
616 sp += 2;
618 NEXT_INSN;
620 insn_lload:
621 LOADL (GET1U ());
622 NEXT_INSN;
624 insn_fload:
625 LOADF (GET1U ());
626 NEXT_INSN;
628 insn_dload:
629 LOADD (GET1U ());
630 NEXT_INSN;
632 insn_aload:
633 LOADA (GET1U ());
634 NEXT_INSN;
636 insn_iload_0:
637 LOADI (0);
638 NEXT_INSN;
640 insn_iload_2:
641 LOADI (2);
642 NEXT_INSN;
644 insn_iload_3:
645 LOADI (3);
646 NEXT_INSN;
648 insn_lload_0:
649 LOADL (0);
650 NEXT_INSN;
652 insn_lload_1:
653 LOADL (1);
654 NEXT_INSN;
656 insn_lload_2:
657 LOADL (2);
658 NEXT_INSN;
660 insn_lload_3:
661 LOADL (3);
662 NEXT_INSN;
664 insn_fload_0:
665 LOADF (0);
666 NEXT_INSN;
668 insn_fload_1:
669 LOADF (1);
670 NEXT_INSN;
672 insn_fload_2:
673 LOADF (2);
674 NEXT_INSN;
676 insn_fload_3:
677 LOADF (3);
678 NEXT_INSN;
680 insn_dload_0:
681 LOADD (0);
682 NEXT_INSN;
684 insn_dload_1:
685 LOADD (1);
686 NEXT_INSN;
688 insn_dload_2:
689 LOADD (2);
690 NEXT_INSN;
692 insn_dload_3:
693 LOADD (3);
694 NEXT_INSN;
696 insn_aload_1:
697 LOADA(1);
698 NEXT_INSN;
700 insn_aload_2:
701 LOADA(2);
702 NEXT_INSN;
704 insn_aload_3:
705 LOADA(3);
706 NEXT_INSN;
708 insn_iaload:
710 jint index = POPI();
711 jintArray arr = (jintArray) POPA();
712 NULLARRAYCHECK (arr);
713 ARRAYBOUNDSCHECK (arr, index);
714 PUSHI( elements(arr)[index] );
716 NEXT_INSN;
718 insn_laload:
720 jint index = POPI();
721 jlongArray arr = (jlongArray) POPA();
722 NULLARRAYCHECK (arr);
723 ARRAYBOUNDSCHECK (arr, index);
724 PUSHL( elements(arr)[index] );
726 NEXT_INSN;
728 insn_faload:
730 jint index = POPI();
731 jfloatArray arr = (jfloatArray) POPA();
732 NULLARRAYCHECK (arr);
733 ARRAYBOUNDSCHECK (arr, index);
734 PUSHF( elements(arr)[index] );
736 NEXT_INSN;
738 insn_daload:
740 jint index = POPI();
741 jdoubleArray arr = (jdoubleArray) POPA();
742 NULLARRAYCHECK (arr);
743 ARRAYBOUNDSCHECK (arr, index);
744 PUSHD( elements(arr)[index] );
746 NEXT_INSN;
748 insn_aaload:
750 jint index = POPI();
751 jobjectArray arr = (jobjectArray) POPA();
752 NULLARRAYCHECK (arr);
753 ARRAYBOUNDSCHECK (arr, index);
754 PUSHA( elements(arr)[index] );
756 NEXT_INSN;
758 insn_baload:
760 jint index = POPI();
761 jbyteArray arr = (jbyteArray) POPA();
762 NULLARRAYCHECK (arr);
763 ARRAYBOUNDSCHECK (arr, index);
764 PUSHI( elements(arr)[index] );
766 NEXT_INSN;
768 insn_caload:
770 jint index = POPI();
771 jcharArray arr = (jcharArray) POPA();
772 NULLARRAYCHECK (arr);
773 ARRAYBOUNDSCHECK (arr, index);
774 PUSHI( elements(arr)[index] );
776 NEXT_INSN;
778 insn_saload:
780 jint index = POPI();
781 jshortArray arr = (jshortArray) POPA();
782 NULLARRAYCHECK (arr);
783 ARRAYBOUNDSCHECK (arr, index);
784 PUSHI( elements(arr)[index] );
786 NEXT_INSN;
788 insn_istore:
789 STOREI (GET1U ());
790 NEXT_INSN;
792 insn_lstore:
793 STOREL (GET1U ());
794 NEXT_INSN;
796 insn_fstore:
797 STOREF (GET1U ());
798 NEXT_INSN;
800 insn_dstore:
801 STORED (GET1U ());
802 NEXT_INSN;
804 insn_astore:
805 STOREA (GET1U ());
806 NEXT_INSN;
808 insn_istore_0:
809 STOREI (0);
810 NEXT_INSN;
812 insn_istore_1:
813 STOREI (1);
814 NEXT_INSN;
816 insn_istore_2:
817 STOREI (2);
818 NEXT_INSN;
820 insn_istore_3:
821 STOREI (3);
822 NEXT_INSN;
824 insn_lstore_0:
825 STOREL (0);
826 NEXT_INSN;
828 insn_lstore_1:
829 STOREL (1);
830 NEXT_INSN;
832 insn_lstore_2:
833 STOREL (2);
834 NEXT_INSN;
836 insn_lstore_3:
837 STOREL (3);
838 NEXT_INSN;
840 insn_fstore_0:
841 STOREF (0);
842 NEXT_INSN;
844 insn_fstore_1:
845 STOREF (1);
846 NEXT_INSN;
848 insn_fstore_2:
849 STOREF (2);
850 NEXT_INSN;
852 insn_fstore_3:
853 STOREF (3);
854 NEXT_INSN;
856 insn_dstore_0:
857 STORED (0);
858 NEXT_INSN;
860 insn_dstore_1:
861 STORED (1);
862 NEXT_INSN;
864 insn_dstore_2:
865 STORED (2);
866 NEXT_INSN;
868 insn_dstore_3:
869 STORED (3);
870 NEXT_INSN;
872 insn_astore_0:
873 STOREA(0);
874 NEXT_INSN;
876 insn_astore_1:
877 STOREA(1);
878 NEXT_INSN;
880 insn_astore_2:
881 STOREA(2);
882 NEXT_INSN;
884 insn_astore_3:
885 STOREA(3);
886 NEXT_INSN;
888 insn_iastore:
890 jint value = POPI();
891 jint index = POPI();
892 jintArray arr = (jintArray) POPA();
893 NULLARRAYCHECK (arr);
894 ARRAYBOUNDSCHECK (arr, index);
895 elements(arr)[index] = value;
897 NEXT_INSN;
899 insn_lastore:
901 jlong value = POPL();
902 jint index = POPI();
903 jlongArray arr = (jlongArray) POPA();
904 NULLARRAYCHECK (arr);
905 ARRAYBOUNDSCHECK (arr, index);
906 elements(arr)[index] = value;
908 NEXT_INSN;
910 insn_fastore:
912 jfloat value = POPF();
913 jint index = POPI();
914 jfloatArray arr = (jfloatArray) POPA();
915 NULLARRAYCHECK (arr);
916 ARRAYBOUNDSCHECK (arr, index);
917 elements(arr)[index] = value;
919 NEXT_INSN;
921 insn_dastore:
923 jdouble value = POPD();
924 jint index = POPI();
925 jdoubleArray arr = (jdoubleArray) POPA();
926 NULLARRAYCHECK (arr);
927 ARRAYBOUNDSCHECK (arr, index);
928 elements(arr)[index] = value;
930 NEXT_INSN;
932 insn_aastore:
934 jobject value = POPA();
935 jint index = POPI();
936 jobjectArray arr = (jobjectArray) POPA();
937 NULLARRAYCHECK (arr);
938 ARRAYBOUNDSCHECK (arr, index);
939 _Jv_CheckArrayStore (arr, value);
940 elements(arr)[index] = value;
942 NEXT_INSN;
944 insn_bastore:
946 jbyte value = (jbyte) POPI();
947 jint index = POPI();
948 jbyteArray arr = (jbyteArray) POPA();
949 NULLARRAYCHECK (arr);
950 ARRAYBOUNDSCHECK (arr, index);
951 elements(arr)[index] = value;
953 NEXT_INSN;
955 insn_castore:
957 jchar value = (jchar) POPI();
958 jint index = POPI();
959 jcharArray arr = (jcharArray) POPA();
960 NULLARRAYCHECK (arr);
961 ARRAYBOUNDSCHECK (arr, index);
962 elements(arr)[index] = value;
964 NEXT_INSN;
966 insn_sastore:
968 jshort value = (jshort) POPI();
969 jint index = POPI();
970 jshortArray arr = (jshortArray) POPA();
971 NULLARRAYCHECK (arr);
972 ARRAYBOUNDSCHECK (arr, index);
973 elements(arr)[index] = value;
975 NEXT_INSN;
977 insn_pop:
978 sp -= 1;
979 NEXT_INSN;
981 insn_pop2:
982 sp -= 2;
983 NEXT_INSN;
985 insn_dup:
986 sp[0] = sp[-1];
987 sp += 1;
988 NEXT_INSN;
990 insn_dup_x1:
991 dupx (sp, 1, 1); sp+=1;
992 NEXT_INSN;
994 insn_dup_x2:
995 dupx (sp, 1, 2); sp+=1;
996 NEXT_INSN;
998 insn_dup2:
999 sp[0] = sp[-2];
1000 sp[1] = sp[-1];
1001 sp += 2;
1002 NEXT_INSN;
1004 insn_dup2_x1:
1005 dupx (sp, 2, 1); sp+=2;
1006 NEXT_INSN;
1008 insn_dup2_x2:
1009 dupx (sp, 2, 2); sp+=2;
1010 NEXT_INSN;
1012 insn_swap:
1014 jobject tmp1 = POPA();
1015 jobject tmp2 = POPA();
1016 PUSHA (tmp1);
1017 PUSHA (tmp2);
1019 NEXT_INSN;
1021 insn_iadd:
1022 BINOPI(+);
1023 NEXT_INSN;
1025 insn_ladd:
1026 BINOPL(+);
1027 NEXT_INSN;
1029 insn_fadd:
1030 BINOPF(+);
1031 NEXT_INSN;
1033 insn_dadd:
1034 BINOPD(+);
1035 NEXT_INSN;
1037 insn_isub:
1038 BINOPI(-);
1039 NEXT_INSN;
1041 insn_lsub:
1042 BINOPL(-);
1043 NEXT_INSN;
1045 insn_fsub:
1046 BINOPF(-);
1047 NEXT_INSN;
1049 insn_dsub:
1050 BINOPD(-);
1051 NEXT_INSN;
1053 insn_imul:
1054 BINOPI(*);
1055 NEXT_INSN;
1057 insn_lmul:
1058 BINOPL(*);
1059 NEXT_INSN;
1061 insn_fmul:
1062 BINOPF(*);
1063 NEXT_INSN;
1065 insn_dmul:
1066 BINOPD(*);
1067 NEXT_INSN;
1069 insn_idiv:
1071 SAVE_PC();
1072 jint value2 = POPI();
1073 jint value1 = POPI();
1074 jint res = _Jv_divI (value1, value2);
1075 PUSHI (res);
1077 NEXT_INSN;
1079 insn_ldiv:
1081 SAVE_PC();
1082 jlong value2 = POPL();
1083 jlong value1 = POPL();
1084 jlong res = _Jv_divJ (value1, value2);
1085 PUSHL (res);
1087 NEXT_INSN;
1089 insn_fdiv:
1091 jfloat value2 = POPF();
1092 jfloat value1 = POPF();
1093 jfloat res = value1 / value2;
1094 PUSHF (res);
1096 NEXT_INSN;
1098 insn_ddiv:
1100 jdouble value2 = POPD();
1101 jdouble value1 = POPD();
1102 jdouble res = value1 / value2;
1103 PUSHD (res);
1105 NEXT_INSN;
1107 insn_irem:
1109 SAVE_PC();
1110 jint value2 = POPI();
1111 jint value1 = POPI();
1112 jint res = _Jv_remI (value1, value2);
1113 PUSHI (res);
1115 NEXT_INSN;
1117 insn_lrem:
1119 SAVE_PC();
1120 jlong value2 = POPL();
1121 jlong value1 = POPL();
1122 jlong res = _Jv_remJ (value1, value2);
1123 PUSHL (res);
1125 NEXT_INSN;
1127 insn_frem:
1129 jfloat value2 = POPF();
1130 jfloat value1 = POPF();
1131 jfloat res = __ieee754_fmod (value1, value2);
1132 PUSHF (res);
1134 NEXT_INSN;
1136 insn_drem:
1138 jdouble value2 = POPD();
1139 jdouble value1 = POPD();
1140 jdouble res = __ieee754_fmod (value1, value2);
1141 PUSHD (res);
1143 NEXT_INSN;
1145 insn_ineg:
1147 jint value = POPI();
1148 PUSHI (value * -1);
1150 NEXT_INSN;
1152 insn_lneg:
1154 jlong value = POPL();
1155 PUSHL (value * -1);
1157 NEXT_INSN;
1159 insn_fneg:
1161 jfloat value = POPF();
1162 PUSHF (value * -1);
1164 NEXT_INSN;
1166 insn_dneg:
1168 jdouble value = POPD();
1169 PUSHD (value * -1);
1171 NEXT_INSN;
1173 insn_ishl:
1175 jint shift = (POPI() & 0x1f);
1176 jint value = POPI();
1177 PUSHI (value << shift);
1179 NEXT_INSN;
1181 insn_lshl:
1183 jint shift = (POPI() & 0x3f);
1184 jlong value = POPL();
1185 PUSHL (value << shift);
1187 NEXT_INSN;
1189 insn_ishr:
1191 jint shift = (POPI() & 0x1f);
1192 jint value = POPI();
1193 PUSHI (value >> shift);
1195 NEXT_INSN;
1197 insn_lshr:
1199 jint shift = (POPI() & 0x3f);
1200 jlong value = POPL();
1201 PUSHL (value >> shift);
1203 NEXT_INSN;
1205 insn_iushr:
1207 jint shift = (POPI() & 0x1f);
1208 _Jv_uint value = (_Jv_uint) POPI();
1209 PUSHI ((jint) (value >> shift));
1211 NEXT_INSN;
1213 insn_lushr:
1215 jint shift = (POPI() & 0x3f);
1216 _Jv_ulong value = (_Jv_ulong) POPL();
1217 PUSHL ((jlong) (value >> shift));
1219 NEXT_INSN;
1221 insn_iand:
1222 BINOPI (&);
1223 NEXT_INSN;
1225 insn_land:
1226 BINOPL (&);
1227 NEXT_INSN;
1229 insn_ior:
1230 BINOPI (|);
1231 NEXT_INSN;
1233 insn_lor:
1234 BINOPL (|);
1235 NEXT_INSN;
1237 insn_ixor:
1238 BINOPI (^);
1239 NEXT_INSN;
1241 insn_lxor:
1242 BINOPL (^);
1243 NEXT_INSN;
1245 insn_iinc:
1247 jint index = GET1U ();
1248 jint amount = GET1S ();
1249 locals[index].i += amount;
1251 NEXT_INSN;
1253 insn_i2l:
1254 {jlong value = POPI(); PUSHL (value);}
1255 NEXT_INSN;
1257 insn_i2f:
1258 {jfloat value = POPI(); PUSHF (value);}
1259 NEXT_INSN;
1261 insn_i2d:
1262 {jdouble value = POPI(); PUSHD (value);}
1263 NEXT_INSN;
1265 insn_l2i:
1266 {jint value = POPL(); PUSHI (value);}
1267 NEXT_INSN;
1269 insn_l2f:
1270 {jfloat value = POPL(); PUSHF (value);}
1271 NEXT_INSN;
1273 insn_l2d:
1274 {jdouble value = POPL(); PUSHD (value);}
1275 NEXT_INSN;
1277 insn_f2i:
1279 using namespace java::lang;
1280 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1281 PUSHI(value);
1283 NEXT_INSN;
1285 insn_f2l:
1287 using namespace java::lang;
1288 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1289 PUSHL(value);
1291 NEXT_INSN;
1293 insn_f2d:
1294 { jdouble value = POPF (); PUSHD(value); }
1295 NEXT_INSN;
1297 insn_d2i:
1299 using namespace java::lang;
1300 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1301 PUSHI(value);
1303 NEXT_INSN;
1305 insn_d2l:
1307 using namespace java::lang;
1308 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1309 PUSHL(value);
1311 NEXT_INSN;
1313 insn_d2f:
1314 { jfloat value = POPD (); PUSHF(value); }
1315 NEXT_INSN;
1317 insn_i2b:
1318 { jbyte value = POPI (); PUSHI(value); }
1319 NEXT_INSN;
1321 insn_i2c:
1322 { jchar value = POPI (); PUSHI(value); }
1323 NEXT_INSN;
1325 insn_i2s:
1326 { jshort value = POPI (); PUSHI(value); }
1327 NEXT_INSN;
1329 insn_lcmp:
1331 jlong value2 = POPL ();
1332 jlong value1 = POPL ();
1333 if (value1 > value2)
1334 { PUSHI (1); }
1335 else if (value1 == value2)
1336 { PUSHI (0); }
1337 else
1338 { PUSHI (-1); }
1340 NEXT_INSN;
1342 insn_fcmpl:
1343 tmpval = -1;
1344 goto fcmp;
1346 insn_fcmpg:
1347 tmpval = 1;
1349 fcmp:
1351 jfloat value2 = POPF ();
1352 jfloat value1 = POPF ();
1353 if (value1 > value2)
1354 PUSHI (1);
1355 else if (value1 == value2)
1356 PUSHI (0);
1357 else if (value1 < value2)
1358 PUSHI (-1);
1359 else
1360 PUSHI (tmpval);
1362 NEXT_INSN;
1364 insn_dcmpl:
1365 tmpval = -1;
1366 goto dcmp;
1368 insn_dcmpg:
1369 tmpval = 1;
1371 dcmp:
1373 jdouble value2 = POPD ();
1374 jdouble value1 = POPD ();
1375 if (value1 > value2)
1376 PUSHI (1);
1377 else if (value1 == value2)
1378 PUSHI (0);
1379 else if (value1 < value2)
1380 PUSHI (-1);
1381 else
1382 PUSHI (tmpval);
1384 NEXT_INSN;
1386 insn_ifeq:
1388 if (POPI() == 0)
1389 TAKE_GOTO;
1390 else
1391 SKIP_GOTO;
1393 NEXT_INSN;
1395 insn_ifne:
1397 if (POPI() != 0)
1398 TAKE_GOTO;
1399 else
1400 SKIP_GOTO;
1402 NEXT_INSN;
1404 insn_iflt:
1406 if (POPI() < 0)
1407 TAKE_GOTO;
1408 else
1409 SKIP_GOTO;
1411 NEXT_INSN;
1413 insn_ifge:
1415 if (POPI() >= 0)
1416 TAKE_GOTO;
1417 else
1418 SKIP_GOTO;
1420 NEXT_INSN;
1422 insn_ifgt:
1424 if (POPI() > 0)
1425 TAKE_GOTO;
1426 else
1427 SKIP_GOTO;
1429 NEXT_INSN;
1431 insn_ifle:
1433 if (POPI() <= 0)
1434 TAKE_GOTO;
1435 else
1436 SKIP_GOTO;
1438 NEXT_INSN;
1440 insn_if_icmpeq:
1442 jint value2 = POPI();
1443 jint value1 = POPI();
1444 if (value1 == value2)
1445 TAKE_GOTO;
1446 else
1447 SKIP_GOTO;
1449 NEXT_INSN;
1451 insn_if_icmpne:
1453 jint value2 = POPI();
1454 jint value1 = POPI();
1455 if (value1 != value2)
1456 TAKE_GOTO;
1457 else
1458 SKIP_GOTO;
1460 NEXT_INSN;
1462 insn_if_icmplt:
1464 jint value2 = POPI();
1465 jint value1 = POPI();
1466 if (value1 < value2)
1467 TAKE_GOTO;
1468 else
1469 SKIP_GOTO;
1471 NEXT_INSN;
1473 insn_if_icmpge:
1475 jint value2 = POPI();
1476 jint value1 = POPI();
1477 if (value1 >= value2)
1478 TAKE_GOTO;
1479 else
1480 SKIP_GOTO;
1482 NEXT_INSN;
1484 insn_if_icmpgt:
1486 jint value2 = POPI();
1487 jint value1 = POPI();
1488 if (value1 > value2)
1489 TAKE_GOTO;
1490 else
1491 SKIP_GOTO;
1493 NEXT_INSN;
1495 insn_if_icmple:
1497 jint value2 = POPI();
1498 jint value1 = POPI();
1499 if (value1 <= value2)
1500 TAKE_GOTO;
1501 else
1502 SKIP_GOTO;
1504 NEXT_INSN;
1506 insn_if_acmpeq:
1508 jobject value2 = POPA();
1509 jobject value1 = POPA();
1510 if (value1 == value2)
1511 TAKE_GOTO;
1512 else
1513 SKIP_GOTO;
1515 NEXT_INSN;
1517 insn_if_acmpne:
1519 jobject value2 = POPA();
1520 jobject value1 = POPA();
1521 if (value1 != value2)
1522 TAKE_GOTO;
1523 else
1524 SKIP_GOTO;
1526 NEXT_INSN;
1528 insn_goto_w:
1529 #ifndef DIRECT_THREADED
1530 // For direct threaded, goto and goto_w are the same.
1531 pc = pc - 1 + get4 (pc);
1532 NEXT_INSN;
1533 #endif /* DIRECT_THREADED */
1534 insn_goto:
1535 TAKE_GOTO;
1536 NEXT_INSN;
1538 insn_jsr_w:
1539 #ifndef DIRECT_THREADED
1540 // For direct threaded, jsr and jsr_w are the same.
1542 pc_t next = pc - 1 + get4 (pc);
1543 pc += 4;
1544 PUSHA ((jobject) pc);
1545 pc = next;
1547 NEXT_INSN;
1548 #endif /* DIRECT_THREADED */
1549 insn_jsr:
1551 pc_t next = GOTO_VAL();
1552 SKIP_GOTO;
1553 PUSHA ((jobject) pc);
1554 pc = next;
1556 NEXT_INSN;
1558 insn_ret:
1560 jint index = GET1U ();
1561 pc = (pc_t) PEEKA (index);
1563 NEXT_INSN;
1565 insn_tableswitch:
1567 #ifdef DIRECT_THREADED
1568 void *def = (pc++)->datum;
1570 int index = POPI();
1572 jint low = INTVAL ();
1573 jint high = INTVAL ();
1575 if (index < low || index > high)
1576 pc = (insn_slot *) def;
1577 else
1578 pc = (insn_slot *) ((pc + index - low)->datum);
1579 #else
1580 pc_t base_pc = pc - 1;
1581 int index = POPI ();
1583 pc_t base = (pc_t) meth->bytecode ();
1584 while ((pc - base) % 4 != 0)
1585 ++pc;
1587 jint def = get4 (pc);
1588 jint low = get4 (pc + 4);
1589 jint high = get4 (pc + 8);
1590 if (index < low || index > high)
1591 pc = base_pc + def;
1592 else
1593 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1594 #endif /* DIRECT_THREADED */
1596 NEXT_INSN;
1598 insn_lookupswitch:
1600 #ifdef DIRECT_THREADED
1601 void *def = (pc++)->insn;
1603 int index = POPI();
1605 jint npairs = INTVAL ();
1607 int max = npairs - 1;
1608 int min = 0;
1610 // Simple binary search...
1611 while (min < max)
1613 int half = (min + max) / 2;
1614 int match = pc[2 * half].int_val;
1616 if (index == match)
1618 // Found it.
1619 pc = (insn_slot *) pc[2 * half + 1].datum;
1620 NEXT_INSN;
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;
1631 if (index == pc[2 * min].int_val)
1632 pc = (insn_slot *) pc[2 * min + 1].datum;
1633 else
1634 pc = (insn_slot *) def;
1635 #else
1636 unsigned char *base_pc = pc-1;
1637 int index = POPI();
1639 unsigned char* base = meth->bytecode ();
1640 while ((pc-base) % 4 != 0)
1641 ++pc;
1643 jint def = get4 (pc);
1644 jint npairs = get4 (pc+4);
1646 int max = npairs-1;
1647 int min = 0;
1649 // Simple binary search...
1650 while (min < max)
1652 int half = (min+max)/2;
1653 int match = get4 (pc+ 4*(2 + 2*half));
1655 if (index == match)
1656 min = max = half;
1657 else if (index < match)
1658 // We can use HALF - 1 here because we check again on
1659 // loop exit.
1660 max = half - 1;
1661 else
1662 // We can use HALF + 1 here because we check again on
1663 // loop exit.
1664 min = half + 1;
1667 if (index == get4 (pc+ 4*(2 + 2*min)))
1668 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1669 else
1670 pc = base_pc + def;
1671 #endif /* DIRECT_THREADED */
1673 NEXT_INSN;
1675 insn_areturn:
1676 *(jobject *) retp = POPA ();
1677 return;
1679 insn_lreturn:
1680 *(jlong *) retp = POPL ();
1681 return;
1683 insn_freturn:
1684 *(jfloat *) retp = POPF ();
1685 return;
1687 insn_dreturn:
1688 *(jdouble *) retp = POPD ();
1689 return;
1691 insn_ireturn:
1692 *(jint *) retp = POPI ();
1693 return;
1695 insn_return:
1696 return;
1698 insn_getstatic:
1700 jint fieldref_index = GET2U ();
1701 SAVE_PC(); // Constant pool resolution could throw.
1702 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1703 _Jv_Field *field = pool_data[fieldref_index].field;
1705 if ((field->flags & Modifier::STATIC) == 0)
1706 throw_incompatible_class_change_error
1707 (JvNewStringLatin1 ("field no longer static"));
1709 jclass type = field->type;
1711 // We rewrite the instruction once we discover what it refers
1712 // to.
1713 void *newinsn = NULL;
1714 if (type->isPrimitive ())
1716 switch (type->size_in_bytes)
1718 case 1:
1719 PUSHI (*field->u.byte_addr);
1720 newinsn = AMPAMP (getstatic_resolved_1);
1721 break;
1723 case 2:
1724 if (type == JvPrimClass (char))
1726 PUSHI (*field->u.char_addr);
1727 newinsn = AMPAMP (getstatic_resolved_char);
1729 else
1731 PUSHI (*field->u.short_addr);
1732 newinsn = AMPAMP (getstatic_resolved_short);
1734 break;
1736 case 4:
1737 PUSHI(*field->u.int_addr);
1738 newinsn = AMPAMP (getstatic_resolved_4);
1739 break;
1741 case 8:
1742 PUSHL(*field->u.long_addr);
1743 newinsn = AMPAMP (getstatic_resolved_8);
1744 break;
1747 else
1749 PUSHA(*field->u.object_addr);
1750 newinsn = AMPAMP (getstatic_resolved_obj);
1753 #ifdef DIRECT_THREADED
1754 pc[-2].insn = newinsn;
1755 pc[-1].datum = field->u.addr;
1756 #endif /* DIRECT_THREADED */
1758 NEXT_INSN;
1760 #ifdef DIRECT_THREADED
1761 getstatic_resolved_1:
1762 PUSHI (*(jbyte *) AVAL ());
1763 NEXT_INSN;
1765 getstatic_resolved_char:
1766 PUSHI (*(jchar *) AVAL ());
1767 NEXT_INSN;
1769 getstatic_resolved_short:
1770 PUSHI (*(jshort *) AVAL ());
1771 NEXT_INSN;
1773 getstatic_resolved_4:
1774 PUSHI (*(jint *) AVAL ());
1775 NEXT_INSN;
1777 getstatic_resolved_8:
1778 PUSHL (*(jlong *) AVAL ());
1779 NEXT_INSN;
1781 getstatic_resolved_obj:
1782 PUSHA (*(jobject *) AVAL ());
1783 NEXT_INSN;
1784 #endif /* DIRECT_THREADED */
1786 insn_getfield:
1788 SAVE_PC();
1789 jint fieldref_index = GET2U ();
1790 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1791 _Jv_Field *field = pool_data[fieldref_index].field;
1793 if ((field->flags & Modifier::STATIC) != 0)
1794 throw_incompatible_class_change_error
1795 (JvNewStringLatin1 ("field is static"));
1797 jclass type = field->type;
1798 jint field_offset = field->u.boffset;
1800 jobject obj = POPA();
1801 NULLCHECK(obj);
1803 void *newinsn = NULL;
1804 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1805 if (type->isPrimitive ())
1807 switch (type->size_in_bytes)
1809 case 1:
1810 PUSHI (val->byte_value);
1811 newinsn = AMPAMP (getfield_resolved_1);
1812 break;
1814 case 2:
1815 if (type == JvPrimClass (char))
1817 PUSHI (val->char_value);
1818 newinsn = AMPAMP (getfield_resolved_char);
1820 else
1822 PUSHI (val->short_value);
1823 newinsn = AMPAMP (getfield_resolved_short);
1825 break;
1827 case 4:
1828 PUSHI (val->int_value);
1829 newinsn = AMPAMP (getfield_resolved_4);
1830 break;
1832 case 8:
1833 PUSHL (val->long_value);
1834 newinsn = AMPAMP (getfield_resolved_8);
1835 break;
1838 else
1840 PUSHA (val->object_value);
1841 newinsn = AMPAMP (getfield_resolved_obj);
1844 #ifdef DIRECT_THREADED
1845 pc[-2].insn = newinsn;
1846 pc[-1].int_val = field_offset;
1847 #endif /* DIRECT_THREADED */
1849 NEXT_INSN;
1851 #ifdef DIRECT_THREADED
1852 getfield_resolved_1:
1854 char *obj = (char *) POPA ();
1855 NULLCHECK (obj);
1856 PUSHI (*(jbyte *) (obj + INTVAL ()));
1858 NEXT_INSN;
1860 getfield_resolved_char:
1862 char *obj = (char *) POPA ();
1863 NULLCHECK (obj);
1864 PUSHI (*(jchar *) (obj + INTVAL ()));
1866 NEXT_INSN;
1868 getfield_resolved_short:
1870 char *obj = (char *) POPA ();
1871 NULLCHECK (obj);
1872 PUSHI (*(jshort *) (obj + INTVAL ()));
1874 NEXT_INSN;
1876 getfield_resolved_4:
1878 char *obj = (char *) POPA ();
1879 NULLCHECK (obj);
1880 PUSHI (*(jint *) (obj + INTVAL ()));
1882 NEXT_INSN;
1884 getfield_resolved_8:
1886 char *obj = (char *) POPA ();
1887 NULLCHECK (obj);
1888 PUSHL (*(jlong *) (obj + INTVAL ()));
1890 NEXT_INSN;
1892 getfield_resolved_obj:
1894 char *obj = (char *) POPA ();
1895 NULLCHECK (obj);
1896 PUSHA (*(jobject *) (obj + INTVAL ()));
1898 NEXT_INSN;
1899 #endif /* DIRECT_THREADED */
1901 insn_putstatic:
1903 SAVE_PC();
1904 jint fieldref_index = GET2U ();
1905 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1906 _Jv_Field *field = pool_data[fieldref_index].field;
1908 jclass type = field->type;
1910 // ResolvePoolEntry cannot check this
1911 if ((field->flags & Modifier::STATIC) == 0)
1912 throw_incompatible_class_change_error
1913 (JvNewStringLatin1 ("field no longer static"));
1915 void *newinsn = NULL;
1916 if (type->isPrimitive ())
1918 switch (type->size_in_bytes)
1920 case 1:
1922 jint value = POPI();
1923 *field->u.byte_addr = value;
1924 newinsn = AMPAMP (putstatic_resolved_1);
1925 break;
1928 case 2:
1930 jint value = POPI();
1931 *field->u.char_addr = value;
1932 newinsn = AMPAMP (putstatic_resolved_2);
1933 break;
1936 case 4:
1938 jint value = POPI();
1939 *field->u.int_addr = value;
1940 newinsn = AMPAMP (putstatic_resolved_4);
1941 break;
1944 case 8:
1946 jlong value = POPL();
1947 *field->u.long_addr = value;
1948 newinsn = AMPAMP (putstatic_resolved_8);
1949 break;
1953 else
1955 jobject value = POPA();
1956 *field->u.object_addr = value;
1957 newinsn = AMPAMP (putstatic_resolved_obj);
1960 #ifdef DIRECT_THREADED
1961 pc[-2].insn = newinsn;
1962 pc[-1].datum = field->u.addr;
1963 #endif /* DIRECT_THREADED */
1965 NEXT_INSN;
1967 #ifdef DIRECT_THREADED
1968 putstatic_resolved_1:
1969 *(jbyte *) AVAL () = POPI ();
1970 NEXT_INSN;
1972 putstatic_resolved_2:
1973 *(jchar *) AVAL () = POPI ();
1974 NEXT_INSN;
1976 putstatic_resolved_4:
1977 *(jint *) AVAL () = POPI ();
1978 NEXT_INSN;
1980 putstatic_resolved_8:
1981 *(jlong *) AVAL () = POPL ();
1982 NEXT_INSN;
1984 putstatic_resolved_obj:
1985 *(jobject *) AVAL () = POPA ();
1986 NEXT_INSN;
1987 #endif /* DIRECT_THREADED */
1989 insn_putfield:
1991 SAVE_PC();
1992 jint fieldref_index = GET2U ();
1993 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1994 _Jv_Field *field = pool_data[fieldref_index].field;
1996 jclass type = field->type;
1998 if ((field->flags & Modifier::STATIC) != 0)
1999 throw_incompatible_class_change_error
2000 (JvNewStringLatin1 ("field is static"));
2002 jint field_offset = field->u.boffset;
2004 void *newinsn = NULL;
2005 if (type->isPrimitive ())
2007 switch (type->size_in_bytes)
2009 case 1:
2011 jint value = POPI();
2012 jobject obj = POPA();
2013 NULLCHECK(obj);
2014 *(jbyte*) ((char*)obj + field_offset) = value;
2015 newinsn = AMPAMP (putfield_resolved_1);
2016 break;
2019 case 2:
2021 jint value = POPI();
2022 jobject obj = POPA();
2023 NULLCHECK(obj);
2024 *(jchar*) ((char*)obj + field_offset) = value;
2025 newinsn = AMPAMP (putfield_resolved_2);
2026 break;
2029 case 4:
2031 jint value = POPI();
2032 jobject obj = POPA();
2033 NULLCHECK(obj);
2034 *(jint*) ((char*)obj + field_offset) = value;
2035 newinsn = AMPAMP (putfield_resolved_4);
2036 break;
2039 case 8:
2041 jlong value = POPL();
2042 jobject obj = POPA();
2043 NULLCHECK(obj);
2044 *(jlong*) ((char*)obj + field_offset) = value;
2045 newinsn = AMPAMP (putfield_resolved_8);
2046 break;
2050 else
2052 jobject value = POPA();
2053 jobject obj = POPA();
2054 NULLCHECK(obj);
2055 *(jobject*) ((char*)obj + field_offset) = value;
2056 newinsn = AMPAMP (putfield_resolved_obj);
2059 #ifdef DIRECT_THREADED
2060 pc[-2].insn = newinsn;
2061 pc[-1].int_val = field_offset;
2062 #endif /* DIRECT_THREADED */
2064 NEXT_INSN;
2066 #ifdef DIRECT_THREADED
2067 putfield_resolved_1:
2069 jint val = POPI ();
2070 char *obj = (char *) POPA ();
2071 NULLCHECK (obj);
2072 *(jbyte *) (obj + INTVAL ()) = val;
2074 NEXT_INSN;
2076 putfield_resolved_2:
2078 jint val = POPI ();
2079 char *obj = (char *) POPA ();
2080 NULLCHECK (obj);
2081 *(jchar *) (obj + INTVAL ()) = val;
2083 NEXT_INSN;
2085 putfield_resolved_4:
2087 jint val = POPI ();
2088 char *obj = (char *) POPA ();
2089 NULLCHECK (obj);
2090 *(jint *) (obj + INTVAL ()) = val;
2092 NEXT_INSN;
2094 putfield_resolved_8:
2096 jlong val = POPL ();
2097 char *obj = (char *) POPA ();
2098 NULLCHECK (obj);
2099 *(jlong *) (obj + INTVAL ()) = val;
2101 NEXT_INSN;
2103 putfield_resolved_obj:
2105 jobject val = POPA ();
2106 char *obj = (char *) POPA ();
2107 NULLCHECK (obj);
2108 *(jobject *) (obj + INTVAL ()) = val;
2110 NEXT_INSN;
2111 #endif /* DIRECT_THREADED */
2113 insn_invokespecial:
2115 SAVE_PC();
2116 int index = GET2U ();
2118 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2119 index)).rmethod;
2121 sp -= rmeth->stack_item_count;
2123 // We don't use NULLCHECK here because we can't rely on that
2124 // working for <init>. So instead we do an explicit test.
2125 if (! sp[0].o)
2127 SAVE_PC();
2128 throw_null_pointer_exception ();
2131 fun = (void (*)()) rmeth->method->ncode;
2133 #ifdef DIRECT_THREADED
2134 // Rewrite instruction so that we use a faster pre-resolved
2135 // method.
2136 pc[-2].insn = &&invokespecial_resolved;
2137 pc[-1].datum = rmeth;
2138 #endif /* DIRECT_THREADED */
2140 goto perform_invoke;
2142 #ifdef DIRECT_THREADED
2143 invokespecial_resolved:
2145 SAVE_PC();
2146 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2147 sp -= rmeth->stack_item_count;
2148 // We don't use NULLCHECK here because we can't rely on that
2149 // working for <init>. So instead we do an explicit test.
2150 if (! sp[0].o)
2152 throw_null_pointer_exception ();
2154 fun = (void (*)()) rmeth->method->ncode;
2156 goto perform_invoke;
2157 #endif /* DIRECT_THREADED */
2159 insn_invokestatic:
2161 SAVE_PC();
2162 int index = GET2U ();
2164 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2165 index)).rmethod;
2167 sp -= rmeth->stack_item_count;
2169 fun = (void (*)()) rmeth->method->ncode;
2171 #ifdef DIRECT_THREADED
2172 // Rewrite instruction so that we use a faster pre-resolved
2173 // method.
2174 pc[-2].insn = &&invokestatic_resolved;
2175 pc[-1].datum = rmeth;
2176 #endif /* DIRECT_THREADED */
2178 goto perform_invoke;
2180 #ifdef DIRECT_THREADED
2181 invokestatic_resolved:
2183 SAVE_PC();
2184 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2185 sp -= rmeth->stack_item_count;
2186 fun = (void (*)()) rmeth->method->ncode;
2188 goto perform_invoke;
2189 #endif /* DIRECT_THREADED */
2191 insn_invokeinterface:
2193 SAVE_PC();
2194 int index = GET2U ();
2196 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2197 index)).rmethod;
2199 sp -= rmeth->stack_item_count;
2201 jobject rcv = sp[0].o;
2203 NULLCHECK (rcv);
2205 fun = (void (*)())
2206 _Jv_LookupInterfaceMethod (rcv->getClass (),
2207 rmeth->method->name,
2208 rmeth->method->signature);
2210 #ifdef DIRECT_THREADED
2211 // Rewrite instruction so that we use a faster pre-resolved
2212 // method.
2213 pc[-2].insn = &&invokeinterface_resolved;
2214 pc[-1].datum = rmeth;
2215 #else
2216 // Skip dummy bytes.
2217 pc += 2;
2218 #endif /* DIRECT_THREADED */
2220 goto perform_invoke;
2222 #ifdef DIRECT_THREADED
2223 invokeinterface_resolved:
2225 SAVE_PC();
2226 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2227 sp -= rmeth->stack_item_count;
2228 jobject rcv = sp[0].o;
2229 NULLCHECK (rcv);
2230 fun = (void (*)())
2231 _Jv_LookupInterfaceMethod (rcv->getClass (),
2232 rmeth->method->name,
2233 rmeth->method->signature);
2235 goto perform_invoke;
2236 #endif /* DIRECT_THREADED */
2238 insn_new:
2240 SAVE_PC();
2241 int index = GET2U ();
2242 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2243 index)).clazz;
2244 /* VM spec, section 3.11.5 */
2245 if ((klass->getModifiers() & Modifier::ABSTRACT)
2246 || klass->isInterface())
2247 throw new java::lang::InstantiationException;
2248 jobject res = _Jv_AllocObject (klass);
2249 PUSHA (res);
2251 #ifdef DIRECT_THREADED
2252 pc[-2].insn = &&new_resolved;
2253 pc[-1].datum = klass;
2254 #endif /* DIRECT_THREADED */
2256 NEXT_INSN;
2258 #ifdef DIRECT_THREADED
2259 new_resolved:
2261 jclass klass = (jclass) AVAL ();
2262 jobject res = _Jv_AllocObject (klass);
2263 PUSHA (res);
2265 NEXT_INSN;
2266 #endif /* DIRECT_THREADED */
2268 insn_newarray:
2270 int atype = GET1U ();
2271 int size = POPI();
2272 jobject result = _Jv_NewArray (atype, size);
2273 PUSHA (result);
2275 NEXT_INSN;
2277 insn_anewarray:
2279 SAVE_PC();
2280 int index = GET2U ();
2281 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2282 index)).clazz;
2283 int size = POPI();
2284 jobject result = _Jv_NewObjectArray (size, klass, 0);
2285 PUSHA (result);
2287 #ifdef DIRECT_THREADED
2288 pc[-2].insn = &&anewarray_resolved;
2289 pc[-1].datum = klass;
2290 #endif /* DIRECT_THREADED */
2292 NEXT_INSN;
2294 #ifdef DIRECT_THREADED
2295 anewarray_resolved:
2297 jclass klass = (jclass) AVAL ();
2298 int size = POPI ();
2299 jobject result = _Jv_NewObjectArray (size, klass, 0);
2300 PUSHA (result);
2302 NEXT_INSN;
2303 #endif /* DIRECT_THREADED */
2305 insn_arraylength:
2307 __JArray *arr = (__JArray*)POPA();
2308 NULLARRAYCHECK (arr);
2309 PUSHI (arr->length);
2311 NEXT_INSN;
2313 insn_athrow:
2315 jobject value = POPA();
2316 throw static_cast<jthrowable>(value);
2318 NEXT_INSN;
2320 insn_checkcast:
2322 SAVE_PC();
2323 jobject value = POPA();
2324 jint index = GET2U ();
2325 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2326 index)).clazz;
2328 value = (jobject) _Jv_CheckCast (to, value);
2330 PUSHA (value);
2332 #ifdef DIRECT_THREADED
2333 pc[-2].insn = &&checkcast_resolved;
2334 pc[-1].datum = to;
2335 #endif /* DIRECT_THREADED */
2337 NEXT_INSN;
2339 #ifdef DIRECT_THREADED
2340 checkcast_resolved:
2342 SAVE_PC();
2343 jobject value = POPA ();
2344 jclass to = (jclass) AVAL ();
2345 value = (jobject) _Jv_CheckCast (to, value);
2346 PUSHA (value);
2348 NEXT_INSN;
2349 #endif /* DIRECT_THREADED */
2351 insn_instanceof:
2353 SAVE_PC();
2354 jobject value = POPA();
2355 jint index = GET2U ();
2356 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2357 index)).clazz;
2358 PUSHI (to->isInstance (value));
2360 #ifdef DIRECT_THREADED
2361 pc[-2].insn = &&instanceof_resolved;
2362 pc[-1].datum = to;
2363 #endif /* DIRECT_THREADED */
2365 NEXT_INSN;
2367 #ifdef DIRECT_THREADED
2368 instanceof_resolved:
2370 jobject value = POPA ();
2371 jclass to = (jclass) AVAL ();
2372 PUSHI (to->isInstance (value));
2374 NEXT_INSN;
2375 #endif /* DIRECT_THREADED */
2377 insn_monitorenter:
2379 jobject value = POPA();
2380 NULLCHECK(value);
2381 _Jv_MonitorEnter (value);
2383 NEXT_INSN;
2385 insn_monitorexit:
2387 jobject value = POPA();
2388 NULLCHECK(value);
2389 _Jv_MonitorExit (value);
2391 NEXT_INSN;
2393 insn_ifnull:
2395 jobject val = POPA();
2396 if (val == NULL)
2397 TAKE_GOTO;
2398 else
2399 SKIP_GOTO;
2401 NEXT_INSN;
2403 insn_ifnonnull:
2405 jobject val = POPA();
2406 if (val != NULL)
2407 TAKE_GOTO;
2408 else
2409 SKIP_GOTO;
2411 NEXT_INSN;
2413 insn_multianewarray:
2415 SAVE_PC();
2416 int kind_index = GET2U ();
2417 int dim = GET1U ();
2419 jclass type
2420 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2421 kind_index)).clazz;
2422 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2424 for (int i = dim - 1; i >= 0; i--)
2426 sizes[i] = POPI ();
2429 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2431 PUSHA (res);
2433 NEXT_INSN;
2435 #ifndef DIRECT_THREADED
2436 insn_wide:
2438 jint the_mod_op = get1u (pc++);
2439 jint wide = get2u (pc); pc += 2;
2441 switch (the_mod_op)
2443 case op_istore:
2444 STOREI (wide);
2445 NEXT_INSN;
2447 case op_fstore:
2448 STOREF (wide);
2449 NEXT_INSN;
2451 case op_astore:
2452 STOREA (wide);
2453 NEXT_INSN;
2455 case op_lload:
2456 LOADL (wide);
2457 NEXT_INSN;
2459 case op_dload:
2460 LOADD (wide);
2461 NEXT_INSN;
2463 case op_iload:
2464 LOADI (wide);
2465 NEXT_INSN;
2467 case op_fload:
2468 LOADF (wide);
2469 NEXT_INSN;
2471 case op_aload:
2472 LOADA (wide);
2473 NEXT_INSN;
2475 case op_lstore:
2476 STOREL (wide);
2477 NEXT_INSN;
2479 case op_dstore:
2480 STORED (wide);
2481 NEXT_INSN;
2483 case op_ret:
2484 pc = (unsigned char*) PEEKA (wide);
2485 NEXT_INSN;
2487 case op_iinc:
2489 jint amount = get2s (pc); pc += 2;
2490 jint value = PEEKI (wide);
2491 POKEI (wide, value+amount);
2493 NEXT_INSN;
2495 default:
2496 throw_internal_error ("illegal bytecode modified by wide");
2500 #endif /* DIRECT_THREADED */
2502 insn_breakpoint:
2504 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2506 // Send JVMTI notification
2507 using namespace ::java::lang;
2508 jmethodID method = meth->self;
2509 jlocation location = meth->insn_index (pc - 1);
2510 Thread *thread = Thread::currentThread ();
2511 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2513 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2514 method, location);
2516 // Continue execution
2517 using namespace gnu::gcj::jvmti;
2518 Breakpoint *bp
2519 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2520 location);
2521 JvAssert (bp != NULL);
2523 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2525 #ifdef DIRECT_THREADED
2526 goto *(opc->insn);
2527 #else
2528 goto *(insn_target[*opc]);
2529 #endif
2532 catch (java::lang::Throwable *ex)
2534 #ifdef DIRECT_THREADED
2535 void *logical_pc = (void *) ((insn_slot *) pc - 1);
2536 #else
2537 int logical_pc = pc - 1 - meth->bytecode ();
2538 #endif
2539 _Jv_InterpException *exc = meth->exceptions ();
2540 jclass exc_class = ex->getClass ();
2542 for (int i = 0; i < meth->exc_count; i++)
2544 if (PCVAL (exc[i].start_pc) <= logical_pc
2545 && logical_pc < PCVAL (exc[i].end_pc))
2547 #ifdef DIRECT_THREADED
2548 jclass handler = (jclass) exc[i].handler_type.p;
2549 #else
2550 jclass handler = NULL;
2551 if (exc[i].handler_type.i != 0)
2552 handler = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2553 exc[i].handler_type.i)).clazz;
2554 #endif /* DIRECT_THREADED */
2556 if (handler == NULL || handler->isAssignableFrom (exc_class))
2559 #ifdef DIRECT_THREADED
2560 pc = (insn_slot *) exc[i].handler_pc.p;
2561 #else
2562 pc = meth->bytecode () + exc[i].handler_pc.i;
2563 #endif /* DIRECT_THREADED */
2564 sp = stack;
2565 sp++->o = ex; // Push exception.
2566 NEXT_INSN;
2571 // No handler, so re-throw.
2572 throw ex;