2007-03-01 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / libjava / interpret-run.cc
blob9d37c19a3a769dc6165f670f2d3318c1226c822b
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 #ifdef DEBUG
31 frame_desc.locals = locals;
32 char locals_type[meth->max_locals];
33 memset (locals_type, 'x', meth->max_locals);
34 frame_desc.locals_type = locals_type;
35 #endif
37 #define INSN_LABEL(op) &&insn_##op
39 static const void *const insn_target[] =
41 INSN_LABEL(nop),
42 INSN_LABEL(aconst_null),
43 INSN_LABEL(iconst_m1),
44 INSN_LABEL(iconst_0),
45 INSN_LABEL(iconst_1),
46 INSN_LABEL(iconst_2),
47 INSN_LABEL(iconst_3),
48 INSN_LABEL(iconst_4),
49 INSN_LABEL(iconst_5),
50 INSN_LABEL(lconst_0),
51 INSN_LABEL(lconst_1),
52 INSN_LABEL(fconst_0),
53 INSN_LABEL(fconst_1),
54 INSN_LABEL(fconst_2),
55 INSN_LABEL(dconst_0),
56 INSN_LABEL(dconst_1),
57 INSN_LABEL(bipush),
58 INSN_LABEL(sipush),
59 INSN_LABEL(ldc),
60 INSN_LABEL(ldc_w),
61 INSN_LABEL(ldc2_w),
62 INSN_LABEL(iload),
63 INSN_LABEL(lload),
64 INSN_LABEL(fload),
65 INSN_LABEL(dload),
66 INSN_LABEL(aload),
67 INSN_LABEL(iload_0),
68 INSN_LABEL(iload_1),
69 INSN_LABEL(iload_2),
70 INSN_LABEL(iload_3),
71 INSN_LABEL(lload_0),
72 INSN_LABEL(lload_1),
73 INSN_LABEL(lload_2),
74 INSN_LABEL(lload_3),
75 INSN_LABEL(fload_0),
76 INSN_LABEL(fload_1),
77 INSN_LABEL(fload_2),
78 INSN_LABEL(fload_3),
79 INSN_LABEL(dload_0),
80 INSN_LABEL(dload_1),
81 INSN_LABEL(dload_2),
82 INSN_LABEL(dload_3),
83 INSN_LABEL(aload_0),
84 INSN_LABEL(aload_1),
85 INSN_LABEL(aload_2),
86 INSN_LABEL(aload_3),
87 INSN_LABEL(iaload),
88 INSN_LABEL(laload),
89 INSN_LABEL(faload),
90 INSN_LABEL(daload),
91 INSN_LABEL(aaload),
92 INSN_LABEL(baload),
93 INSN_LABEL(caload),
94 INSN_LABEL(saload),
95 INSN_LABEL(istore),
96 INSN_LABEL(lstore),
97 INSN_LABEL(fstore),
98 INSN_LABEL(dstore),
99 INSN_LABEL(astore),
100 INSN_LABEL(istore_0),
101 INSN_LABEL(istore_1),
102 INSN_LABEL(istore_2),
103 INSN_LABEL(istore_3),
104 INSN_LABEL(lstore_0),
105 INSN_LABEL(lstore_1),
106 INSN_LABEL(lstore_2),
107 INSN_LABEL(lstore_3),
108 INSN_LABEL(fstore_0),
109 INSN_LABEL(fstore_1),
110 INSN_LABEL(fstore_2),
111 INSN_LABEL(fstore_3),
112 INSN_LABEL(dstore_0),
113 INSN_LABEL(dstore_1),
114 INSN_LABEL(dstore_2),
115 INSN_LABEL(dstore_3),
116 INSN_LABEL(astore_0),
117 INSN_LABEL(astore_1),
118 INSN_LABEL(astore_2),
119 INSN_LABEL(astore_3),
120 INSN_LABEL(iastore),
121 INSN_LABEL(lastore),
122 INSN_LABEL(fastore),
123 INSN_LABEL(dastore),
124 INSN_LABEL(aastore),
125 INSN_LABEL(bastore),
126 INSN_LABEL(castore),
127 INSN_LABEL(sastore),
128 INSN_LABEL(pop),
129 INSN_LABEL(pop2),
130 INSN_LABEL(dup),
131 INSN_LABEL(dup_x1),
132 INSN_LABEL(dup_x2),
133 INSN_LABEL(dup2),
134 INSN_LABEL(dup2_x1),
135 INSN_LABEL(dup2_x2),
136 INSN_LABEL(swap),
137 INSN_LABEL(iadd),
138 INSN_LABEL(ladd),
139 INSN_LABEL(fadd),
140 INSN_LABEL(dadd),
141 INSN_LABEL(isub),
142 INSN_LABEL(lsub),
143 INSN_LABEL(fsub),
144 INSN_LABEL(dsub),
145 INSN_LABEL(imul),
146 INSN_LABEL(lmul),
147 INSN_LABEL(fmul),
148 INSN_LABEL(dmul),
149 INSN_LABEL(idiv),
150 INSN_LABEL(ldiv),
151 INSN_LABEL(fdiv),
152 INSN_LABEL(ddiv),
153 INSN_LABEL(irem),
154 INSN_LABEL(lrem),
155 INSN_LABEL(frem),
156 INSN_LABEL(drem),
157 INSN_LABEL(ineg),
158 INSN_LABEL(lneg),
159 INSN_LABEL(fneg),
160 INSN_LABEL(dneg),
161 INSN_LABEL(ishl),
162 INSN_LABEL(lshl),
163 INSN_LABEL(ishr),
164 INSN_LABEL(lshr),
165 INSN_LABEL(iushr),
166 INSN_LABEL(lushr),
167 INSN_LABEL(iand),
168 INSN_LABEL(land),
169 INSN_LABEL(ior),
170 INSN_LABEL(lor),
171 INSN_LABEL(ixor),
172 INSN_LABEL(lxor),
173 INSN_LABEL(iinc),
174 INSN_LABEL(i2l),
175 INSN_LABEL(i2f),
176 INSN_LABEL(i2d),
177 INSN_LABEL(l2i),
178 INSN_LABEL(l2f),
179 INSN_LABEL(l2d),
180 INSN_LABEL(f2i),
181 INSN_LABEL(f2l),
182 INSN_LABEL(f2d),
183 INSN_LABEL(d2i),
184 INSN_LABEL(d2l),
185 INSN_LABEL(d2f),
186 INSN_LABEL(i2b),
187 INSN_LABEL(i2c),
188 INSN_LABEL(i2s),
189 INSN_LABEL(lcmp),
190 INSN_LABEL(fcmpl),
191 INSN_LABEL(fcmpg),
192 INSN_LABEL(dcmpl),
193 INSN_LABEL(dcmpg),
194 INSN_LABEL(ifeq),
195 INSN_LABEL(ifne),
196 INSN_LABEL(iflt),
197 INSN_LABEL(ifge),
198 INSN_LABEL(ifgt),
199 INSN_LABEL(ifle),
200 INSN_LABEL(if_icmpeq),
201 INSN_LABEL(if_icmpne),
202 INSN_LABEL(if_icmplt),
203 INSN_LABEL(if_icmpge),
204 INSN_LABEL(if_icmpgt),
205 INSN_LABEL(if_icmple),
206 INSN_LABEL(if_acmpeq),
207 INSN_LABEL(if_acmpne),
208 INSN_LABEL(goto),
209 INSN_LABEL(jsr),
210 INSN_LABEL(ret),
211 INSN_LABEL(tableswitch),
212 INSN_LABEL(lookupswitch),
213 INSN_LABEL(ireturn),
214 INSN_LABEL(lreturn),
215 INSN_LABEL(freturn),
216 INSN_LABEL(dreturn),
217 INSN_LABEL(areturn),
218 INSN_LABEL(return),
219 INSN_LABEL(getstatic),
220 INSN_LABEL(putstatic),
221 INSN_LABEL(getfield),
222 INSN_LABEL(putfield),
223 INSN_LABEL(invokevirtual),
224 INSN_LABEL(invokespecial),
225 INSN_LABEL(invokestatic),
226 INSN_LABEL(invokeinterface),
227 INSN_LABEL(breakpoint),
228 INSN_LABEL(new),
229 INSN_LABEL(newarray),
230 INSN_LABEL(anewarray),
231 INSN_LABEL(arraylength),
232 INSN_LABEL(athrow),
233 INSN_LABEL(checkcast),
234 INSN_LABEL(instanceof),
235 INSN_LABEL(monitorenter),
236 INSN_LABEL(monitorexit),
237 #ifdef DIRECT_THREADED
238 0, // wide
239 #else
240 INSN_LABEL(wide),
241 #endif
242 INSN_LABEL(multianewarray),
243 INSN_LABEL(ifnull),
244 INSN_LABEL(ifnonnull),
245 INSN_LABEL(goto_w),
246 INSN_LABEL(jsr_w),
247 #ifdef DIRECT_THREADED
248 INSN_LABEL (ldc_class)
249 #else
251 #endif
254 pc_t pc;
256 #ifdef DIRECT_THREADED
258 #ifdef DEBUG
259 #undef NEXT_INSN
260 #define NEXT_INSN \
261 do \
263 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
265 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
266 jmethodID method = meth->self; \
267 jlocation loc = meth->insn_index (pc); \
268 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
269 env, method, loc); \
271 goto *((pc++)->insn); \
273 while (0)
274 #else
275 #undef NEXT_INSN
276 #define NEXT_INSN goto *((pc++)->insn)
277 #endif
279 #define INTVAL() ((pc++)->int_val)
280 #define AVAL() ((pc++)->datum)
282 #define GET1S() INTVAL ()
283 #define GET2S() INTVAL ()
284 #define GET1U() INTVAL ()
285 #define GET2U() INTVAL ()
286 #define AVAL1U() AVAL ()
287 #define AVAL2U() AVAL ()
288 #define AVAL2UP() AVAL ()
289 #define SKIP_GOTO ++pc
290 #define GOTO_VAL() (insn_slot *) pc->datum
291 #define PCVAL(unionval) unionval.p
292 #define AMPAMP(label) &&label
294 // Compile if we must. NOTE: Double-check locking.
295 if (meth->prepared == NULL)
297 _Jv_MutexLock (&compile_mutex);
298 if (meth->prepared == NULL)
299 meth->compile (insn_target);
300 _Jv_MutexUnlock (&compile_mutex);
303 // If we're only compiling, stop here
304 if (args == NULL)
305 return;
307 pc = (insn_slot *) meth->prepared;
309 #else
311 #ifdef DEBUG
312 #define NEXT_INSN \
313 do \
315 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
317 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
318 jmethodID method = meth->self; \
319 jlocation loc = meth->insn_index (pc); \
320 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
321 env, method, loc); \
323 goto *(insn_target[*pc++])
324 #else
325 #define NEXT_INSN goto *(insn_target[*pc++])
326 #endif
328 #define GET1S() get1s (pc++)
329 #define GET2S() (pc += 2, get2s (pc- 2))
330 #define GET1U() get1u (pc++)
331 #define GET2U() (pc += 2, get2u (pc - 2))
332 // Note that these could be more efficient when not handling 'ldc
333 // class'.
334 #define AVAL1U() \
335 ({ int index = get1u (pc++); \
336 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
337 #define AVAL2U() \
338 ({ int index = get2u (pc); pc += 2; \
339 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
340 // Note that we don't need to resolve the pool entry here as class
341 // constants are never wide.
342 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
343 #define SKIP_GOTO pc += 2
344 #define GOTO_VAL() pc - 1 + get2s (pc)
345 #define PCVAL(unionval) unionval.i
346 #define AMPAMP(label) NULL
348 pc = meth->bytecode ();
350 #endif /* DIRECT_THREADED */
352 #define TAKE_GOTO pc = GOTO_VAL ()
354 /* Go straight at it! the ffi raw format matches the internal
355 stack representation exactly. At least, that's the idea.
357 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
359 #ifdef DEBUG
360 // Get the object pointer for this method, after checking that it is
361 // non-static.
362 _Jv_Method *method = meth->get_method ();
364 if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
365 frame_desc.obj_ptr = locals[0].o;
366 #endif
368 _Jv_word *pool_data = meth->defining_class->constants.data;
370 /* These three are temporaries for common code used by several
371 instructions. */
372 void (*fun)();
373 _Jv_ResolvedMethod* rmeth;
374 int tmpval;
378 // We keep nop around. It is used if we're interpreting the
379 // bytecodes and not doing direct threading.
380 insn_nop:
381 NEXT_INSN;
383 /* The first few instructions here are ordered according to their
384 frequency, in the hope that this will improve code locality a
385 little. */
387 insn_aload_0: // 0x2a
388 LOADA (0);
389 NEXT_INSN;
391 insn_iload: // 0x15
392 LOADI (GET1U ());
393 NEXT_INSN;
395 insn_iload_1: // 0x1b
396 LOADI (1);
397 NEXT_INSN;
399 insn_invokevirtual: // 0xb6
401 SAVE_PC();
402 int index = GET2U ();
404 /* _Jv_Linker::resolve_pool_entry returns immediately if the
405 * value already is resolved. If we want to clutter up the
406 * code here to gain a little performance, then we can check
407 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
408 * directly. For now, I don't think it is worth it. */
410 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
411 index)).rmethod;
413 sp -= rmeth->stack_item_count;
415 if (rmeth->method->accflags & Modifier::FINAL)
417 // We can't rely on NULLCHECK working if the method is final.
418 if (! sp[0].o)
419 throw_null_pointer_exception ();
421 // Final methods might not appear in the vtable.
422 fun = (void (*)()) rmeth->method->ncode;
424 else
426 NULLCHECK (sp[0].o);
427 jobject rcv = sp[0].o;
428 _Jv_VTable *table = *(_Jv_VTable**) rcv;
429 fun = (void (*)()) table->get_method (rmeth->method->index);
432 #ifdef DIRECT_THREADED
433 // Rewrite instruction so that we use a faster pre-resolved
434 // method.
435 pc[-2].insn = &&invokevirtual_resolved;
436 pc[-1].datum = rmeth;
437 #endif /* DIRECT_THREADED */
439 goto perform_invoke;
441 #ifdef DIRECT_THREADED
442 invokevirtual_resolved:
444 SAVE_PC();
445 rmeth = (_Jv_ResolvedMethod *) AVAL ();
446 sp -= rmeth->stack_item_count;
448 if (rmeth->method->accflags & Modifier::FINAL)
450 // We can't rely on NULLCHECK working if the method is final.
451 if (! sp[0].o)
452 throw_null_pointer_exception ();
454 // Final methods might not appear in the vtable.
455 fun = (void (*)()) rmeth->method->ncode;
457 else
459 jobject rcv = sp[0].o;
460 _Jv_VTable *table = *(_Jv_VTable**) rcv;
461 fun = (void (*)()) table->get_method (rmeth->method->index);
464 goto perform_invoke;
465 #endif /* DIRECT_THREADED */
467 perform_invoke:
469 /* here goes the magic again... */
470 ffi_cif *cif = &rmeth->cif;
471 ffi_raw *raw = (ffi_raw*) sp;
473 _Jv_value rvalue;
475 #if FFI_NATIVE_RAW_API
476 /* We assume that this is only implemented if it's correct */
477 /* to use it here. On a 64 bit machine, it never is. */
478 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
479 #else
480 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
481 #endif
483 int rtype = cif->rtype->type;
485 /* the likelyhood of object, int, or void return is very high,
486 * so those are checked before the switch */
487 if (rtype == FFI_TYPE_POINTER)
489 PUSHA (rvalue.object_value);
491 else if (rtype == FFI_TYPE_SINT32)
493 PUSHI (rvalue.int_value);
495 else if (rtype == FFI_TYPE_VOID)
497 /* skip */
499 else
501 switch (rtype)
503 case FFI_TYPE_SINT8:
504 PUSHI ((jbyte)(rvalue.int_value & 0xff));
505 break;
507 case FFI_TYPE_SINT16:
508 PUSHI ((jshort)(rvalue.int_value & 0xffff));
509 break;
511 case FFI_TYPE_UINT16:
512 PUSHI (rvalue.int_value & 0xffff);
513 break;
515 case FFI_TYPE_FLOAT:
516 PUSHF (rvalue.float_value);
517 break;
519 case FFI_TYPE_DOUBLE:
520 PUSHD (rvalue.double_value);
521 break;
523 case FFI_TYPE_SINT64:
524 PUSHL (rvalue.long_value);
525 break;
527 default:
528 throw_internal_error ("unknown return type in invokeXXX");
532 NEXT_INSN;
534 insn_aconst_null:
535 PUSHA (NULL);
536 NEXT_INSN;
538 insn_iconst_m1:
539 PUSHI (-1);
540 NEXT_INSN;
542 insn_iconst_0:
543 PUSHI (0);
544 NEXT_INSN;
546 insn_iconst_1:
547 PUSHI (1);
548 NEXT_INSN;
550 insn_iconst_2:
551 PUSHI (2);
552 NEXT_INSN;
554 insn_iconst_3:
555 PUSHI (3);
556 NEXT_INSN;
558 insn_iconst_4:
559 PUSHI (4);
560 NEXT_INSN;
562 insn_iconst_5:
563 PUSHI (5);
564 NEXT_INSN;
566 insn_lconst_0:
567 PUSHL (0);
568 NEXT_INSN;
570 insn_lconst_1:
571 PUSHL (1);
572 NEXT_INSN;
574 insn_fconst_0:
575 PUSHF (0);
576 NEXT_INSN;
578 insn_fconst_1:
579 PUSHF (1);
580 NEXT_INSN;
582 insn_fconst_2:
583 PUSHF (2);
584 NEXT_INSN;
586 insn_dconst_0:
587 PUSHD (0);
588 NEXT_INSN;
590 insn_dconst_1:
591 PUSHD (1);
592 NEXT_INSN;
594 insn_bipush:
595 // For direct threaded, bipush and sipush are the same.
596 #ifndef DIRECT_THREADED
597 PUSHI (GET1S ());
598 NEXT_INSN;
599 #endif /* DIRECT_THREADED */
600 insn_sipush:
601 PUSHI (GET2S ());
602 NEXT_INSN;
604 insn_ldc:
605 // For direct threaded, ldc and ldc_w are the same.
606 #ifndef DIRECT_THREADED
607 PUSHA ((jobject) AVAL1U ());
608 NEXT_INSN;
609 #endif /* DIRECT_THREADED */
610 insn_ldc_w:
611 PUSHA ((jobject) AVAL2U ());
612 NEXT_INSN;
614 #ifdef DIRECT_THREADED
615 // For direct threaded we have a separate 'ldc class' operation.
616 insn_ldc_class:
618 SAVE_PC();
619 // We could rewrite the instruction at this point.
620 int index = INTVAL ();
621 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
622 index)).o;
623 PUSHA (k);
625 NEXT_INSN;
626 #endif /* DIRECT_THREADED */
628 insn_ldc2_w:
630 void *where = AVAL2UP ();
631 memcpy (sp, where, 2*sizeof (_Jv_word));
632 sp += 2;
634 NEXT_INSN;
636 insn_lload:
637 LOADL (GET1U ());
638 NEXT_INSN;
640 insn_fload:
641 LOADF (GET1U ());
642 NEXT_INSN;
644 insn_dload:
645 LOADD (GET1U ());
646 NEXT_INSN;
648 insn_aload:
649 LOADA (GET1U ());
650 NEXT_INSN;
652 insn_iload_0:
653 LOADI (0);
654 NEXT_INSN;
656 insn_iload_2:
657 LOADI (2);
658 NEXT_INSN;
660 insn_iload_3:
661 LOADI (3);
662 NEXT_INSN;
664 insn_lload_0:
665 LOADL (0);
666 NEXT_INSN;
668 insn_lload_1:
669 LOADL (1);
670 NEXT_INSN;
672 insn_lload_2:
673 LOADL (2);
674 NEXT_INSN;
676 insn_lload_3:
677 LOADL (3);
678 NEXT_INSN;
680 insn_fload_0:
681 LOADF (0);
682 NEXT_INSN;
684 insn_fload_1:
685 LOADF (1);
686 NEXT_INSN;
688 insn_fload_2:
689 LOADF (2);
690 NEXT_INSN;
692 insn_fload_3:
693 LOADF (3);
694 NEXT_INSN;
696 insn_dload_0:
697 LOADD (0);
698 NEXT_INSN;
700 insn_dload_1:
701 LOADD (1);
702 NEXT_INSN;
704 insn_dload_2:
705 LOADD (2);
706 NEXT_INSN;
708 insn_dload_3:
709 LOADD (3);
710 NEXT_INSN;
712 insn_aload_1:
713 LOADA(1);
714 NEXT_INSN;
716 insn_aload_2:
717 LOADA(2);
718 NEXT_INSN;
720 insn_aload_3:
721 LOADA(3);
722 NEXT_INSN;
724 insn_iaload:
726 jint index = POPI();
727 jintArray arr = (jintArray) POPA();
728 NULLARRAYCHECK (arr);
729 ARRAYBOUNDSCHECK (arr, index);
730 PUSHI( elements(arr)[index] );
732 NEXT_INSN;
734 insn_laload:
736 jint index = POPI();
737 jlongArray arr = (jlongArray) POPA();
738 NULLARRAYCHECK (arr);
739 ARRAYBOUNDSCHECK (arr, index);
740 PUSHL( elements(arr)[index] );
742 NEXT_INSN;
744 insn_faload:
746 jint index = POPI();
747 jfloatArray arr = (jfloatArray) POPA();
748 NULLARRAYCHECK (arr);
749 ARRAYBOUNDSCHECK (arr, index);
750 PUSHF( elements(arr)[index] );
752 NEXT_INSN;
754 insn_daload:
756 jint index = POPI();
757 jdoubleArray arr = (jdoubleArray) POPA();
758 NULLARRAYCHECK (arr);
759 ARRAYBOUNDSCHECK (arr, index);
760 PUSHD( elements(arr)[index] );
762 NEXT_INSN;
764 insn_aaload:
766 jint index = POPI();
767 jobjectArray arr = (jobjectArray) POPA();
768 NULLARRAYCHECK (arr);
769 ARRAYBOUNDSCHECK (arr, index);
770 PUSHA( elements(arr)[index] );
772 NEXT_INSN;
774 insn_baload:
776 jint index = POPI();
777 jbyteArray arr = (jbyteArray) POPA();
778 NULLARRAYCHECK (arr);
779 ARRAYBOUNDSCHECK (arr, index);
780 PUSHI( elements(arr)[index] );
782 NEXT_INSN;
784 insn_caload:
786 jint index = POPI();
787 jcharArray arr = (jcharArray) POPA();
788 NULLARRAYCHECK (arr);
789 ARRAYBOUNDSCHECK (arr, index);
790 PUSHI( elements(arr)[index] );
792 NEXT_INSN;
794 insn_saload:
796 jint index = POPI();
797 jshortArray arr = (jshortArray) POPA();
798 NULLARRAYCHECK (arr);
799 ARRAYBOUNDSCHECK (arr, index);
800 PUSHI( elements(arr)[index] );
802 NEXT_INSN;
804 insn_istore:
805 STOREI (GET1U ());
806 NEXT_INSN;
808 insn_lstore:
809 STOREL (GET1U ());
810 NEXT_INSN;
812 insn_fstore:
813 STOREF (GET1U ());
814 NEXT_INSN;
816 insn_dstore:
817 STORED (GET1U ());
818 NEXT_INSN;
820 insn_astore:
821 STOREA (GET1U ());
822 NEXT_INSN;
824 insn_istore_0:
825 STOREI (0);
826 NEXT_INSN;
828 insn_istore_1:
829 STOREI (1);
830 NEXT_INSN;
832 insn_istore_2:
833 STOREI (2);
834 NEXT_INSN;
836 insn_istore_3:
837 STOREI (3);
838 NEXT_INSN;
840 insn_lstore_0:
841 STOREL (0);
842 NEXT_INSN;
844 insn_lstore_1:
845 STOREL (1);
846 NEXT_INSN;
848 insn_lstore_2:
849 STOREL (2);
850 NEXT_INSN;
852 insn_lstore_3:
853 STOREL (3);
854 NEXT_INSN;
856 insn_fstore_0:
857 STOREF (0);
858 NEXT_INSN;
860 insn_fstore_1:
861 STOREF (1);
862 NEXT_INSN;
864 insn_fstore_2:
865 STOREF (2);
866 NEXT_INSN;
868 insn_fstore_3:
869 STOREF (3);
870 NEXT_INSN;
872 insn_dstore_0:
873 STORED (0);
874 NEXT_INSN;
876 insn_dstore_1:
877 STORED (1);
878 NEXT_INSN;
880 insn_dstore_2:
881 STORED (2);
882 NEXT_INSN;
884 insn_dstore_3:
885 STORED (3);
886 NEXT_INSN;
888 insn_astore_0:
889 STOREA(0);
890 NEXT_INSN;
892 insn_astore_1:
893 STOREA(1);
894 NEXT_INSN;
896 insn_astore_2:
897 STOREA(2);
898 NEXT_INSN;
900 insn_astore_3:
901 STOREA(3);
902 NEXT_INSN;
904 insn_iastore:
906 jint value = POPI();
907 jint index = POPI();
908 jintArray arr = (jintArray) POPA();
909 NULLARRAYCHECK (arr);
910 ARRAYBOUNDSCHECK (arr, index);
911 elements(arr)[index] = value;
913 NEXT_INSN;
915 insn_lastore:
917 jlong value = POPL();
918 jint index = POPI();
919 jlongArray arr = (jlongArray) POPA();
920 NULLARRAYCHECK (arr);
921 ARRAYBOUNDSCHECK (arr, index);
922 elements(arr)[index] = value;
924 NEXT_INSN;
926 insn_fastore:
928 jfloat value = POPF();
929 jint index = POPI();
930 jfloatArray arr = (jfloatArray) POPA();
931 NULLARRAYCHECK (arr);
932 ARRAYBOUNDSCHECK (arr, index);
933 elements(arr)[index] = value;
935 NEXT_INSN;
937 insn_dastore:
939 jdouble value = POPD();
940 jint index = POPI();
941 jdoubleArray arr = (jdoubleArray) POPA();
942 NULLARRAYCHECK (arr);
943 ARRAYBOUNDSCHECK (arr, index);
944 elements(arr)[index] = value;
946 NEXT_INSN;
948 insn_aastore:
950 jobject value = POPA();
951 jint index = POPI();
952 jobjectArray arr = (jobjectArray) POPA();
953 NULLARRAYCHECK (arr);
954 ARRAYBOUNDSCHECK (arr, index);
955 _Jv_CheckArrayStore (arr, value);
956 elements(arr)[index] = value;
958 NEXT_INSN;
960 insn_bastore:
962 jbyte value = (jbyte) POPI();
963 jint index = POPI();
964 jbyteArray arr = (jbyteArray) POPA();
965 NULLARRAYCHECK (arr);
966 ARRAYBOUNDSCHECK (arr, index);
967 elements(arr)[index] = value;
969 NEXT_INSN;
971 insn_castore:
973 jchar value = (jchar) POPI();
974 jint index = POPI();
975 jcharArray arr = (jcharArray) POPA();
976 NULLARRAYCHECK (arr);
977 ARRAYBOUNDSCHECK (arr, index);
978 elements(arr)[index] = value;
980 NEXT_INSN;
982 insn_sastore:
984 jshort value = (jshort) POPI();
985 jint index = POPI();
986 jshortArray arr = (jshortArray) POPA();
987 NULLARRAYCHECK (arr);
988 ARRAYBOUNDSCHECK (arr, index);
989 elements(arr)[index] = value;
991 NEXT_INSN;
993 insn_pop:
994 sp -= 1;
995 NEXT_INSN;
997 insn_pop2:
998 sp -= 2;
999 NEXT_INSN;
1001 insn_dup:
1002 sp[0] = sp[-1];
1003 sp += 1;
1004 NEXT_INSN;
1006 insn_dup_x1:
1007 dupx (sp, 1, 1); sp+=1;
1008 NEXT_INSN;
1010 insn_dup_x2:
1011 dupx (sp, 1, 2); sp+=1;
1012 NEXT_INSN;
1014 insn_dup2:
1015 sp[0] = sp[-2];
1016 sp[1] = sp[-1];
1017 sp += 2;
1018 NEXT_INSN;
1020 insn_dup2_x1:
1021 dupx (sp, 2, 1); sp+=2;
1022 NEXT_INSN;
1024 insn_dup2_x2:
1025 dupx (sp, 2, 2); sp+=2;
1026 NEXT_INSN;
1028 insn_swap:
1030 jobject tmp1 = POPA();
1031 jobject tmp2 = POPA();
1032 PUSHA (tmp1);
1033 PUSHA (tmp2);
1035 NEXT_INSN;
1037 insn_iadd:
1038 BINOPI(+);
1039 NEXT_INSN;
1041 insn_ladd:
1042 BINOPL(+);
1043 NEXT_INSN;
1045 insn_fadd:
1046 BINOPF(+);
1047 NEXT_INSN;
1049 insn_dadd:
1050 BINOPD(+);
1051 NEXT_INSN;
1053 insn_isub:
1054 BINOPI(-);
1055 NEXT_INSN;
1057 insn_lsub:
1058 BINOPL(-);
1059 NEXT_INSN;
1061 insn_fsub:
1062 BINOPF(-);
1063 NEXT_INSN;
1065 insn_dsub:
1066 BINOPD(-);
1067 NEXT_INSN;
1069 insn_imul:
1070 BINOPI(*);
1071 NEXT_INSN;
1073 insn_lmul:
1074 BINOPL(*);
1075 NEXT_INSN;
1077 insn_fmul:
1078 BINOPF(*);
1079 NEXT_INSN;
1081 insn_dmul:
1082 BINOPD(*);
1083 NEXT_INSN;
1085 insn_idiv:
1087 SAVE_PC();
1088 jint value2 = POPI();
1089 jint value1 = POPI();
1090 jint res = _Jv_divI (value1, value2);
1091 PUSHI (res);
1093 NEXT_INSN;
1095 insn_ldiv:
1097 SAVE_PC();
1098 jlong value2 = POPL();
1099 jlong value1 = POPL();
1100 jlong res = _Jv_divJ (value1, value2);
1101 PUSHL (res);
1103 NEXT_INSN;
1105 insn_fdiv:
1107 jfloat value2 = POPF();
1108 jfloat value1 = POPF();
1109 jfloat res = value1 / value2;
1110 PUSHF (res);
1112 NEXT_INSN;
1114 insn_ddiv:
1116 jdouble value2 = POPD();
1117 jdouble value1 = POPD();
1118 jdouble res = value1 / value2;
1119 PUSHD (res);
1121 NEXT_INSN;
1123 insn_irem:
1125 SAVE_PC();
1126 jint value2 = POPI();
1127 jint value1 = POPI();
1128 jint res = _Jv_remI (value1, value2);
1129 PUSHI (res);
1131 NEXT_INSN;
1133 insn_lrem:
1135 SAVE_PC();
1136 jlong value2 = POPL();
1137 jlong value1 = POPL();
1138 jlong res = _Jv_remJ (value1, value2);
1139 PUSHL (res);
1141 NEXT_INSN;
1143 insn_frem:
1145 jfloat value2 = POPF();
1146 jfloat value1 = POPF();
1147 jfloat res = __ieee754_fmod (value1, value2);
1148 PUSHF (res);
1150 NEXT_INSN;
1152 insn_drem:
1154 jdouble value2 = POPD();
1155 jdouble value1 = POPD();
1156 jdouble res = __ieee754_fmod (value1, value2);
1157 PUSHD (res);
1159 NEXT_INSN;
1161 insn_ineg:
1163 jint value = POPI();
1164 PUSHI (value * -1);
1166 NEXT_INSN;
1168 insn_lneg:
1170 jlong value = POPL();
1171 PUSHL (value * -1);
1173 NEXT_INSN;
1175 insn_fneg:
1177 jfloat value = POPF();
1178 PUSHF (value * -1);
1180 NEXT_INSN;
1182 insn_dneg:
1184 jdouble value = POPD();
1185 PUSHD (value * -1);
1187 NEXT_INSN;
1189 insn_ishl:
1191 jint shift = (POPI() & 0x1f);
1192 jint value = POPI();
1193 PUSHI (value << shift);
1195 NEXT_INSN;
1197 insn_lshl:
1199 jint shift = (POPI() & 0x3f);
1200 jlong value = POPL();
1201 PUSHL (value << shift);
1203 NEXT_INSN;
1205 insn_ishr:
1207 jint shift = (POPI() & 0x1f);
1208 jint value = POPI();
1209 PUSHI (value >> shift);
1211 NEXT_INSN;
1213 insn_lshr:
1215 jint shift = (POPI() & 0x3f);
1216 jlong value = POPL();
1217 PUSHL (value >> shift);
1219 NEXT_INSN;
1221 insn_iushr:
1223 jint shift = (POPI() & 0x1f);
1224 _Jv_uint value = (_Jv_uint) POPI();
1225 PUSHI ((jint) (value >> shift));
1227 NEXT_INSN;
1229 insn_lushr:
1231 jint shift = (POPI() & 0x3f);
1232 _Jv_ulong value = (_Jv_ulong) POPL();
1233 PUSHL ((jlong) (value >> shift));
1235 NEXT_INSN;
1237 insn_iand:
1238 BINOPI (&);
1239 NEXT_INSN;
1241 insn_land:
1242 BINOPL (&);
1243 NEXT_INSN;
1245 insn_ior:
1246 BINOPI (|);
1247 NEXT_INSN;
1249 insn_lor:
1250 BINOPL (|);
1251 NEXT_INSN;
1253 insn_ixor:
1254 BINOPI (^);
1255 NEXT_INSN;
1257 insn_lxor:
1258 BINOPL (^);
1259 NEXT_INSN;
1261 insn_iinc:
1263 jint index = GET1U ();
1264 jint amount = GET1S ();
1265 locals[index].i += amount;
1267 NEXT_INSN;
1269 insn_i2l:
1270 {jlong value = POPI(); PUSHL (value);}
1271 NEXT_INSN;
1273 insn_i2f:
1274 {jfloat value = POPI(); PUSHF (value);}
1275 NEXT_INSN;
1277 insn_i2d:
1278 {jdouble value = POPI(); PUSHD (value);}
1279 NEXT_INSN;
1281 insn_l2i:
1282 {jint value = POPL(); PUSHI (value);}
1283 NEXT_INSN;
1285 insn_l2f:
1286 {jfloat value = POPL(); PUSHF (value);}
1287 NEXT_INSN;
1289 insn_l2d:
1290 {jdouble value = POPL(); PUSHD (value);}
1291 NEXT_INSN;
1293 insn_f2i:
1295 using namespace java::lang;
1296 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1297 PUSHI(value);
1299 NEXT_INSN;
1301 insn_f2l:
1303 using namespace java::lang;
1304 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1305 PUSHL(value);
1307 NEXT_INSN;
1309 insn_f2d:
1310 { jdouble value = POPF (); PUSHD(value); }
1311 NEXT_INSN;
1313 insn_d2i:
1315 using namespace java::lang;
1316 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1317 PUSHI(value);
1319 NEXT_INSN;
1321 insn_d2l:
1323 using namespace java::lang;
1324 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1325 PUSHL(value);
1327 NEXT_INSN;
1329 insn_d2f:
1330 { jfloat value = POPD (); PUSHF(value); }
1331 NEXT_INSN;
1333 insn_i2b:
1334 { jbyte value = POPI (); PUSHI(value); }
1335 NEXT_INSN;
1337 insn_i2c:
1338 { jchar value = POPI (); PUSHI(value); }
1339 NEXT_INSN;
1341 insn_i2s:
1342 { jshort value = POPI (); PUSHI(value); }
1343 NEXT_INSN;
1345 insn_lcmp:
1347 jlong value2 = POPL ();
1348 jlong value1 = POPL ();
1349 if (value1 > value2)
1350 { PUSHI (1); }
1351 else if (value1 == value2)
1352 { PUSHI (0); }
1353 else
1354 { PUSHI (-1); }
1356 NEXT_INSN;
1358 insn_fcmpl:
1359 tmpval = -1;
1360 goto fcmp;
1362 insn_fcmpg:
1363 tmpval = 1;
1365 fcmp:
1367 jfloat value2 = POPF ();
1368 jfloat value1 = POPF ();
1369 if (value1 > value2)
1370 PUSHI (1);
1371 else if (value1 == value2)
1372 PUSHI (0);
1373 else if (value1 < value2)
1374 PUSHI (-1);
1375 else
1376 PUSHI (tmpval);
1378 NEXT_INSN;
1380 insn_dcmpl:
1381 tmpval = -1;
1382 goto dcmp;
1384 insn_dcmpg:
1385 tmpval = 1;
1387 dcmp:
1389 jdouble value2 = POPD ();
1390 jdouble value1 = POPD ();
1391 if (value1 > value2)
1392 PUSHI (1);
1393 else if (value1 == value2)
1394 PUSHI (0);
1395 else if (value1 < value2)
1396 PUSHI (-1);
1397 else
1398 PUSHI (tmpval);
1400 NEXT_INSN;
1402 insn_ifeq:
1404 if (POPI() == 0)
1405 TAKE_GOTO;
1406 else
1407 SKIP_GOTO;
1409 NEXT_INSN;
1411 insn_ifne:
1413 if (POPI() != 0)
1414 TAKE_GOTO;
1415 else
1416 SKIP_GOTO;
1418 NEXT_INSN;
1420 insn_iflt:
1422 if (POPI() < 0)
1423 TAKE_GOTO;
1424 else
1425 SKIP_GOTO;
1427 NEXT_INSN;
1429 insn_ifge:
1431 if (POPI() >= 0)
1432 TAKE_GOTO;
1433 else
1434 SKIP_GOTO;
1436 NEXT_INSN;
1438 insn_ifgt:
1440 if (POPI() > 0)
1441 TAKE_GOTO;
1442 else
1443 SKIP_GOTO;
1445 NEXT_INSN;
1447 insn_ifle:
1449 if (POPI() <= 0)
1450 TAKE_GOTO;
1451 else
1452 SKIP_GOTO;
1454 NEXT_INSN;
1456 insn_if_icmpeq:
1458 jint value2 = POPI();
1459 jint value1 = POPI();
1460 if (value1 == value2)
1461 TAKE_GOTO;
1462 else
1463 SKIP_GOTO;
1465 NEXT_INSN;
1467 insn_if_icmpne:
1469 jint value2 = POPI();
1470 jint value1 = POPI();
1471 if (value1 != value2)
1472 TAKE_GOTO;
1473 else
1474 SKIP_GOTO;
1476 NEXT_INSN;
1478 insn_if_icmplt:
1480 jint value2 = POPI();
1481 jint value1 = POPI();
1482 if (value1 < value2)
1483 TAKE_GOTO;
1484 else
1485 SKIP_GOTO;
1487 NEXT_INSN;
1489 insn_if_icmpge:
1491 jint value2 = POPI();
1492 jint value1 = POPI();
1493 if (value1 >= value2)
1494 TAKE_GOTO;
1495 else
1496 SKIP_GOTO;
1498 NEXT_INSN;
1500 insn_if_icmpgt:
1502 jint value2 = POPI();
1503 jint value1 = POPI();
1504 if (value1 > value2)
1505 TAKE_GOTO;
1506 else
1507 SKIP_GOTO;
1509 NEXT_INSN;
1511 insn_if_icmple:
1513 jint value2 = POPI();
1514 jint value1 = POPI();
1515 if (value1 <= value2)
1516 TAKE_GOTO;
1517 else
1518 SKIP_GOTO;
1520 NEXT_INSN;
1522 insn_if_acmpeq:
1524 jobject value2 = POPA();
1525 jobject value1 = POPA();
1526 if (value1 == value2)
1527 TAKE_GOTO;
1528 else
1529 SKIP_GOTO;
1531 NEXT_INSN;
1533 insn_if_acmpne:
1535 jobject value2 = POPA();
1536 jobject value1 = POPA();
1537 if (value1 != value2)
1538 TAKE_GOTO;
1539 else
1540 SKIP_GOTO;
1542 NEXT_INSN;
1544 insn_goto_w:
1545 #ifndef DIRECT_THREADED
1546 // For direct threaded, goto and goto_w are the same.
1547 pc = pc - 1 + get4 (pc);
1548 NEXT_INSN;
1549 #endif /* DIRECT_THREADED */
1550 insn_goto:
1551 TAKE_GOTO;
1552 NEXT_INSN;
1554 insn_jsr_w:
1555 #ifndef DIRECT_THREADED
1556 // For direct threaded, jsr and jsr_w are the same.
1558 pc_t next = pc - 1 + get4 (pc);
1559 pc += 4;
1560 PUSHA ((jobject) pc);
1561 pc = next;
1563 NEXT_INSN;
1564 #endif /* DIRECT_THREADED */
1565 insn_jsr:
1567 pc_t next = GOTO_VAL();
1568 SKIP_GOTO;
1569 PUSHA ((jobject) pc);
1570 pc = next;
1572 NEXT_INSN;
1574 insn_ret:
1576 jint index = GET1U ();
1577 pc = (pc_t) PEEKA (index);
1579 NEXT_INSN;
1581 insn_tableswitch:
1583 #ifdef DIRECT_THREADED
1584 void *def = (pc++)->datum;
1586 int index = POPI();
1588 jint low = INTVAL ();
1589 jint high = INTVAL ();
1591 if (index < low || index > high)
1592 pc = (insn_slot *) def;
1593 else
1594 pc = (insn_slot *) ((pc + index - low)->datum);
1595 #else
1596 pc_t base_pc = pc - 1;
1597 int index = POPI ();
1599 pc_t base = (pc_t) meth->bytecode ();
1600 while ((pc - base) % 4 != 0)
1601 ++pc;
1603 jint def = get4 (pc);
1604 jint low = get4 (pc + 4);
1605 jint high = get4 (pc + 8);
1606 if (index < low || index > high)
1607 pc = base_pc + def;
1608 else
1609 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1610 #endif /* DIRECT_THREADED */
1612 NEXT_INSN;
1614 insn_lookupswitch:
1616 #ifdef DIRECT_THREADED
1617 void *def = (pc++)->insn;
1619 int index = POPI();
1621 jint npairs = INTVAL ();
1623 int max = npairs - 1;
1624 int min = 0;
1626 // Simple binary search...
1627 while (min < max)
1629 int half = (min + max) / 2;
1630 int match = pc[2 * half].int_val;
1632 if (index == match)
1634 // Found it.
1635 pc = (insn_slot *) pc[2 * half + 1].datum;
1636 NEXT_INSN;
1638 else if (index < match)
1639 // We can use HALF - 1 here because we check again on
1640 // loop exit.
1641 max = half - 1;
1642 else
1643 // We can use HALF + 1 here because we check again on
1644 // loop exit.
1645 min = half + 1;
1647 if (index == pc[2 * min].int_val)
1648 pc = (insn_slot *) pc[2 * min + 1].datum;
1649 else
1650 pc = (insn_slot *) def;
1651 #else
1652 unsigned char *base_pc = pc-1;
1653 int index = POPI();
1655 unsigned char* base = meth->bytecode ();
1656 while ((pc-base) % 4 != 0)
1657 ++pc;
1659 jint def = get4 (pc);
1660 jint npairs = get4 (pc+4);
1662 int max = npairs-1;
1663 int min = 0;
1665 // Simple binary search...
1666 while (min < max)
1668 int half = (min+max)/2;
1669 int match = get4 (pc+ 4*(2 + 2*half));
1671 if (index == match)
1672 min = max = half;
1673 else if (index < match)
1674 // We can use HALF - 1 here because we check again on
1675 // loop exit.
1676 max = half - 1;
1677 else
1678 // We can use HALF + 1 here because we check again on
1679 // loop exit.
1680 min = half + 1;
1683 if (index == get4 (pc+ 4*(2 + 2*min)))
1684 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1685 else
1686 pc = base_pc + def;
1687 #endif /* DIRECT_THREADED */
1689 NEXT_INSN;
1691 insn_areturn:
1692 *(jobject *) retp = POPA ();
1693 return;
1695 insn_lreturn:
1696 *(jlong *) retp = POPL ();
1697 return;
1699 insn_freturn:
1700 *(jfloat *) retp = POPF ();
1701 return;
1703 insn_dreturn:
1704 *(jdouble *) retp = POPD ();
1705 return;
1707 insn_ireturn:
1708 *(jint *) retp = POPI ();
1709 return;
1711 insn_return:
1712 return;
1714 insn_getstatic:
1716 jint fieldref_index = GET2U ();
1717 SAVE_PC(); // Constant pool resolution could throw.
1718 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1719 _Jv_Field *field = pool_data[fieldref_index].field;
1721 if ((field->flags & Modifier::STATIC) == 0)
1722 throw_incompatible_class_change_error
1723 (JvNewStringLatin1 ("field no longer static"));
1725 jclass type = field->type;
1727 // We rewrite the instruction once we discover what it refers
1728 // to.
1729 void *newinsn = NULL;
1730 if (type->isPrimitive ())
1732 switch (type->size_in_bytes)
1734 case 1:
1735 PUSHI (*field->u.byte_addr);
1736 newinsn = AMPAMP (getstatic_resolved_1);
1737 break;
1739 case 2:
1740 if (type == JvPrimClass (char))
1742 PUSHI (*field->u.char_addr);
1743 newinsn = AMPAMP (getstatic_resolved_char);
1745 else
1747 PUSHI (*field->u.short_addr);
1748 newinsn = AMPAMP (getstatic_resolved_short);
1750 break;
1752 case 4:
1753 PUSHI(*field->u.int_addr);
1754 newinsn = AMPAMP (getstatic_resolved_4);
1755 break;
1757 case 8:
1758 PUSHL(*field->u.long_addr);
1759 newinsn = AMPAMP (getstatic_resolved_8);
1760 break;
1763 else
1765 PUSHA(*field->u.object_addr);
1766 newinsn = AMPAMP (getstatic_resolved_obj);
1769 #ifdef DIRECT_THREADED
1770 pc[-2].insn = newinsn;
1771 pc[-1].datum = field->u.addr;
1772 #endif /* DIRECT_THREADED */
1774 NEXT_INSN;
1776 #ifdef DIRECT_THREADED
1777 getstatic_resolved_1:
1778 PUSHI (*(jbyte *) AVAL ());
1779 NEXT_INSN;
1781 getstatic_resolved_char:
1782 PUSHI (*(jchar *) AVAL ());
1783 NEXT_INSN;
1785 getstatic_resolved_short:
1786 PUSHI (*(jshort *) AVAL ());
1787 NEXT_INSN;
1789 getstatic_resolved_4:
1790 PUSHI (*(jint *) AVAL ());
1791 NEXT_INSN;
1793 getstatic_resolved_8:
1794 PUSHL (*(jlong *) AVAL ());
1795 NEXT_INSN;
1797 getstatic_resolved_obj:
1798 PUSHA (*(jobject *) AVAL ());
1799 NEXT_INSN;
1800 #endif /* DIRECT_THREADED */
1802 insn_getfield:
1804 SAVE_PC();
1805 jint fieldref_index = GET2U ();
1806 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1807 _Jv_Field *field = pool_data[fieldref_index].field;
1809 if ((field->flags & Modifier::STATIC) != 0)
1810 throw_incompatible_class_change_error
1811 (JvNewStringLatin1 ("field is static"));
1813 jclass type = field->type;
1814 jint field_offset = field->u.boffset;
1816 jobject obj = POPA();
1817 NULLCHECK(obj);
1819 void *newinsn = NULL;
1820 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1821 if (type->isPrimitive ())
1823 switch (type->size_in_bytes)
1825 case 1:
1826 PUSHI (val->byte_value);
1827 newinsn = AMPAMP (getfield_resolved_1);
1828 break;
1830 case 2:
1831 if (type == JvPrimClass (char))
1833 PUSHI (val->char_value);
1834 newinsn = AMPAMP (getfield_resolved_char);
1836 else
1838 PUSHI (val->short_value);
1839 newinsn = AMPAMP (getfield_resolved_short);
1841 break;
1843 case 4:
1844 PUSHI (val->int_value);
1845 newinsn = AMPAMP (getfield_resolved_4);
1846 break;
1848 case 8:
1849 PUSHL (val->long_value);
1850 newinsn = AMPAMP (getfield_resolved_8);
1851 break;
1854 else
1856 PUSHA (val->object_value);
1857 newinsn = AMPAMP (getfield_resolved_obj);
1860 #ifdef DIRECT_THREADED
1861 pc[-2].insn = newinsn;
1862 pc[-1].int_val = field_offset;
1863 #endif /* DIRECT_THREADED */
1865 NEXT_INSN;
1867 #ifdef DIRECT_THREADED
1868 getfield_resolved_1:
1870 char *obj = (char *) POPA ();
1871 NULLCHECK (obj);
1872 PUSHI (*(jbyte *) (obj + INTVAL ()));
1874 NEXT_INSN;
1876 getfield_resolved_char:
1878 char *obj = (char *) POPA ();
1879 NULLCHECK (obj);
1880 PUSHI (*(jchar *) (obj + INTVAL ()));
1882 NEXT_INSN;
1884 getfield_resolved_short:
1886 char *obj = (char *) POPA ();
1887 NULLCHECK (obj);
1888 PUSHI (*(jshort *) (obj + INTVAL ()));
1890 NEXT_INSN;
1892 getfield_resolved_4:
1894 char *obj = (char *) POPA ();
1895 NULLCHECK (obj);
1896 PUSHI (*(jint *) (obj + INTVAL ()));
1898 NEXT_INSN;
1900 getfield_resolved_8:
1902 char *obj = (char *) POPA ();
1903 NULLCHECK (obj);
1904 PUSHL (*(jlong *) (obj + INTVAL ()));
1906 NEXT_INSN;
1908 getfield_resolved_obj:
1910 char *obj = (char *) POPA ();
1911 NULLCHECK (obj);
1912 PUSHA (*(jobject *) (obj + INTVAL ()));
1914 NEXT_INSN;
1915 #endif /* DIRECT_THREADED */
1917 insn_putstatic:
1919 SAVE_PC();
1920 jint fieldref_index = GET2U ();
1921 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1922 _Jv_Field *field = pool_data[fieldref_index].field;
1924 jclass type = field->type;
1926 // ResolvePoolEntry cannot check this
1927 if ((field->flags & Modifier::STATIC) == 0)
1928 throw_incompatible_class_change_error
1929 (JvNewStringLatin1 ("field no longer static"));
1931 void *newinsn = NULL;
1932 if (type->isPrimitive ())
1934 switch (type->size_in_bytes)
1936 case 1:
1938 jint value = POPI();
1939 *field->u.byte_addr = value;
1940 newinsn = AMPAMP (putstatic_resolved_1);
1941 break;
1944 case 2:
1946 jint value = POPI();
1947 *field->u.char_addr = value;
1948 newinsn = AMPAMP (putstatic_resolved_2);
1949 break;
1952 case 4:
1954 jint value = POPI();
1955 *field->u.int_addr = value;
1956 newinsn = AMPAMP (putstatic_resolved_4);
1957 break;
1960 case 8:
1962 jlong value = POPL();
1963 *field->u.long_addr = value;
1964 newinsn = AMPAMP (putstatic_resolved_8);
1965 break;
1969 else
1971 jobject value = POPA();
1972 *field->u.object_addr = value;
1973 newinsn = AMPAMP (putstatic_resolved_obj);
1976 #ifdef DIRECT_THREADED
1977 pc[-2].insn = newinsn;
1978 pc[-1].datum = field->u.addr;
1979 #endif /* DIRECT_THREADED */
1981 NEXT_INSN;
1983 #ifdef DIRECT_THREADED
1984 putstatic_resolved_1:
1985 *(jbyte *) AVAL () = POPI ();
1986 NEXT_INSN;
1988 putstatic_resolved_2:
1989 *(jchar *) AVAL () = POPI ();
1990 NEXT_INSN;
1992 putstatic_resolved_4:
1993 *(jint *) AVAL () = POPI ();
1994 NEXT_INSN;
1996 putstatic_resolved_8:
1997 *(jlong *) AVAL () = POPL ();
1998 NEXT_INSN;
2000 putstatic_resolved_obj:
2001 *(jobject *) AVAL () = POPA ();
2002 NEXT_INSN;
2003 #endif /* DIRECT_THREADED */
2005 insn_putfield:
2007 SAVE_PC();
2008 jint fieldref_index = GET2U ();
2009 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2010 _Jv_Field *field = pool_data[fieldref_index].field;
2012 jclass type = field->type;
2014 if ((field->flags & Modifier::STATIC) != 0)
2015 throw_incompatible_class_change_error
2016 (JvNewStringLatin1 ("field is static"));
2018 jint field_offset = field->u.boffset;
2020 void *newinsn = NULL;
2021 if (type->isPrimitive ())
2023 switch (type->size_in_bytes)
2025 case 1:
2027 jint value = POPI();
2028 jobject obj = POPA();
2029 NULLCHECK(obj);
2030 *(jbyte*) ((char*)obj + field_offset) = value;
2031 newinsn = AMPAMP (putfield_resolved_1);
2032 break;
2035 case 2:
2037 jint value = POPI();
2038 jobject obj = POPA();
2039 NULLCHECK(obj);
2040 *(jchar*) ((char*)obj + field_offset) = value;
2041 newinsn = AMPAMP (putfield_resolved_2);
2042 break;
2045 case 4:
2047 jint value = POPI();
2048 jobject obj = POPA();
2049 NULLCHECK(obj);
2050 *(jint*) ((char*)obj + field_offset) = value;
2051 newinsn = AMPAMP (putfield_resolved_4);
2052 break;
2055 case 8:
2057 jlong value = POPL();
2058 jobject obj = POPA();
2059 NULLCHECK(obj);
2060 *(jlong*) ((char*)obj + field_offset) = value;
2061 newinsn = AMPAMP (putfield_resolved_8);
2062 break;
2066 else
2068 jobject value = POPA();
2069 jobject obj = POPA();
2070 NULLCHECK(obj);
2071 *(jobject*) ((char*)obj + field_offset) = value;
2072 newinsn = AMPAMP (putfield_resolved_obj);
2075 #ifdef DIRECT_THREADED
2076 pc[-2].insn = newinsn;
2077 pc[-1].int_val = field_offset;
2078 #endif /* DIRECT_THREADED */
2080 NEXT_INSN;
2082 #ifdef DIRECT_THREADED
2083 putfield_resolved_1:
2085 jint val = POPI ();
2086 char *obj = (char *) POPA ();
2087 NULLCHECK (obj);
2088 *(jbyte *) (obj + INTVAL ()) = val;
2090 NEXT_INSN;
2092 putfield_resolved_2:
2094 jint val = POPI ();
2095 char *obj = (char *) POPA ();
2096 NULLCHECK (obj);
2097 *(jchar *) (obj + INTVAL ()) = val;
2099 NEXT_INSN;
2101 putfield_resolved_4:
2103 jint val = POPI ();
2104 char *obj = (char *) POPA ();
2105 NULLCHECK (obj);
2106 *(jint *) (obj + INTVAL ()) = val;
2108 NEXT_INSN;
2110 putfield_resolved_8:
2112 jlong val = POPL ();
2113 char *obj = (char *) POPA ();
2114 NULLCHECK (obj);
2115 *(jlong *) (obj + INTVAL ()) = val;
2117 NEXT_INSN;
2119 putfield_resolved_obj:
2121 jobject val = POPA ();
2122 char *obj = (char *) POPA ();
2123 NULLCHECK (obj);
2124 *(jobject *) (obj + INTVAL ()) = val;
2126 NEXT_INSN;
2127 #endif /* DIRECT_THREADED */
2129 insn_invokespecial:
2131 SAVE_PC();
2132 int index = GET2U ();
2134 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2135 index)).rmethod;
2137 sp -= rmeth->stack_item_count;
2139 // We don't use NULLCHECK here because we can't rely on that
2140 // working for <init>. So instead we do an explicit test.
2141 if (! sp[0].o)
2143 SAVE_PC();
2144 throw_null_pointer_exception ();
2147 fun = (void (*)()) rmeth->method->ncode;
2149 #ifdef DIRECT_THREADED
2150 // Rewrite instruction so that we use a faster pre-resolved
2151 // method.
2152 pc[-2].insn = &&invokespecial_resolved;
2153 pc[-1].datum = rmeth;
2154 #endif /* DIRECT_THREADED */
2156 goto perform_invoke;
2158 #ifdef DIRECT_THREADED
2159 invokespecial_resolved:
2161 SAVE_PC();
2162 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2163 sp -= rmeth->stack_item_count;
2164 // We don't use NULLCHECK here because we can't rely on that
2165 // working for <init>. So instead we do an explicit test.
2166 if (! sp[0].o)
2168 throw_null_pointer_exception ();
2170 fun = (void (*)()) rmeth->method->ncode;
2172 goto perform_invoke;
2173 #endif /* DIRECT_THREADED */
2175 insn_invokestatic:
2177 SAVE_PC();
2178 int index = GET2U ();
2180 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2181 index)).rmethod;
2183 sp -= rmeth->stack_item_count;
2185 fun = (void (*)()) rmeth->method->ncode;
2187 #ifdef DIRECT_THREADED
2188 // Rewrite instruction so that we use a faster pre-resolved
2189 // method.
2190 pc[-2].insn = &&invokestatic_resolved;
2191 pc[-1].datum = rmeth;
2192 #endif /* DIRECT_THREADED */
2194 goto perform_invoke;
2196 #ifdef DIRECT_THREADED
2197 invokestatic_resolved:
2199 SAVE_PC();
2200 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2201 sp -= rmeth->stack_item_count;
2202 fun = (void (*)()) rmeth->method->ncode;
2204 goto perform_invoke;
2205 #endif /* DIRECT_THREADED */
2207 insn_invokeinterface:
2209 SAVE_PC();
2210 int index = GET2U ();
2212 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2213 index)).rmethod;
2215 sp -= rmeth->stack_item_count;
2217 jobject rcv = sp[0].o;
2219 NULLCHECK (rcv);
2221 fun = (void (*)())
2222 _Jv_LookupInterfaceMethod (rcv->getClass (),
2223 rmeth->method->name,
2224 rmeth->method->signature);
2226 #ifdef DIRECT_THREADED
2227 // Rewrite instruction so that we use a faster pre-resolved
2228 // method.
2229 pc[-2].insn = &&invokeinterface_resolved;
2230 pc[-1].datum = rmeth;
2231 #else
2232 // Skip dummy bytes.
2233 pc += 2;
2234 #endif /* DIRECT_THREADED */
2236 goto perform_invoke;
2238 #ifdef DIRECT_THREADED
2239 invokeinterface_resolved:
2241 SAVE_PC();
2242 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2243 sp -= rmeth->stack_item_count;
2244 jobject rcv = sp[0].o;
2245 NULLCHECK (rcv);
2246 fun = (void (*)())
2247 _Jv_LookupInterfaceMethod (rcv->getClass (),
2248 rmeth->method->name,
2249 rmeth->method->signature);
2251 goto perform_invoke;
2252 #endif /* DIRECT_THREADED */
2254 insn_new:
2256 SAVE_PC();
2257 int index = GET2U ();
2258 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2259 index)).clazz;
2260 /* VM spec, section 3.11.5 */
2261 if ((klass->getModifiers() & Modifier::ABSTRACT)
2262 || klass->isInterface())
2263 throw new java::lang::InstantiationException;
2264 jobject res = _Jv_AllocObject (klass);
2265 PUSHA (res);
2267 #ifdef DIRECT_THREADED
2268 pc[-2].insn = &&new_resolved;
2269 pc[-1].datum = klass;
2270 #endif /* DIRECT_THREADED */
2272 NEXT_INSN;
2274 #ifdef DIRECT_THREADED
2275 new_resolved:
2277 jclass klass = (jclass) AVAL ();
2278 jobject res = _Jv_AllocObject (klass);
2279 PUSHA (res);
2281 NEXT_INSN;
2282 #endif /* DIRECT_THREADED */
2284 insn_newarray:
2286 int atype = GET1U ();
2287 int size = POPI();
2288 jobject result = _Jv_NewArray (atype, size);
2289 PUSHA (result);
2291 NEXT_INSN;
2293 insn_anewarray:
2295 SAVE_PC();
2296 int index = GET2U ();
2297 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2298 index)).clazz;
2299 int size = POPI();
2300 jobject result = _Jv_NewObjectArray (size, klass, 0);
2301 PUSHA (result);
2303 #ifdef DIRECT_THREADED
2304 pc[-2].insn = &&anewarray_resolved;
2305 pc[-1].datum = klass;
2306 #endif /* DIRECT_THREADED */
2308 NEXT_INSN;
2310 #ifdef DIRECT_THREADED
2311 anewarray_resolved:
2313 jclass klass = (jclass) AVAL ();
2314 int size = POPI ();
2315 jobject result = _Jv_NewObjectArray (size, klass, 0);
2316 PUSHA (result);
2318 NEXT_INSN;
2319 #endif /* DIRECT_THREADED */
2321 insn_arraylength:
2323 __JArray *arr = (__JArray*)POPA();
2324 NULLARRAYCHECK (arr);
2325 PUSHI (arr->length);
2327 NEXT_INSN;
2329 insn_athrow:
2331 jobject value = POPA();
2332 throw static_cast<jthrowable>(value);
2334 NEXT_INSN;
2336 insn_checkcast:
2338 SAVE_PC();
2339 jobject value = POPA();
2340 jint index = GET2U ();
2341 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2342 index)).clazz;
2344 value = (jobject) _Jv_CheckCast (to, value);
2346 PUSHA (value);
2348 #ifdef DIRECT_THREADED
2349 pc[-2].insn = &&checkcast_resolved;
2350 pc[-1].datum = to;
2351 #endif /* DIRECT_THREADED */
2353 NEXT_INSN;
2355 #ifdef DIRECT_THREADED
2356 checkcast_resolved:
2358 SAVE_PC();
2359 jobject value = POPA ();
2360 jclass to = (jclass) AVAL ();
2361 value = (jobject) _Jv_CheckCast (to, value);
2362 PUSHA (value);
2364 NEXT_INSN;
2365 #endif /* DIRECT_THREADED */
2367 insn_instanceof:
2369 SAVE_PC();
2370 jobject value = POPA();
2371 jint index = GET2U ();
2372 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2373 index)).clazz;
2374 PUSHI (to->isInstance (value));
2376 #ifdef DIRECT_THREADED
2377 pc[-2].insn = &&instanceof_resolved;
2378 pc[-1].datum = to;
2379 #endif /* DIRECT_THREADED */
2381 NEXT_INSN;
2383 #ifdef DIRECT_THREADED
2384 instanceof_resolved:
2386 jobject value = POPA ();
2387 jclass to = (jclass) AVAL ();
2388 PUSHI (to->isInstance (value));
2390 NEXT_INSN;
2391 #endif /* DIRECT_THREADED */
2393 insn_monitorenter:
2395 jobject value = POPA();
2396 NULLCHECK(value);
2397 _Jv_MonitorEnter (value);
2399 NEXT_INSN;
2401 insn_monitorexit:
2403 jobject value = POPA();
2404 NULLCHECK(value);
2405 _Jv_MonitorExit (value);
2407 NEXT_INSN;
2409 insn_ifnull:
2411 jobject val = POPA();
2412 if (val == NULL)
2413 TAKE_GOTO;
2414 else
2415 SKIP_GOTO;
2417 NEXT_INSN;
2419 insn_ifnonnull:
2421 jobject val = POPA();
2422 if (val != NULL)
2423 TAKE_GOTO;
2424 else
2425 SKIP_GOTO;
2427 NEXT_INSN;
2429 insn_multianewarray:
2431 SAVE_PC();
2432 int kind_index = GET2U ();
2433 int dim = GET1U ();
2435 jclass type
2436 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2437 kind_index)).clazz;
2438 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2440 for (int i = dim - 1; i >= 0; i--)
2442 sizes[i] = POPI ();
2445 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2447 PUSHA (res);
2449 NEXT_INSN;
2451 #ifndef DIRECT_THREADED
2452 insn_wide:
2454 jint the_mod_op = get1u (pc++);
2455 jint wide = get2u (pc); pc += 2;
2457 switch (the_mod_op)
2459 case op_istore:
2460 STOREI (wide);
2461 NEXT_INSN;
2463 case op_fstore:
2464 STOREF (wide);
2465 NEXT_INSN;
2467 case op_astore:
2468 STOREA (wide);
2469 NEXT_INSN;
2471 case op_lload:
2472 LOADL (wide);
2473 NEXT_INSN;
2475 case op_dload:
2476 LOADD (wide);
2477 NEXT_INSN;
2479 case op_iload:
2480 LOADI (wide);
2481 NEXT_INSN;
2483 case op_fload:
2484 LOADF (wide);
2485 NEXT_INSN;
2487 case op_aload:
2488 LOADA (wide);
2489 NEXT_INSN;
2491 case op_lstore:
2492 STOREL (wide);
2493 NEXT_INSN;
2495 case op_dstore:
2496 STORED (wide);
2497 NEXT_INSN;
2499 case op_ret:
2500 pc = (unsigned char*) PEEKA (wide);
2501 NEXT_INSN;
2503 case op_iinc:
2505 jint amount = get2s (pc); pc += 2;
2506 jint value = PEEKI (wide);
2507 POKEI (wide, value+amount);
2509 NEXT_INSN;
2511 default:
2512 throw_internal_error ("illegal bytecode modified by wide");
2516 #endif /* DIRECT_THREADED */
2518 insn_breakpoint:
2520 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2522 // Send JVMTI notification
2523 using namespace ::java::lang;
2524 jmethodID method = meth->self;
2525 jlocation location = meth->insn_index (pc - 1);
2526 Thread *thread = Thread::currentThread ();
2527 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2529 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2530 method, location);
2532 // Continue execution
2533 using namespace gnu::gcj::jvmti;
2534 Breakpoint *bp
2535 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2536 location);
2537 JvAssert (bp != NULL);
2539 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2541 #ifdef DIRECT_THREADED
2542 goto *(opc->insn);
2543 #else
2544 goto *(insn_target[*opc]);
2545 #endif
2548 catch (java::lang::Throwable *ex)
2550 #ifdef DEBUG
2551 // This needs to be done before the pc is changed.
2552 jlong throw_loc = meth->insn_index (pc);
2553 #endif
2554 // Check if the exception is handled and, if so, set the pc to the start
2555 // of the appropriate catch block.
2556 if (meth->check_handler (&pc, meth, ex))
2558 sp = stack;
2559 sp++->o = ex; // Push exception.
2560 #ifdef DEBUG
2561 if (JVMTI_REQUESTED_EVENT (Exception))
2563 using namespace gnu::gcj::jvmti;
2564 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2565 jlong catch_loc = meth->insn_index (pc);
2566 ExceptionEvent::postExceptionEvent (thread, throw_meth,
2567 throw_loc, ex, throw_meth,
2568 catch_loc);
2570 #endif
2571 NEXT_INSN;
2573 #ifdef DEBUG
2574 if (JVMTI_REQUESTED_EVENT (Exception))
2576 using namespace gnu::gcj::jvmti;
2577 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2578 ExceptionEvent::postExceptionEvent (thread, throw_meth, throw_loc,
2579 ex, NULL, NULL);
2581 #endif
2582 // No handler, so re-throw.
2583 throw ex;