PR c++/31074
[official-gcc.git] / libjava / interpret-run.cc
blobb8c88af78278c865f27cba843f6f6002d6365fb5
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 // This is the information needed to get and set local variables with
32 // proper type checking.
33 frame_desc.locals = locals;
34 char locals_type[meth->max_locals];
35 frame_desc.locals_type = locals_type;
37 // Set all slots as invalid until they are written to.
38 memset (locals_type, 'x', meth->max_locals);
40 // We need to set the local variable types for the method arguments since
41 // they are valid at invocation.
43 _Jv_Method *method = meth->get_method ();
44 int type_ctr = 0;
46 // If the method is non-static, we need to set the type for the "this" pointer.
47 if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
49 if (args)
51 // Set the "this" pointer for this frame.
52 _Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args);
53 frame_desc.obj_ptr = this_ptr[0].o;
56 frame_desc.locals_type[0] = 'o';
57 type_ctr++;
60 // Now parse the method signature to set the types of the other arguments.
61 int sig_len = method->signature->len ();
62 char *signature = method->signature->chars ();
63 for (int i = 1; signature[i] != ')' && i <= sig_len; i++)
65 if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C'
66 || signature[i] == 'S' || signature[i] == 'I')
68 frame_desc.locals_type[type_ctr] = 'i';
69 type_ctr++;
70 continue;
72 else if (signature[i] == 'F')
74 frame_desc.locals_type[type_ctr] = 'f';
75 type_ctr++;
76 continue;
78 else if (signature[i] == 'J')
80 frame_desc.locals_type[type_ctr] = 'l';
81 frame_desc.locals_type[type_ctr+1] = 'x';
82 type_ctr += 2;
83 continue;
85 else if (signature[i] == 'D')
87 frame_desc.locals_type[type_ctr] = 'd';
88 frame_desc.locals_type[type_ctr+1] = 'x';
89 type_ctr += 2;
90 continue;
92 else if (signature[i] == 'L')
94 frame_desc.locals_type[type_ctr] = 'o';
95 type_ctr++;
96 while (signature[i] != ';')
97 i++;
98 continue;
100 else if (signature[i] == '[')
102 frame_desc.locals_type[type_ctr] = 'o';
103 type_ctr++;
105 // Ignore multi-dimensional arrays.
106 while (signature[i] == '[')
107 i++;
109 // Check for an object array
110 if (signature[i] == 'L')
112 while (signature[i] != ';')
113 i++;
115 continue;
118 #endif /* DEBUG */
120 #define INSN_LABEL(op) &&insn_##op
122 static const void *const insn_target[] =
124 INSN_LABEL(nop),
125 INSN_LABEL(aconst_null),
126 INSN_LABEL(iconst_m1),
127 INSN_LABEL(iconst_0),
128 INSN_LABEL(iconst_1),
129 INSN_LABEL(iconst_2),
130 INSN_LABEL(iconst_3),
131 INSN_LABEL(iconst_4),
132 INSN_LABEL(iconst_5),
133 INSN_LABEL(lconst_0),
134 INSN_LABEL(lconst_1),
135 INSN_LABEL(fconst_0),
136 INSN_LABEL(fconst_1),
137 INSN_LABEL(fconst_2),
138 INSN_LABEL(dconst_0),
139 INSN_LABEL(dconst_1),
140 INSN_LABEL(bipush),
141 INSN_LABEL(sipush),
142 INSN_LABEL(ldc),
143 INSN_LABEL(ldc_w),
144 INSN_LABEL(ldc2_w),
145 INSN_LABEL(iload),
146 INSN_LABEL(lload),
147 INSN_LABEL(fload),
148 INSN_LABEL(dload),
149 INSN_LABEL(aload),
150 INSN_LABEL(iload_0),
151 INSN_LABEL(iload_1),
152 INSN_LABEL(iload_2),
153 INSN_LABEL(iload_3),
154 INSN_LABEL(lload_0),
155 INSN_LABEL(lload_1),
156 INSN_LABEL(lload_2),
157 INSN_LABEL(lload_3),
158 INSN_LABEL(fload_0),
159 INSN_LABEL(fload_1),
160 INSN_LABEL(fload_2),
161 INSN_LABEL(fload_3),
162 INSN_LABEL(dload_0),
163 INSN_LABEL(dload_1),
164 INSN_LABEL(dload_2),
165 INSN_LABEL(dload_3),
166 INSN_LABEL(aload_0),
167 INSN_LABEL(aload_1),
168 INSN_LABEL(aload_2),
169 INSN_LABEL(aload_3),
170 INSN_LABEL(iaload),
171 INSN_LABEL(laload),
172 INSN_LABEL(faload),
173 INSN_LABEL(daload),
174 INSN_LABEL(aaload),
175 INSN_LABEL(baload),
176 INSN_LABEL(caload),
177 INSN_LABEL(saload),
178 INSN_LABEL(istore),
179 INSN_LABEL(lstore),
180 INSN_LABEL(fstore),
181 INSN_LABEL(dstore),
182 INSN_LABEL(astore),
183 INSN_LABEL(istore_0),
184 INSN_LABEL(istore_1),
185 INSN_LABEL(istore_2),
186 INSN_LABEL(istore_3),
187 INSN_LABEL(lstore_0),
188 INSN_LABEL(lstore_1),
189 INSN_LABEL(lstore_2),
190 INSN_LABEL(lstore_3),
191 INSN_LABEL(fstore_0),
192 INSN_LABEL(fstore_1),
193 INSN_LABEL(fstore_2),
194 INSN_LABEL(fstore_3),
195 INSN_LABEL(dstore_0),
196 INSN_LABEL(dstore_1),
197 INSN_LABEL(dstore_2),
198 INSN_LABEL(dstore_3),
199 INSN_LABEL(astore_0),
200 INSN_LABEL(astore_1),
201 INSN_LABEL(astore_2),
202 INSN_LABEL(astore_3),
203 INSN_LABEL(iastore),
204 INSN_LABEL(lastore),
205 INSN_LABEL(fastore),
206 INSN_LABEL(dastore),
207 INSN_LABEL(aastore),
208 INSN_LABEL(bastore),
209 INSN_LABEL(castore),
210 INSN_LABEL(sastore),
211 INSN_LABEL(pop),
212 INSN_LABEL(pop2),
213 INSN_LABEL(dup),
214 INSN_LABEL(dup_x1),
215 INSN_LABEL(dup_x2),
216 INSN_LABEL(dup2),
217 INSN_LABEL(dup2_x1),
218 INSN_LABEL(dup2_x2),
219 INSN_LABEL(swap),
220 INSN_LABEL(iadd),
221 INSN_LABEL(ladd),
222 INSN_LABEL(fadd),
223 INSN_LABEL(dadd),
224 INSN_LABEL(isub),
225 INSN_LABEL(lsub),
226 INSN_LABEL(fsub),
227 INSN_LABEL(dsub),
228 INSN_LABEL(imul),
229 INSN_LABEL(lmul),
230 INSN_LABEL(fmul),
231 INSN_LABEL(dmul),
232 INSN_LABEL(idiv),
233 INSN_LABEL(ldiv),
234 INSN_LABEL(fdiv),
235 INSN_LABEL(ddiv),
236 INSN_LABEL(irem),
237 INSN_LABEL(lrem),
238 INSN_LABEL(frem),
239 INSN_LABEL(drem),
240 INSN_LABEL(ineg),
241 INSN_LABEL(lneg),
242 INSN_LABEL(fneg),
243 INSN_LABEL(dneg),
244 INSN_LABEL(ishl),
245 INSN_LABEL(lshl),
246 INSN_LABEL(ishr),
247 INSN_LABEL(lshr),
248 INSN_LABEL(iushr),
249 INSN_LABEL(lushr),
250 INSN_LABEL(iand),
251 INSN_LABEL(land),
252 INSN_LABEL(ior),
253 INSN_LABEL(lor),
254 INSN_LABEL(ixor),
255 INSN_LABEL(lxor),
256 INSN_LABEL(iinc),
257 INSN_LABEL(i2l),
258 INSN_LABEL(i2f),
259 INSN_LABEL(i2d),
260 INSN_LABEL(l2i),
261 INSN_LABEL(l2f),
262 INSN_LABEL(l2d),
263 INSN_LABEL(f2i),
264 INSN_LABEL(f2l),
265 INSN_LABEL(f2d),
266 INSN_LABEL(d2i),
267 INSN_LABEL(d2l),
268 INSN_LABEL(d2f),
269 INSN_LABEL(i2b),
270 INSN_LABEL(i2c),
271 INSN_LABEL(i2s),
272 INSN_LABEL(lcmp),
273 INSN_LABEL(fcmpl),
274 INSN_LABEL(fcmpg),
275 INSN_LABEL(dcmpl),
276 INSN_LABEL(dcmpg),
277 INSN_LABEL(ifeq),
278 INSN_LABEL(ifne),
279 INSN_LABEL(iflt),
280 INSN_LABEL(ifge),
281 INSN_LABEL(ifgt),
282 INSN_LABEL(ifle),
283 INSN_LABEL(if_icmpeq),
284 INSN_LABEL(if_icmpne),
285 INSN_LABEL(if_icmplt),
286 INSN_LABEL(if_icmpge),
287 INSN_LABEL(if_icmpgt),
288 INSN_LABEL(if_icmple),
289 INSN_LABEL(if_acmpeq),
290 INSN_LABEL(if_acmpne),
291 INSN_LABEL(goto),
292 INSN_LABEL(jsr),
293 INSN_LABEL(ret),
294 INSN_LABEL(tableswitch),
295 INSN_LABEL(lookupswitch),
296 INSN_LABEL(ireturn),
297 INSN_LABEL(lreturn),
298 INSN_LABEL(freturn),
299 INSN_LABEL(dreturn),
300 INSN_LABEL(areturn),
301 INSN_LABEL(return),
302 INSN_LABEL(getstatic),
303 INSN_LABEL(putstatic),
304 INSN_LABEL(getfield),
305 INSN_LABEL(putfield),
306 INSN_LABEL(invokevirtual),
307 INSN_LABEL(invokespecial),
308 INSN_LABEL(invokestatic),
309 INSN_LABEL(invokeinterface),
310 INSN_LABEL(breakpoint),
311 INSN_LABEL(new),
312 INSN_LABEL(newarray),
313 INSN_LABEL(anewarray),
314 INSN_LABEL(arraylength),
315 INSN_LABEL(athrow),
316 INSN_LABEL(checkcast),
317 INSN_LABEL(instanceof),
318 INSN_LABEL(monitorenter),
319 INSN_LABEL(monitorexit),
320 #ifdef DIRECT_THREADED
321 0, // wide
322 #else
323 INSN_LABEL(wide),
324 #endif
325 INSN_LABEL(multianewarray),
326 INSN_LABEL(ifnull),
327 INSN_LABEL(ifnonnull),
328 INSN_LABEL(goto_w),
329 INSN_LABEL(jsr_w),
330 #ifdef DIRECT_THREADED
331 INSN_LABEL (ldc_class)
332 #else
334 #endif
337 pc_t pc;
339 #ifdef DIRECT_THREADED
341 #ifdef DEBUG
342 #undef NEXT_INSN
343 #define NEXT_INSN \
344 do \
346 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
348 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
349 jmethodID method = meth->self; \
350 jlocation loc = meth->insn_index (pc); \
351 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
352 env, method, loc); \
354 goto *((pc++)->insn); \
356 while (0)
357 #else
358 #undef NEXT_INSN
359 #define NEXT_INSN goto *((pc++)->insn)
360 #endif
362 #define INTVAL() ((pc++)->int_val)
363 #define AVAL() ((pc++)->datum)
365 #define GET1S() INTVAL ()
366 #define GET2S() INTVAL ()
367 #define GET1U() INTVAL ()
368 #define GET2U() INTVAL ()
369 #define AVAL1U() AVAL ()
370 #define AVAL2U() AVAL ()
371 #define AVAL2UP() AVAL ()
372 #define SKIP_GOTO ++pc
373 #define GOTO_VAL() (insn_slot *) pc->datum
374 #define PCVAL(unionval) unionval.p
375 #define AMPAMP(label) &&label
377 // Compile if we must. NOTE: Double-check locking.
378 if (meth->prepared == NULL)
380 _Jv_MutexLock (&compile_mutex);
381 if (meth->prepared == NULL)
382 meth->compile (insn_target);
383 _Jv_MutexUnlock (&compile_mutex);
386 // If we're only compiling, stop here
387 if (args == NULL)
388 return;
390 pc = (insn_slot *) meth->prepared;
392 #else
394 #ifdef DEBUG
395 #define NEXT_INSN \
396 do \
398 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
400 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
401 jmethodID method = meth->self; \
402 jlocation loc = meth->insn_index (pc); \
403 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
404 env, method, loc); \
406 goto *(insn_target[*pc++])
407 #else
408 #define NEXT_INSN goto *(insn_target[*pc++])
409 #endif
411 #define GET1S() get1s (pc++)
412 #define GET2S() (pc += 2, get2s (pc- 2))
413 #define GET1U() get1u (pc++)
414 #define GET2U() (pc += 2, get2u (pc - 2))
415 // Note that these could be more efficient when not handling 'ldc
416 // class'.
417 #define AVAL1U() \
418 ({ int index = get1u (pc++); \
419 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
420 #define AVAL2U() \
421 ({ int index = get2u (pc); pc += 2; \
422 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
423 // Note that we don't need to resolve the pool entry here as class
424 // constants are never wide.
425 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
426 #define SKIP_GOTO pc += 2
427 #define GOTO_VAL() pc - 1 + get2s (pc)
428 #define PCVAL(unionval) unionval.i
429 #define AMPAMP(label) NULL
431 pc = meth->bytecode ();
433 #endif /* DIRECT_THREADED */
435 #define TAKE_GOTO pc = GOTO_VAL ()
437 /* Go straight at it! the ffi raw format matches the internal
438 stack representation exactly. At least, that's the idea.
440 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
442 _Jv_word *pool_data = meth->defining_class->constants.data;
444 /* These three are temporaries for common code used by several
445 instructions. */
446 void (*fun)();
447 _Jv_ResolvedMethod* rmeth;
448 int tmpval;
452 // We keep nop around. It is used if we're interpreting the
453 // bytecodes and not doing direct threading.
454 insn_nop:
455 NEXT_INSN;
457 /* The first few instructions here are ordered according to their
458 frequency, in the hope that this will improve code locality a
459 little. */
461 insn_aload_0: // 0x2a
462 LOADA (0);
463 NEXT_INSN;
465 insn_iload: // 0x15
466 LOADI (GET1U ());
467 NEXT_INSN;
469 insn_iload_1: // 0x1b
470 LOADI (1);
471 NEXT_INSN;
473 insn_invokevirtual: // 0xb6
475 SAVE_PC();
476 int index = GET2U ();
478 /* _Jv_Linker::resolve_pool_entry returns immediately if the
479 * value already is resolved. If we want to clutter up the
480 * code here to gain a little performance, then we can check
481 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
482 * directly. For now, I don't think it is worth it. */
484 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
485 index)).rmethod;
487 sp -= rmeth->stack_item_count;
489 if (rmeth->method->accflags & Modifier::FINAL)
491 // We can't rely on NULLCHECK working if the method is final.
492 if (! sp[0].o)
493 throw_null_pointer_exception ();
495 // Final methods might not appear in the vtable.
496 fun = (void (*)()) rmeth->method->ncode;
498 else
500 NULLCHECK (sp[0].o);
501 jobject rcv = sp[0].o;
502 _Jv_VTable *table = *(_Jv_VTable**) rcv;
503 fun = (void (*)()) table->get_method (rmeth->method->index);
506 #ifdef DIRECT_THREADED
507 // Rewrite instruction so that we use a faster pre-resolved
508 // method.
509 pc[-2].insn = &&invokevirtual_resolved;
510 pc[-1].datum = rmeth;
511 #endif /* DIRECT_THREADED */
513 goto perform_invoke;
515 #ifdef DIRECT_THREADED
516 invokevirtual_resolved:
518 SAVE_PC();
519 rmeth = (_Jv_ResolvedMethod *) AVAL ();
520 sp -= rmeth->stack_item_count;
522 if (rmeth->method->accflags & Modifier::FINAL)
524 // We can't rely on NULLCHECK working if the method is final.
525 if (! sp[0].o)
526 throw_null_pointer_exception ();
528 // Final methods might not appear in the vtable.
529 fun = (void (*)()) rmeth->method->ncode;
531 else
533 jobject rcv = sp[0].o;
534 _Jv_VTable *table = *(_Jv_VTable**) rcv;
535 fun = (void (*)()) table->get_method (rmeth->method->index);
538 goto perform_invoke;
539 #endif /* DIRECT_THREADED */
541 perform_invoke:
543 /* here goes the magic again... */
544 ffi_cif *cif = &rmeth->cif;
545 ffi_raw *raw = (ffi_raw*) sp;
547 _Jv_value rvalue;
549 #if FFI_NATIVE_RAW_API
550 /* We assume that this is only implemented if it's correct */
551 /* to use it here. On a 64 bit machine, it never is. */
552 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
553 #else
554 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
555 #endif
557 int rtype = cif->rtype->type;
559 /* the likelyhood of object, int, or void return is very high,
560 * so those are checked before the switch */
561 if (rtype == FFI_TYPE_POINTER)
563 PUSHA (rvalue.object_value);
565 else if (rtype == FFI_TYPE_SINT32)
567 PUSHI (rvalue.int_value);
569 else if (rtype == FFI_TYPE_VOID)
571 /* skip */
573 else
575 switch (rtype)
577 case FFI_TYPE_SINT8:
578 PUSHI ((jbyte)(rvalue.int_value & 0xff));
579 break;
581 case FFI_TYPE_SINT16:
582 PUSHI ((jshort)(rvalue.int_value & 0xffff));
583 break;
585 case FFI_TYPE_UINT16:
586 PUSHI (rvalue.int_value & 0xffff);
587 break;
589 case FFI_TYPE_FLOAT:
590 PUSHF (rvalue.float_value);
591 break;
593 case FFI_TYPE_DOUBLE:
594 PUSHD (rvalue.double_value);
595 break;
597 case FFI_TYPE_SINT64:
598 PUSHL (rvalue.long_value);
599 break;
601 default:
602 throw_internal_error ("unknown return type in invokeXXX");
606 NEXT_INSN;
608 insn_aconst_null:
609 PUSHA (NULL);
610 NEXT_INSN;
612 insn_iconst_m1:
613 PUSHI (-1);
614 NEXT_INSN;
616 insn_iconst_0:
617 PUSHI (0);
618 NEXT_INSN;
620 insn_iconst_1:
621 PUSHI (1);
622 NEXT_INSN;
624 insn_iconst_2:
625 PUSHI (2);
626 NEXT_INSN;
628 insn_iconst_3:
629 PUSHI (3);
630 NEXT_INSN;
632 insn_iconst_4:
633 PUSHI (4);
634 NEXT_INSN;
636 insn_iconst_5:
637 PUSHI (5);
638 NEXT_INSN;
640 insn_lconst_0:
641 PUSHL (0);
642 NEXT_INSN;
644 insn_lconst_1:
645 PUSHL (1);
646 NEXT_INSN;
648 insn_fconst_0:
649 PUSHF (0);
650 NEXT_INSN;
652 insn_fconst_1:
653 PUSHF (1);
654 NEXT_INSN;
656 insn_fconst_2:
657 PUSHF (2);
658 NEXT_INSN;
660 insn_dconst_0:
661 PUSHD (0);
662 NEXT_INSN;
664 insn_dconst_1:
665 PUSHD (1);
666 NEXT_INSN;
668 insn_bipush:
669 // For direct threaded, bipush and sipush are the same.
670 #ifndef DIRECT_THREADED
671 PUSHI (GET1S ());
672 NEXT_INSN;
673 #endif /* DIRECT_THREADED */
674 insn_sipush:
675 PUSHI (GET2S ());
676 NEXT_INSN;
678 insn_ldc:
679 // For direct threaded, ldc and ldc_w are the same.
680 #ifndef DIRECT_THREADED
681 PUSHA ((jobject) AVAL1U ());
682 NEXT_INSN;
683 #endif /* DIRECT_THREADED */
684 insn_ldc_w:
685 PUSHA ((jobject) AVAL2U ());
686 NEXT_INSN;
688 #ifdef DIRECT_THREADED
689 // For direct threaded we have a separate 'ldc class' operation.
690 insn_ldc_class:
692 SAVE_PC();
693 // We could rewrite the instruction at this point.
694 int index = INTVAL ();
695 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
696 index)).o;
697 PUSHA (k);
699 NEXT_INSN;
700 #endif /* DIRECT_THREADED */
702 insn_ldc2_w:
704 void *where = AVAL2UP ();
705 memcpy (sp, where, 2*sizeof (_Jv_word));
706 sp += 2;
708 NEXT_INSN;
710 insn_lload:
711 LOADL (GET1U ());
712 NEXT_INSN;
714 insn_fload:
715 LOADF (GET1U ());
716 NEXT_INSN;
718 insn_dload:
719 LOADD (GET1U ());
720 NEXT_INSN;
722 insn_aload:
723 LOADA (GET1U ());
724 NEXT_INSN;
726 insn_iload_0:
727 LOADI (0);
728 NEXT_INSN;
730 insn_iload_2:
731 LOADI (2);
732 NEXT_INSN;
734 insn_iload_3:
735 LOADI (3);
736 NEXT_INSN;
738 insn_lload_0:
739 LOADL (0);
740 NEXT_INSN;
742 insn_lload_1:
743 LOADL (1);
744 NEXT_INSN;
746 insn_lload_2:
747 LOADL (2);
748 NEXT_INSN;
750 insn_lload_3:
751 LOADL (3);
752 NEXT_INSN;
754 insn_fload_0:
755 LOADF (0);
756 NEXT_INSN;
758 insn_fload_1:
759 LOADF (1);
760 NEXT_INSN;
762 insn_fload_2:
763 LOADF (2);
764 NEXT_INSN;
766 insn_fload_3:
767 LOADF (3);
768 NEXT_INSN;
770 insn_dload_0:
771 LOADD (0);
772 NEXT_INSN;
774 insn_dload_1:
775 LOADD (1);
776 NEXT_INSN;
778 insn_dload_2:
779 LOADD (2);
780 NEXT_INSN;
782 insn_dload_3:
783 LOADD (3);
784 NEXT_INSN;
786 insn_aload_1:
787 LOADA(1);
788 NEXT_INSN;
790 insn_aload_2:
791 LOADA(2);
792 NEXT_INSN;
794 insn_aload_3:
795 LOADA(3);
796 NEXT_INSN;
798 insn_iaload:
800 jint index = POPI();
801 jintArray arr = (jintArray) POPA();
802 NULLARRAYCHECK (arr);
803 ARRAYBOUNDSCHECK (arr, index);
804 PUSHI( elements(arr)[index] );
806 NEXT_INSN;
808 insn_laload:
810 jint index = POPI();
811 jlongArray arr = (jlongArray) POPA();
812 NULLARRAYCHECK (arr);
813 ARRAYBOUNDSCHECK (arr, index);
814 PUSHL( elements(arr)[index] );
816 NEXT_INSN;
818 insn_faload:
820 jint index = POPI();
821 jfloatArray arr = (jfloatArray) POPA();
822 NULLARRAYCHECK (arr);
823 ARRAYBOUNDSCHECK (arr, index);
824 PUSHF( elements(arr)[index] );
826 NEXT_INSN;
828 insn_daload:
830 jint index = POPI();
831 jdoubleArray arr = (jdoubleArray) POPA();
832 NULLARRAYCHECK (arr);
833 ARRAYBOUNDSCHECK (arr, index);
834 PUSHD( elements(arr)[index] );
836 NEXT_INSN;
838 insn_aaload:
840 jint index = POPI();
841 jobjectArray arr = (jobjectArray) POPA();
842 NULLARRAYCHECK (arr);
843 ARRAYBOUNDSCHECK (arr, index);
844 PUSHA( elements(arr)[index] );
846 NEXT_INSN;
848 insn_baload:
850 jint index = POPI();
851 jbyteArray arr = (jbyteArray) POPA();
852 NULLARRAYCHECK (arr);
853 ARRAYBOUNDSCHECK (arr, index);
854 PUSHI( elements(arr)[index] );
856 NEXT_INSN;
858 insn_caload:
860 jint index = POPI();
861 jcharArray arr = (jcharArray) POPA();
862 NULLARRAYCHECK (arr);
863 ARRAYBOUNDSCHECK (arr, index);
864 PUSHI( elements(arr)[index] );
866 NEXT_INSN;
868 insn_saload:
870 jint index = POPI();
871 jshortArray arr = (jshortArray) POPA();
872 NULLARRAYCHECK (arr);
873 ARRAYBOUNDSCHECK (arr, index);
874 PUSHI( elements(arr)[index] );
876 NEXT_INSN;
878 insn_istore:
879 STOREI (GET1U ());
880 NEXT_INSN;
882 insn_lstore:
883 STOREL (GET1U ());
884 NEXT_INSN;
886 insn_fstore:
887 STOREF (GET1U ());
888 NEXT_INSN;
890 insn_dstore:
891 STORED (GET1U ());
892 NEXT_INSN;
894 insn_astore:
895 STOREA (GET1U ());
896 NEXT_INSN;
898 insn_istore_0:
899 STOREI (0);
900 NEXT_INSN;
902 insn_istore_1:
903 STOREI (1);
904 NEXT_INSN;
906 insn_istore_2:
907 STOREI (2);
908 NEXT_INSN;
910 insn_istore_3:
911 STOREI (3);
912 NEXT_INSN;
914 insn_lstore_0:
915 STOREL (0);
916 NEXT_INSN;
918 insn_lstore_1:
919 STOREL (1);
920 NEXT_INSN;
922 insn_lstore_2:
923 STOREL (2);
924 NEXT_INSN;
926 insn_lstore_3:
927 STOREL (3);
928 NEXT_INSN;
930 insn_fstore_0:
931 STOREF (0);
932 NEXT_INSN;
934 insn_fstore_1:
935 STOREF (1);
936 NEXT_INSN;
938 insn_fstore_2:
939 STOREF (2);
940 NEXT_INSN;
942 insn_fstore_3:
943 STOREF (3);
944 NEXT_INSN;
946 insn_dstore_0:
947 STORED (0);
948 NEXT_INSN;
950 insn_dstore_1:
951 STORED (1);
952 NEXT_INSN;
954 insn_dstore_2:
955 STORED (2);
956 NEXT_INSN;
958 insn_dstore_3:
959 STORED (3);
960 NEXT_INSN;
962 insn_astore_0:
963 STOREA(0);
964 NEXT_INSN;
966 insn_astore_1:
967 STOREA(1);
968 NEXT_INSN;
970 insn_astore_2:
971 STOREA(2);
972 NEXT_INSN;
974 insn_astore_3:
975 STOREA(3);
976 NEXT_INSN;
978 insn_iastore:
980 jint value = POPI();
981 jint index = POPI();
982 jintArray arr = (jintArray) POPA();
983 NULLARRAYCHECK (arr);
984 ARRAYBOUNDSCHECK (arr, index);
985 elements(arr)[index] = value;
987 NEXT_INSN;
989 insn_lastore:
991 jlong value = POPL();
992 jint index = POPI();
993 jlongArray arr = (jlongArray) POPA();
994 NULLARRAYCHECK (arr);
995 ARRAYBOUNDSCHECK (arr, index);
996 elements(arr)[index] = value;
998 NEXT_INSN;
1000 insn_fastore:
1002 jfloat value = POPF();
1003 jint index = POPI();
1004 jfloatArray arr = (jfloatArray) POPA();
1005 NULLARRAYCHECK (arr);
1006 ARRAYBOUNDSCHECK (arr, index);
1007 elements(arr)[index] = value;
1009 NEXT_INSN;
1011 insn_dastore:
1013 jdouble value = POPD();
1014 jint index = POPI();
1015 jdoubleArray arr = (jdoubleArray) POPA();
1016 NULLARRAYCHECK (arr);
1017 ARRAYBOUNDSCHECK (arr, index);
1018 elements(arr)[index] = value;
1020 NEXT_INSN;
1022 insn_aastore:
1024 jobject value = POPA();
1025 jint index = POPI();
1026 jobjectArray arr = (jobjectArray) POPA();
1027 NULLARRAYCHECK (arr);
1028 ARRAYBOUNDSCHECK (arr, index);
1029 _Jv_CheckArrayStore (arr, value);
1030 elements(arr)[index] = value;
1032 NEXT_INSN;
1034 insn_bastore:
1036 jbyte value = (jbyte) POPI();
1037 jint index = POPI();
1038 jbyteArray arr = (jbyteArray) POPA();
1039 NULLARRAYCHECK (arr);
1040 ARRAYBOUNDSCHECK (arr, index);
1041 elements(arr)[index] = value;
1043 NEXT_INSN;
1045 insn_castore:
1047 jchar value = (jchar) POPI();
1048 jint index = POPI();
1049 jcharArray arr = (jcharArray) POPA();
1050 NULLARRAYCHECK (arr);
1051 ARRAYBOUNDSCHECK (arr, index);
1052 elements(arr)[index] = value;
1054 NEXT_INSN;
1056 insn_sastore:
1058 jshort value = (jshort) POPI();
1059 jint index = POPI();
1060 jshortArray arr = (jshortArray) POPA();
1061 NULLARRAYCHECK (arr);
1062 ARRAYBOUNDSCHECK (arr, index);
1063 elements(arr)[index] = value;
1065 NEXT_INSN;
1067 insn_pop:
1068 sp -= 1;
1069 NEXT_INSN;
1071 insn_pop2:
1072 sp -= 2;
1073 NEXT_INSN;
1075 insn_dup:
1076 sp[0] = sp[-1];
1077 sp += 1;
1078 NEXT_INSN;
1080 insn_dup_x1:
1081 dupx (sp, 1, 1); sp+=1;
1082 NEXT_INSN;
1084 insn_dup_x2:
1085 dupx (sp, 1, 2); sp+=1;
1086 NEXT_INSN;
1088 insn_dup2:
1089 sp[0] = sp[-2];
1090 sp[1] = sp[-1];
1091 sp += 2;
1092 NEXT_INSN;
1094 insn_dup2_x1:
1095 dupx (sp, 2, 1); sp+=2;
1096 NEXT_INSN;
1098 insn_dup2_x2:
1099 dupx (sp, 2, 2); sp+=2;
1100 NEXT_INSN;
1102 insn_swap:
1104 jobject tmp1 = POPA();
1105 jobject tmp2 = POPA();
1106 PUSHA (tmp1);
1107 PUSHA (tmp2);
1109 NEXT_INSN;
1111 insn_iadd:
1112 BINOPI(+);
1113 NEXT_INSN;
1115 insn_ladd:
1116 BINOPL(+);
1117 NEXT_INSN;
1119 insn_fadd:
1120 BINOPF(+);
1121 NEXT_INSN;
1123 insn_dadd:
1124 BINOPD(+);
1125 NEXT_INSN;
1127 insn_isub:
1128 BINOPI(-);
1129 NEXT_INSN;
1131 insn_lsub:
1132 BINOPL(-);
1133 NEXT_INSN;
1135 insn_fsub:
1136 BINOPF(-);
1137 NEXT_INSN;
1139 insn_dsub:
1140 BINOPD(-);
1141 NEXT_INSN;
1143 insn_imul:
1144 BINOPI(*);
1145 NEXT_INSN;
1147 insn_lmul:
1148 BINOPL(*);
1149 NEXT_INSN;
1151 insn_fmul:
1152 BINOPF(*);
1153 NEXT_INSN;
1155 insn_dmul:
1156 BINOPD(*);
1157 NEXT_INSN;
1159 insn_idiv:
1161 SAVE_PC();
1162 jint value2 = POPI();
1163 jint value1 = POPI();
1164 jint res = _Jv_divI (value1, value2);
1165 PUSHI (res);
1167 NEXT_INSN;
1169 insn_ldiv:
1171 SAVE_PC();
1172 jlong value2 = POPL();
1173 jlong value1 = POPL();
1174 jlong res = _Jv_divJ (value1, value2);
1175 PUSHL (res);
1177 NEXT_INSN;
1179 insn_fdiv:
1181 jfloat value2 = POPF();
1182 jfloat value1 = POPF();
1183 jfloat res = value1 / value2;
1184 PUSHF (res);
1186 NEXT_INSN;
1188 insn_ddiv:
1190 jdouble value2 = POPD();
1191 jdouble value1 = POPD();
1192 jdouble res = value1 / value2;
1193 PUSHD (res);
1195 NEXT_INSN;
1197 insn_irem:
1199 SAVE_PC();
1200 jint value2 = POPI();
1201 jint value1 = POPI();
1202 jint res = _Jv_remI (value1, value2);
1203 PUSHI (res);
1205 NEXT_INSN;
1207 insn_lrem:
1209 SAVE_PC();
1210 jlong value2 = POPL();
1211 jlong value1 = POPL();
1212 jlong res = _Jv_remJ (value1, value2);
1213 PUSHL (res);
1215 NEXT_INSN;
1217 insn_frem:
1219 jfloat value2 = POPF();
1220 jfloat value1 = POPF();
1221 jfloat res = __ieee754_fmod (value1, value2);
1222 PUSHF (res);
1224 NEXT_INSN;
1226 insn_drem:
1228 jdouble value2 = POPD();
1229 jdouble value1 = POPD();
1230 jdouble res = __ieee754_fmod (value1, value2);
1231 PUSHD (res);
1233 NEXT_INSN;
1235 insn_ineg:
1237 jint value = POPI();
1238 PUSHI (value * -1);
1240 NEXT_INSN;
1242 insn_lneg:
1244 jlong value = POPL();
1245 PUSHL (value * -1);
1247 NEXT_INSN;
1249 insn_fneg:
1251 jfloat value = POPF();
1252 PUSHF (value * -1);
1254 NEXT_INSN;
1256 insn_dneg:
1258 jdouble value = POPD();
1259 PUSHD (value * -1);
1261 NEXT_INSN;
1263 insn_ishl:
1265 jint shift = (POPI() & 0x1f);
1266 jint value = POPI();
1267 PUSHI (value << shift);
1269 NEXT_INSN;
1271 insn_lshl:
1273 jint shift = (POPI() & 0x3f);
1274 jlong value = POPL();
1275 PUSHL (value << shift);
1277 NEXT_INSN;
1279 insn_ishr:
1281 jint shift = (POPI() & 0x1f);
1282 jint value = POPI();
1283 PUSHI (value >> shift);
1285 NEXT_INSN;
1287 insn_lshr:
1289 jint shift = (POPI() & 0x3f);
1290 jlong value = POPL();
1291 PUSHL (value >> shift);
1293 NEXT_INSN;
1295 insn_iushr:
1297 jint shift = (POPI() & 0x1f);
1298 _Jv_uint value = (_Jv_uint) POPI();
1299 PUSHI ((jint) (value >> shift));
1301 NEXT_INSN;
1303 insn_lushr:
1305 jint shift = (POPI() & 0x3f);
1306 _Jv_ulong value = (_Jv_ulong) POPL();
1307 PUSHL ((jlong) (value >> shift));
1309 NEXT_INSN;
1311 insn_iand:
1312 BINOPI (&);
1313 NEXT_INSN;
1315 insn_land:
1316 BINOPL (&);
1317 NEXT_INSN;
1319 insn_ior:
1320 BINOPI (|);
1321 NEXT_INSN;
1323 insn_lor:
1324 BINOPL (|);
1325 NEXT_INSN;
1327 insn_ixor:
1328 BINOPI (^);
1329 NEXT_INSN;
1331 insn_lxor:
1332 BINOPL (^);
1333 NEXT_INSN;
1335 insn_iinc:
1337 jint index = GET1U ();
1338 jint amount = GET1S ();
1339 locals[index].i += amount;
1341 NEXT_INSN;
1343 insn_i2l:
1344 {jlong value = POPI(); PUSHL (value);}
1345 NEXT_INSN;
1347 insn_i2f:
1348 {jfloat value = POPI(); PUSHF (value);}
1349 NEXT_INSN;
1351 insn_i2d:
1352 {jdouble value = POPI(); PUSHD (value);}
1353 NEXT_INSN;
1355 insn_l2i:
1356 {jint value = POPL(); PUSHI (value);}
1357 NEXT_INSN;
1359 insn_l2f:
1360 {jfloat value = POPL(); PUSHF (value);}
1361 NEXT_INSN;
1363 insn_l2d:
1364 {jdouble value = POPL(); PUSHD (value);}
1365 NEXT_INSN;
1367 insn_f2i:
1369 using namespace java::lang;
1370 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1371 PUSHI(value);
1373 NEXT_INSN;
1375 insn_f2l:
1377 using namespace java::lang;
1378 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1379 PUSHL(value);
1381 NEXT_INSN;
1383 insn_f2d:
1384 { jdouble value = POPF (); PUSHD(value); }
1385 NEXT_INSN;
1387 insn_d2i:
1389 using namespace java::lang;
1390 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1391 PUSHI(value);
1393 NEXT_INSN;
1395 insn_d2l:
1397 using namespace java::lang;
1398 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1399 PUSHL(value);
1401 NEXT_INSN;
1403 insn_d2f:
1404 { jfloat value = POPD (); PUSHF(value); }
1405 NEXT_INSN;
1407 insn_i2b:
1408 { jbyte value = POPI (); PUSHI(value); }
1409 NEXT_INSN;
1411 insn_i2c:
1412 { jchar value = POPI (); PUSHI(value); }
1413 NEXT_INSN;
1415 insn_i2s:
1416 { jshort value = POPI (); PUSHI(value); }
1417 NEXT_INSN;
1419 insn_lcmp:
1421 jlong value2 = POPL ();
1422 jlong value1 = POPL ();
1423 if (value1 > value2)
1424 { PUSHI (1); }
1425 else if (value1 == value2)
1426 { PUSHI (0); }
1427 else
1428 { PUSHI (-1); }
1430 NEXT_INSN;
1432 insn_fcmpl:
1433 tmpval = -1;
1434 goto fcmp;
1436 insn_fcmpg:
1437 tmpval = 1;
1439 fcmp:
1441 jfloat value2 = POPF ();
1442 jfloat value1 = POPF ();
1443 if (value1 > value2)
1444 PUSHI (1);
1445 else if (value1 == value2)
1446 PUSHI (0);
1447 else if (value1 < value2)
1448 PUSHI (-1);
1449 else
1450 PUSHI (tmpval);
1452 NEXT_INSN;
1454 insn_dcmpl:
1455 tmpval = -1;
1456 goto dcmp;
1458 insn_dcmpg:
1459 tmpval = 1;
1461 dcmp:
1463 jdouble value2 = POPD ();
1464 jdouble value1 = POPD ();
1465 if (value1 > value2)
1466 PUSHI (1);
1467 else if (value1 == value2)
1468 PUSHI (0);
1469 else if (value1 < value2)
1470 PUSHI (-1);
1471 else
1472 PUSHI (tmpval);
1474 NEXT_INSN;
1476 insn_ifeq:
1478 if (POPI() == 0)
1479 TAKE_GOTO;
1480 else
1481 SKIP_GOTO;
1483 NEXT_INSN;
1485 insn_ifne:
1487 if (POPI() != 0)
1488 TAKE_GOTO;
1489 else
1490 SKIP_GOTO;
1492 NEXT_INSN;
1494 insn_iflt:
1496 if (POPI() < 0)
1497 TAKE_GOTO;
1498 else
1499 SKIP_GOTO;
1501 NEXT_INSN;
1503 insn_ifge:
1505 if (POPI() >= 0)
1506 TAKE_GOTO;
1507 else
1508 SKIP_GOTO;
1510 NEXT_INSN;
1512 insn_ifgt:
1514 if (POPI() > 0)
1515 TAKE_GOTO;
1516 else
1517 SKIP_GOTO;
1519 NEXT_INSN;
1521 insn_ifle:
1523 if (POPI() <= 0)
1524 TAKE_GOTO;
1525 else
1526 SKIP_GOTO;
1528 NEXT_INSN;
1530 insn_if_icmpeq:
1532 jint value2 = POPI();
1533 jint value1 = POPI();
1534 if (value1 == value2)
1535 TAKE_GOTO;
1536 else
1537 SKIP_GOTO;
1539 NEXT_INSN;
1541 insn_if_icmpne:
1543 jint value2 = POPI();
1544 jint value1 = POPI();
1545 if (value1 != value2)
1546 TAKE_GOTO;
1547 else
1548 SKIP_GOTO;
1550 NEXT_INSN;
1552 insn_if_icmplt:
1554 jint value2 = POPI();
1555 jint value1 = POPI();
1556 if (value1 < value2)
1557 TAKE_GOTO;
1558 else
1559 SKIP_GOTO;
1561 NEXT_INSN;
1563 insn_if_icmpge:
1565 jint value2 = POPI();
1566 jint value1 = POPI();
1567 if (value1 >= value2)
1568 TAKE_GOTO;
1569 else
1570 SKIP_GOTO;
1572 NEXT_INSN;
1574 insn_if_icmpgt:
1576 jint value2 = POPI();
1577 jint value1 = POPI();
1578 if (value1 > value2)
1579 TAKE_GOTO;
1580 else
1581 SKIP_GOTO;
1583 NEXT_INSN;
1585 insn_if_icmple:
1587 jint value2 = POPI();
1588 jint value1 = POPI();
1589 if (value1 <= value2)
1590 TAKE_GOTO;
1591 else
1592 SKIP_GOTO;
1594 NEXT_INSN;
1596 insn_if_acmpeq:
1598 jobject value2 = POPA();
1599 jobject value1 = POPA();
1600 if (value1 == value2)
1601 TAKE_GOTO;
1602 else
1603 SKIP_GOTO;
1605 NEXT_INSN;
1607 insn_if_acmpne:
1609 jobject value2 = POPA();
1610 jobject value1 = POPA();
1611 if (value1 != value2)
1612 TAKE_GOTO;
1613 else
1614 SKIP_GOTO;
1616 NEXT_INSN;
1618 insn_goto_w:
1619 #ifndef DIRECT_THREADED
1620 // For direct threaded, goto and goto_w are the same.
1621 pc = pc - 1 + get4 (pc);
1622 NEXT_INSN;
1623 #endif /* DIRECT_THREADED */
1624 insn_goto:
1625 TAKE_GOTO;
1626 NEXT_INSN;
1628 insn_jsr_w:
1629 #ifndef DIRECT_THREADED
1630 // For direct threaded, jsr and jsr_w are the same.
1632 pc_t next = pc - 1 + get4 (pc);
1633 pc += 4;
1634 PUSHA ((jobject) pc);
1635 pc = next;
1637 NEXT_INSN;
1638 #endif /* DIRECT_THREADED */
1639 insn_jsr:
1641 pc_t next = GOTO_VAL();
1642 SKIP_GOTO;
1643 PUSHA ((jobject) pc);
1644 pc = next;
1646 NEXT_INSN;
1648 insn_ret:
1650 jint index = GET1U ();
1651 pc = (pc_t) PEEKA (index);
1653 NEXT_INSN;
1655 insn_tableswitch:
1657 #ifdef DIRECT_THREADED
1658 void *def = (pc++)->datum;
1660 int index = POPI();
1662 jint low = INTVAL ();
1663 jint high = INTVAL ();
1665 if (index < low || index > high)
1666 pc = (insn_slot *) def;
1667 else
1668 pc = (insn_slot *) ((pc + index - low)->datum);
1669 #else
1670 pc_t base_pc = pc - 1;
1671 int index = POPI ();
1673 pc_t base = (pc_t) meth->bytecode ();
1674 while ((pc - base) % 4 != 0)
1675 ++pc;
1677 jint def = get4 (pc);
1678 jint low = get4 (pc + 4);
1679 jint high = get4 (pc + 8);
1680 if (index < low || index > high)
1681 pc = base_pc + def;
1682 else
1683 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1684 #endif /* DIRECT_THREADED */
1686 NEXT_INSN;
1688 insn_lookupswitch:
1690 #ifdef DIRECT_THREADED
1691 void *def = (pc++)->insn;
1693 int index = POPI();
1695 jint npairs = INTVAL ();
1697 int max = npairs - 1;
1698 int min = 0;
1700 // Simple binary search...
1701 while (min < max)
1703 int half = (min + max) / 2;
1704 int match = pc[2 * half].int_val;
1706 if (index == match)
1708 // Found it.
1709 pc = (insn_slot *) pc[2 * half + 1].datum;
1710 NEXT_INSN;
1712 else if (index < match)
1713 // We can use HALF - 1 here because we check again on
1714 // loop exit.
1715 max = half - 1;
1716 else
1717 // We can use HALF + 1 here because we check again on
1718 // loop exit.
1719 min = half + 1;
1721 if (index == pc[2 * min].int_val)
1722 pc = (insn_slot *) pc[2 * min + 1].datum;
1723 else
1724 pc = (insn_slot *) def;
1725 #else
1726 unsigned char *base_pc = pc-1;
1727 int index = POPI();
1729 unsigned char* base = meth->bytecode ();
1730 while ((pc-base) % 4 != 0)
1731 ++pc;
1733 jint def = get4 (pc);
1734 jint npairs = get4 (pc+4);
1736 int max = npairs-1;
1737 int min = 0;
1739 // Simple binary search...
1740 while (min < max)
1742 int half = (min+max)/2;
1743 int match = get4 (pc+ 4*(2 + 2*half));
1745 if (index == match)
1746 min = max = half;
1747 else if (index < match)
1748 // We can use HALF - 1 here because we check again on
1749 // loop exit.
1750 max = half - 1;
1751 else
1752 // We can use HALF + 1 here because we check again on
1753 // loop exit.
1754 min = half + 1;
1757 if (index == get4 (pc+ 4*(2 + 2*min)))
1758 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1759 else
1760 pc = base_pc + def;
1761 #endif /* DIRECT_THREADED */
1763 NEXT_INSN;
1765 insn_areturn:
1766 *(jobject *) retp = POPA ();
1767 return;
1769 insn_lreturn:
1770 *(jlong *) retp = POPL ();
1771 return;
1773 insn_freturn:
1774 *(jfloat *) retp = POPF ();
1775 return;
1777 insn_dreturn:
1778 *(jdouble *) retp = POPD ();
1779 return;
1781 insn_ireturn:
1782 *(jint *) retp = POPI ();
1783 return;
1785 insn_return:
1786 return;
1788 insn_getstatic:
1790 jint fieldref_index = GET2U ();
1791 SAVE_PC(); // Constant pool resolution could throw.
1792 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1793 _Jv_Field *field = pool_data[fieldref_index].field;
1795 if ((field->flags & Modifier::STATIC) == 0)
1796 throw_incompatible_class_change_error
1797 (JvNewStringLatin1 ("field no longer static"));
1799 jclass type = field->type;
1801 // We rewrite the instruction once we discover what it refers
1802 // to.
1803 void *newinsn = NULL;
1804 if (type->isPrimitive ())
1806 switch (type->size_in_bytes)
1808 case 1:
1809 PUSHI (*field->u.byte_addr);
1810 newinsn = AMPAMP (getstatic_resolved_1);
1811 break;
1813 case 2:
1814 if (type == JvPrimClass (char))
1816 PUSHI (*field->u.char_addr);
1817 newinsn = AMPAMP (getstatic_resolved_char);
1819 else
1821 PUSHI (*field->u.short_addr);
1822 newinsn = AMPAMP (getstatic_resolved_short);
1824 break;
1826 case 4:
1827 PUSHI(*field->u.int_addr);
1828 newinsn = AMPAMP (getstatic_resolved_4);
1829 break;
1831 case 8:
1832 PUSHL(*field->u.long_addr);
1833 newinsn = AMPAMP (getstatic_resolved_8);
1834 break;
1837 else
1839 PUSHA(*field->u.object_addr);
1840 newinsn = AMPAMP (getstatic_resolved_obj);
1843 #ifdef DIRECT_THREADED
1844 pc[-2].insn = newinsn;
1845 pc[-1].datum = field->u.addr;
1846 #endif /* DIRECT_THREADED */
1848 NEXT_INSN;
1850 #ifdef DIRECT_THREADED
1851 getstatic_resolved_1:
1852 PUSHI (*(jbyte *) AVAL ());
1853 NEXT_INSN;
1855 getstatic_resolved_char:
1856 PUSHI (*(jchar *) AVAL ());
1857 NEXT_INSN;
1859 getstatic_resolved_short:
1860 PUSHI (*(jshort *) AVAL ());
1861 NEXT_INSN;
1863 getstatic_resolved_4:
1864 PUSHI (*(jint *) AVAL ());
1865 NEXT_INSN;
1867 getstatic_resolved_8:
1868 PUSHL (*(jlong *) AVAL ());
1869 NEXT_INSN;
1871 getstatic_resolved_obj:
1872 PUSHA (*(jobject *) AVAL ());
1873 NEXT_INSN;
1874 #endif /* DIRECT_THREADED */
1876 insn_getfield:
1878 SAVE_PC();
1879 jint fieldref_index = GET2U ();
1880 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1881 _Jv_Field *field = pool_data[fieldref_index].field;
1883 if ((field->flags & Modifier::STATIC) != 0)
1884 throw_incompatible_class_change_error
1885 (JvNewStringLatin1 ("field is static"));
1887 jclass type = field->type;
1888 jint field_offset = field->u.boffset;
1890 jobject obj = POPA();
1891 NULLCHECK(obj);
1893 void *newinsn = NULL;
1894 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1895 if (type->isPrimitive ())
1897 switch (type->size_in_bytes)
1899 case 1:
1900 PUSHI (val->byte_value);
1901 newinsn = AMPAMP (getfield_resolved_1);
1902 break;
1904 case 2:
1905 if (type == JvPrimClass (char))
1907 PUSHI (val->char_value);
1908 newinsn = AMPAMP (getfield_resolved_char);
1910 else
1912 PUSHI (val->short_value);
1913 newinsn = AMPAMP (getfield_resolved_short);
1915 break;
1917 case 4:
1918 PUSHI (val->int_value);
1919 newinsn = AMPAMP (getfield_resolved_4);
1920 break;
1922 case 8:
1923 PUSHL (val->long_value);
1924 newinsn = AMPAMP (getfield_resolved_8);
1925 break;
1928 else
1930 PUSHA (val->object_value);
1931 newinsn = AMPAMP (getfield_resolved_obj);
1934 #ifdef DIRECT_THREADED
1935 pc[-2].insn = newinsn;
1936 pc[-1].int_val = field_offset;
1937 #endif /* DIRECT_THREADED */
1939 NEXT_INSN;
1941 #ifdef DIRECT_THREADED
1942 getfield_resolved_1:
1944 char *obj = (char *) POPA ();
1945 NULLCHECK (obj);
1946 PUSHI (*(jbyte *) (obj + INTVAL ()));
1948 NEXT_INSN;
1950 getfield_resolved_char:
1952 char *obj = (char *) POPA ();
1953 NULLCHECK (obj);
1954 PUSHI (*(jchar *) (obj + INTVAL ()));
1956 NEXT_INSN;
1958 getfield_resolved_short:
1960 char *obj = (char *) POPA ();
1961 NULLCHECK (obj);
1962 PUSHI (*(jshort *) (obj + INTVAL ()));
1964 NEXT_INSN;
1966 getfield_resolved_4:
1968 char *obj = (char *) POPA ();
1969 NULLCHECK (obj);
1970 PUSHI (*(jint *) (obj + INTVAL ()));
1972 NEXT_INSN;
1974 getfield_resolved_8:
1976 char *obj = (char *) POPA ();
1977 NULLCHECK (obj);
1978 PUSHL (*(jlong *) (obj + INTVAL ()));
1980 NEXT_INSN;
1982 getfield_resolved_obj:
1984 char *obj = (char *) POPA ();
1985 NULLCHECK (obj);
1986 PUSHA (*(jobject *) (obj + INTVAL ()));
1988 NEXT_INSN;
1989 #endif /* DIRECT_THREADED */
1991 insn_putstatic:
1993 SAVE_PC();
1994 jint fieldref_index = GET2U ();
1995 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1996 _Jv_Field *field = pool_data[fieldref_index].field;
1998 jclass type = field->type;
2000 // ResolvePoolEntry cannot check this
2001 if ((field->flags & Modifier::STATIC) == 0)
2002 throw_incompatible_class_change_error
2003 (JvNewStringLatin1 ("field no longer static"));
2005 void *newinsn = NULL;
2006 if (type->isPrimitive ())
2008 switch (type->size_in_bytes)
2010 case 1:
2012 jint value = POPI();
2013 *field->u.byte_addr = value;
2014 newinsn = AMPAMP (putstatic_resolved_1);
2015 break;
2018 case 2:
2020 jint value = POPI();
2021 *field->u.char_addr = value;
2022 newinsn = AMPAMP (putstatic_resolved_2);
2023 break;
2026 case 4:
2028 jint value = POPI();
2029 *field->u.int_addr = value;
2030 newinsn = AMPAMP (putstatic_resolved_4);
2031 break;
2034 case 8:
2036 jlong value = POPL();
2037 *field->u.long_addr = value;
2038 newinsn = AMPAMP (putstatic_resolved_8);
2039 break;
2043 else
2045 jobject value = POPA();
2046 *field->u.object_addr = value;
2047 newinsn = AMPAMP (putstatic_resolved_obj);
2050 #ifdef DIRECT_THREADED
2051 pc[-2].insn = newinsn;
2052 pc[-1].datum = field->u.addr;
2053 #endif /* DIRECT_THREADED */
2055 NEXT_INSN;
2057 #ifdef DIRECT_THREADED
2058 putstatic_resolved_1:
2059 *(jbyte *) AVAL () = POPI ();
2060 NEXT_INSN;
2062 putstatic_resolved_2:
2063 *(jchar *) AVAL () = POPI ();
2064 NEXT_INSN;
2066 putstatic_resolved_4:
2067 *(jint *) AVAL () = POPI ();
2068 NEXT_INSN;
2070 putstatic_resolved_8:
2071 *(jlong *) AVAL () = POPL ();
2072 NEXT_INSN;
2074 putstatic_resolved_obj:
2075 *(jobject *) AVAL () = POPA ();
2076 NEXT_INSN;
2077 #endif /* DIRECT_THREADED */
2079 insn_putfield:
2081 SAVE_PC();
2082 jint fieldref_index = GET2U ();
2083 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2084 _Jv_Field *field = pool_data[fieldref_index].field;
2086 jclass type = field->type;
2088 if ((field->flags & Modifier::STATIC) != 0)
2089 throw_incompatible_class_change_error
2090 (JvNewStringLatin1 ("field is static"));
2092 jint field_offset = field->u.boffset;
2094 void *newinsn = NULL;
2095 if (type->isPrimitive ())
2097 switch (type->size_in_bytes)
2099 case 1:
2101 jint value = POPI();
2102 jobject obj = POPA();
2103 NULLCHECK(obj);
2104 *(jbyte*) ((char*)obj + field_offset) = value;
2105 newinsn = AMPAMP (putfield_resolved_1);
2106 break;
2109 case 2:
2111 jint value = POPI();
2112 jobject obj = POPA();
2113 NULLCHECK(obj);
2114 *(jchar*) ((char*)obj + field_offset) = value;
2115 newinsn = AMPAMP (putfield_resolved_2);
2116 break;
2119 case 4:
2121 jint value = POPI();
2122 jobject obj = POPA();
2123 NULLCHECK(obj);
2124 *(jint*) ((char*)obj + field_offset) = value;
2125 newinsn = AMPAMP (putfield_resolved_4);
2126 break;
2129 case 8:
2131 jlong value = POPL();
2132 jobject obj = POPA();
2133 NULLCHECK(obj);
2134 *(jlong*) ((char*)obj + field_offset) = value;
2135 newinsn = AMPAMP (putfield_resolved_8);
2136 break;
2140 else
2142 jobject value = POPA();
2143 jobject obj = POPA();
2144 NULLCHECK(obj);
2145 *(jobject*) ((char*)obj + field_offset) = value;
2146 newinsn = AMPAMP (putfield_resolved_obj);
2149 #ifdef DIRECT_THREADED
2150 pc[-2].insn = newinsn;
2151 pc[-1].int_val = field_offset;
2152 #endif /* DIRECT_THREADED */
2154 NEXT_INSN;
2156 #ifdef DIRECT_THREADED
2157 putfield_resolved_1:
2159 jint val = POPI ();
2160 char *obj = (char *) POPA ();
2161 NULLCHECK (obj);
2162 *(jbyte *) (obj + INTVAL ()) = val;
2164 NEXT_INSN;
2166 putfield_resolved_2:
2168 jint val = POPI ();
2169 char *obj = (char *) POPA ();
2170 NULLCHECK (obj);
2171 *(jchar *) (obj + INTVAL ()) = val;
2173 NEXT_INSN;
2175 putfield_resolved_4:
2177 jint val = POPI ();
2178 char *obj = (char *) POPA ();
2179 NULLCHECK (obj);
2180 *(jint *) (obj + INTVAL ()) = val;
2182 NEXT_INSN;
2184 putfield_resolved_8:
2186 jlong val = POPL ();
2187 char *obj = (char *) POPA ();
2188 NULLCHECK (obj);
2189 *(jlong *) (obj + INTVAL ()) = val;
2191 NEXT_INSN;
2193 putfield_resolved_obj:
2195 jobject val = POPA ();
2196 char *obj = (char *) POPA ();
2197 NULLCHECK (obj);
2198 *(jobject *) (obj + INTVAL ()) = val;
2200 NEXT_INSN;
2201 #endif /* DIRECT_THREADED */
2203 insn_invokespecial:
2205 SAVE_PC();
2206 int index = GET2U ();
2208 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2209 index)).rmethod;
2211 sp -= rmeth->stack_item_count;
2213 // We don't use NULLCHECK here because we can't rely on that
2214 // working for <init>. So instead we do an explicit test.
2215 if (! sp[0].o)
2217 SAVE_PC();
2218 throw_null_pointer_exception ();
2221 fun = (void (*)()) rmeth->method->ncode;
2223 #ifdef DIRECT_THREADED
2224 // Rewrite instruction so that we use a faster pre-resolved
2225 // method.
2226 pc[-2].insn = &&invokespecial_resolved;
2227 pc[-1].datum = rmeth;
2228 #endif /* DIRECT_THREADED */
2230 goto perform_invoke;
2232 #ifdef DIRECT_THREADED
2233 invokespecial_resolved:
2235 SAVE_PC();
2236 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2237 sp -= rmeth->stack_item_count;
2238 // We don't use NULLCHECK here because we can't rely on that
2239 // working for <init>. So instead we do an explicit test.
2240 if (! sp[0].o)
2242 throw_null_pointer_exception ();
2244 fun = (void (*)()) rmeth->method->ncode;
2246 goto perform_invoke;
2247 #endif /* DIRECT_THREADED */
2249 insn_invokestatic:
2251 SAVE_PC();
2252 int index = GET2U ();
2254 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2255 index)).rmethod;
2257 sp -= rmeth->stack_item_count;
2259 fun = (void (*)()) rmeth->method->ncode;
2261 #ifdef DIRECT_THREADED
2262 // Rewrite instruction so that we use a faster pre-resolved
2263 // method.
2264 pc[-2].insn = &&invokestatic_resolved;
2265 pc[-1].datum = rmeth;
2266 #endif /* DIRECT_THREADED */
2268 goto perform_invoke;
2270 #ifdef DIRECT_THREADED
2271 invokestatic_resolved:
2273 SAVE_PC();
2274 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2275 sp -= rmeth->stack_item_count;
2276 fun = (void (*)()) rmeth->method->ncode;
2278 goto perform_invoke;
2279 #endif /* DIRECT_THREADED */
2281 insn_invokeinterface:
2283 SAVE_PC();
2284 int index = GET2U ();
2286 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2287 index)).rmethod;
2289 sp -= rmeth->stack_item_count;
2291 jobject rcv = sp[0].o;
2293 NULLCHECK (rcv);
2295 fun = (void (*)())
2296 _Jv_LookupInterfaceMethod (rcv->getClass (),
2297 rmeth->method->name,
2298 rmeth->method->signature);
2300 #ifdef DIRECT_THREADED
2301 // Rewrite instruction so that we use a faster pre-resolved
2302 // method.
2303 pc[-2].insn = &&invokeinterface_resolved;
2304 pc[-1].datum = rmeth;
2305 #else
2306 // Skip dummy bytes.
2307 pc += 2;
2308 #endif /* DIRECT_THREADED */
2310 goto perform_invoke;
2312 #ifdef DIRECT_THREADED
2313 invokeinterface_resolved:
2315 SAVE_PC();
2316 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2317 sp -= rmeth->stack_item_count;
2318 jobject rcv = sp[0].o;
2319 NULLCHECK (rcv);
2320 fun = (void (*)())
2321 _Jv_LookupInterfaceMethod (rcv->getClass (),
2322 rmeth->method->name,
2323 rmeth->method->signature);
2325 goto perform_invoke;
2326 #endif /* DIRECT_THREADED */
2328 insn_new:
2330 SAVE_PC();
2331 int index = GET2U ();
2332 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2333 index)).clazz;
2334 /* VM spec, section 3.11.5 */
2335 if ((klass->getModifiers() & Modifier::ABSTRACT)
2336 || klass->isInterface())
2337 throw new java::lang::InstantiationException;
2338 jobject res = _Jv_AllocObject (klass);
2339 PUSHA (res);
2341 #ifdef DIRECT_THREADED
2342 pc[-2].insn = &&new_resolved;
2343 pc[-1].datum = klass;
2344 #endif /* DIRECT_THREADED */
2346 NEXT_INSN;
2348 #ifdef DIRECT_THREADED
2349 new_resolved:
2351 jclass klass = (jclass) AVAL ();
2352 jobject res = _Jv_AllocObject (klass);
2353 PUSHA (res);
2355 NEXT_INSN;
2356 #endif /* DIRECT_THREADED */
2358 insn_newarray:
2360 int atype = GET1U ();
2361 int size = POPI();
2362 jobject result = _Jv_NewArray (atype, size);
2363 PUSHA (result);
2365 NEXT_INSN;
2367 insn_anewarray:
2369 SAVE_PC();
2370 int index = GET2U ();
2371 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2372 index)).clazz;
2373 int size = POPI();
2374 jobject result = _Jv_NewObjectArray (size, klass, 0);
2375 PUSHA (result);
2377 #ifdef DIRECT_THREADED
2378 pc[-2].insn = &&anewarray_resolved;
2379 pc[-1].datum = klass;
2380 #endif /* DIRECT_THREADED */
2382 NEXT_INSN;
2384 #ifdef DIRECT_THREADED
2385 anewarray_resolved:
2387 jclass klass = (jclass) AVAL ();
2388 int size = POPI ();
2389 jobject result = _Jv_NewObjectArray (size, klass, 0);
2390 PUSHA (result);
2392 NEXT_INSN;
2393 #endif /* DIRECT_THREADED */
2395 insn_arraylength:
2397 __JArray *arr = (__JArray*)POPA();
2398 NULLARRAYCHECK (arr);
2399 PUSHI (arr->length);
2401 NEXT_INSN;
2403 insn_athrow:
2405 jobject value = POPA();
2406 throw static_cast<jthrowable>(value);
2408 NEXT_INSN;
2410 insn_checkcast:
2412 SAVE_PC();
2413 jobject value = POPA();
2414 jint index = GET2U ();
2415 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2416 index)).clazz;
2418 value = (jobject) _Jv_CheckCast (to, value);
2420 PUSHA (value);
2422 #ifdef DIRECT_THREADED
2423 pc[-2].insn = &&checkcast_resolved;
2424 pc[-1].datum = to;
2425 #endif /* DIRECT_THREADED */
2427 NEXT_INSN;
2429 #ifdef DIRECT_THREADED
2430 checkcast_resolved:
2432 SAVE_PC();
2433 jobject value = POPA ();
2434 jclass to = (jclass) AVAL ();
2435 value = (jobject) _Jv_CheckCast (to, value);
2436 PUSHA (value);
2438 NEXT_INSN;
2439 #endif /* DIRECT_THREADED */
2441 insn_instanceof:
2443 SAVE_PC();
2444 jobject value = POPA();
2445 jint index = GET2U ();
2446 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2447 index)).clazz;
2448 PUSHI (to->isInstance (value));
2450 #ifdef DIRECT_THREADED
2451 pc[-2].insn = &&instanceof_resolved;
2452 pc[-1].datum = to;
2453 #endif /* DIRECT_THREADED */
2455 NEXT_INSN;
2457 #ifdef DIRECT_THREADED
2458 instanceof_resolved:
2460 jobject value = POPA ();
2461 jclass to = (jclass) AVAL ();
2462 PUSHI (to->isInstance (value));
2464 NEXT_INSN;
2465 #endif /* DIRECT_THREADED */
2467 insn_monitorenter:
2469 jobject value = POPA();
2470 NULLCHECK(value);
2471 _Jv_MonitorEnter (value);
2473 NEXT_INSN;
2475 insn_monitorexit:
2477 jobject value = POPA();
2478 NULLCHECK(value);
2479 _Jv_MonitorExit (value);
2481 NEXT_INSN;
2483 insn_ifnull:
2485 jobject val = POPA();
2486 if (val == NULL)
2487 TAKE_GOTO;
2488 else
2489 SKIP_GOTO;
2491 NEXT_INSN;
2493 insn_ifnonnull:
2495 jobject val = POPA();
2496 if (val != NULL)
2497 TAKE_GOTO;
2498 else
2499 SKIP_GOTO;
2501 NEXT_INSN;
2503 insn_multianewarray:
2505 SAVE_PC();
2506 int kind_index = GET2U ();
2507 int dim = GET1U ();
2509 jclass type
2510 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2511 kind_index)).clazz;
2512 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2514 for (int i = dim - 1; i >= 0; i--)
2516 sizes[i] = POPI ();
2519 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2521 PUSHA (res);
2523 NEXT_INSN;
2525 #ifndef DIRECT_THREADED
2526 insn_wide:
2528 jint the_mod_op = get1u (pc++);
2529 jint wide = get2u (pc); pc += 2;
2531 switch (the_mod_op)
2533 case op_istore:
2534 STOREI (wide);
2535 NEXT_INSN;
2537 case op_fstore:
2538 STOREF (wide);
2539 NEXT_INSN;
2541 case op_astore:
2542 STOREA (wide);
2543 NEXT_INSN;
2545 case op_lload:
2546 LOADL (wide);
2547 NEXT_INSN;
2549 case op_dload:
2550 LOADD (wide);
2551 NEXT_INSN;
2553 case op_iload:
2554 LOADI (wide);
2555 NEXT_INSN;
2557 case op_fload:
2558 LOADF (wide);
2559 NEXT_INSN;
2561 case op_aload:
2562 LOADA (wide);
2563 NEXT_INSN;
2565 case op_lstore:
2566 STOREL (wide);
2567 NEXT_INSN;
2569 case op_dstore:
2570 STORED (wide);
2571 NEXT_INSN;
2573 case op_ret:
2574 pc = (unsigned char*) PEEKA (wide);
2575 NEXT_INSN;
2577 case op_iinc:
2579 jint amount = get2s (pc); pc += 2;
2580 jint value = PEEKI (wide);
2581 POKEI (wide, value+amount);
2583 NEXT_INSN;
2585 default:
2586 throw_internal_error ("illegal bytecode modified by wide");
2590 #endif /* DIRECT_THREADED */
2592 insn_breakpoint:
2594 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2596 // Send JVMTI notification
2597 using namespace ::java::lang;
2598 jmethodID method = meth->self;
2599 jlocation location = meth->insn_index (pc - 1);
2600 Thread *thread = Thread::currentThread ();
2601 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2603 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2604 method, location);
2606 // Continue execution
2607 using namespace gnu::gcj::jvmti;
2608 Breakpoint *bp
2609 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2610 location);
2611 JvAssert (bp != NULL);
2613 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2615 #ifdef DIRECT_THREADED
2616 goto *(opc->insn);
2617 #else
2618 goto *(insn_target[*opc]);
2619 #endif
2622 catch (java::lang::Throwable *ex)
2624 #ifdef DEBUG
2625 // This needs to be done before the pc is changed.
2626 jlong throw_loc = meth->insn_index (pc);
2627 #endif
2628 // Check if the exception is handled and, if so, set the pc to the start
2629 // of the appropriate catch block.
2630 if (meth->check_handler (&pc, meth, ex))
2632 sp = stack;
2633 sp++->o = ex; // Push exception.
2634 #ifdef DEBUG
2635 if (JVMTI_REQUESTED_EVENT (Exception))
2637 using namespace gnu::gcj::jvmti;
2638 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2639 jlong catch_loc = meth->insn_index (pc);
2640 ExceptionEvent::postExceptionEvent (thread, throw_meth,
2641 throw_loc, ex, throw_meth,
2642 catch_loc);
2644 #endif
2645 NEXT_INSN;
2647 #ifdef DEBUG
2648 if (JVMTI_REQUESTED_EVENT (Exception))
2650 using namespace gnu::gcj::jvmti;
2651 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2652 ExceptionEvent::postExceptionEvent (thread, throw_meth, throw_loc,
2653 ex, NULL, NULL);
2655 #endif
2656 // No handler, so re-throw.
2657 throw ex;