interpret-run.cc: Add code to properly set up variable slots when debugging.
[gcc.git] / libjava / interpret-run.cc
1 // interpret-run.cc - Code to interpret bytecode
2
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 /* This file is meant only to be included in interpret.cc, it should not be
12 * compiled directly. */
13
14 using namespace java::lang::reflect;
15
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);
24
25 _Jv_word stack[meth->max_stack];
26 _Jv_word *sp = stack;
27
28 _Jv_word locals[meth->max_locals];
29
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;
36
37 // Set all slots as invalid until they are written to.
38 memset (locals_type, 'x', meth->max_locals);
39
40 // We need to set the local variable types for the method arguments since
41 // they are valid at invocation.
42
43 _Jv_Method *method = meth->get_method ();
44 int type_ctr = 0;
45
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)
48 {
49 // Set the "this" pointer for this frame
50 _Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args);
51 frame_desc.obj_ptr = this_ptr[0].o;
52 frame_desc.locals_type[0] = 'o';
53 type_ctr++;
54 }
55
56 // Now parse the method signature to set the types of the other arguments.
57 int sig_len = method->signature->len ();
58 char *signature = method->signature->chars ();
59 for (int i = 1; signature[i] != ')' && i <= sig_len; i++)
60 {
61 if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C'
62 || signature[i] == 'S' || signature[i] == 'I')
63 {
64 frame_desc.locals_type[type_ctr] = 'i';
65 type_ctr++;
66 continue;
67 }
68 else if (signature[i] == 'F')
69 {
70 frame_desc.locals_type[type_ctr] = 'f';
71 type_ctr++;
72 continue;
73 }
74 else if (signature[i] == 'J')
75 {
76 frame_desc.locals_type[type_ctr] = 'l';
77 frame_desc.locals_type[type_ctr+1] = 'x';
78 type_ctr += 2;
79 continue;
80 }
81 else if (signature[i] == 'D')
82 {
83 frame_desc.locals_type[type_ctr] = 'd';
84 frame_desc.locals_type[type_ctr+1] = 'x';
85 type_ctr += 2;
86 continue;
87 }
88 else if (signature[i] == 'L')
89 {
90 frame_desc.locals_type[type_ctr] = 'o';
91 type_ctr++;
92 while (signature[i] != ';')
93 i++;
94 continue;
95 }
96 else if (signature[i] == '[')
97 {
98 frame_desc.locals_type[type_ctr] = 'o';
99 type_ctr++;
100
101 // Ignore multi-dimensional arrays.
102 while (signature[i] == '[')
103 i++;
104
105 // Check for an object array
106 if (signature[i] == 'L')
107 {
108 while (signature[i] != ';')
109 i++;
110 }
111 continue;
112 }
113 }
114 #endif /* DEBUG */
115
116 #define INSN_LABEL(op) &&insn_##op
117
118 static const void *const insn_target[] =
119 {
120 INSN_LABEL(nop),
121 INSN_LABEL(aconst_null),
122 INSN_LABEL(iconst_m1),
123 INSN_LABEL(iconst_0),
124 INSN_LABEL(iconst_1),
125 INSN_LABEL(iconst_2),
126 INSN_LABEL(iconst_3),
127 INSN_LABEL(iconst_4),
128 INSN_LABEL(iconst_5),
129 INSN_LABEL(lconst_0),
130 INSN_LABEL(lconst_1),
131 INSN_LABEL(fconst_0),
132 INSN_LABEL(fconst_1),
133 INSN_LABEL(fconst_2),
134 INSN_LABEL(dconst_0),
135 INSN_LABEL(dconst_1),
136 INSN_LABEL(bipush),
137 INSN_LABEL(sipush),
138 INSN_LABEL(ldc),
139 INSN_LABEL(ldc_w),
140 INSN_LABEL(ldc2_w),
141 INSN_LABEL(iload),
142 INSN_LABEL(lload),
143 INSN_LABEL(fload),
144 INSN_LABEL(dload),
145 INSN_LABEL(aload),
146 INSN_LABEL(iload_0),
147 INSN_LABEL(iload_1),
148 INSN_LABEL(iload_2),
149 INSN_LABEL(iload_3),
150 INSN_LABEL(lload_0),
151 INSN_LABEL(lload_1),
152 INSN_LABEL(lload_2),
153 INSN_LABEL(lload_3),
154 INSN_LABEL(fload_0),
155 INSN_LABEL(fload_1),
156 INSN_LABEL(fload_2),
157 INSN_LABEL(fload_3),
158 INSN_LABEL(dload_0),
159 INSN_LABEL(dload_1),
160 INSN_LABEL(dload_2),
161 INSN_LABEL(dload_3),
162 INSN_LABEL(aload_0),
163 INSN_LABEL(aload_1),
164 INSN_LABEL(aload_2),
165 INSN_LABEL(aload_3),
166 INSN_LABEL(iaload),
167 INSN_LABEL(laload),
168 INSN_LABEL(faload),
169 INSN_LABEL(daload),
170 INSN_LABEL(aaload),
171 INSN_LABEL(baload),
172 INSN_LABEL(caload),
173 INSN_LABEL(saload),
174 INSN_LABEL(istore),
175 INSN_LABEL(lstore),
176 INSN_LABEL(fstore),
177 INSN_LABEL(dstore),
178 INSN_LABEL(astore),
179 INSN_LABEL(istore_0),
180 INSN_LABEL(istore_1),
181 INSN_LABEL(istore_2),
182 INSN_LABEL(istore_3),
183 INSN_LABEL(lstore_0),
184 INSN_LABEL(lstore_1),
185 INSN_LABEL(lstore_2),
186 INSN_LABEL(lstore_3),
187 INSN_LABEL(fstore_0),
188 INSN_LABEL(fstore_1),
189 INSN_LABEL(fstore_2),
190 INSN_LABEL(fstore_3),
191 INSN_LABEL(dstore_0),
192 INSN_LABEL(dstore_1),
193 INSN_LABEL(dstore_2),
194 INSN_LABEL(dstore_3),
195 INSN_LABEL(astore_0),
196 INSN_LABEL(astore_1),
197 INSN_LABEL(astore_2),
198 INSN_LABEL(astore_3),
199 INSN_LABEL(iastore),
200 INSN_LABEL(lastore),
201 INSN_LABEL(fastore),
202 INSN_LABEL(dastore),
203 INSN_LABEL(aastore),
204 INSN_LABEL(bastore),
205 INSN_LABEL(castore),
206 INSN_LABEL(sastore),
207 INSN_LABEL(pop),
208 INSN_LABEL(pop2),
209 INSN_LABEL(dup),
210 INSN_LABEL(dup_x1),
211 INSN_LABEL(dup_x2),
212 INSN_LABEL(dup2),
213 INSN_LABEL(dup2_x1),
214 INSN_LABEL(dup2_x2),
215 INSN_LABEL(swap),
216 INSN_LABEL(iadd),
217 INSN_LABEL(ladd),
218 INSN_LABEL(fadd),
219 INSN_LABEL(dadd),
220 INSN_LABEL(isub),
221 INSN_LABEL(lsub),
222 INSN_LABEL(fsub),
223 INSN_LABEL(dsub),
224 INSN_LABEL(imul),
225 INSN_LABEL(lmul),
226 INSN_LABEL(fmul),
227 INSN_LABEL(dmul),
228 INSN_LABEL(idiv),
229 INSN_LABEL(ldiv),
230 INSN_LABEL(fdiv),
231 INSN_LABEL(ddiv),
232 INSN_LABEL(irem),
233 INSN_LABEL(lrem),
234 INSN_LABEL(frem),
235 INSN_LABEL(drem),
236 INSN_LABEL(ineg),
237 INSN_LABEL(lneg),
238 INSN_LABEL(fneg),
239 INSN_LABEL(dneg),
240 INSN_LABEL(ishl),
241 INSN_LABEL(lshl),
242 INSN_LABEL(ishr),
243 INSN_LABEL(lshr),
244 INSN_LABEL(iushr),
245 INSN_LABEL(lushr),
246 INSN_LABEL(iand),
247 INSN_LABEL(land),
248 INSN_LABEL(ior),
249 INSN_LABEL(lor),
250 INSN_LABEL(ixor),
251 INSN_LABEL(lxor),
252 INSN_LABEL(iinc),
253 INSN_LABEL(i2l),
254 INSN_LABEL(i2f),
255 INSN_LABEL(i2d),
256 INSN_LABEL(l2i),
257 INSN_LABEL(l2f),
258 INSN_LABEL(l2d),
259 INSN_LABEL(f2i),
260 INSN_LABEL(f2l),
261 INSN_LABEL(f2d),
262 INSN_LABEL(d2i),
263 INSN_LABEL(d2l),
264 INSN_LABEL(d2f),
265 INSN_LABEL(i2b),
266 INSN_LABEL(i2c),
267 INSN_LABEL(i2s),
268 INSN_LABEL(lcmp),
269 INSN_LABEL(fcmpl),
270 INSN_LABEL(fcmpg),
271 INSN_LABEL(dcmpl),
272 INSN_LABEL(dcmpg),
273 INSN_LABEL(ifeq),
274 INSN_LABEL(ifne),
275 INSN_LABEL(iflt),
276 INSN_LABEL(ifge),
277 INSN_LABEL(ifgt),
278 INSN_LABEL(ifle),
279 INSN_LABEL(if_icmpeq),
280 INSN_LABEL(if_icmpne),
281 INSN_LABEL(if_icmplt),
282 INSN_LABEL(if_icmpge),
283 INSN_LABEL(if_icmpgt),
284 INSN_LABEL(if_icmple),
285 INSN_LABEL(if_acmpeq),
286 INSN_LABEL(if_acmpne),
287 INSN_LABEL(goto),
288 INSN_LABEL(jsr),
289 INSN_LABEL(ret),
290 INSN_LABEL(tableswitch),
291 INSN_LABEL(lookupswitch),
292 INSN_LABEL(ireturn),
293 INSN_LABEL(lreturn),
294 INSN_LABEL(freturn),
295 INSN_LABEL(dreturn),
296 INSN_LABEL(areturn),
297 INSN_LABEL(return),
298 INSN_LABEL(getstatic),
299 INSN_LABEL(putstatic),
300 INSN_LABEL(getfield),
301 INSN_LABEL(putfield),
302 INSN_LABEL(invokevirtual),
303 INSN_LABEL(invokespecial),
304 INSN_LABEL(invokestatic),
305 INSN_LABEL(invokeinterface),
306 INSN_LABEL(breakpoint),
307 INSN_LABEL(new),
308 INSN_LABEL(newarray),
309 INSN_LABEL(anewarray),
310 INSN_LABEL(arraylength),
311 INSN_LABEL(athrow),
312 INSN_LABEL(checkcast),
313 INSN_LABEL(instanceof),
314 INSN_LABEL(monitorenter),
315 INSN_LABEL(monitorexit),
316 #ifdef DIRECT_THREADED
317 0, // wide
318 #else
319 INSN_LABEL(wide),
320 #endif
321 INSN_LABEL(multianewarray),
322 INSN_LABEL(ifnull),
323 INSN_LABEL(ifnonnull),
324 INSN_LABEL(goto_w),
325 INSN_LABEL(jsr_w),
326 #ifdef DIRECT_THREADED
327 INSN_LABEL (ldc_class)
328 #else
329 0
330 #endif
331 };
332
333 pc_t pc;
334
335 #ifdef DIRECT_THREADED
336
337 #ifdef DEBUG
338 #undef NEXT_INSN
339 #define NEXT_INSN \
340 do \
341 { \
342 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
343 { \
344 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
345 jmethodID method = meth->self; \
346 jlocation loc = meth->insn_index (pc); \
347 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
348 env, method, loc); \
349 } \
350 goto *((pc++)->insn); \
351 } \
352 while (0)
353 #else
354 #undef NEXT_INSN
355 #define NEXT_INSN goto *((pc++)->insn)
356 #endif
357
358 #define INTVAL() ((pc++)->int_val)
359 #define AVAL() ((pc++)->datum)
360
361 #define GET1S() INTVAL ()
362 #define GET2S() INTVAL ()
363 #define GET1U() INTVAL ()
364 #define GET2U() INTVAL ()
365 #define AVAL1U() AVAL ()
366 #define AVAL2U() AVAL ()
367 #define AVAL2UP() AVAL ()
368 #define SKIP_GOTO ++pc
369 #define GOTO_VAL() (insn_slot *) pc->datum
370 #define PCVAL(unionval) unionval.p
371 #define AMPAMP(label) &&label
372
373 // Compile if we must. NOTE: Double-check locking.
374 if (meth->prepared == NULL)
375 {
376 _Jv_MutexLock (&compile_mutex);
377 if (meth->prepared == NULL)
378 meth->compile (insn_target);
379 _Jv_MutexUnlock (&compile_mutex);
380 }
381
382 // If we're only compiling, stop here
383 if (args == NULL)
384 return;
385
386 pc = (insn_slot *) meth->prepared;
387
388 #else
389
390 #ifdef DEBUG
391 #define NEXT_INSN \
392 do \
393 { \
394 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
395 { \
396 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
397 jmethodID method = meth->self; \
398 jlocation loc = meth->insn_index (pc); \
399 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
400 env, method, loc); \
401 } \
402 goto *(insn_target[*pc++])
403 #else
404 #define NEXT_INSN goto *(insn_target[*pc++])
405 #endif
406
407 #define GET1S() get1s (pc++)
408 #define GET2S() (pc += 2, get2s (pc- 2))
409 #define GET1U() get1u (pc++)
410 #define GET2U() (pc += 2, get2u (pc - 2))
411 // Note that these could be more efficient when not handling 'ldc
412 // class'.
413 #define AVAL1U() \
414 ({ int index = get1u (pc++); \
415 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
416 #define AVAL2U() \
417 ({ int index = get2u (pc); pc += 2; \
418 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
419 // Note that we don't need to resolve the pool entry here as class
420 // constants are never wide.
421 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
422 #define SKIP_GOTO pc += 2
423 #define GOTO_VAL() pc - 1 + get2s (pc)
424 #define PCVAL(unionval) unionval.i
425 #define AMPAMP(label) NULL
426
427 pc = meth->bytecode ();
428
429 #endif /* DIRECT_THREADED */
430
431 #define TAKE_GOTO pc = GOTO_VAL ()
432
433 /* Go straight at it! the ffi raw format matches the internal
434 stack representation exactly. At least, that's the idea.
435 */
436 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
437
438 _Jv_word *pool_data = meth->defining_class->constants.data;
439
440 /* These three are temporaries for common code used by several
441 instructions. */
442 void (*fun)();
443 _Jv_ResolvedMethod* rmeth;
444 int tmpval;
445
446 try
447 {
448 // We keep nop around. It is used if we're interpreting the
449 // bytecodes and not doing direct threading.
450 insn_nop:
451 NEXT_INSN;
452
453 /* The first few instructions here are ordered according to their
454 frequency, in the hope that this will improve code locality a
455 little. */
456
457 insn_aload_0: // 0x2a
458 LOADA (0);
459 NEXT_INSN;
460
461 insn_iload: // 0x15
462 LOADI (GET1U ());
463 NEXT_INSN;
464
465 insn_iload_1: // 0x1b
466 LOADI (1);
467 NEXT_INSN;
468
469 insn_invokevirtual: // 0xb6
470 {
471 SAVE_PC();
472 int index = GET2U ();
473
474 /* _Jv_Linker::resolve_pool_entry returns immediately if the
475 * value already is resolved. If we want to clutter up the
476 * code here to gain a little performance, then we can check
477 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
478 * directly. For now, I don't think it is worth it. */
479
480 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
481 index)).rmethod;
482
483 sp -= rmeth->stack_item_count;
484
485 if (rmeth->method->accflags & Modifier::FINAL)
486 {
487 // We can't rely on NULLCHECK working if the method is final.
488 if (! sp[0].o)
489 throw_null_pointer_exception ();
490
491 // Final methods might not appear in the vtable.
492 fun = (void (*)()) rmeth->method->ncode;
493 }
494 else
495 {
496 NULLCHECK (sp[0].o);
497 jobject rcv = sp[0].o;
498 _Jv_VTable *table = *(_Jv_VTable**) rcv;
499 fun = (void (*)()) table->get_method (rmeth->method->index);
500 }
501
502 #ifdef DIRECT_THREADED
503 // Rewrite instruction so that we use a faster pre-resolved
504 // method.
505 pc[-2].insn = &&invokevirtual_resolved;
506 pc[-1].datum = rmeth;
507 #endif /* DIRECT_THREADED */
508 }
509 goto perform_invoke;
510
511 #ifdef DIRECT_THREADED
512 invokevirtual_resolved:
513 {
514 SAVE_PC();
515 rmeth = (_Jv_ResolvedMethod *) AVAL ();
516 sp -= rmeth->stack_item_count;
517
518 if (rmeth->method->accflags & Modifier::FINAL)
519 {
520 // We can't rely on NULLCHECK working if the method is final.
521 if (! sp[0].o)
522 throw_null_pointer_exception ();
523
524 // Final methods might not appear in the vtable.
525 fun = (void (*)()) rmeth->method->ncode;
526 }
527 else
528 {
529 jobject rcv = sp[0].o;
530 _Jv_VTable *table = *(_Jv_VTable**) rcv;
531 fun = (void (*)()) table->get_method (rmeth->method->index);
532 }
533 }
534 goto perform_invoke;
535 #endif /* DIRECT_THREADED */
536
537 perform_invoke:
538 {
539 /* here goes the magic again... */
540 ffi_cif *cif = &rmeth->cif;
541 ffi_raw *raw = (ffi_raw*) sp;
542
543 _Jv_value rvalue;
544
545 #if FFI_NATIVE_RAW_API
546 /* We assume that this is only implemented if it's correct */
547 /* to use it here. On a 64 bit machine, it never is. */
548 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
549 #else
550 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
551 #endif
552
553 int rtype = cif->rtype->type;
554
555 /* the likelyhood of object, int, or void return is very high,
556 * so those are checked before the switch */
557 if (rtype == FFI_TYPE_POINTER)
558 {
559 PUSHA (rvalue.object_value);
560 }
561 else if (rtype == FFI_TYPE_SINT32)
562 {
563 PUSHI (rvalue.int_value);
564 }
565 else if (rtype == FFI_TYPE_VOID)
566 {
567 /* skip */
568 }
569 else
570 {
571 switch (rtype)
572 {
573 case FFI_TYPE_SINT8:
574 PUSHI ((jbyte)(rvalue.int_value & 0xff));
575 break;
576
577 case FFI_TYPE_SINT16:
578 PUSHI ((jshort)(rvalue.int_value & 0xffff));
579 break;
580
581 case FFI_TYPE_UINT16:
582 PUSHI (rvalue.int_value & 0xffff);
583 break;
584
585 case FFI_TYPE_FLOAT:
586 PUSHF (rvalue.float_value);
587 break;
588
589 case FFI_TYPE_DOUBLE:
590 PUSHD (rvalue.double_value);
591 break;
592
593 case FFI_TYPE_SINT64:
594 PUSHL (rvalue.long_value);
595 break;
596
597 default:
598 throw_internal_error ("unknown return type in invokeXXX");
599 }
600 }
601 }
602 NEXT_INSN;
603
604 insn_aconst_null:
605 PUSHA (NULL);
606 NEXT_INSN;
607
608 insn_iconst_m1:
609 PUSHI (-1);
610 NEXT_INSN;
611
612 insn_iconst_0:
613 PUSHI (0);
614 NEXT_INSN;
615
616 insn_iconst_1:
617 PUSHI (1);
618 NEXT_INSN;
619
620 insn_iconst_2:
621 PUSHI (2);
622 NEXT_INSN;
623
624 insn_iconst_3:
625 PUSHI (3);
626 NEXT_INSN;
627
628 insn_iconst_4:
629 PUSHI (4);
630 NEXT_INSN;
631
632 insn_iconst_5:
633 PUSHI (5);
634 NEXT_INSN;
635
636 insn_lconst_0:
637 PUSHL (0);
638 NEXT_INSN;
639
640 insn_lconst_1:
641 PUSHL (1);
642 NEXT_INSN;
643
644 insn_fconst_0:
645 PUSHF (0);
646 NEXT_INSN;
647
648 insn_fconst_1:
649 PUSHF (1);
650 NEXT_INSN;
651
652 insn_fconst_2:
653 PUSHF (2);
654 NEXT_INSN;
655
656 insn_dconst_0:
657 PUSHD (0);
658 NEXT_INSN;
659
660 insn_dconst_1:
661 PUSHD (1);
662 NEXT_INSN;
663
664 insn_bipush:
665 // For direct threaded, bipush and sipush are the same.
666 #ifndef DIRECT_THREADED
667 PUSHI (GET1S ());
668 NEXT_INSN;
669 #endif /* DIRECT_THREADED */
670 insn_sipush:
671 PUSHI (GET2S ());
672 NEXT_INSN;
673
674 insn_ldc:
675 // For direct threaded, ldc and ldc_w are the same.
676 #ifndef DIRECT_THREADED
677 PUSHA ((jobject) AVAL1U ());
678 NEXT_INSN;
679 #endif /* DIRECT_THREADED */
680 insn_ldc_w:
681 PUSHA ((jobject) AVAL2U ());
682 NEXT_INSN;
683
684 #ifdef DIRECT_THREADED
685 // For direct threaded we have a separate 'ldc class' operation.
686 insn_ldc_class:
687 {
688 SAVE_PC();
689 // We could rewrite the instruction at this point.
690 int index = INTVAL ();
691 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
692 index)).o;
693 PUSHA (k);
694 }
695 NEXT_INSN;
696 #endif /* DIRECT_THREADED */
697
698 insn_ldc2_w:
699 {
700 void *where = AVAL2UP ();
701 memcpy (sp, where, 2*sizeof (_Jv_word));
702 sp += 2;
703 }
704 NEXT_INSN;
705
706 insn_lload:
707 LOADL (GET1U ());
708 NEXT_INSN;
709
710 insn_fload:
711 LOADF (GET1U ());
712 NEXT_INSN;
713
714 insn_dload:
715 LOADD (GET1U ());
716 NEXT_INSN;
717
718 insn_aload:
719 LOADA (GET1U ());
720 NEXT_INSN;
721
722 insn_iload_0:
723 LOADI (0);
724 NEXT_INSN;
725
726 insn_iload_2:
727 LOADI (2);
728 NEXT_INSN;
729
730 insn_iload_3:
731 LOADI (3);
732 NEXT_INSN;
733
734 insn_lload_0:
735 LOADL (0);
736 NEXT_INSN;
737
738 insn_lload_1:
739 LOADL (1);
740 NEXT_INSN;
741
742 insn_lload_2:
743 LOADL (2);
744 NEXT_INSN;
745
746 insn_lload_3:
747 LOADL (3);
748 NEXT_INSN;
749
750 insn_fload_0:
751 LOADF (0);
752 NEXT_INSN;
753
754 insn_fload_1:
755 LOADF (1);
756 NEXT_INSN;
757
758 insn_fload_2:
759 LOADF (2);
760 NEXT_INSN;
761
762 insn_fload_3:
763 LOADF (3);
764 NEXT_INSN;
765
766 insn_dload_0:
767 LOADD (0);
768 NEXT_INSN;
769
770 insn_dload_1:
771 LOADD (1);
772 NEXT_INSN;
773
774 insn_dload_2:
775 LOADD (2);
776 NEXT_INSN;
777
778 insn_dload_3:
779 LOADD (3);
780 NEXT_INSN;
781
782 insn_aload_1:
783 LOADA(1);
784 NEXT_INSN;
785
786 insn_aload_2:
787 LOADA(2);
788 NEXT_INSN;
789
790 insn_aload_3:
791 LOADA(3);
792 NEXT_INSN;
793
794 insn_iaload:
795 {
796 jint index = POPI();
797 jintArray arr = (jintArray) POPA();
798 NULLARRAYCHECK (arr);
799 ARRAYBOUNDSCHECK (arr, index);
800 PUSHI( elements(arr)[index] );
801 }
802 NEXT_INSN;
803
804 insn_laload:
805 {
806 jint index = POPI();
807 jlongArray arr = (jlongArray) POPA();
808 NULLARRAYCHECK (arr);
809 ARRAYBOUNDSCHECK (arr, index);
810 PUSHL( elements(arr)[index] );
811 }
812 NEXT_INSN;
813
814 insn_faload:
815 {
816 jint index = POPI();
817 jfloatArray arr = (jfloatArray) POPA();
818 NULLARRAYCHECK (arr);
819 ARRAYBOUNDSCHECK (arr, index);
820 PUSHF( elements(arr)[index] );
821 }
822 NEXT_INSN;
823
824 insn_daload:
825 {
826 jint index = POPI();
827 jdoubleArray arr = (jdoubleArray) POPA();
828 NULLARRAYCHECK (arr);
829 ARRAYBOUNDSCHECK (arr, index);
830 PUSHD( elements(arr)[index] );
831 }
832 NEXT_INSN;
833
834 insn_aaload:
835 {
836 jint index = POPI();
837 jobjectArray arr = (jobjectArray) POPA();
838 NULLARRAYCHECK (arr);
839 ARRAYBOUNDSCHECK (arr, index);
840 PUSHA( elements(arr)[index] );
841 }
842 NEXT_INSN;
843
844 insn_baload:
845 {
846 jint index = POPI();
847 jbyteArray arr = (jbyteArray) POPA();
848 NULLARRAYCHECK (arr);
849 ARRAYBOUNDSCHECK (arr, index);
850 PUSHI( elements(arr)[index] );
851 }
852 NEXT_INSN;
853
854 insn_caload:
855 {
856 jint index = POPI();
857 jcharArray arr = (jcharArray) POPA();
858 NULLARRAYCHECK (arr);
859 ARRAYBOUNDSCHECK (arr, index);
860 PUSHI( elements(arr)[index] );
861 }
862 NEXT_INSN;
863
864 insn_saload:
865 {
866 jint index = POPI();
867 jshortArray arr = (jshortArray) POPA();
868 NULLARRAYCHECK (arr);
869 ARRAYBOUNDSCHECK (arr, index);
870 PUSHI( elements(arr)[index] );
871 }
872 NEXT_INSN;
873
874 insn_istore:
875 STOREI (GET1U ());
876 NEXT_INSN;
877
878 insn_lstore:
879 STOREL (GET1U ());
880 NEXT_INSN;
881
882 insn_fstore:
883 STOREF (GET1U ());
884 NEXT_INSN;
885
886 insn_dstore:
887 STORED (GET1U ());
888 NEXT_INSN;
889
890 insn_astore:
891 STOREA (GET1U ());
892 NEXT_INSN;
893
894 insn_istore_0:
895 STOREI (0);
896 NEXT_INSN;
897
898 insn_istore_1:
899 STOREI (1);
900 NEXT_INSN;
901
902 insn_istore_2:
903 STOREI (2);
904 NEXT_INSN;
905
906 insn_istore_3:
907 STOREI (3);
908 NEXT_INSN;
909
910 insn_lstore_0:
911 STOREL (0);
912 NEXT_INSN;
913
914 insn_lstore_1:
915 STOREL (1);
916 NEXT_INSN;
917
918 insn_lstore_2:
919 STOREL (2);
920 NEXT_INSN;
921
922 insn_lstore_3:
923 STOREL (3);
924 NEXT_INSN;
925
926 insn_fstore_0:
927 STOREF (0);
928 NEXT_INSN;
929
930 insn_fstore_1:
931 STOREF (1);
932 NEXT_INSN;
933
934 insn_fstore_2:
935 STOREF (2);
936 NEXT_INSN;
937
938 insn_fstore_3:
939 STOREF (3);
940 NEXT_INSN;
941
942 insn_dstore_0:
943 STORED (0);
944 NEXT_INSN;
945
946 insn_dstore_1:
947 STORED (1);
948 NEXT_INSN;
949
950 insn_dstore_2:
951 STORED (2);
952 NEXT_INSN;
953
954 insn_dstore_3:
955 STORED (3);
956 NEXT_INSN;
957
958 insn_astore_0:
959 STOREA(0);
960 NEXT_INSN;
961
962 insn_astore_1:
963 STOREA(1);
964 NEXT_INSN;
965
966 insn_astore_2:
967 STOREA(2);
968 NEXT_INSN;
969
970 insn_astore_3:
971 STOREA(3);
972 NEXT_INSN;
973
974 insn_iastore:
975 {
976 jint value = POPI();
977 jint index = POPI();
978 jintArray arr = (jintArray) POPA();
979 NULLARRAYCHECK (arr);
980 ARRAYBOUNDSCHECK (arr, index);
981 elements(arr)[index] = value;
982 }
983 NEXT_INSN;
984
985 insn_lastore:
986 {
987 jlong value = POPL();
988 jint index = POPI();
989 jlongArray arr = (jlongArray) POPA();
990 NULLARRAYCHECK (arr);
991 ARRAYBOUNDSCHECK (arr, index);
992 elements(arr)[index] = value;
993 }
994 NEXT_INSN;
995
996 insn_fastore:
997 {
998 jfloat value = POPF();
999 jint index = POPI();
1000 jfloatArray arr = (jfloatArray) POPA();
1001 NULLARRAYCHECK (arr);
1002 ARRAYBOUNDSCHECK (arr, index);
1003 elements(arr)[index] = value;
1004 }
1005 NEXT_INSN;
1006
1007 insn_dastore:
1008 {
1009 jdouble value = POPD();
1010 jint index = POPI();
1011 jdoubleArray arr = (jdoubleArray) POPA();
1012 NULLARRAYCHECK (arr);
1013 ARRAYBOUNDSCHECK (arr, index);
1014 elements(arr)[index] = value;
1015 }
1016 NEXT_INSN;
1017
1018 insn_aastore:
1019 {
1020 jobject value = POPA();
1021 jint index = POPI();
1022 jobjectArray arr = (jobjectArray) POPA();
1023 NULLARRAYCHECK (arr);
1024 ARRAYBOUNDSCHECK (arr, index);
1025 _Jv_CheckArrayStore (arr, value);
1026 elements(arr)[index] = value;
1027 }
1028 NEXT_INSN;
1029
1030 insn_bastore:
1031 {
1032 jbyte value = (jbyte) POPI();
1033 jint index = POPI();
1034 jbyteArray arr = (jbyteArray) POPA();
1035 NULLARRAYCHECK (arr);
1036 ARRAYBOUNDSCHECK (arr, index);
1037 elements(arr)[index] = value;
1038 }
1039 NEXT_INSN;
1040
1041 insn_castore:
1042 {
1043 jchar value = (jchar) POPI();
1044 jint index = POPI();
1045 jcharArray arr = (jcharArray) POPA();
1046 NULLARRAYCHECK (arr);
1047 ARRAYBOUNDSCHECK (arr, index);
1048 elements(arr)[index] = value;
1049 }
1050 NEXT_INSN;
1051
1052 insn_sastore:
1053 {
1054 jshort value = (jshort) POPI();
1055 jint index = POPI();
1056 jshortArray arr = (jshortArray) POPA();
1057 NULLARRAYCHECK (arr);
1058 ARRAYBOUNDSCHECK (arr, index);
1059 elements(arr)[index] = value;
1060 }
1061 NEXT_INSN;
1062
1063 insn_pop:
1064 sp -= 1;
1065 NEXT_INSN;
1066
1067 insn_pop2:
1068 sp -= 2;
1069 NEXT_INSN;
1070
1071 insn_dup:
1072 sp[0] = sp[-1];
1073 sp += 1;
1074 NEXT_INSN;
1075
1076 insn_dup_x1:
1077 dupx (sp, 1, 1); sp+=1;
1078 NEXT_INSN;
1079
1080 insn_dup_x2:
1081 dupx (sp, 1, 2); sp+=1;
1082 NEXT_INSN;
1083
1084 insn_dup2:
1085 sp[0] = sp[-2];
1086 sp[1] = sp[-1];
1087 sp += 2;
1088 NEXT_INSN;
1089
1090 insn_dup2_x1:
1091 dupx (sp, 2, 1); sp+=2;
1092 NEXT_INSN;
1093
1094 insn_dup2_x2:
1095 dupx (sp, 2, 2); sp+=2;
1096 NEXT_INSN;
1097
1098 insn_swap:
1099 {
1100 jobject tmp1 = POPA();
1101 jobject tmp2 = POPA();
1102 PUSHA (tmp1);
1103 PUSHA (tmp2);
1104 }
1105 NEXT_INSN;
1106
1107 insn_iadd:
1108 BINOPI(+);
1109 NEXT_INSN;
1110
1111 insn_ladd:
1112 BINOPL(+);
1113 NEXT_INSN;
1114
1115 insn_fadd:
1116 BINOPF(+);
1117 NEXT_INSN;
1118
1119 insn_dadd:
1120 BINOPD(+);
1121 NEXT_INSN;
1122
1123 insn_isub:
1124 BINOPI(-);
1125 NEXT_INSN;
1126
1127 insn_lsub:
1128 BINOPL(-);
1129 NEXT_INSN;
1130
1131 insn_fsub:
1132 BINOPF(-);
1133 NEXT_INSN;
1134
1135 insn_dsub:
1136 BINOPD(-);
1137 NEXT_INSN;
1138
1139 insn_imul:
1140 BINOPI(*);
1141 NEXT_INSN;
1142
1143 insn_lmul:
1144 BINOPL(*);
1145 NEXT_INSN;
1146
1147 insn_fmul:
1148 BINOPF(*);
1149 NEXT_INSN;
1150
1151 insn_dmul:
1152 BINOPD(*);
1153 NEXT_INSN;
1154
1155 insn_idiv:
1156 {
1157 SAVE_PC();
1158 jint value2 = POPI();
1159 jint value1 = POPI();
1160 jint res = _Jv_divI (value1, value2);
1161 PUSHI (res);
1162 }
1163 NEXT_INSN;
1164
1165 insn_ldiv:
1166 {
1167 SAVE_PC();
1168 jlong value2 = POPL();
1169 jlong value1 = POPL();
1170 jlong res = _Jv_divJ (value1, value2);
1171 PUSHL (res);
1172 }
1173 NEXT_INSN;
1174
1175 insn_fdiv:
1176 {
1177 jfloat value2 = POPF();
1178 jfloat value1 = POPF();
1179 jfloat res = value1 / value2;
1180 PUSHF (res);
1181 }
1182 NEXT_INSN;
1183
1184 insn_ddiv:
1185 {
1186 jdouble value2 = POPD();
1187 jdouble value1 = POPD();
1188 jdouble res = value1 / value2;
1189 PUSHD (res);
1190 }
1191 NEXT_INSN;
1192
1193 insn_irem:
1194 {
1195 SAVE_PC();
1196 jint value2 = POPI();
1197 jint value1 = POPI();
1198 jint res = _Jv_remI (value1, value2);
1199 PUSHI (res);
1200 }
1201 NEXT_INSN;
1202
1203 insn_lrem:
1204 {
1205 SAVE_PC();
1206 jlong value2 = POPL();
1207 jlong value1 = POPL();
1208 jlong res = _Jv_remJ (value1, value2);
1209 PUSHL (res);
1210 }
1211 NEXT_INSN;
1212
1213 insn_frem:
1214 {
1215 jfloat value2 = POPF();
1216 jfloat value1 = POPF();
1217 jfloat res = __ieee754_fmod (value1, value2);
1218 PUSHF (res);
1219 }
1220 NEXT_INSN;
1221
1222 insn_drem:
1223 {
1224 jdouble value2 = POPD();
1225 jdouble value1 = POPD();
1226 jdouble res = __ieee754_fmod (value1, value2);
1227 PUSHD (res);
1228 }
1229 NEXT_INSN;
1230
1231 insn_ineg:
1232 {
1233 jint value = POPI();
1234 PUSHI (value * -1);
1235 }
1236 NEXT_INSN;
1237
1238 insn_lneg:
1239 {
1240 jlong value = POPL();
1241 PUSHL (value * -1);
1242 }
1243 NEXT_INSN;
1244
1245 insn_fneg:
1246 {
1247 jfloat value = POPF();
1248 PUSHF (value * -1);
1249 }
1250 NEXT_INSN;
1251
1252 insn_dneg:
1253 {
1254 jdouble value = POPD();
1255 PUSHD (value * -1);
1256 }
1257 NEXT_INSN;
1258
1259 insn_ishl:
1260 {
1261 jint shift = (POPI() & 0x1f);
1262 jint value = POPI();
1263 PUSHI (value << shift);
1264 }
1265 NEXT_INSN;
1266
1267 insn_lshl:
1268 {
1269 jint shift = (POPI() & 0x3f);
1270 jlong value = POPL();
1271 PUSHL (value << shift);
1272 }
1273 NEXT_INSN;
1274
1275 insn_ishr:
1276 {
1277 jint shift = (POPI() & 0x1f);
1278 jint value = POPI();
1279 PUSHI (value >> shift);
1280 }
1281 NEXT_INSN;
1282
1283 insn_lshr:
1284 {
1285 jint shift = (POPI() & 0x3f);
1286 jlong value = POPL();
1287 PUSHL (value >> shift);
1288 }
1289 NEXT_INSN;
1290
1291 insn_iushr:
1292 {
1293 jint shift = (POPI() & 0x1f);
1294 _Jv_uint value = (_Jv_uint) POPI();
1295 PUSHI ((jint) (value >> shift));
1296 }
1297 NEXT_INSN;
1298
1299 insn_lushr:
1300 {
1301 jint shift = (POPI() & 0x3f);
1302 _Jv_ulong value = (_Jv_ulong) POPL();
1303 PUSHL ((jlong) (value >> shift));
1304 }
1305 NEXT_INSN;
1306
1307 insn_iand:
1308 BINOPI (&);
1309 NEXT_INSN;
1310
1311 insn_land:
1312 BINOPL (&);
1313 NEXT_INSN;
1314
1315 insn_ior:
1316 BINOPI (|);
1317 NEXT_INSN;
1318
1319 insn_lor:
1320 BINOPL (|);
1321 NEXT_INSN;
1322
1323 insn_ixor:
1324 BINOPI (^);
1325 NEXT_INSN;
1326
1327 insn_lxor:
1328 BINOPL (^);
1329 NEXT_INSN;
1330
1331 insn_iinc:
1332 {
1333 jint index = GET1U ();
1334 jint amount = GET1S ();
1335 locals[index].i += amount;
1336 }
1337 NEXT_INSN;
1338
1339 insn_i2l:
1340 {jlong value = POPI(); PUSHL (value);}
1341 NEXT_INSN;
1342
1343 insn_i2f:
1344 {jfloat value = POPI(); PUSHF (value);}
1345 NEXT_INSN;
1346
1347 insn_i2d:
1348 {jdouble value = POPI(); PUSHD (value);}
1349 NEXT_INSN;
1350
1351 insn_l2i:
1352 {jint value = POPL(); PUSHI (value);}
1353 NEXT_INSN;
1354
1355 insn_l2f:
1356 {jfloat value = POPL(); PUSHF (value);}
1357 NEXT_INSN;
1358
1359 insn_l2d:
1360 {jdouble value = POPL(); PUSHD (value);}
1361 NEXT_INSN;
1362
1363 insn_f2i:
1364 {
1365 using namespace java::lang;
1366 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1367 PUSHI(value);
1368 }
1369 NEXT_INSN;
1370
1371 insn_f2l:
1372 {
1373 using namespace java::lang;
1374 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1375 PUSHL(value);
1376 }
1377 NEXT_INSN;
1378
1379 insn_f2d:
1380 { jdouble value = POPF (); PUSHD(value); }
1381 NEXT_INSN;
1382
1383 insn_d2i:
1384 {
1385 using namespace java::lang;
1386 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1387 PUSHI(value);
1388 }
1389 NEXT_INSN;
1390
1391 insn_d2l:
1392 {
1393 using namespace java::lang;
1394 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1395 PUSHL(value);
1396 }
1397 NEXT_INSN;
1398
1399 insn_d2f:
1400 { jfloat value = POPD (); PUSHF(value); }
1401 NEXT_INSN;
1402
1403 insn_i2b:
1404 { jbyte value = POPI (); PUSHI(value); }
1405 NEXT_INSN;
1406
1407 insn_i2c:
1408 { jchar value = POPI (); PUSHI(value); }
1409 NEXT_INSN;
1410
1411 insn_i2s:
1412 { jshort value = POPI (); PUSHI(value); }
1413 NEXT_INSN;
1414
1415 insn_lcmp:
1416 {
1417 jlong value2 = POPL ();
1418 jlong value1 = POPL ();
1419 if (value1 > value2)
1420 { PUSHI (1); }
1421 else if (value1 == value2)
1422 { PUSHI (0); }
1423 else
1424 { PUSHI (-1); }
1425 }
1426 NEXT_INSN;
1427
1428 insn_fcmpl:
1429 tmpval = -1;
1430 goto fcmp;
1431
1432 insn_fcmpg:
1433 tmpval = 1;
1434
1435 fcmp:
1436 {
1437 jfloat value2 = POPF ();
1438 jfloat value1 = POPF ();
1439 if (value1 > value2)
1440 PUSHI (1);
1441 else if (value1 == value2)
1442 PUSHI (0);
1443 else if (value1 < value2)
1444 PUSHI (-1);
1445 else
1446 PUSHI (tmpval);
1447 }
1448 NEXT_INSN;
1449
1450 insn_dcmpl:
1451 tmpval = -1;
1452 goto dcmp;
1453
1454 insn_dcmpg:
1455 tmpval = 1;
1456
1457 dcmp:
1458 {
1459 jdouble value2 = POPD ();
1460 jdouble value1 = POPD ();
1461 if (value1 > value2)
1462 PUSHI (1);
1463 else if (value1 == value2)
1464 PUSHI (0);
1465 else if (value1 < value2)
1466 PUSHI (-1);
1467 else
1468 PUSHI (tmpval);
1469 }
1470 NEXT_INSN;
1471
1472 insn_ifeq:
1473 {
1474 if (POPI() == 0)
1475 TAKE_GOTO;
1476 else
1477 SKIP_GOTO;
1478 }
1479 NEXT_INSN;
1480
1481 insn_ifne:
1482 {
1483 if (POPI() != 0)
1484 TAKE_GOTO;
1485 else
1486 SKIP_GOTO;
1487 }
1488 NEXT_INSN;
1489
1490 insn_iflt:
1491 {
1492 if (POPI() < 0)
1493 TAKE_GOTO;
1494 else
1495 SKIP_GOTO;
1496 }
1497 NEXT_INSN;
1498
1499 insn_ifge:
1500 {
1501 if (POPI() >= 0)
1502 TAKE_GOTO;
1503 else
1504 SKIP_GOTO;
1505 }
1506 NEXT_INSN;
1507
1508 insn_ifgt:
1509 {
1510 if (POPI() > 0)
1511 TAKE_GOTO;
1512 else
1513 SKIP_GOTO;
1514 }
1515 NEXT_INSN;
1516
1517 insn_ifle:
1518 {
1519 if (POPI() <= 0)
1520 TAKE_GOTO;
1521 else
1522 SKIP_GOTO;
1523 }
1524 NEXT_INSN;
1525
1526 insn_if_icmpeq:
1527 {
1528 jint value2 = POPI();
1529 jint value1 = POPI();
1530 if (value1 == value2)
1531 TAKE_GOTO;
1532 else
1533 SKIP_GOTO;
1534 }
1535 NEXT_INSN;
1536
1537 insn_if_icmpne:
1538 {
1539 jint value2 = POPI();
1540 jint value1 = POPI();
1541 if (value1 != value2)
1542 TAKE_GOTO;
1543 else
1544 SKIP_GOTO;
1545 }
1546 NEXT_INSN;
1547
1548 insn_if_icmplt:
1549 {
1550 jint value2 = POPI();
1551 jint value1 = POPI();
1552 if (value1 < value2)
1553 TAKE_GOTO;
1554 else
1555 SKIP_GOTO;
1556 }
1557 NEXT_INSN;
1558
1559 insn_if_icmpge:
1560 {
1561 jint value2 = POPI();
1562 jint value1 = POPI();
1563 if (value1 >= value2)
1564 TAKE_GOTO;
1565 else
1566 SKIP_GOTO;
1567 }
1568 NEXT_INSN;
1569
1570 insn_if_icmpgt:
1571 {
1572 jint value2 = POPI();
1573 jint value1 = POPI();
1574 if (value1 > value2)
1575 TAKE_GOTO;
1576 else
1577 SKIP_GOTO;
1578 }
1579 NEXT_INSN;
1580
1581 insn_if_icmple:
1582 {
1583 jint value2 = POPI();
1584 jint value1 = POPI();
1585 if (value1 <= value2)
1586 TAKE_GOTO;
1587 else
1588 SKIP_GOTO;
1589 }
1590 NEXT_INSN;
1591
1592 insn_if_acmpeq:
1593 {
1594 jobject value2 = POPA();
1595 jobject value1 = POPA();
1596 if (value1 == value2)
1597 TAKE_GOTO;
1598 else
1599 SKIP_GOTO;
1600 }
1601 NEXT_INSN;
1602
1603 insn_if_acmpne:
1604 {
1605 jobject value2 = POPA();
1606 jobject value1 = POPA();
1607 if (value1 != value2)
1608 TAKE_GOTO;
1609 else
1610 SKIP_GOTO;
1611 }
1612 NEXT_INSN;
1613
1614 insn_goto_w:
1615 #ifndef DIRECT_THREADED
1616 // For direct threaded, goto and goto_w are the same.
1617 pc = pc - 1 + get4 (pc);
1618 NEXT_INSN;
1619 #endif /* DIRECT_THREADED */
1620 insn_goto:
1621 TAKE_GOTO;
1622 NEXT_INSN;
1623
1624 insn_jsr_w:
1625 #ifndef DIRECT_THREADED
1626 // For direct threaded, jsr and jsr_w are the same.
1627 {
1628 pc_t next = pc - 1 + get4 (pc);
1629 pc += 4;
1630 PUSHA ((jobject) pc);
1631 pc = next;
1632 }
1633 NEXT_INSN;
1634 #endif /* DIRECT_THREADED */
1635 insn_jsr:
1636 {
1637 pc_t next = GOTO_VAL();
1638 SKIP_GOTO;
1639 PUSHA ((jobject) pc);
1640 pc = next;
1641 }
1642 NEXT_INSN;
1643
1644 insn_ret:
1645 {
1646 jint index = GET1U ();
1647 pc = (pc_t) PEEKA (index);
1648 }
1649 NEXT_INSN;
1650
1651 insn_tableswitch:
1652 {
1653 #ifdef DIRECT_THREADED
1654 void *def = (pc++)->datum;
1655
1656 int index = POPI();
1657
1658 jint low = INTVAL ();
1659 jint high = INTVAL ();
1660
1661 if (index < low || index > high)
1662 pc = (insn_slot *) def;
1663 else
1664 pc = (insn_slot *) ((pc + index - low)->datum);
1665 #else
1666 pc_t base_pc = pc - 1;
1667 int index = POPI ();
1668
1669 pc_t base = (pc_t) meth->bytecode ();
1670 while ((pc - base) % 4 != 0)
1671 ++pc;
1672
1673 jint def = get4 (pc);
1674 jint low = get4 (pc + 4);
1675 jint high = get4 (pc + 8);
1676 if (index < low || index > high)
1677 pc = base_pc + def;
1678 else
1679 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1680 #endif /* DIRECT_THREADED */
1681 }
1682 NEXT_INSN;
1683
1684 insn_lookupswitch:
1685 {
1686 #ifdef DIRECT_THREADED
1687 void *def = (pc++)->insn;
1688
1689 int index = POPI();
1690
1691 jint npairs = INTVAL ();
1692
1693 int max = npairs - 1;
1694 int min = 0;
1695
1696 // Simple binary search...
1697 while (min < max)
1698 {
1699 int half = (min + max) / 2;
1700 int match = pc[2 * half].int_val;
1701
1702 if (index == match)
1703 {
1704 // Found it.
1705 pc = (insn_slot *) pc[2 * half + 1].datum;
1706 NEXT_INSN;
1707 }
1708 else if (index < match)
1709 // We can use HALF - 1 here because we check again on
1710 // loop exit.
1711 max = half - 1;
1712 else
1713 // We can use HALF + 1 here because we check again on
1714 // loop exit.
1715 min = half + 1;
1716 }
1717 if (index == pc[2 * min].int_val)
1718 pc = (insn_slot *) pc[2 * min + 1].datum;
1719 else
1720 pc = (insn_slot *) def;
1721 #else
1722 unsigned char *base_pc = pc-1;
1723 int index = POPI();
1724
1725 unsigned char* base = meth->bytecode ();
1726 while ((pc-base) % 4 != 0)
1727 ++pc;
1728
1729 jint def = get4 (pc);
1730 jint npairs = get4 (pc+4);
1731
1732 int max = npairs-1;
1733 int min = 0;
1734
1735 // Simple binary search...
1736 while (min < max)
1737 {
1738 int half = (min+max)/2;
1739 int match = get4 (pc+ 4*(2 + 2*half));
1740
1741 if (index == match)
1742 min = max = half;
1743 else if (index < match)
1744 // We can use HALF - 1 here because we check again on
1745 // loop exit.
1746 max = half - 1;
1747 else
1748 // We can use HALF + 1 here because we check again on
1749 // loop exit.
1750 min = half + 1;
1751 }
1752
1753 if (index == get4 (pc+ 4*(2 + 2*min)))
1754 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1755 else
1756 pc = base_pc + def;
1757 #endif /* DIRECT_THREADED */
1758 }
1759 NEXT_INSN;
1760
1761 insn_areturn:
1762 *(jobject *) retp = POPA ();
1763 return;
1764
1765 insn_lreturn:
1766 *(jlong *) retp = POPL ();
1767 return;
1768
1769 insn_freturn:
1770 *(jfloat *) retp = POPF ();
1771 return;
1772
1773 insn_dreturn:
1774 *(jdouble *) retp = POPD ();
1775 return;
1776
1777 insn_ireturn:
1778 *(jint *) retp = POPI ();
1779 return;
1780
1781 insn_return:
1782 return;
1783
1784 insn_getstatic:
1785 {
1786 jint fieldref_index = GET2U ();
1787 SAVE_PC(); // Constant pool resolution could throw.
1788 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1789 _Jv_Field *field = pool_data[fieldref_index].field;
1790
1791 if ((field->flags & Modifier::STATIC) == 0)
1792 throw_incompatible_class_change_error
1793 (JvNewStringLatin1 ("field no longer static"));
1794
1795 jclass type = field->type;
1796
1797 // We rewrite the instruction once we discover what it refers
1798 // to.
1799 void *newinsn = NULL;
1800 if (type->isPrimitive ())
1801 {
1802 switch (type->size_in_bytes)
1803 {
1804 case 1:
1805 PUSHI (*field->u.byte_addr);
1806 newinsn = AMPAMP (getstatic_resolved_1);
1807 break;
1808
1809 case 2:
1810 if (type == JvPrimClass (char))
1811 {
1812 PUSHI (*field->u.char_addr);
1813 newinsn = AMPAMP (getstatic_resolved_char);
1814 }
1815 else
1816 {
1817 PUSHI (*field->u.short_addr);
1818 newinsn = AMPAMP (getstatic_resolved_short);
1819 }
1820 break;
1821
1822 case 4:
1823 PUSHI(*field->u.int_addr);
1824 newinsn = AMPAMP (getstatic_resolved_4);
1825 break;
1826
1827 case 8:
1828 PUSHL(*field->u.long_addr);
1829 newinsn = AMPAMP (getstatic_resolved_8);
1830 break;
1831 }
1832 }
1833 else
1834 {
1835 PUSHA(*field->u.object_addr);
1836 newinsn = AMPAMP (getstatic_resolved_obj);
1837 }
1838
1839 #ifdef DIRECT_THREADED
1840 pc[-2].insn = newinsn;
1841 pc[-1].datum = field->u.addr;
1842 #endif /* DIRECT_THREADED */
1843 }
1844 NEXT_INSN;
1845
1846 #ifdef DIRECT_THREADED
1847 getstatic_resolved_1:
1848 PUSHI (*(jbyte *) AVAL ());
1849 NEXT_INSN;
1850
1851 getstatic_resolved_char:
1852 PUSHI (*(jchar *) AVAL ());
1853 NEXT_INSN;
1854
1855 getstatic_resolved_short:
1856 PUSHI (*(jshort *) AVAL ());
1857 NEXT_INSN;
1858
1859 getstatic_resolved_4:
1860 PUSHI (*(jint *) AVAL ());
1861 NEXT_INSN;
1862
1863 getstatic_resolved_8:
1864 PUSHL (*(jlong *) AVAL ());
1865 NEXT_INSN;
1866
1867 getstatic_resolved_obj:
1868 PUSHA (*(jobject *) AVAL ());
1869 NEXT_INSN;
1870 #endif /* DIRECT_THREADED */
1871
1872 insn_getfield:
1873 {
1874 SAVE_PC();
1875 jint fieldref_index = GET2U ();
1876 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1877 _Jv_Field *field = pool_data[fieldref_index].field;
1878
1879 if ((field->flags & Modifier::STATIC) != 0)
1880 throw_incompatible_class_change_error
1881 (JvNewStringLatin1 ("field is static"));
1882
1883 jclass type = field->type;
1884 jint field_offset = field->u.boffset;
1885
1886 jobject obj = POPA();
1887 NULLCHECK(obj);
1888
1889 void *newinsn = NULL;
1890 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1891 if (type->isPrimitive ())
1892 {
1893 switch (type->size_in_bytes)
1894 {
1895 case 1:
1896 PUSHI (val->byte_value);
1897 newinsn = AMPAMP (getfield_resolved_1);
1898 break;
1899
1900 case 2:
1901 if (type == JvPrimClass (char))
1902 {
1903 PUSHI (val->char_value);
1904 newinsn = AMPAMP (getfield_resolved_char);
1905 }
1906 else
1907 {
1908 PUSHI (val->short_value);
1909 newinsn = AMPAMP (getfield_resolved_short);
1910 }
1911 break;
1912
1913 case 4:
1914 PUSHI (val->int_value);
1915 newinsn = AMPAMP (getfield_resolved_4);
1916 break;
1917
1918 case 8:
1919 PUSHL (val->long_value);
1920 newinsn = AMPAMP (getfield_resolved_8);
1921 break;
1922 }
1923 }
1924 else
1925 {
1926 PUSHA (val->object_value);
1927 newinsn = AMPAMP (getfield_resolved_obj);
1928 }
1929
1930 #ifdef DIRECT_THREADED
1931 pc[-2].insn = newinsn;
1932 pc[-1].int_val = field_offset;
1933 #endif /* DIRECT_THREADED */
1934 }
1935 NEXT_INSN;
1936
1937 #ifdef DIRECT_THREADED
1938 getfield_resolved_1:
1939 {
1940 char *obj = (char *) POPA ();
1941 NULLCHECK (obj);
1942 PUSHI (*(jbyte *) (obj + INTVAL ()));
1943 }
1944 NEXT_INSN;
1945
1946 getfield_resolved_char:
1947 {
1948 char *obj = (char *) POPA ();
1949 NULLCHECK (obj);
1950 PUSHI (*(jchar *) (obj + INTVAL ()));
1951 }
1952 NEXT_INSN;
1953
1954 getfield_resolved_short:
1955 {
1956 char *obj = (char *) POPA ();
1957 NULLCHECK (obj);
1958 PUSHI (*(jshort *) (obj + INTVAL ()));
1959 }
1960 NEXT_INSN;
1961
1962 getfield_resolved_4:
1963 {
1964 char *obj = (char *) POPA ();
1965 NULLCHECK (obj);
1966 PUSHI (*(jint *) (obj + INTVAL ()));
1967 }
1968 NEXT_INSN;
1969
1970 getfield_resolved_8:
1971 {
1972 char *obj = (char *) POPA ();
1973 NULLCHECK (obj);
1974 PUSHL (*(jlong *) (obj + INTVAL ()));
1975 }
1976 NEXT_INSN;
1977
1978 getfield_resolved_obj:
1979 {
1980 char *obj = (char *) POPA ();
1981 NULLCHECK (obj);
1982 PUSHA (*(jobject *) (obj + INTVAL ()));
1983 }
1984 NEXT_INSN;
1985 #endif /* DIRECT_THREADED */
1986
1987 insn_putstatic:
1988 {
1989 SAVE_PC();
1990 jint fieldref_index = GET2U ();
1991 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1992 _Jv_Field *field = pool_data[fieldref_index].field;
1993
1994 jclass type = field->type;
1995
1996 // ResolvePoolEntry cannot check this
1997 if ((field->flags & Modifier::STATIC) == 0)
1998 throw_incompatible_class_change_error
1999 (JvNewStringLatin1 ("field no longer static"));
2000
2001 void *newinsn = NULL;
2002 if (type->isPrimitive ())
2003 {
2004 switch (type->size_in_bytes)
2005 {
2006 case 1:
2007 {
2008 jint value = POPI();
2009 *field->u.byte_addr = value;
2010 newinsn = AMPAMP (putstatic_resolved_1);
2011 break;
2012 }
2013
2014 case 2:
2015 {
2016 jint value = POPI();
2017 *field->u.char_addr = value;
2018 newinsn = AMPAMP (putstatic_resolved_2);
2019 break;
2020 }
2021
2022 case 4:
2023 {
2024 jint value = POPI();
2025 *field->u.int_addr = value;
2026 newinsn = AMPAMP (putstatic_resolved_4);
2027 break;
2028 }
2029
2030 case 8:
2031 {
2032 jlong value = POPL();
2033 *field->u.long_addr = value;
2034 newinsn = AMPAMP (putstatic_resolved_8);
2035 break;
2036 }
2037 }
2038 }
2039 else
2040 {
2041 jobject value = POPA();
2042 *field->u.object_addr = value;
2043 newinsn = AMPAMP (putstatic_resolved_obj);
2044 }
2045
2046 #ifdef DIRECT_THREADED
2047 pc[-2].insn = newinsn;
2048 pc[-1].datum = field->u.addr;
2049 #endif /* DIRECT_THREADED */
2050 }
2051 NEXT_INSN;
2052
2053 #ifdef DIRECT_THREADED
2054 putstatic_resolved_1:
2055 *(jbyte *) AVAL () = POPI ();
2056 NEXT_INSN;
2057
2058 putstatic_resolved_2:
2059 *(jchar *) AVAL () = POPI ();
2060 NEXT_INSN;
2061
2062 putstatic_resolved_4:
2063 *(jint *) AVAL () = POPI ();
2064 NEXT_INSN;
2065
2066 putstatic_resolved_8:
2067 *(jlong *) AVAL () = POPL ();
2068 NEXT_INSN;
2069
2070 putstatic_resolved_obj:
2071 *(jobject *) AVAL () = POPA ();
2072 NEXT_INSN;
2073 #endif /* DIRECT_THREADED */
2074
2075 insn_putfield:
2076 {
2077 SAVE_PC();
2078 jint fieldref_index = GET2U ();
2079 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2080 _Jv_Field *field = pool_data[fieldref_index].field;
2081
2082 jclass type = field->type;
2083
2084 if ((field->flags & Modifier::STATIC) != 0)
2085 throw_incompatible_class_change_error
2086 (JvNewStringLatin1 ("field is static"));
2087
2088 jint field_offset = field->u.boffset;
2089
2090 void *newinsn = NULL;
2091 if (type->isPrimitive ())
2092 {
2093 switch (type->size_in_bytes)
2094 {
2095 case 1:
2096 {
2097 jint value = POPI();
2098 jobject obj = POPA();
2099 NULLCHECK(obj);
2100 *(jbyte*) ((char*)obj + field_offset) = value;
2101 newinsn = AMPAMP (putfield_resolved_1);
2102 break;
2103 }
2104
2105 case 2:
2106 {
2107 jint value = POPI();
2108 jobject obj = POPA();
2109 NULLCHECK(obj);
2110 *(jchar*) ((char*)obj + field_offset) = value;
2111 newinsn = AMPAMP (putfield_resolved_2);
2112 break;
2113 }
2114
2115 case 4:
2116 {
2117 jint value = POPI();
2118 jobject obj = POPA();
2119 NULLCHECK(obj);
2120 *(jint*) ((char*)obj + field_offset) = value;
2121 newinsn = AMPAMP (putfield_resolved_4);
2122 break;
2123 }
2124
2125 case 8:
2126 {
2127 jlong value = POPL();
2128 jobject obj = POPA();
2129 NULLCHECK(obj);
2130 *(jlong*) ((char*)obj + field_offset) = value;
2131 newinsn = AMPAMP (putfield_resolved_8);
2132 break;
2133 }
2134 }
2135 }
2136 else
2137 {
2138 jobject value = POPA();
2139 jobject obj = POPA();
2140 NULLCHECK(obj);
2141 *(jobject*) ((char*)obj + field_offset) = value;
2142 newinsn = AMPAMP (putfield_resolved_obj);
2143 }
2144
2145 #ifdef DIRECT_THREADED
2146 pc[-2].insn = newinsn;
2147 pc[-1].int_val = field_offset;
2148 #endif /* DIRECT_THREADED */
2149 }
2150 NEXT_INSN;
2151
2152 #ifdef DIRECT_THREADED
2153 putfield_resolved_1:
2154 {
2155 jint val = POPI ();
2156 char *obj = (char *) POPA ();
2157 NULLCHECK (obj);
2158 *(jbyte *) (obj + INTVAL ()) = val;
2159 }
2160 NEXT_INSN;
2161
2162 putfield_resolved_2:
2163 {
2164 jint val = POPI ();
2165 char *obj = (char *) POPA ();
2166 NULLCHECK (obj);
2167 *(jchar *) (obj + INTVAL ()) = val;
2168 }
2169 NEXT_INSN;
2170
2171 putfield_resolved_4:
2172 {
2173 jint val = POPI ();
2174 char *obj = (char *) POPA ();
2175 NULLCHECK (obj);
2176 *(jint *) (obj + INTVAL ()) = val;
2177 }
2178 NEXT_INSN;
2179
2180 putfield_resolved_8:
2181 {
2182 jlong val = POPL ();
2183 char *obj = (char *) POPA ();
2184 NULLCHECK (obj);
2185 *(jlong *) (obj + INTVAL ()) = val;
2186 }
2187 NEXT_INSN;
2188
2189 putfield_resolved_obj:
2190 {
2191 jobject val = POPA ();
2192 char *obj = (char *) POPA ();
2193 NULLCHECK (obj);
2194 *(jobject *) (obj + INTVAL ()) = val;
2195 }
2196 NEXT_INSN;
2197 #endif /* DIRECT_THREADED */
2198
2199 insn_invokespecial:
2200 {
2201 SAVE_PC();
2202 int index = GET2U ();
2203
2204 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2205 index)).rmethod;
2206
2207 sp -= rmeth->stack_item_count;
2208
2209 // We don't use NULLCHECK here because we can't rely on that
2210 // working for <init>. So instead we do an explicit test.
2211 if (! sp[0].o)
2212 {
2213 SAVE_PC();
2214 throw_null_pointer_exception ();
2215 }
2216
2217 fun = (void (*)()) rmeth->method->ncode;
2218
2219 #ifdef DIRECT_THREADED
2220 // Rewrite instruction so that we use a faster pre-resolved
2221 // method.
2222 pc[-2].insn = &&invokespecial_resolved;
2223 pc[-1].datum = rmeth;
2224 #endif /* DIRECT_THREADED */
2225 }
2226 goto perform_invoke;
2227
2228 #ifdef DIRECT_THREADED
2229 invokespecial_resolved:
2230 {
2231 SAVE_PC();
2232 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2233 sp -= rmeth->stack_item_count;
2234 // We don't use NULLCHECK here because we can't rely on that
2235 // working for <init>. So instead we do an explicit test.
2236 if (! sp[0].o)
2237 {
2238 throw_null_pointer_exception ();
2239 }
2240 fun = (void (*)()) rmeth->method->ncode;
2241 }
2242 goto perform_invoke;
2243 #endif /* DIRECT_THREADED */
2244
2245 insn_invokestatic:
2246 {
2247 SAVE_PC();
2248 int index = GET2U ();
2249
2250 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2251 index)).rmethod;
2252
2253 sp -= rmeth->stack_item_count;
2254
2255 fun = (void (*)()) rmeth->method->ncode;
2256
2257 #ifdef DIRECT_THREADED
2258 // Rewrite instruction so that we use a faster pre-resolved
2259 // method.
2260 pc[-2].insn = &&invokestatic_resolved;
2261 pc[-1].datum = rmeth;
2262 #endif /* DIRECT_THREADED */
2263 }
2264 goto perform_invoke;
2265
2266 #ifdef DIRECT_THREADED
2267 invokestatic_resolved:
2268 {
2269 SAVE_PC();
2270 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2271 sp -= rmeth->stack_item_count;
2272 fun = (void (*)()) rmeth->method->ncode;
2273 }
2274 goto perform_invoke;
2275 #endif /* DIRECT_THREADED */
2276
2277 insn_invokeinterface:
2278 {
2279 SAVE_PC();
2280 int index = GET2U ();
2281
2282 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2283 index)).rmethod;
2284
2285 sp -= rmeth->stack_item_count;
2286
2287 jobject rcv = sp[0].o;
2288
2289 NULLCHECK (rcv);
2290
2291 fun = (void (*)())
2292 _Jv_LookupInterfaceMethod (rcv->getClass (),
2293 rmeth->method->name,
2294 rmeth->method->signature);
2295
2296 #ifdef DIRECT_THREADED
2297 // Rewrite instruction so that we use a faster pre-resolved
2298 // method.
2299 pc[-2].insn = &&invokeinterface_resolved;
2300 pc[-1].datum = rmeth;
2301 #else
2302 // Skip dummy bytes.
2303 pc += 2;
2304 #endif /* DIRECT_THREADED */
2305 }
2306 goto perform_invoke;
2307
2308 #ifdef DIRECT_THREADED
2309 invokeinterface_resolved:
2310 {
2311 SAVE_PC();
2312 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2313 sp -= rmeth->stack_item_count;
2314 jobject rcv = sp[0].o;
2315 NULLCHECK (rcv);
2316 fun = (void (*)())
2317 _Jv_LookupInterfaceMethod (rcv->getClass (),
2318 rmeth->method->name,
2319 rmeth->method->signature);
2320 }
2321 goto perform_invoke;
2322 #endif /* DIRECT_THREADED */
2323
2324 insn_new:
2325 {
2326 SAVE_PC();
2327 int index = GET2U ();
2328 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2329 index)).clazz;
2330 /* VM spec, section 3.11.5 */
2331 if ((klass->getModifiers() & Modifier::ABSTRACT)
2332 || klass->isInterface())
2333 throw new java::lang::InstantiationException;
2334 jobject res = _Jv_AllocObject (klass);
2335 PUSHA (res);
2336
2337 #ifdef DIRECT_THREADED
2338 pc[-2].insn = &&new_resolved;
2339 pc[-1].datum = klass;
2340 #endif /* DIRECT_THREADED */
2341 }
2342 NEXT_INSN;
2343
2344 #ifdef DIRECT_THREADED
2345 new_resolved:
2346 {
2347 jclass klass = (jclass) AVAL ();
2348 jobject res = _Jv_AllocObject (klass);
2349 PUSHA (res);
2350 }
2351 NEXT_INSN;
2352 #endif /* DIRECT_THREADED */
2353
2354 insn_newarray:
2355 {
2356 int atype = GET1U ();
2357 int size = POPI();
2358 jobject result = _Jv_NewArray (atype, size);
2359 PUSHA (result);
2360 }
2361 NEXT_INSN;
2362
2363 insn_anewarray:
2364 {
2365 SAVE_PC();
2366 int index = GET2U ();
2367 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2368 index)).clazz;
2369 int size = POPI();
2370 jobject result = _Jv_NewObjectArray (size, klass, 0);
2371 PUSHA (result);
2372
2373 #ifdef DIRECT_THREADED
2374 pc[-2].insn = &&anewarray_resolved;
2375 pc[-1].datum = klass;
2376 #endif /* DIRECT_THREADED */
2377 }
2378 NEXT_INSN;
2379
2380 #ifdef DIRECT_THREADED
2381 anewarray_resolved:
2382 {
2383 jclass klass = (jclass) AVAL ();
2384 int size = POPI ();
2385 jobject result = _Jv_NewObjectArray (size, klass, 0);
2386 PUSHA (result);
2387 }
2388 NEXT_INSN;
2389 #endif /* DIRECT_THREADED */
2390
2391 insn_arraylength:
2392 {
2393 __JArray *arr = (__JArray*)POPA();
2394 NULLARRAYCHECK (arr);
2395 PUSHI (arr->length);
2396 }
2397 NEXT_INSN;
2398
2399 insn_athrow:
2400 {
2401 jobject value = POPA();
2402 throw static_cast<jthrowable>(value);
2403 }
2404 NEXT_INSN;
2405
2406 insn_checkcast:
2407 {
2408 SAVE_PC();
2409 jobject value = POPA();
2410 jint index = GET2U ();
2411 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2412 index)).clazz;
2413
2414 value = (jobject) _Jv_CheckCast (to, value);
2415
2416 PUSHA (value);
2417
2418 #ifdef DIRECT_THREADED
2419 pc[-2].insn = &&checkcast_resolved;
2420 pc[-1].datum = to;
2421 #endif /* DIRECT_THREADED */
2422 }
2423 NEXT_INSN;
2424
2425 #ifdef DIRECT_THREADED
2426 checkcast_resolved:
2427 {
2428 SAVE_PC();
2429 jobject value = POPA ();
2430 jclass to = (jclass) AVAL ();
2431 value = (jobject) _Jv_CheckCast (to, value);
2432 PUSHA (value);
2433 }
2434 NEXT_INSN;
2435 #endif /* DIRECT_THREADED */
2436
2437 insn_instanceof:
2438 {
2439 SAVE_PC();
2440 jobject value = POPA();
2441 jint index = GET2U ();
2442 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2443 index)).clazz;
2444 PUSHI (to->isInstance (value));
2445
2446 #ifdef DIRECT_THREADED
2447 pc[-2].insn = &&instanceof_resolved;
2448 pc[-1].datum = to;
2449 #endif /* DIRECT_THREADED */
2450 }
2451 NEXT_INSN;
2452
2453 #ifdef DIRECT_THREADED
2454 instanceof_resolved:
2455 {
2456 jobject value = POPA ();
2457 jclass to = (jclass) AVAL ();
2458 PUSHI (to->isInstance (value));
2459 }
2460 NEXT_INSN;
2461 #endif /* DIRECT_THREADED */
2462
2463 insn_monitorenter:
2464 {
2465 jobject value = POPA();
2466 NULLCHECK(value);
2467 _Jv_MonitorEnter (value);
2468 }
2469 NEXT_INSN;
2470
2471 insn_monitorexit:
2472 {
2473 jobject value = POPA();
2474 NULLCHECK(value);
2475 _Jv_MonitorExit (value);
2476 }
2477 NEXT_INSN;
2478
2479 insn_ifnull:
2480 {
2481 jobject val = POPA();
2482 if (val == NULL)
2483 TAKE_GOTO;
2484 else
2485 SKIP_GOTO;
2486 }
2487 NEXT_INSN;
2488
2489 insn_ifnonnull:
2490 {
2491 jobject val = POPA();
2492 if (val != NULL)
2493 TAKE_GOTO;
2494 else
2495 SKIP_GOTO;
2496 }
2497 NEXT_INSN;
2498
2499 insn_multianewarray:
2500 {
2501 SAVE_PC();
2502 int kind_index = GET2U ();
2503 int dim = GET1U ();
2504
2505 jclass type
2506 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2507 kind_index)).clazz;
2508 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2509
2510 for (int i = dim - 1; i >= 0; i--)
2511 {
2512 sizes[i] = POPI ();
2513 }
2514
2515 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2516
2517 PUSHA (res);
2518 }
2519 NEXT_INSN;
2520
2521 #ifndef DIRECT_THREADED
2522 insn_wide:
2523 {
2524 jint the_mod_op = get1u (pc++);
2525 jint wide = get2u (pc); pc += 2;
2526
2527 switch (the_mod_op)
2528 {
2529 case op_istore:
2530 STOREI (wide);
2531 NEXT_INSN;
2532
2533 case op_fstore:
2534 STOREF (wide);
2535 NEXT_INSN;
2536
2537 case op_astore:
2538 STOREA (wide);
2539 NEXT_INSN;
2540
2541 case op_lload:
2542 LOADL (wide);
2543 NEXT_INSN;
2544
2545 case op_dload:
2546 LOADD (wide);
2547 NEXT_INSN;
2548
2549 case op_iload:
2550 LOADI (wide);
2551 NEXT_INSN;
2552
2553 case op_fload:
2554 LOADF (wide);
2555 NEXT_INSN;
2556
2557 case op_aload:
2558 LOADA (wide);
2559 NEXT_INSN;
2560
2561 case op_lstore:
2562 STOREL (wide);
2563 NEXT_INSN;
2564
2565 case op_dstore:
2566 STORED (wide);
2567 NEXT_INSN;
2568
2569 case op_ret:
2570 pc = (unsigned char*) PEEKA (wide);
2571 NEXT_INSN;
2572
2573 case op_iinc:
2574 {
2575 jint amount = get2s (pc); pc += 2;
2576 jint value = PEEKI (wide);
2577 POKEI (wide, value+amount);
2578 }
2579 NEXT_INSN;
2580
2581 default:
2582 throw_internal_error ("illegal bytecode modified by wide");
2583 }
2584
2585 }
2586 #endif /* DIRECT_THREADED */
2587
2588 insn_breakpoint:
2589 {
2590 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2591
2592 // Send JVMTI notification
2593 using namespace ::java::lang;
2594 jmethodID method = meth->self;
2595 jlocation location = meth->insn_index (pc - 1);
2596 Thread *thread = Thread::currentThread ();
2597 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2598
2599 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2600 method, location);
2601
2602 // Continue execution
2603 using namespace gnu::gcj::jvmti;
2604 Breakpoint *bp
2605 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2606 location);
2607 JvAssert (bp != NULL);
2608
2609 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2610
2611 #ifdef DIRECT_THREADED
2612 goto *(opc->insn);
2613 #else
2614 goto *(insn_target[*opc]);
2615 #endif
2616 }
2617 }
2618 catch (java::lang::Throwable *ex)
2619 {
2620 #ifdef DEBUG
2621 // This needs to be done before the pc is changed.
2622 jlong throw_loc = meth->insn_index (pc);
2623 #endif
2624 // Check if the exception is handled and, if so, set the pc to the start
2625 // of the appropriate catch block.
2626 if (meth->check_handler (&pc, meth, ex))
2627 {
2628 sp = stack;
2629 sp++->o = ex; // Push exception.
2630 #ifdef DEBUG
2631 if (JVMTI_REQUESTED_EVENT (Exception))
2632 {
2633 using namespace gnu::gcj::jvmti;
2634 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2635 jlong catch_loc = meth->insn_index (pc);
2636 ExceptionEvent::postExceptionEvent (thread, throw_meth,
2637 throw_loc, ex, throw_meth,
2638 catch_loc);
2639 }
2640 #endif
2641 NEXT_INSN;
2642 }
2643 #ifdef DEBUG
2644 if (JVMTI_REQUESTED_EVENT (Exception))
2645 {
2646 using namespace gnu::gcj::jvmti;
2647 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2648 ExceptionEvent::postExceptionEvent (thread, throw_meth, throw_loc,
2649 ex, NULL, NULL);
2650 }
2651 #endif
2652 // No handler, so re-throw.
2653 throw ex;
2654 }