./:
[official-gcc.git] / libjava / interpret-run.cc
blobb98092efb1aaf9ef89f1593b91317b533a11595f
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 #ifdef DEBUG
353 // Get the object pointer for this method, after checking that it is
354 // non-static.
355 _Jv_Method *method = meth->get_method ();
357 if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
358 frame_desc.obj_ptr = locals[0].o;
359 #endif
361 _Jv_word *pool_data = meth->defining_class->constants.data;
363 /* These three are temporaries for common code used by several
364 instructions. */
365 void (*fun)();
366 _Jv_ResolvedMethod* rmeth;
367 int tmpval;
371 // We keep nop around. It is used if we're interpreting the
372 // bytecodes and not doing direct threading.
373 insn_nop:
374 NEXT_INSN;
376 /* The first few instructions here are ordered according to their
377 frequency, in the hope that this will improve code locality a
378 little. */
380 insn_aload_0: // 0x2a
381 LOADA (0);
382 NEXT_INSN;
384 insn_iload: // 0x15
385 LOADI (GET1U ());
386 NEXT_INSN;
388 insn_iload_1: // 0x1b
389 LOADI (1);
390 NEXT_INSN;
392 insn_invokevirtual: // 0xb6
394 SAVE_PC();
395 int index = GET2U ();
397 /* _Jv_Linker::resolve_pool_entry returns immediately if the
398 * value already is resolved. If we want to clutter up the
399 * code here to gain a little performance, then we can check
400 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
401 * directly. For now, I don't think it is worth it. */
403 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
404 index)).rmethod;
406 sp -= rmeth->stack_item_count;
408 if (rmeth->method->accflags & Modifier::FINAL)
410 // We can't rely on NULLCHECK working if the method is final.
411 if (! sp[0].o)
412 throw_null_pointer_exception ();
414 // Final methods might not appear in the vtable.
415 fun = (void (*)()) rmeth->method->ncode;
417 else
419 NULLCHECK (sp[0].o);
420 jobject rcv = sp[0].o;
421 _Jv_VTable *table = *(_Jv_VTable**) rcv;
422 fun = (void (*)()) table->get_method (rmeth->method->index);
425 #ifdef DIRECT_THREADED
426 // Rewrite instruction so that we use a faster pre-resolved
427 // method.
428 pc[-2].insn = &&invokevirtual_resolved;
429 pc[-1].datum = rmeth;
430 #endif /* DIRECT_THREADED */
432 goto perform_invoke;
434 #ifdef DIRECT_THREADED
435 invokevirtual_resolved:
437 SAVE_PC();
438 rmeth = (_Jv_ResolvedMethod *) AVAL ();
439 sp -= rmeth->stack_item_count;
441 if (rmeth->method->accflags & Modifier::FINAL)
443 // We can't rely on NULLCHECK working if the method is final.
444 if (! sp[0].o)
445 throw_null_pointer_exception ();
447 // Final methods might not appear in the vtable.
448 fun = (void (*)()) rmeth->method->ncode;
450 else
452 jobject rcv = sp[0].o;
453 _Jv_VTable *table = *(_Jv_VTable**) rcv;
454 fun = (void (*)()) table->get_method (rmeth->method->index);
457 goto perform_invoke;
458 #endif /* DIRECT_THREADED */
460 perform_invoke:
462 /* here goes the magic again... */
463 ffi_cif *cif = &rmeth->cif;
464 ffi_raw *raw = (ffi_raw*) sp;
466 _Jv_value rvalue;
468 #if FFI_NATIVE_RAW_API
469 /* We assume that this is only implemented if it's correct */
470 /* to use it here. On a 64 bit machine, it never is. */
471 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
472 #else
473 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
474 #endif
476 int rtype = cif->rtype->type;
478 /* the likelyhood of object, int, or void return is very high,
479 * so those are checked before the switch */
480 if (rtype == FFI_TYPE_POINTER)
482 PUSHA (rvalue.object_value);
484 else if (rtype == FFI_TYPE_SINT32)
486 PUSHI (rvalue.int_value);
488 else if (rtype == FFI_TYPE_VOID)
490 /* skip */
492 else
494 switch (rtype)
496 case FFI_TYPE_SINT8:
497 PUSHI ((jbyte)(rvalue.int_value & 0xff));
498 break;
500 case FFI_TYPE_SINT16:
501 PUSHI ((jshort)(rvalue.int_value & 0xffff));
502 break;
504 case FFI_TYPE_UINT16:
505 PUSHI (rvalue.int_value & 0xffff);
506 break;
508 case FFI_TYPE_FLOAT:
509 PUSHF (rvalue.float_value);
510 break;
512 case FFI_TYPE_DOUBLE:
513 PUSHD (rvalue.double_value);
514 break;
516 case FFI_TYPE_SINT64:
517 PUSHL (rvalue.long_value);
518 break;
520 default:
521 throw_internal_error ("unknown return type in invokeXXX");
525 NEXT_INSN;
527 insn_aconst_null:
528 PUSHA (NULL);
529 NEXT_INSN;
531 insn_iconst_m1:
532 PUSHI (-1);
533 NEXT_INSN;
535 insn_iconst_0:
536 PUSHI (0);
537 NEXT_INSN;
539 insn_iconst_1:
540 PUSHI (1);
541 NEXT_INSN;
543 insn_iconst_2:
544 PUSHI (2);
545 NEXT_INSN;
547 insn_iconst_3:
548 PUSHI (3);
549 NEXT_INSN;
551 insn_iconst_4:
552 PUSHI (4);
553 NEXT_INSN;
555 insn_iconst_5:
556 PUSHI (5);
557 NEXT_INSN;
559 insn_lconst_0:
560 PUSHL (0);
561 NEXT_INSN;
563 insn_lconst_1:
564 PUSHL (1);
565 NEXT_INSN;
567 insn_fconst_0:
568 PUSHF (0);
569 NEXT_INSN;
571 insn_fconst_1:
572 PUSHF (1);
573 NEXT_INSN;
575 insn_fconst_2:
576 PUSHF (2);
577 NEXT_INSN;
579 insn_dconst_0:
580 PUSHD (0);
581 NEXT_INSN;
583 insn_dconst_1:
584 PUSHD (1);
585 NEXT_INSN;
587 insn_bipush:
588 // For direct threaded, bipush and sipush are the same.
589 #ifndef DIRECT_THREADED
590 PUSHI (GET1S ());
591 NEXT_INSN;
592 #endif /* DIRECT_THREADED */
593 insn_sipush:
594 PUSHI (GET2S ());
595 NEXT_INSN;
597 insn_ldc:
598 // For direct threaded, ldc and ldc_w are the same.
599 #ifndef DIRECT_THREADED
600 PUSHA ((jobject) AVAL1U ());
601 NEXT_INSN;
602 #endif /* DIRECT_THREADED */
603 insn_ldc_w:
604 PUSHA ((jobject) AVAL2U ());
605 NEXT_INSN;
607 #ifdef DIRECT_THREADED
608 // For direct threaded we have a separate 'ldc class' operation.
609 insn_ldc_class:
611 SAVE_PC();
612 // We could rewrite the instruction at this point.
613 int index = INTVAL ();
614 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
615 index)).o;
616 PUSHA (k);
618 NEXT_INSN;
619 #endif /* DIRECT_THREADED */
621 insn_ldc2_w:
623 void *where = AVAL2UP ();
624 memcpy (sp, where, 2*sizeof (_Jv_word));
625 sp += 2;
627 NEXT_INSN;
629 insn_lload:
630 LOADL (GET1U ());
631 NEXT_INSN;
633 insn_fload:
634 LOADF (GET1U ());
635 NEXT_INSN;
637 insn_dload:
638 LOADD (GET1U ());
639 NEXT_INSN;
641 insn_aload:
642 LOADA (GET1U ());
643 NEXT_INSN;
645 insn_iload_0:
646 LOADI (0);
647 NEXT_INSN;
649 insn_iload_2:
650 LOADI (2);
651 NEXT_INSN;
653 insn_iload_3:
654 LOADI (3);
655 NEXT_INSN;
657 insn_lload_0:
658 LOADL (0);
659 NEXT_INSN;
661 insn_lload_1:
662 LOADL (1);
663 NEXT_INSN;
665 insn_lload_2:
666 LOADL (2);
667 NEXT_INSN;
669 insn_lload_3:
670 LOADL (3);
671 NEXT_INSN;
673 insn_fload_0:
674 LOADF (0);
675 NEXT_INSN;
677 insn_fload_1:
678 LOADF (1);
679 NEXT_INSN;
681 insn_fload_2:
682 LOADF (2);
683 NEXT_INSN;
685 insn_fload_3:
686 LOADF (3);
687 NEXT_INSN;
689 insn_dload_0:
690 LOADD (0);
691 NEXT_INSN;
693 insn_dload_1:
694 LOADD (1);
695 NEXT_INSN;
697 insn_dload_2:
698 LOADD (2);
699 NEXT_INSN;
701 insn_dload_3:
702 LOADD (3);
703 NEXT_INSN;
705 insn_aload_1:
706 LOADA(1);
707 NEXT_INSN;
709 insn_aload_2:
710 LOADA(2);
711 NEXT_INSN;
713 insn_aload_3:
714 LOADA(3);
715 NEXT_INSN;
717 insn_iaload:
719 jint index = POPI();
720 jintArray arr = (jintArray) POPA();
721 NULLARRAYCHECK (arr);
722 ARRAYBOUNDSCHECK (arr, index);
723 PUSHI( elements(arr)[index] );
725 NEXT_INSN;
727 insn_laload:
729 jint index = POPI();
730 jlongArray arr = (jlongArray) POPA();
731 NULLARRAYCHECK (arr);
732 ARRAYBOUNDSCHECK (arr, index);
733 PUSHL( elements(arr)[index] );
735 NEXT_INSN;
737 insn_faload:
739 jint index = POPI();
740 jfloatArray arr = (jfloatArray) POPA();
741 NULLARRAYCHECK (arr);
742 ARRAYBOUNDSCHECK (arr, index);
743 PUSHF( elements(arr)[index] );
745 NEXT_INSN;
747 insn_daload:
749 jint index = POPI();
750 jdoubleArray arr = (jdoubleArray) POPA();
751 NULLARRAYCHECK (arr);
752 ARRAYBOUNDSCHECK (arr, index);
753 PUSHD( elements(arr)[index] );
755 NEXT_INSN;
757 insn_aaload:
759 jint index = POPI();
760 jobjectArray arr = (jobjectArray) POPA();
761 NULLARRAYCHECK (arr);
762 ARRAYBOUNDSCHECK (arr, index);
763 PUSHA( elements(arr)[index] );
765 NEXT_INSN;
767 insn_baload:
769 jint index = POPI();
770 jbyteArray arr = (jbyteArray) POPA();
771 NULLARRAYCHECK (arr);
772 ARRAYBOUNDSCHECK (arr, index);
773 PUSHI( elements(arr)[index] );
775 NEXT_INSN;
777 insn_caload:
779 jint index = POPI();
780 jcharArray arr = (jcharArray) POPA();
781 NULLARRAYCHECK (arr);
782 ARRAYBOUNDSCHECK (arr, index);
783 PUSHI( elements(arr)[index] );
785 NEXT_INSN;
787 insn_saload:
789 jint index = POPI();
790 jshortArray arr = (jshortArray) POPA();
791 NULLARRAYCHECK (arr);
792 ARRAYBOUNDSCHECK (arr, index);
793 PUSHI( elements(arr)[index] );
795 NEXT_INSN;
797 insn_istore:
798 STOREI (GET1U ());
799 NEXT_INSN;
801 insn_lstore:
802 STOREL (GET1U ());
803 NEXT_INSN;
805 insn_fstore:
806 STOREF (GET1U ());
807 NEXT_INSN;
809 insn_dstore:
810 STORED (GET1U ());
811 NEXT_INSN;
813 insn_astore:
814 STOREA (GET1U ());
815 NEXT_INSN;
817 insn_istore_0:
818 STOREI (0);
819 NEXT_INSN;
821 insn_istore_1:
822 STOREI (1);
823 NEXT_INSN;
825 insn_istore_2:
826 STOREI (2);
827 NEXT_INSN;
829 insn_istore_3:
830 STOREI (3);
831 NEXT_INSN;
833 insn_lstore_0:
834 STOREL (0);
835 NEXT_INSN;
837 insn_lstore_1:
838 STOREL (1);
839 NEXT_INSN;
841 insn_lstore_2:
842 STOREL (2);
843 NEXT_INSN;
845 insn_lstore_3:
846 STOREL (3);
847 NEXT_INSN;
849 insn_fstore_0:
850 STOREF (0);
851 NEXT_INSN;
853 insn_fstore_1:
854 STOREF (1);
855 NEXT_INSN;
857 insn_fstore_2:
858 STOREF (2);
859 NEXT_INSN;
861 insn_fstore_3:
862 STOREF (3);
863 NEXT_INSN;
865 insn_dstore_0:
866 STORED (0);
867 NEXT_INSN;
869 insn_dstore_1:
870 STORED (1);
871 NEXT_INSN;
873 insn_dstore_2:
874 STORED (2);
875 NEXT_INSN;
877 insn_dstore_3:
878 STORED (3);
879 NEXT_INSN;
881 insn_astore_0:
882 STOREA(0);
883 NEXT_INSN;
885 insn_astore_1:
886 STOREA(1);
887 NEXT_INSN;
889 insn_astore_2:
890 STOREA(2);
891 NEXT_INSN;
893 insn_astore_3:
894 STOREA(3);
895 NEXT_INSN;
897 insn_iastore:
899 jint value = POPI();
900 jint index = POPI();
901 jintArray arr = (jintArray) POPA();
902 NULLARRAYCHECK (arr);
903 ARRAYBOUNDSCHECK (arr, index);
904 elements(arr)[index] = value;
906 NEXT_INSN;
908 insn_lastore:
910 jlong value = POPL();
911 jint index = POPI();
912 jlongArray arr = (jlongArray) POPA();
913 NULLARRAYCHECK (arr);
914 ARRAYBOUNDSCHECK (arr, index);
915 elements(arr)[index] = value;
917 NEXT_INSN;
919 insn_fastore:
921 jfloat value = POPF();
922 jint index = POPI();
923 jfloatArray arr = (jfloatArray) POPA();
924 NULLARRAYCHECK (arr);
925 ARRAYBOUNDSCHECK (arr, index);
926 elements(arr)[index] = value;
928 NEXT_INSN;
930 insn_dastore:
932 jdouble value = POPD();
933 jint index = POPI();
934 jdoubleArray arr = (jdoubleArray) POPA();
935 NULLARRAYCHECK (arr);
936 ARRAYBOUNDSCHECK (arr, index);
937 elements(arr)[index] = value;
939 NEXT_INSN;
941 insn_aastore:
943 jobject value = POPA();
944 jint index = POPI();
945 jobjectArray arr = (jobjectArray) POPA();
946 NULLARRAYCHECK (arr);
947 ARRAYBOUNDSCHECK (arr, index);
948 _Jv_CheckArrayStore (arr, value);
949 elements(arr)[index] = value;
951 NEXT_INSN;
953 insn_bastore:
955 jbyte value = (jbyte) POPI();
956 jint index = POPI();
957 jbyteArray arr = (jbyteArray) POPA();
958 NULLARRAYCHECK (arr);
959 ARRAYBOUNDSCHECK (arr, index);
960 elements(arr)[index] = value;
962 NEXT_INSN;
964 insn_castore:
966 jchar value = (jchar) POPI();
967 jint index = POPI();
968 jcharArray arr = (jcharArray) POPA();
969 NULLARRAYCHECK (arr);
970 ARRAYBOUNDSCHECK (arr, index);
971 elements(arr)[index] = value;
973 NEXT_INSN;
975 insn_sastore:
977 jshort value = (jshort) POPI();
978 jint index = POPI();
979 jshortArray arr = (jshortArray) POPA();
980 NULLARRAYCHECK (arr);
981 ARRAYBOUNDSCHECK (arr, index);
982 elements(arr)[index] = value;
984 NEXT_INSN;
986 insn_pop:
987 sp -= 1;
988 NEXT_INSN;
990 insn_pop2:
991 sp -= 2;
992 NEXT_INSN;
994 insn_dup:
995 sp[0] = sp[-1];
996 sp += 1;
997 NEXT_INSN;
999 insn_dup_x1:
1000 dupx (sp, 1, 1); sp+=1;
1001 NEXT_INSN;
1003 insn_dup_x2:
1004 dupx (sp, 1, 2); sp+=1;
1005 NEXT_INSN;
1007 insn_dup2:
1008 sp[0] = sp[-2];
1009 sp[1] = sp[-1];
1010 sp += 2;
1011 NEXT_INSN;
1013 insn_dup2_x1:
1014 dupx (sp, 2, 1); sp+=2;
1015 NEXT_INSN;
1017 insn_dup2_x2:
1018 dupx (sp, 2, 2); sp+=2;
1019 NEXT_INSN;
1021 insn_swap:
1023 jobject tmp1 = POPA();
1024 jobject tmp2 = POPA();
1025 PUSHA (tmp1);
1026 PUSHA (tmp2);
1028 NEXT_INSN;
1030 insn_iadd:
1031 BINOPI(+);
1032 NEXT_INSN;
1034 insn_ladd:
1035 BINOPL(+);
1036 NEXT_INSN;
1038 insn_fadd:
1039 BINOPF(+);
1040 NEXT_INSN;
1042 insn_dadd:
1043 BINOPD(+);
1044 NEXT_INSN;
1046 insn_isub:
1047 BINOPI(-);
1048 NEXT_INSN;
1050 insn_lsub:
1051 BINOPL(-);
1052 NEXT_INSN;
1054 insn_fsub:
1055 BINOPF(-);
1056 NEXT_INSN;
1058 insn_dsub:
1059 BINOPD(-);
1060 NEXT_INSN;
1062 insn_imul:
1063 BINOPI(*);
1064 NEXT_INSN;
1066 insn_lmul:
1067 BINOPL(*);
1068 NEXT_INSN;
1070 insn_fmul:
1071 BINOPF(*);
1072 NEXT_INSN;
1074 insn_dmul:
1075 BINOPD(*);
1076 NEXT_INSN;
1078 insn_idiv:
1080 SAVE_PC();
1081 jint value2 = POPI();
1082 jint value1 = POPI();
1083 jint res = _Jv_divI (value1, value2);
1084 PUSHI (res);
1086 NEXT_INSN;
1088 insn_ldiv:
1090 SAVE_PC();
1091 jlong value2 = POPL();
1092 jlong value1 = POPL();
1093 jlong res = _Jv_divJ (value1, value2);
1094 PUSHL (res);
1096 NEXT_INSN;
1098 insn_fdiv:
1100 jfloat value2 = POPF();
1101 jfloat value1 = POPF();
1102 jfloat res = value1 / value2;
1103 PUSHF (res);
1105 NEXT_INSN;
1107 insn_ddiv:
1109 jdouble value2 = POPD();
1110 jdouble value1 = POPD();
1111 jdouble res = value1 / value2;
1112 PUSHD (res);
1114 NEXT_INSN;
1116 insn_irem:
1118 SAVE_PC();
1119 jint value2 = POPI();
1120 jint value1 = POPI();
1121 jint res = _Jv_remI (value1, value2);
1122 PUSHI (res);
1124 NEXT_INSN;
1126 insn_lrem:
1128 SAVE_PC();
1129 jlong value2 = POPL();
1130 jlong value1 = POPL();
1131 jlong res = _Jv_remJ (value1, value2);
1132 PUSHL (res);
1134 NEXT_INSN;
1136 insn_frem:
1138 jfloat value2 = POPF();
1139 jfloat value1 = POPF();
1140 jfloat res = __ieee754_fmod (value1, value2);
1141 PUSHF (res);
1143 NEXT_INSN;
1145 insn_drem:
1147 jdouble value2 = POPD();
1148 jdouble value1 = POPD();
1149 jdouble res = __ieee754_fmod (value1, value2);
1150 PUSHD (res);
1152 NEXT_INSN;
1154 insn_ineg:
1156 jint value = POPI();
1157 PUSHI (value * -1);
1159 NEXT_INSN;
1161 insn_lneg:
1163 jlong value = POPL();
1164 PUSHL (value * -1);
1166 NEXT_INSN;
1168 insn_fneg:
1170 jfloat value = POPF();
1171 PUSHF (value * -1);
1173 NEXT_INSN;
1175 insn_dneg:
1177 jdouble value = POPD();
1178 PUSHD (value * -1);
1180 NEXT_INSN;
1182 insn_ishl:
1184 jint shift = (POPI() & 0x1f);
1185 jint value = POPI();
1186 PUSHI (value << shift);
1188 NEXT_INSN;
1190 insn_lshl:
1192 jint shift = (POPI() & 0x3f);
1193 jlong value = POPL();
1194 PUSHL (value << shift);
1196 NEXT_INSN;
1198 insn_ishr:
1200 jint shift = (POPI() & 0x1f);
1201 jint value = POPI();
1202 PUSHI (value >> shift);
1204 NEXT_INSN;
1206 insn_lshr:
1208 jint shift = (POPI() & 0x3f);
1209 jlong value = POPL();
1210 PUSHL (value >> shift);
1212 NEXT_INSN;
1214 insn_iushr:
1216 jint shift = (POPI() & 0x1f);
1217 _Jv_uint value = (_Jv_uint) POPI();
1218 PUSHI ((jint) (value >> shift));
1220 NEXT_INSN;
1222 insn_lushr:
1224 jint shift = (POPI() & 0x3f);
1225 _Jv_ulong value = (_Jv_ulong) POPL();
1226 PUSHL ((jlong) (value >> shift));
1228 NEXT_INSN;
1230 insn_iand:
1231 BINOPI (&);
1232 NEXT_INSN;
1234 insn_land:
1235 BINOPL (&);
1236 NEXT_INSN;
1238 insn_ior:
1239 BINOPI (|);
1240 NEXT_INSN;
1242 insn_lor:
1243 BINOPL (|);
1244 NEXT_INSN;
1246 insn_ixor:
1247 BINOPI (^);
1248 NEXT_INSN;
1250 insn_lxor:
1251 BINOPL (^);
1252 NEXT_INSN;
1254 insn_iinc:
1256 jint index = GET1U ();
1257 jint amount = GET1S ();
1258 locals[index].i += amount;
1260 NEXT_INSN;
1262 insn_i2l:
1263 {jlong value = POPI(); PUSHL (value);}
1264 NEXT_INSN;
1266 insn_i2f:
1267 {jfloat value = POPI(); PUSHF (value);}
1268 NEXT_INSN;
1270 insn_i2d:
1271 {jdouble value = POPI(); PUSHD (value);}
1272 NEXT_INSN;
1274 insn_l2i:
1275 {jint value = POPL(); PUSHI (value);}
1276 NEXT_INSN;
1278 insn_l2f:
1279 {jfloat value = POPL(); PUSHF (value);}
1280 NEXT_INSN;
1282 insn_l2d:
1283 {jdouble value = POPL(); PUSHD (value);}
1284 NEXT_INSN;
1286 insn_f2i:
1288 using namespace java::lang;
1289 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1290 PUSHI(value);
1292 NEXT_INSN;
1294 insn_f2l:
1296 using namespace java::lang;
1297 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1298 PUSHL(value);
1300 NEXT_INSN;
1302 insn_f2d:
1303 { jdouble value = POPF (); PUSHD(value); }
1304 NEXT_INSN;
1306 insn_d2i:
1308 using namespace java::lang;
1309 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1310 PUSHI(value);
1312 NEXT_INSN;
1314 insn_d2l:
1316 using namespace java::lang;
1317 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1318 PUSHL(value);
1320 NEXT_INSN;
1322 insn_d2f:
1323 { jfloat value = POPD (); PUSHF(value); }
1324 NEXT_INSN;
1326 insn_i2b:
1327 { jbyte value = POPI (); PUSHI(value); }
1328 NEXT_INSN;
1330 insn_i2c:
1331 { jchar value = POPI (); PUSHI(value); }
1332 NEXT_INSN;
1334 insn_i2s:
1335 { jshort value = POPI (); PUSHI(value); }
1336 NEXT_INSN;
1338 insn_lcmp:
1340 jlong value2 = POPL ();
1341 jlong value1 = POPL ();
1342 if (value1 > value2)
1343 { PUSHI (1); }
1344 else if (value1 == value2)
1345 { PUSHI (0); }
1346 else
1347 { PUSHI (-1); }
1349 NEXT_INSN;
1351 insn_fcmpl:
1352 tmpval = -1;
1353 goto fcmp;
1355 insn_fcmpg:
1356 tmpval = 1;
1358 fcmp:
1360 jfloat value2 = POPF ();
1361 jfloat value1 = POPF ();
1362 if (value1 > value2)
1363 PUSHI (1);
1364 else if (value1 == value2)
1365 PUSHI (0);
1366 else if (value1 < value2)
1367 PUSHI (-1);
1368 else
1369 PUSHI (tmpval);
1371 NEXT_INSN;
1373 insn_dcmpl:
1374 tmpval = -1;
1375 goto dcmp;
1377 insn_dcmpg:
1378 tmpval = 1;
1380 dcmp:
1382 jdouble value2 = POPD ();
1383 jdouble value1 = POPD ();
1384 if (value1 > value2)
1385 PUSHI (1);
1386 else if (value1 == value2)
1387 PUSHI (0);
1388 else if (value1 < value2)
1389 PUSHI (-1);
1390 else
1391 PUSHI (tmpval);
1393 NEXT_INSN;
1395 insn_ifeq:
1397 if (POPI() == 0)
1398 TAKE_GOTO;
1399 else
1400 SKIP_GOTO;
1402 NEXT_INSN;
1404 insn_ifne:
1406 if (POPI() != 0)
1407 TAKE_GOTO;
1408 else
1409 SKIP_GOTO;
1411 NEXT_INSN;
1413 insn_iflt:
1415 if (POPI() < 0)
1416 TAKE_GOTO;
1417 else
1418 SKIP_GOTO;
1420 NEXT_INSN;
1422 insn_ifge:
1424 if (POPI() >= 0)
1425 TAKE_GOTO;
1426 else
1427 SKIP_GOTO;
1429 NEXT_INSN;
1431 insn_ifgt:
1433 if (POPI() > 0)
1434 TAKE_GOTO;
1435 else
1436 SKIP_GOTO;
1438 NEXT_INSN;
1440 insn_ifle:
1442 if (POPI() <= 0)
1443 TAKE_GOTO;
1444 else
1445 SKIP_GOTO;
1447 NEXT_INSN;
1449 insn_if_icmpeq:
1451 jint value2 = POPI();
1452 jint value1 = POPI();
1453 if (value1 == value2)
1454 TAKE_GOTO;
1455 else
1456 SKIP_GOTO;
1458 NEXT_INSN;
1460 insn_if_icmpne:
1462 jint value2 = POPI();
1463 jint value1 = POPI();
1464 if (value1 != value2)
1465 TAKE_GOTO;
1466 else
1467 SKIP_GOTO;
1469 NEXT_INSN;
1471 insn_if_icmplt:
1473 jint value2 = POPI();
1474 jint value1 = POPI();
1475 if (value1 < value2)
1476 TAKE_GOTO;
1477 else
1478 SKIP_GOTO;
1480 NEXT_INSN;
1482 insn_if_icmpge:
1484 jint value2 = POPI();
1485 jint value1 = POPI();
1486 if (value1 >= value2)
1487 TAKE_GOTO;
1488 else
1489 SKIP_GOTO;
1491 NEXT_INSN;
1493 insn_if_icmpgt:
1495 jint value2 = POPI();
1496 jint value1 = POPI();
1497 if (value1 > value2)
1498 TAKE_GOTO;
1499 else
1500 SKIP_GOTO;
1502 NEXT_INSN;
1504 insn_if_icmple:
1506 jint value2 = POPI();
1507 jint value1 = POPI();
1508 if (value1 <= value2)
1509 TAKE_GOTO;
1510 else
1511 SKIP_GOTO;
1513 NEXT_INSN;
1515 insn_if_acmpeq:
1517 jobject value2 = POPA();
1518 jobject value1 = POPA();
1519 if (value1 == value2)
1520 TAKE_GOTO;
1521 else
1522 SKIP_GOTO;
1524 NEXT_INSN;
1526 insn_if_acmpne:
1528 jobject value2 = POPA();
1529 jobject value1 = POPA();
1530 if (value1 != value2)
1531 TAKE_GOTO;
1532 else
1533 SKIP_GOTO;
1535 NEXT_INSN;
1537 insn_goto_w:
1538 #ifndef DIRECT_THREADED
1539 // For direct threaded, goto and goto_w are the same.
1540 pc = pc - 1 + get4 (pc);
1541 NEXT_INSN;
1542 #endif /* DIRECT_THREADED */
1543 insn_goto:
1544 TAKE_GOTO;
1545 NEXT_INSN;
1547 insn_jsr_w:
1548 #ifndef DIRECT_THREADED
1549 // For direct threaded, jsr and jsr_w are the same.
1551 pc_t next = pc - 1 + get4 (pc);
1552 pc += 4;
1553 PUSHA ((jobject) pc);
1554 pc = next;
1556 NEXT_INSN;
1557 #endif /* DIRECT_THREADED */
1558 insn_jsr:
1560 pc_t next = GOTO_VAL();
1561 SKIP_GOTO;
1562 PUSHA ((jobject) pc);
1563 pc = next;
1565 NEXT_INSN;
1567 insn_ret:
1569 jint index = GET1U ();
1570 pc = (pc_t) PEEKA (index);
1572 NEXT_INSN;
1574 insn_tableswitch:
1576 #ifdef DIRECT_THREADED
1577 void *def = (pc++)->datum;
1579 int index = POPI();
1581 jint low = INTVAL ();
1582 jint high = INTVAL ();
1584 if (index < low || index > high)
1585 pc = (insn_slot *) def;
1586 else
1587 pc = (insn_slot *) ((pc + index - low)->datum);
1588 #else
1589 pc_t base_pc = pc - 1;
1590 int index = POPI ();
1592 pc_t base = (pc_t) meth->bytecode ();
1593 while ((pc - base) % 4 != 0)
1594 ++pc;
1596 jint def = get4 (pc);
1597 jint low = get4 (pc + 4);
1598 jint high = get4 (pc + 8);
1599 if (index < low || index > high)
1600 pc = base_pc + def;
1601 else
1602 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1603 #endif /* DIRECT_THREADED */
1605 NEXT_INSN;
1607 insn_lookupswitch:
1609 #ifdef DIRECT_THREADED
1610 void *def = (pc++)->insn;
1612 int index = POPI();
1614 jint npairs = INTVAL ();
1616 int max = npairs - 1;
1617 int min = 0;
1619 // Simple binary search...
1620 while (min < max)
1622 int half = (min + max) / 2;
1623 int match = pc[2 * half].int_val;
1625 if (index == match)
1627 // Found it.
1628 pc = (insn_slot *) pc[2 * half + 1].datum;
1629 NEXT_INSN;
1631 else if (index < match)
1632 // We can use HALF - 1 here because we check again on
1633 // loop exit.
1634 max = half - 1;
1635 else
1636 // We can use HALF + 1 here because we check again on
1637 // loop exit.
1638 min = half + 1;
1640 if (index == pc[2 * min].int_val)
1641 pc = (insn_slot *) pc[2 * min + 1].datum;
1642 else
1643 pc = (insn_slot *) def;
1644 #else
1645 unsigned char *base_pc = pc-1;
1646 int index = POPI();
1648 unsigned char* base = meth->bytecode ();
1649 while ((pc-base) % 4 != 0)
1650 ++pc;
1652 jint def = get4 (pc);
1653 jint npairs = get4 (pc+4);
1655 int max = npairs-1;
1656 int min = 0;
1658 // Simple binary search...
1659 while (min < max)
1661 int half = (min+max)/2;
1662 int match = get4 (pc+ 4*(2 + 2*half));
1664 if (index == match)
1665 min = max = half;
1666 else if (index < match)
1667 // We can use HALF - 1 here because we check again on
1668 // loop exit.
1669 max = half - 1;
1670 else
1671 // We can use HALF + 1 here because we check again on
1672 // loop exit.
1673 min = half + 1;
1676 if (index == get4 (pc+ 4*(2 + 2*min)))
1677 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1678 else
1679 pc = base_pc + def;
1680 #endif /* DIRECT_THREADED */
1682 NEXT_INSN;
1684 insn_areturn:
1685 *(jobject *) retp = POPA ();
1686 return;
1688 insn_lreturn:
1689 *(jlong *) retp = POPL ();
1690 return;
1692 insn_freturn:
1693 *(jfloat *) retp = POPF ();
1694 return;
1696 insn_dreturn:
1697 *(jdouble *) retp = POPD ();
1698 return;
1700 insn_ireturn:
1701 *(jint *) retp = POPI ();
1702 return;
1704 insn_return:
1705 return;
1707 insn_getstatic:
1709 jint fieldref_index = GET2U ();
1710 SAVE_PC(); // Constant pool resolution could throw.
1711 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1712 _Jv_Field *field = pool_data[fieldref_index].field;
1714 if ((field->flags & Modifier::STATIC) == 0)
1715 throw_incompatible_class_change_error
1716 (JvNewStringLatin1 ("field no longer static"));
1718 jclass type = field->type;
1720 // We rewrite the instruction once we discover what it refers
1721 // to.
1722 void *newinsn = NULL;
1723 if (type->isPrimitive ())
1725 switch (type->size_in_bytes)
1727 case 1:
1728 PUSHI (*field->u.byte_addr);
1729 newinsn = AMPAMP (getstatic_resolved_1);
1730 break;
1732 case 2:
1733 if (type == JvPrimClass (char))
1735 PUSHI (*field->u.char_addr);
1736 newinsn = AMPAMP (getstatic_resolved_char);
1738 else
1740 PUSHI (*field->u.short_addr);
1741 newinsn = AMPAMP (getstatic_resolved_short);
1743 break;
1745 case 4:
1746 PUSHI(*field->u.int_addr);
1747 newinsn = AMPAMP (getstatic_resolved_4);
1748 break;
1750 case 8:
1751 PUSHL(*field->u.long_addr);
1752 newinsn = AMPAMP (getstatic_resolved_8);
1753 break;
1756 else
1758 PUSHA(*field->u.object_addr);
1759 newinsn = AMPAMP (getstatic_resolved_obj);
1762 #ifdef DIRECT_THREADED
1763 pc[-2].insn = newinsn;
1764 pc[-1].datum = field->u.addr;
1765 #endif /* DIRECT_THREADED */
1767 NEXT_INSN;
1769 #ifdef DIRECT_THREADED
1770 getstatic_resolved_1:
1771 PUSHI (*(jbyte *) AVAL ());
1772 NEXT_INSN;
1774 getstatic_resolved_char:
1775 PUSHI (*(jchar *) AVAL ());
1776 NEXT_INSN;
1778 getstatic_resolved_short:
1779 PUSHI (*(jshort *) AVAL ());
1780 NEXT_INSN;
1782 getstatic_resolved_4:
1783 PUSHI (*(jint *) AVAL ());
1784 NEXT_INSN;
1786 getstatic_resolved_8:
1787 PUSHL (*(jlong *) AVAL ());
1788 NEXT_INSN;
1790 getstatic_resolved_obj:
1791 PUSHA (*(jobject *) AVAL ());
1792 NEXT_INSN;
1793 #endif /* DIRECT_THREADED */
1795 insn_getfield:
1797 SAVE_PC();
1798 jint fieldref_index = GET2U ();
1799 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1800 _Jv_Field *field = pool_data[fieldref_index].field;
1802 if ((field->flags & Modifier::STATIC) != 0)
1803 throw_incompatible_class_change_error
1804 (JvNewStringLatin1 ("field is static"));
1806 jclass type = field->type;
1807 jint field_offset = field->u.boffset;
1809 jobject obj = POPA();
1810 NULLCHECK(obj);
1812 void *newinsn = NULL;
1813 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1814 if (type->isPrimitive ())
1816 switch (type->size_in_bytes)
1818 case 1:
1819 PUSHI (val->byte_value);
1820 newinsn = AMPAMP (getfield_resolved_1);
1821 break;
1823 case 2:
1824 if (type == JvPrimClass (char))
1826 PUSHI (val->char_value);
1827 newinsn = AMPAMP (getfield_resolved_char);
1829 else
1831 PUSHI (val->short_value);
1832 newinsn = AMPAMP (getfield_resolved_short);
1834 break;
1836 case 4:
1837 PUSHI (val->int_value);
1838 newinsn = AMPAMP (getfield_resolved_4);
1839 break;
1841 case 8:
1842 PUSHL (val->long_value);
1843 newinsn = AMPAMP (getfield_resolved_8);
1844 break;
1847 else
1849 PUSHA (val->object_value);
1850 newinsn = AMPAMP (getfield_resolved_obj);
1853 #ifdef DIRECT_THREADED
1854 pc[-2].insn = newinsn;
1855 pc[-1].int_val = field_offset;
1856 #endif /* DIRECT_THREADED */
1858 NEXT_INSN;
1860 #ifdef DIRECT_THREADED
1861 getfield_resolved_1:
1863 char *obj = (char *) POPA ();
1864 NULLCHECK (obj);
1865 PUSHI (*(jbyte *) (obj + INTVAL ()));
1867 NEXT_INSN;
1869 getfield_resolved_char:
1871 char *obj = (char *) POPA ();
1872 NULLCHECK (obj);
1873 PUSHI (*(jchar *) (obj + INTVAL ()));
1875 NEXT_INSN;
1877 getfield_resolved_short:
1879 char *obj = (char *) POPA ();
1880 NULLCHECK (obj);
1881 PUSHI (*(jshort *) (obj + INTVAL ()));
1883 NEXT_INSN;
1885 getfield_resolved_4:
1887 char *obj = (char *) POPA ();
1888 NULLCHECK (obj);
1889 PUSHI (*(jint *) (obj + INTVAL ()));
1891 NEXT_INSN;
1893 getfield_resolved_8:
1895 char *obj = (char *) POPA ();
1896 NULLCHECK (obj);
1897 PUSHL (*(jlong *) (obj + INTVAL ()));
1899 NEXT_INSN;
1901 getfield_resolved_obj:
1903 char *obj = (char *) POPA ();
1904 NULLCHECK (obj);
1905 PUSHA (*(jobject *) (obj + INTVAL ()));
1907 NEXT_INSN;
1908 #endif /* DIRECT_THREADED */
1910 insn_putstatic:
1912 SAVE_PC();
1913 jint fieldref_index = GET2U ();
1914 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1915 _Jv_Field *field = pool_data[fieldref_index].field;
1917 jclass type = field->type;
1919 // ResolvePoolEntry cannot check this
1920 if ((field->flags & Modifier::STATIC) == 0)
1921 throw_incompatible_class_change_error
1922 (JvNewStringLatin1 ("field no longer static"));
1924 void *newinsn = NULL;
1925 if (type->isPrimitive ())
1927 switch (type->size_in_bytes)
1929 case 1:
1931 jint value = POPI();
1932 *field->u.byte_addr = value;
1933 newinsn = AMPAMP (putstatic_resolved_1);
1934 break;
1937 case 2:
1939 jint value = POPI();
1940 *field->u.char_addr = value;
1941 newinsn = AMPAMP (putstatic_resolved_2);
1942 break;
1945 case 4:
1947 jint value = POPI();
1948 *field->u.int_addr = value;
1949 newinsn = AMPAMP (putstatic_resolved_4);
1950 break;
1953 case 8:
1955 jlong value = POPL();
1956 *field->u.long_addr = value;
1957 newinsn = AMPAMP (putstatic_resolved_8);
1958 break;
1962 else
1964 jobject value = POPA();
1965 *field->u.object_addr = value;
1966 newinsn = AMPAMP (putstatic_resolved_obj);
1969 #ifdef DIRECT_THREADED
1970 pc[-2].insn = newinsn;
1971 pc[-1].datum = field->u.addr;
1972 #endif /* DIRECT_THREADED */
1974 NEXT_INSN;
1976 #ifdef DIRECT_THREADED
1977 putstatic_resolved_1:
1978 *(jbyte *) AVAL () = POPI ();
1979 NEXT_INSN;
1981 putstatic_resolved_2:
1982 *(jchar *) AVAL () = POPI ();
1983 NEXT_INSN;
1985 putstatic_resolved_4:
1986 *(jint *) AVAL () = POPI ();
1987 NEXT_INSN;
1989 putstatic_resolved_8:
1990 *(jlong *) AVAL () = POPL ();
1991 NEXT_INSN;
1993 putstatic_resolved_obj:
1994 *(jobject *) AVAL () = POPA ();
1995 NEXT_INSN;
1996 #endif /* DIRECT_THREADED */
1998 insn_putfield:
2000 SAVE_PC();
2001 jint fieldref_index = GET2U ();
2002 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2003 _Jv_Field *field = pool_data[fieldref_index].field;
2005 jclass type = field->type;
2007 if ((field->flags & Modifier::STATIC) != 0)
2008 throw_incompatible_class_change_error
2009 (JvNewStringLatin1 ("field is static"));
2011 jint field_offset = field->u.boffset;
2013 void *newinsn = NULL;
2014 if (type->isPrimitive ())
2016 switch (type->size_in_bytes)
2018 case 1:
2020 jint value = POPI();
2021 jobject obj = POPA();
2022 NULLCHECK(obj);
2023 *(jbyte*) ((char*)obj + field_offset) = value;
2024 newinsn = AMPAMP (putfield_resolved_1);
2025 break;
2028 case 2:
2030 jint value = POPI();
2031 jobject obj = POPA();
2032 NULLCHECK(obj);
2033 *(jchar*) ((char*)obj + field_offset) = value;
2034 newinsn = AMPAMP (putfield_resolved_2);
2035 break;
2038 case 4:
2040 jint value = POPI();
2041 jobject obj = POPA();
2042 NULLCHECK(obj);
2043 *(jint*) ((char*)obj + field_offset) = value;
2044 newinsn = AMPAMP (putfield_resolved_4);
2045 break;
2048 case 8:
2050 jlong value = POPL();
2051 jobject obj = POPA();
2052 NULLCHECK(obj);
2053 *(jlong*) ((char*)obj + field_offset) = value;
2054 newinsn = AMPAMP (putfield_resolved_8);
2055 break;
2059 else
2061 jobject value = POPA();
2062 jobject obj = POPA();
2063 NULLCHECK(obj);
2064 *(jobject*) ((char*)obj + field_offset) = value;
2065 newinsn = AMPAMP (putfield_resolved_obj);
2068 #ifdef DIRECT_THREADED
2069 pc[-2].insn = newinsn;
2070 pc[-1].int_val = field_offset;
2071 #endif /* DIRECT_THREADED */
2073 NEXT_INSN;
2075 #ifdef DIRECT_THREADED
2076 putfield_resolved_1:
2078 jint val = POPI ();
2079 char *obj = (char *) POPA ();
2080 NULLCHECK (obj);
2081 *(jbyte *) (obj + INTVAL ()) = val;
2083 NEXT_INSN;
2085 putfield_resolved_2:
2087 jint val = POPI ();
2088 char *obj = (char *) POPA ();
2089 NULLCHECK (obj);
2090 *(jchar *) (obj + INTVAL ()) = val;
2092 NEXT_INSN;
2094 putfield_resolved_4:
2096 jint val = POPI ();
2097 char *obj = (char *) POPA ();
2098 NULLCHECK (obj);
2099 *(jint *) (obj + INTVAL ()) = val;
2101 NEXT_INSN;
2103 putfield_resolved_8:
2105 jlong val = POPL ();
2106 char *obj = (char *) POPA ();
2107 NULLCHECK (obj);
2108 *(jlong *) (obj + INTVAL ()) = val;
2110 NEXT_INSN;
2112 putfield_resolved_obj:
2114 jobject val = POPA ();
2115 char *obj = (char *) POPA ();
2116 NULLCHECK (obj);
2117 *(jobject *) (obj + INTVAL ()) = val;
2119 NEXT_INSN;
2120 #endif /* DIRECT_THREADED */
2122 insn_invokespecial:
2124 SAVE_PC();
2125 int index = GET2U ();
2127 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2128 index)).rmethod;
2130 sp -= rmeth->stack_item_count;
2132 // We don't use NULLCHECK here because we can't rely on that
2133 // working for <init>. So instead we do an explicit test.
2134 if (! sp[0].o)
2136 SAVE_PC();
2137 throw_null_pointer_exception ();
2140 fun = (void (*)()) rmeth->method->ncode;
2142 #ifdef DIRECT_THREADED
2143 // Rewrite instruction so that we use a faster pre-resolved
2144 // method.
2145 pc[-2].insn = &&invokespecial_resolved;
2146 pc[-1].datum = rmeth;
2147 #endif /* DIRECT_THREADED */
2149 goto perform_invoke;
2151 #ifdef DIRECT_THREADED
2152 invokespecial_resolved:
2154 SAVE_PC();
2155 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2156 sp -= rmeth->stack_item_count;
2157 // We don't use NULLCHECK here because we can't rely on that
2158 // working for <init>. So instead we do an explicit test.
2159 if (! sp[0].o)
2161 throw_null_pointer_exception ();
2163 fun = (void (*)()) rmeth->method->ncode;
2165 goto perform_invoke;
2166 #endif /* DIRECT_THREADED */
2168 insn_invokestatic:
2170 SAVE_PC();
2171 int index = GET2U ();
2173 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2174 index)).rmethod;
2176 sp -= rmeth->stack_item_count;
2178 fun = (void (*)()) rmeth->method->ncode;
2180 #ifdef DIRECT_THREADED
2181 // Rewrite instruction so that we use a faster pre-resolved
2182 // method.
2183 pc[-2].insn = &&invokestatic_resolved;
2184 pc[-1].datum = rmeth;
2185 #endif /* DIRECT_THREADED */
2187 goto perform_invoke;
2189 #ifdef DIRECT_THREADED
2190 invokestatic_resolved:
2192 SAVE_PC();
2193 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2194 sp -= rmeth->stack_item_count;
2195 fun = (void (*)()) rmeth->method->ncode;
2197 goto perform_invoke;
2198 #endif /* DIRECT_THREADED */
2200 insn_invokeinterface:
2202 SAVE_PC();
2203 int index = GET2U ();
2205 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2206 index)).rmethod;
2208 sp -= rmeth->stack_item_count;
2210 jobject rcv = sp[0].o;
2212 NULLCHECK (rcv);
2214 fun = (void (*)())
2215 _Jv_LookupInterfaceMethod (rcv->getClass (),
2216 rmeth->method->name,
2217 rmeth->method->signature);
2219 #ifdef DIRECT_THREADED
2220 // Rewrite instruction so that we use a faster pre-resolved
2221 // method.
2222 pc[-2].insn = &&invokeinterface_resolved;
2223 pc[-1].datum = rmeth;
2224 #else
2225 // Skip dummy bytes.
2226 pc += 2;
2227 #endif /* DIRECT_THREADED */
2229 goto perform_invoke;
2231 #ifdef DIRECT_THREADED
2232 invokeinterface_resolved:
2234 SAVE_PC();
2235 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2236 sp -= rmeth->stack_item_count;
2237 jobject rcv = sp[0].o;
2238 NULLCHECK (rcv);
2239 fun = (void (*)())
2240 _Jv_LookupInterfaceMethod (rcv->getClass (),
2241 rmeth->method->name,
2242 rmeth->method->signature);
2244 goto perform_invoke;
2245 #endif /* DIRECT_THREADED */
2247 insn_new:
2249 SAVE_PC();
2250 int index = GET2U ();
2251 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2252 index)).clazz;
2253 /* VM spec, section 3.11.5 */
2254 if ((klass->getModifiers() & Modifier::ABSTRACT)
2255 || klass->isInterface())
2256 throw new java::lang::InstantiationException;
2257 jobject res = _Jv_AllocObject (klass);
2258 PUSHA (res);
2260 #ifdef DIRECT_THREADED
2261 pc[-2].insn = &&new_resolved;
2262 pc[-1].datum = klass;
2263 #endif /* DIRECT_THREADED */
2265 NEXT_INSN;
2267 #ifdef DIRECT_THREADED
2268 new_resolved:
2270 jclass klass = (jclass) AVAL ();
2271 jobject res = _Jv_AllocObject (klass);
2272 PUSHA (res);
2274 NEXT_INSN;
2275 #endif /* DIRECT_THREADED */
2277 insn_newarray:
2279 int atype = GET1U ();
2280 int size = POPI();
2281 jobject result = _Jv_NewArray (atype, size);
2282 PUSHA (result);
2284 NEXT_INSN;
2286 insn_anewarray:
2288 SAVE_PC();
2289 int index = GET2U ();
2290 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2291 index)).clazz;
2292 int size = POPI();
2293 jobject result = _Jv_NewObjectArray (size, klass, 0);
2294 PUSHA (result);
2296 #ifdef DIRECT_THREADED
2297 pc[-2].insn = &&anewarray_resolved;
2298 pc[-1].datum = klass;
2299 #endif /* DIRECT_THREADED */
2301 NEXT_INSN;
2303 #ifdef DIRECT_THREADED
2304 anewarray_resolved:
2306 jclass klass = (jclass) AVAL ();
2307 int size = POPI ();
2308 jobject result = _Jv_NewObjectArray (size, klass, 0);
2309 PUSHA (result);
2311 NEXT_INSN;
2312 #endif /* DIRECT_THREADED */
2314 insn_arraylength:
2316 __JArray *arr = (__JArray*)POPA();
2317 NULLARRAYCHECK (arr);
2318 PUSHI (arr->length);
2320 NEXT_INSN;
2322 insn_athrow:
2324 jobject value = POPA();
2325 throw static_cast<jthrowable>(value);
2327 NEXT_INSN;
2329 insn_checkcast:
2331 SAVE_PC();
2332 jobject value = POPA();
2333 jint index = GET2U ();
2334 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2335 index)).clazz;
2337 value = (jobject) _Jv_CheckCast (to, value);
2339 PUSHA (value);
2341 #ifdef DIRECT_THREADED
2342 pc[-2].insn = &&checkcast_resolved;
2343 pc[-1].datum = to;
2344 #endif /* DIRECT_THREADED */
2346 NEXT_INSN;
2348 #ifdef DIRECT_THREADED
2349 checkcast_resolved:
2351 SAVE_PC();
2352 jobject value = POPA ();
2353 jclass to = (jclass) AVAL ();
2354 value = (jobject) _Jv_CheckCast (to, value);
2355 PUSHA (value);
2357 NEXT_INSN;
2358 #endif /* DIRECT_THREADED */
2360 insn_instanceof:
2362 SAVE_PC();
2363 jobject value = POPA();
2364 jint index = GET2U ();
2365 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2366 index)).clazz;
2367 PUSHI (to->isInstance (value));
2369 #ifdef DIRECT_THREADED
2370 pc[-2].insn = &&instanceof_resolved;
2371 pc[-1].datum = to;
2372 #endif /* DIRECT_THREADED */
2374 NEXT_INSN;
2376 #ifdef DIRECT_THREADED
2377 instanceof_resolved:
2379 jobject value = POPA ();
2380 jclass to = (jclass) AVAL ();
2381 PUSHI (to->isInstance (value));
2383 NEXT_INSN;
2384 #endif /* DIRECT_THREADED */
2386 insn_monitorenter:
2388 jobject value = POPA();
2389 NULLCHECK(value);
2390 _Jv_MonitorEnter (value);
2392 NEXT_INSN;
2394 insn_monitorexit:
2396 jobject value = POPA();
2397 NULLCHECK(value);
2398 _Jv_MonitorExit (value);
2400 NEXT_INSN;
2402 insn_ifnull:
2404 jobject val = POPA();
2405 if (val == NULL)
2406 TAKE_GOTO;
2407 else
2408 SKIP_GOTO;
2410 NEXT_INSN;
2412 insn_ifnonnull:
2414 jobject val = POPA();
2415 if (val != NULL)
2416 TAKE_GOTO;
2417 else
2418 SKIP_GOTO;
2420 NEXT_INSN;
2422 insn_multianewarray:
2424 SAVE_PC();
2425 int kind_index = GET2U ();
2426 int dim = GET1U ();
2428 jclass type
2429 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2430 kind_index)).clazz;
2431 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2433 for (int i = dim - 1; i >= 0; i--)
2435 sizes[i] = POPI ();
2438 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2440 PUSHA (res);
2442 NEXT_INSN;
2444 #ifndef DIRECT_THREADED
2445 insn_wide:
2447 jint the_mod_op = get1u (pc++);
2448 jint wide = get2u (pc); pc += 2;
2450 switch (the_mod_op)
2452 case op_istore:
2453 STOREI (wide);
2454 NEXT_INSN;
2456 case op_fstore:
2457 STOREF (wide);
2458 NEXT_INSN;
2460 case op_astore:
2461 STOREA (wide);
2462 NEXT_INSN;
2464 case op_lload:
2465 LOADL (wide);
2466 NEXT_INSN;
2468 case op_dload:
2469 LOADD (wide);
2470 NEXT_INSN;
2472 case op_iload:
2473 LOADI (wide);
2474 NEXT_INSN;
2476 case op_fload:
2477 LOADF (wide);
2478 NEXT_INSN;
2480 case op_aload:
2481 LOADA (wide);
2482 NEXT_INSN;
2484 case op_lstore:
2485 STOREL (wide);
2486 NEXT_INSN;
2488 case op_dstore:
2489 STORED (wide);
2490 NEXT_INSN;
2492 case op_ret:
2493 pc = (unsigned char*) PEEKA (wide);
2494 NEXT_INSN;
2496 case op_iinc:
2498 jint amount = get2s (pc); pc += 2;
2499 jint value = PEEKI (wide);
2500 POKEI (wide, value+amount);
2502 NEXT_INSN;
2504 default:
2505 throw_internal_error ("illegal bytecode modified by wide");
2509 #endif /* DIRECT_THREADED */
2511 insn_breakpoint:
2513 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2515 // Send JVMTI notification
2516 using namespace ::java::lang;
2517 jmethodID method = meth->self;
2518 jlocation location = meth->insn_index (pc - 1);
2519 Thread *thread = Thread::currentThread ();
2520 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2522 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2523 method, location);
2525 // Continue execution
2526 using namespace gnu::gcj::jvmti;
2527 Breakpoint *bp
2528 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2529 location);
2530 JvAssert (bp != NULL);
2532 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2534 #ifdef DIRECT_THREADED
2535 goto *(opc->insn);
2536 #else
2537 goto *(insn_target[*opc]);
2538 #endif
2541 catch (java::lang::Throwable *ex)
2543 #ifdef DEBUG
2544 // This needs to be done before the pc is changed.
2545 jlong throw_loc = meth->insn_index (pc);
2546 #endif
2547 // Check if the exception is handled and, if so, set the pc to the start
2548 // of the appropriate catch block.
2549 if (meth->check_handler (&pc, meth, ex))
2551 sp = stack;
2552 sp++->o = ex; // Push exception.
2553 #ifdef DEBUG
2554 if (JVMTI_REQUESTED_EVENT (Exception))
2556 using namespace gnu::gcj::jvmti;
2557 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2558 jlong catch_loc = meth->insn_index (pc);
2559 ExceptionEvent::postExceptionEvent (thread, throw_meth,
2560 throw_loc, ex, throw_meth,
2561 catch_loc);
2563 #endif
2564 NEXT_INSN;
2566 #ifdef DEBUG
2567 if (JVMTI_REQUESTED_EVENT (Exception))
2569 using namespace gnu::gcj::jvmti;
2570 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2571 ExceptionEvent::postExceptionEvent (thread, throw_meth, throw_loc,
2572 ex, NULL, NULL);
2574 #endif
2575 // No handler, so re-throw.
2576 throw ex;