* config/mips/mips.h (ISA_HAS_EXTS): New macro.
[official-gcc.git] / libjava / interpret-run.cc
blob2934b9b89567965de69857f518688e789f02103a
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 pc_t pc = NULL;
18 // FRAME_DESC registers this particular invocation as the top-most
19 // interpreter frame. This lets the stack tracing code (for
20 // Throwable) print information about the method being interpreted
21 // rather than about the interpreter itself. FRAME_DESC has a
22 // destructor so it cleans up automatically when the interpreter
23 // returns.
24 java::lang::Thread *thread = java::lang::Thread::currentThread();
26 #ifdef DEBUG
27 _Jv_InterpFrame frame_desc (meth, thread, NULL, &pc);
28 #else
29 _Jv_InterpFrame frame_desc (meth, thread);
30 #endif
32 _Jv_word stack[meth->max_stack];
33 _Jv_word *sp = stack;
35 _Jv_word locals[meth->max_locals];
37 #ifdef DEBUG
38 // This is the information needed to get and set local variables with
39 // proper type checking.
40 frame_desc.locals = locals;
41 char locals_type[meth->max_locals];
42 frame_desc.locals_type = locals_type;
44 // Set all slots as invalid until they are written to.
45 memset (locals_type, 'x', meth->max_locals);
47 // We need to set the local variable types for the method arguments since
48 // they are valid at invocation.
50 _Jv_Method *method = meth->get_method ();
51 int type_ctr = 0;
53 // If the method is non-static, we need to set the type for the "this" pointer.
54 if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
56 if (args)
58 // Set the "this" pointer for this frame.
59 _Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args);
60 frame_desc.obj_ptr = this_ptr[0].o;
63 frame_desc.locals_type[0] = 'o';
64 type_ctr++;
67 // Now parse the method signature to set the types of the other arguments.
68 int sig_len = method->signature->len ();
69 char *signature = method->signature->chars ();
70 for (int i = 1; signature[i] != ')' && i <= sig_len; i++)
72 if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C'
73 || signature[i] == 'S' || signature[i] == 'I')
75 frame_desc.locals_type[type_ctr] = 'i';
76 type_ctr++;
77 continue;
79 else if (signature[i] == 'F')
81 frame_desc.locals_type[type_ctr] = 'f';
82 type_ctr++;
83 continue;
85 else if (signature[i] == 'J')
87 frame_desc.locals_type[type_ctr] = 'l';
88 frame_desc.locals_type[type_ctr+1] = 'x';
89 type_ctr += 2;
90 continue;
92 else if (signature[i] == 'D')
94 frame_desc.locals_type[type_ctr] = 'd';
95 frame_desc.locals_type[type_ctr+1] = 'x';
96 type_ctr += 2;
97 continue;
99 else if (signature[i] == 'L')
101 frame_desc.locals_type[type_ctr] = 'o';
102 type_ctr++;
103 while (signature[i] != ';')
104 i++;
105 continue;
107 else if (signature[i] == '[')
109 frame_desc.locals_type[type_ctr] = 'o';
110 type_ctr++;
112 // Ignore multi-dimensional arrays.
113 while (signature[i] == '[')
114 i++;
116 // Check for an object array
117 if (signature[i] == 'L')
119 while (signature[i] != ';')
120 i++;
122 continue;
125 #endif /* DEBUG */
127 #define INSN_LABEL(op) &&insn_##op
129 static const void *const insn_target[] =
131 INSN_LABEL(nop),
132 INSN_LABEL(aconst_null),
133 INSN_LABEL(iconst_m1),
134 INSN_LABEL(iconst_0),
135 INSN_LABEL(iconst_1),
136 INSN_LABEL(iconst_2),
137 INSN_LABEL(iconst_3),
138 INSN_LABEL(iconst_4),
139 INSN_LABEL(iconst_5),
140 INSN_LABEL(lconst_0),
141 INSN_LABEL(lconst_1),
142 INSN_LABEL(fconst_0),
143 INSN_LABEL(fconst_1),
144 INSN_LABEL(fconst_2),
145 INSN_LABEL(dconst_0),
146 INSN_LABEL(dconst_1),
147 INSN_LABEL(bipush),
148 INSN_LABEL(sipush),
149 INSN_LABEL(ldc),
150 INSN_LABEL(ldc_w),
151 INSN_LABEL(ldc2_w),
152 INSN_LABEL(iload),
153 INSN_LABEL(lload),
154 INSN_LABEL(fload),
155 INSN_LABEL(dload),
156 INSN_LABEL(aload),
157 INSN_LABEL(iload_0),
158 INSN_LABEL(iload_1),
159 INSN_LABEL(iload_2),
160 INSN_LABEL(iload_3),
161 INSN_LABEL(lload_0),
162 INSN_LABEL(lload_1),
163 INSN_LABEL(lload_2),
164 INSN_LABEL(lload_3),
165 INSN_LABEL(fload_0),
166 INSN_LABEL(fload_1),
167 INSN_LABEL(fload_2),
168 INSN_LABEL(fload_3),
169 INSN_LABEL(dload_0),
170 INSN_LABEL(dload_1),
171 INSN_LABEL(dload_2),
172 INSN_LABEL(dload_3),
173 INSN_LABEL(aload_0),
174 INSN_LABEL(aload_1),
175 INSN_LABEL(aload_2),
176 INSN_LABEL(aload_3),
177 INSN_LABEL(iaload),
178 INSN_LABEL(laload),
179 INSN_LABEL(faload),
180 INSN_LABEL(daload),
181 INSN_LABEL(aaload),
182 INSN_LABEL(baload),
183 INSN_LABEL(caload),
184 INSN_LABEL(saload),
185 INSN_LABEL(istore),
186 INSN_LABEL(lstore),
187 INSN_LABEL(fstore),
188 INSN_LABEL(dstore),
189 INSN_LABEL(astore),
190 INSN_LABEL(istore_0),
191 INSN_LABEL(istore_1),
192 INSN_LABEL(istore_2),
193 INSN_LABEL(istore_3),
194 INSN_LABEL(lstore_0),
195 INSN_LABEL(lstore_1),
196 INSN_LABEL(lstore_2),
197 INSN_LABEL(lstore_3),
198 INSN_LABEL(fstore_0),
199 INSN_LABEL(fstore_1),
200 INSN_LABEL(fstore_2),
201 INSN_LABEL(fstore_3),
202 INSN_LABEL(dstore_0),
203 INSN_LABEL(dstore_1),
204 INSN_LABEL(dstore_2),
205 INSN_LABEL(dstore_3),
206 INSN_LABEL(astore_0),
207 INSN_LABEL(astore_1),
208 INSN_LABEL(astore_2),
209 INSN_LABEL(astore_3),
210 INSN_LABEL(iastore),
211 INSN_LABEL(lastore),
212 INSN_LABEL(fastore),
213 INSN_LABEL(dastore),
214 INSN_LABEL(aastore),
215 INSN_LABEL(bastore),
216 INSN_LABEL(castore),
217 INSN_LABEL(sastore),
218 INSN_LABEL(pop),
219 INSN_LABEL(pop2),
220 INSN_LABEL(dup),
221 INSN_LABEL(dup_x1),
222 INSN_LABEL(dup_x2),
223 INSN_LABEL(dup2),
224 INSN_LABEL(dup2_x1),
225 INSN_LABEL(dup2_x2),
226 INSN_LABEL(swap),
227 INSN_LABEL(iadd),
228 INSN_LABEL(ladd),
229 INSN_LABEL(fadd),
230 INSN_LABEL(dadd),
231 INSN_LABEL(isub),
232 INSN_LABEL(lsub),
233 INSN_LABEL(fsub),
234 INSN_LABEL(dsub),
235 INSN_LABEL(imul),
236 INSN_LABEL(lmul),
237 INSN_LABEL(fmul),
238 INSN_LABEL(dmul),
239 INSN_LABEL(idiv),
240 INSN_LABEL(ldiv),
241 INSN_LABEL(fdiv),
242 INSN_LABEL(ddiv),
243 INSN_LABEL(irem),
244 INSN_LABEL(lrem),
245 INSN_LABEL(frem),
246 INSN_LABEL(drem),
247 INSN_LABEL(ineg),
248 INSN_LABEL(lneg),
249 INSN_LABEL(fneg),
250 INSN_LABEL(dneg),
251 INSN_LABEL(ishl),
252 INSN_LABEL(lshl),
253 INSN_LABEL(ishr),
254 INSN_LABEL(lshr),
255 INSN_LABEL(iushr),
256 INSN_LABEL(lushr),
257 INSN_LABEL(iand),
258 INSN_LABEL(land),
259 INSN_LABEL(ior),
260 INSN_LABEL(lor),
261 INSN_LABEL(ixor),
262 INSN_LABEL(lxor),
263 INSN_LABEL(iinc),
264 INSN_LABEL(i2l),
265 INSN_LABEL(i2f),
266 INSN_LABEL(i2d),
267 INSN_LABEL(l2i),
268 INSN_LABEL(l2f),
269 INSN_LABEL(l2d),
270 INSN_LABEL(f2i),
271 INSN_LABEL(f2l),
272 INSN_LABEL(f2d),
273 INSN_LABEL(d2i),
274 INSN_LABEL(d2l),
275 INSN_LABEL(d2f),
276 INSN_LABEL(i2b),
277 INSN_LABEL(i2c),
278 INSN_LABEL(i2s),
279 INSN_LABEL(lcmp),
280 INSN_LABEL(fcmpl),
281 INSN_LABEL(fcmpg),
282 INSN_LABEL(dcmpl),
283 INSN_LABEL(dcmpg),
284 INSN_LABEL(ifeq),
285 INSN_LABEL(ifne),
286 INSN_LABEL(iflt),
287 INSN_LABEL(ifge),
288 INSN_LABEL(ifgt),
289 INSN_LABEL(ifle),
290 INSN_LABEL(if_icmpeq),
291 INSN_LABEL(if_icmpne),
292 INSN_LABEL(if_icmplt),
293 INSN_LABEL(if_icmpge),
294 INSN_LABEL(if_icmpgt),
295 INSN_LABEL(if_icmple),
296 INSN_LABEL(if_acmpeq),
297 INSN_LABEL(if_acmpne),
298 INSN_LABEL(goto),
299 INSN_LABEL(jsr),
300 INSN_LABEL(ret),
301 INSN_LABEL(tableswitch),
302 INSN_LABEL(lookupswitch),
303 INSN_LABEL(ireturn),
304 INSN_LABEL(lreturn),
305 INSN_LABEL(freturn),
306 INSN_LABEL(dreturn),
307 INSN_LABEL(areturn),
308 INSN_LABEL(return),
309 INSN_LABEL(getstatic),
310 INSN_LABEL(putstatic),
311 INSN_LABEL(getfield),
312 INSN_LABEL(putfield),
313 INSN_LABEL(invokevirtual),
314 INSN_LABEL(invokespecial),
315 INSN_LABEL(invokestatic),
316 INSN_LABEL(invokeinterface),
317 INSN_LABEL(breakpoint),
318 INSN_LABEL(new),
319 INSN_LABEL(newarray),
320 INSN_LABEL(anewarray),
321 INSN_LABEL(arraylength),
322 INSN_LABEL(athrow),
323 INSN_LABEL(checkcast),
324 INSN_LABEL(instanceof),
325 INSN_LABEL(monitorenter),
326 INSN_LABEL(monitorexit),
327 #ifdef DIRECT_THREADED
328 0, // wide
329 #else
330 INSN_LABEL(wide),
331 #endif
332 INSN_LABEL(multianewarray),
333 INSN_LABEL(ifnull),
334 INSN_LABEL(ifnonnull),
335 INSN_LABEL(goto_w),
336 INSN_LABEL(jsr_w),
337 #ifdef DIRECT_THREADED
338 INSN_LABEL (ldc_class)
339 #else
341 #endif
344 #ifdef DIRECT_THREADED
346 #ifdef DEBUG
347 #undef NEXT_INSN
348 #define NEXT_INSN \
349 do \
351 pc_t insn = pc++; \
352 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
354 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
355 jmethodID method = meth->self; \
356 jlocation loc = meth->insn_index (insn); \
357 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
358 env, method, loc); \
360 goto *(insn->insn); \
362 while (0)
364 #undef REWRITE_INSN
365 #define REWRITE_INSN(INSN,SLOT,VALUE) \
366 do { \
367 if (pc[-2].insn == breakpoint_insn->insn) \
369 using namespace ::gnu::gcj::jvmti; \
370 jlocation location = meth->insn_index (pc - 2); \
371 _Jv_RewriteBreakpointInsn (meth->self, location, (pc_t) INSN); \
373 else \
374 pc[-2].insn = INSN; \
376 pc[-1].SLOT = VALUE; \
378 while (0)
380 #undef INTERP_REPORT_EXCEPTION
381 #define INTERP_REPORT_EXCEPTION(Jthrowable) REPORT_EXCEPTION (Jthrowable)
382 #else // !DEBUG
383 #undef NEXT_INSN
384 #define NEXT_INSN goto *((pc++)->insn)
386 // REWRITE_INSN does nothing.
388 // Rewriting a multi-word instruction in the presence of multiple
389 // threads leads to a data race if a thread reads part of an
390 // instruction while some other thread is rewriting that instruction.
391 // For example, an invokespecial instruction may be rewritten to
392 // invokespecial_resolved and its operand changed from an index to a
393 // pointer while another thread is executing invokespecial. This
394 // other thread then reads the pointer that is now the operand of
395 // invokespecial_resolved and tries to use it as an index.
397 // Fixing this requires either spinlocks, a more elaborate data
398 // structure, or even per-thread allocated pages. It's clear from the
399 // locking in meth->compile below that the presence of multiple
400 // threads was contemplated when this code was written, but the full
401 // consequences were not fully appreciated.
402 #define REWRITE_INSN(INSN,SLOT,VALUE)
404 #undef INTERP_REPORT_EXCEPTION
405 #define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */
406 #endif // !DEBUG
408 #define INTVAL() ((pc++)->int_val)
409 #define AVAL() ((pc++)->datum)
411 #define GET1S() INTVAL ()
412 #define GET2S() INTVAL ()
413 #define GET1U() INTVAL ()
414 #define GET2U() INTVAL ()
415 #define AVAL1U() AVAL ()
416 #define AVAL2U() AVAL ()
417 #define AVAL2UP() AVAL ()
418 #define SKIP_GOTO ++pc
419 #define GOTO_VAL() (insn_slot *) pc->datum
420 #define PCVAL(unionval) unionval.p
421 #define AMPAMP(label) &&label
423 // Compile if we must. NOTE: Double-check locking.
424 if (meth->prepared == NULL)
426 _Jv_MutexLock (&compile_mutex);
427 if (meth->prepared == NULL)
428 meth->compile (insn_target);
429 _Jv_MutexUnlock (&compile_mutex);
432 // If we're only compiling, stop here
433 if (args == NULL)
434 return;
436 pc = (insn_slot *) meth->prepared;
438 #else
440 #ifdef DEBUG
441 #define NEXT_INSN \
442 do \
444 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
446 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
447 jmethodID method = meth->self; \
448 jlocation loc = meth->insn_index (pc); \
449 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
450 env, method, loc); \
452 goto *(insn_target[*pc++])
453 #else
454 #define NEXT_INSN goto *(insn_target[*pc++])
455 #endif
457 #define GET1S() get1s (pc++)
458 #define GET2S() (pc += 2, get2s (pc- 2))
459 #define GET1U() get1u (pc++)
460 #define GET2U() (pc += 2, get2u (pc - 2))
461 // Note that these could be more efficient when not handling 'ldc
462 // class'.
463 #define AVAL1U() \
464 ({ int index = get1u (pc++); \
465 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
466 #define AVAL2U() \
467 ({ int index = get2u (pc); pc += 2; \
468 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
469 // Note that we don't need to resolve the pool entry here as class
470 // constants are never wide.
471 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
472 #define SKIP_GOTO pc += 2
473 #define GOTO_VAL() pc - 1 + get2s (pc)
474 #define PCVAL(unionval) unionval.i
475 #define AMPAMP(label) NULL
477 pc = meth->bytecode ();
479 #endif /* DIRECT_THREADED */
481 #define TAKE_GOTO pc = GOTO_VAL ()
483 /* Go straight at it! the ffi raw format matches the internal
484 stack representation exactly. At least, that's the idea.
486 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
488 _Jv_word *pool_data = meth->defining_class->constants.data;
490 /* These three are temporaries for common code used by several
491 instructions. */
492 void (*fun)();
493 _Jv_ResolvedMethod* rmeth;
494 int tmpval;
498 // We keep nop around. It is used if we're interpreting the
499 // bytecodes and not doing direct threading.
500 insn_nop:
501 NEXT_INSN;
503 /* The first few instructions here are ordered according to their
504 frequency, in the hope that this will improve code locality a
505 little. */
507 insn_aload_0: // 0x2a
508 LOADA (0);
509 NEXT_INSN;
511 insn_iload: // 0x15
512 LOADI (GET1U ());
513 NEXT_INSN;
515 insn_iload_1: // 0x1b
516 LOADI (1);
517 NEXT_INSN;
519 insn_invokevirtual: // 0xb6
521 SAVE_PC();
522 int index = GET2U ();
524 /* _Jv_Linker::resolve_pool_entry returns immediately if the
525 * value already is resolved. If we want to clutter up the
526 * code here to gain a little performance, then we can check
527 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
528 * directly. For now, I don't think it is worth it. */
530 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
531 index)).rmethod;
533 sp -= rmeth->stack_item_count;
535 if (rmeth->method->accflags & Modifier::FINAL)
537 // We can't rely on NULLCHECK working if the method is final.
538 if (! sp[0].o)
539 throw_null_pointer_exception ();
541 // Final methods might not appear in the vtable.
542 fun = (void (*)()) rmeth->method->ncode;
544 else
546 NULLCHECK (sp[0].o);
547 jobject rcv = sp[0].o;
548 _Jv_VTable *table = *(_Jv_VTable**) rcv;
549 fun = (void (*)()) table->get_method (rmeth->method->index);
552 #ifdef DIRECT_THREADED
553 // Rewrite instruction so that we use a faster pre-resolved
554 // method.
555 REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth);
556 #endif /* DIRECT_THREADED */
558 goto perform_invoke;
560 #ifdef DIRECT_THREADED
561 invokevirtual_resolved:
563 SAVE_PC();
564 rmeth = (_Jv_ResolvedMethod *) AVAL ();
565 sp -= rmeth->stack_item_count;
567 if (rmeth->method->accflags & Modifier::FINAL)
569 // We can't rely on NULLCHECK working if the method is final.
570 if (! sp[0].o)
571 throw_null_pointer_exception ();
573 // Final methods might not appear in the vtable.
574 fun = (void (*)()) rmeth->method->ncode;
576 else
578 NULLCHECK (sp[0].o);
579 jobject rcv = sp[0].o;
580 _Jv_VTable *table = *(_Jv_VTable**) rcv;
581 fun = (void (*)()) table->get_method (rmeth->method->index);
584 goto perform_invoke;
585 #endif /* DIRECT_THREADED */
587 perform_invoke:
589 /* here goes the magic again... */
590 ffi_cif *cif = &rmeth->cif;
591 INTERP_FFI_RAW_TYPE *raw = (INTERP_FFI_RAW_TYPE *) sp;
593 _Jv_value rvalue;
595 #if FFI_NATIVE_RAW_API
596 /* We assume that this is only implemented if it's correct */
597 /* to use it here. On a 64 bit machine, it never is. */
598 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
599 #else
600 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
601 #endif
603 int rtype = cif->rtype->type;
605 /* the likelyhood of object, int, or void return is very high,
606 * so those are checked before the switch */
607 if (rtype == FFI_TYPE_POINTER)
609 PUSHA (rvalue.object_value);
611 else if (rtype == FFI_TYPE_SINT32)
613 PUSHI (rvalue.int_value);
615 else if (rtype == FFI_TYPE_VOID)
617 /* skip */
619 else
621 switch (rtype)
623 case FFI_TYPE_SINT8:
624 PUSHI ((jbyte)(rvalue.int_value & 0xff));
625 break;
627 case FFI_TYPE_SINT16:
628 PUSHI ((jshort)(rvalue.int_value & 0xffff));
629 break;
631 case FFI_TYPE_UINT16:
632 PUSHI (rvalue.int_value & 0xffff);
633 break;
635 case FFI_TYPE_FLOAT:
636 PUSHF (rvalue.float_value);
637 break;
639 case FFI_TYPE_DOUBLE:
640 PUSHD (rvalue.double_value);
641 break;
643 case FFI_TYPE_SINT64:
644 PUSHL (rvalue.long_value);
645 break;
647 default:
648 throw_internal_error ("unknown return type in invokeXXX");
652 NEXT_INSN;
654 insn_aconst_null:
655 PUSHA (NULL);
656 NEXT_INSN;
658 insn_iconst_m1:
659 PUSHI (-1);
660 NEXT_INSN;
662 insn_iconst_0:
663 PUSHI (0);
664 NEXT_INSN;
666 insn_iconst_1:
667 PUSHI (1);
668 NEXT_INSN;
670 insn_iconst_2:
671 PUSHI (2);
672 NEXT_INSN;
674 insn_iconst_3:
675 PUSHI (3);
676 NEXT_INSN;
678 insn_iconst_4:
679 PUSHI (4);
680 NEXT_INSN;
682 insn_iconst_5:
683 PUSHI (5);
684 NEXT_INSN;
686 insn_lconst_0:
687 PUSHL (0);
688 NEXT_INSN;
690 insn_lconst_1:
691 PUSHL (1);
692 NEXT_INSN;
694 insn_fconst_0:
695 PUSHF (0);
696 NEXT_INSN;
698 insn_fconst_1:
699 PUSHF (1);
700 NEXT_INSN;
702 insn_fconst_2:
703 PUSHF (2);
704 NEXT_INSN;
706 insn_dconst_0:
707 PUSHD (0);
708 NEXT_INSN;
710 insn_dconst_1:
711 PUSHD (1);
712 NEXT_INSN;
714 insn_bipush:
715 // For direct threaded, bipush and sipush are the same.
716 #ifndef DIRECT_THREADED
717 PUSHI (GET1S ());
718 NEXT_INSN;
719 #endif /* DIRECT_THREADED */
720 insn_sipush:
721 PUSHI (GET2S ());
722 NEXT_INSN;
724 insn_ldc:
725 // For direct threaded, ldc and ldc_w are the same.
726 #ifndef DIRECT_THREADED
727 PUSHA ((jobject) AVAL1U ());
728 NEXT_INSN;
729 #endif /* DIRECT_THREADED */
730 insn_ldc_w:
731 PUSHA ((jobject) AVAL2U ());
732 NEXT_INSN;
734 #ifdef DIRECT_THREADED
735 // For direct threaded we have a separate 'ldc class' operation.
736 insn_ldc_class:
738 SAVE_PC();
739 // We could rewrite the instruction at this point.
740 int index = INTVAL ();
741 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
742 index)).o;
743 PUSHA (k);
745 NEXT_INSN;
746 #endif /* DIRECT_THREADED */
748 insn_ldc2_w:
750 void *where = AVAL2UP ();
751 memcpy (sp, where, 2*sizeof (_Jv_word));
752 sp += 2;
754 NEXT_INSN;
756 insn_lload:
757 LOADL (GET1U ());
758 NEXT_INSN;
760 insn_fload:
761 LOADF (GET1U ());
762 NEXT_INSN;
764 insn_dload:
765 LOADD (GET1U ());
766 NEXT_INSN;
768 insn_aload:
769 LOADA (GET1U ());
770 NEXT_INSN;
772 insn_iload_0:
773 LOADI (0);
774 NEXT_INSN;
776 insn_iload_2:
777 LOADI (2);
778 NEXT_INSN;
780 insn_iload_3:
781 LOADI (3);
782 NEXT_INSN;
784 insn_lload_0:
785 LOADL (0);
786 NEXT_INSN;
788 insn_lload_1:
789 LOADL (1);
790 NEXT_INSN;
792 insn_lload_2:
793 LOADL (2);
794 NEXT_INSN;
796 insn_lload_3:
797 LOADL (3);
798 NEXT_INSN;
800 insn_fload_0:
801 LOADF (0);
802 NEXT_INSN;
804 insn_fload_1:
805 LOADF (1);
806 NEXT_INSN;
808 insn_fload_2:
809 LOADF (2);
810 NEXT_INSN;
812 insn_fload_3:
813 LOADF (3);
814 NEXT_INSN;
816 insn_dload_0:
817 LOADD (0);
818 NEXT_INSN;
820 insn_dload_1:
821 LOADD (1);
822 NEXT_INSN;
824 insn_dload_2:
825 LOADD (2);
826 NEXT_INSN;
828 insn_dload_3:
829 LOADD (3);
830 NEXT_INSN;
832 insn_aload_1:
833 LOADA(1);
834 NEXT_INSN;
836 insn_aload_2:
837 LOADA(2);
838 NEXT_INSN;
840 insn_aload_3:
841 LOADA(3);
842 NEXT_INSN;
844 insn_iaload:
846 jint index = POPI();
847 jintArray arr = (jintArray) POPA();
848 NULLARRAYCHECK (arr);
849 ARRAYBOUNDSCHECK (arr, index);
850 PUSHI( elements(arr)[index] );
852 NEXT_INSN;
854 insn_laload:
856 jint index = POPI();
857 jlongArray arr = (jlongArray) POPA();
858 NULLARRAYCHECK (arr);
859 ARRAYBOUNDSCHECK (arr, index);
860 PUSHL( elements(arr)[index] );
862 NEXT_INSN;
864 insn_faload:
866 jint index = POPI();
867 jfloatArray arr = (jfloatArray) POPA();
868 NULLARRAYCHECK (arr);
869 ARRAYBOUNDSCHECK (arr, index);
870 PUSHF( elements(arr)[index] );
872 NEXT_INSN;
874 insn_daload:
876 jint index = POPI();
877 jdoubleArray arr = (jdoubleArray) POPA();
878 NULLARRAYCHECK (arr);
879 ARRAYBOUNDSCHECK (arr, index);
880 PUSHD( elements(arr)[index] );
882 NEXT_INSN;
884 insn_aaload:
886 jint index = POPI();
887 jobjectArray arr = (jobjectArray) POPA();
888 NULLARRAYCHECK (arr);
889 ARRAYBOUNDSCHECK (arr, index);
890 PUSHA( elements(arr)[index] );
892 NEXT_INSN;
894 insn_baload:
896 jint index = POPI();
897 jbyteArray arr = (jbyteArray) POPA();
898 NULLARRAYCHECK (arr);
899 ARRAYBOUNDSCHECK (arr, index);
900 PUSHI( elements(arr)[index] );
902 NEXT_INSN;
904 insn_caload:
906 jint index = POPI();
907 jcharArray arr = (jcharArray) POPA();
908 NULLARRAYCHECK (arr);
909 ARRAYBOUNDSCHECK (arr, index);
910 PUSHI( elements(arr)[index] );
912 NEXT_INSN;
914 insn_saload:
916 jint index = POPI();
917 jshortArray arr = (jshortArray) POPA();
918 NULLARRAYCHECK (arr);
919 ARRAYBOUNDSCHECK (arr, index);
920 PUSHI( elements(arr)[index] );
922 NEXT_INSN;
924 insn_istore:
925 STOREI (GET1U ());
926 NEXT_INSN;
928 insn_lstore:
929 STOREL (GET1U ());
930 NEXT_INSN;
932 insn_fstore:
933 STOREF (GET1U ());
934 NEXT_INSN;
936 insn_dstore:
937 STORED (GET1U ());
938 NEXT_INSN;
940 insn_astore:
941 STOREA (GET1U ());
942 NEXT_INSN;
944 insn_istore_0:
945 STOREI (0);
946 NEXT_INSN;
948 insn_istore_1:
949 STOREI (1);
950 NEXT_INSN;
952 insn_istore_2:
953 STOREI (2);
954 NEXT_INSN;
956 insn_istore_3:
957 STOREI (3);
958 NEXT_INSN;
960 insn_lstore_0:
961 STOREL (0);
962 NEXT_INSN;
964 insn_lstore_1:
965 STOREL (1);
966 NEXT_INSN;
968 insn_lstore_2:
969 STOREL (2);
970 NEXT_INSN;
972 insn_lstore_3:
973 STOREL (3);
974 NEXT_INSN;
976 insn_fstore_0:
977 STOREF (0);
978 NEXT_INSN;
980 insn_fstore_1:
981 STOREF (1);
982 NEXT_INSN;
984 insn_fstore_2:
985 STOREF (2);
986 NEXT_INSN;
988 insn_fstore_3:
989 STOREF (3);
990 NEXT_INSN;
992 insn_dstore_0:
993 STORED (0);
994 NEXT_INSN;
996 insn_dstore_1:
997 STORED (1);
998 NEXT_INSN;
1000 insn_dstore_2:
1001 STORED (2);
1002 NEXT_INSN;
1004 insn_dstore_3:
1005 STORED (3);
1006 NEXT_INSN;
1008 insn_astore_0:
1009 STOREA(0);
1010 NEXT_INSN;
1012 insn_astore_1:
1013 STOREA(1);
1014 NEXT_INSN;
1016 insn_astore_2:
1017 STOREA(2);
1018 NEXT_INSN;
1020 insn_astore_3:
1021 STOREA(3);
1022 NEXT_INSN;
1024 insn_iastore:
1026 jint value = POPI();
1027 jint index = POPI();
1028 jintArray arr = (jintArray) POPA();
1029 NULLARRAYCHECK (arr);
1030 ARRAYBOUNDSCHECK (arr, index);
1031 elements(arr)[index] = value;
1033 NEXT_INSN;
1035 insn_lastore:
1037 jlong value = POPL();
1038 jint index = POPI();
1039 jlongArray arr = (jlongArray) POPA();
1040 NULLARRAYCHECK (arr);
1041 ARRAYBOUNDSCHECK (arr, index);
1042 elements(arr)[index] = value;
1044 NEXT_INSN;
1046 insn_fastore:
1048 jfloat value = POPF();
1049 jint index = POPI();
1050 jfloatArray arr = (jfloatArray) POPA();
1051 NULLARRAYCHECK (arr);
1052 ARRAYBOUNDSCHECK (arr, index);
1053 elements(arr)[index] = value;
1055 NEXT_INSN;
1057 insn_dastore:
1059 jdouble value = POPD();
1060 jint index = POPI();
1061 jdoubleArray arr = (jdoubleArray) POPA();
1062 NULLARRAYCHECK (arr);
1063 ARRAYBOUNDSCHECK (arr, index);
1064 elements(arr)[index] = value;
1066 NEXT_INSN;
1068 insn_aastore:
1070 jobject value = POPA();
1071 jint index = POPI();
1072 jobjectArray arr = (jobjectArray) POPA();
1073 NULLARRAYCHECK (arr);
1074 ARRAYBOUNDSCHECK (arr, index);
1075 _Jv_CheckArrayStore (arr, value);
1076 elements(arr)[index] = value;
1078 NEXT_INSN;
1080 insn_bastore:
1082 jbyte value = (jbyte) POPI();
1083 jint index = POPI();
1084 jbyteArray arr = (jbyteArray) POPA();
1085 NULLARRAYCHECK (arr);
1086 ARRAYBOUNDSCHECK (arr, index);
1087 elements(arr)[index] = value;
1089 NEXT_INSN;
1091 insn_castore:
1093 jchar value = (jchar) POPI();
1094 jint index = POPI();
1095 jcharArray arr = (jcharArray) POPA();
1096 NULLARRAYCHECK (arr);
1097 ARRAYBOUNDSCHECK (arr, index);
1098 elements(arr)[index] = value;
1100 NEXT_INSN;
1102 insn_sastore:
1104 jshort value = (jshort) POPI();
1105 jint index = POPI();
1106 jshortArray arr = (jshortArray) POPA();
1107 NULLARRAYCHECK (arr);
1108 ARRAYBOUNDSCHECK (arr, index);
1109 elements(arr)[index] = value;
1111 NEXT_INSN;
1113 insn_pop:
1114 sp -= 1;
1115 NEXT_INSN;
1117 insn_pop2:
1118 sp -= 2;
1119 NEXT_INSN;
1121 insn_dup:
1122 sp[0] = sp[-1];
1123 sp += 1;
1124 NEXT_INSN;
1126 insn_dup_x1:
1127 dupx (sp, 1, 1); sp+=1;
1128 NEXT_INSN;
1130 insn_dup_x2:
1131 dupx (sp, 1, 2); sp+=1;
1132 NEXT_INSN;
1134 insn_dup2:
1135 sp[0] = sp[-2];
1136 sp[1] = sp[-1];
1137 sp += 2;
1138 NEXT_INSN;
1140 insn_dup2_x1:
1141 dupx (sp, 2, 1); sp+=2;
1142 NEXT_INSN;
1144 insn_dup2_x2:
1145 dupx (sp, 2, 2); sp+=2;
1146 NEXT_INSN;
1148 insn_swap:
1150 jobject tmp1 = POPA();
1151 jobject tmp2 = POPA();
1152 PUSHA (tmp1);
1153 PUSHA (tmp2);
1155 NEXT_INSN;
1157 insn_iadd:
1158 BINOPI(+);
1159 NEXT_INSN;
1161 insn_ladd:
1162 BINOPL(+);
1163 NEXT_INSN;
1165 insn_fadd:
1166 BINOPF(+);
1167 NEXT_INSN;
1169 insn_dadd:
1170 BINOPD(+);
1171 NEXT_INSN;
1173 insn_isub:
1174 BINOPI(-);
1175 NEXT_INSN;
1177 insn_lsub:
1178 BINOPL(-);
1179 NEXT_INSN;
1181 insn_fsub:
1182 BINOPF(-);
1183 NEXT_INSN;
1185 insn_dsub:
1186 BINOPD(-);
1187 NEXT_INSN;
1189 insn_imul:
1190 BINOPI(*);
1191 NEXT_INSN;
1193 insn_lmul:
1194 BINOPL(*);
1195 NEXT_INSN;
1197 insn_fmul:
1198 BINOPF(*);
1199 NEXT_INSN;
1201 insn_dmul:
1202 BINOPD(*);
1203 NEXT_INSN;
1205 insn_idiv:
1207 SAVE_PC();
1208 jint value2 = POPI();
1209 jint value1 = POPI();
1210 jint res = _Jv_divI (value1, value2);
1211 PUSHI (res);
1213 NEXT_INSN;
1215 insn_ldiv:
1217 SAVE_PC();
1218 jlong value2 = POPL();
1219 jlong value1 = POPL();
1220 jlong res = _Jv_divJ (value1, value2);
1221 PUSHL (res);
1223 NEXT_INSN;
1225 insn_fdiv:
1227 jfloat value2 = POPF();
1228 jfloat value1 = POPF();
1229 jfloat res = value1 / value2;
1230 PUSHF (res);
1232 NEXT_INSN;
1234 insn_ddiv:
1236 jdouble value2 = POPD();
1237 jdouble value1 = POPD();
1238 jdouble res = value1 / value2;
1239 PUSHD (res);
1241 NEXT_INSN;
1243 insn_irem:
1245 SAVE_PC();
1246 jint value2 = POPI();
1247 jint value1 = POPI();
1248 jint res = _Jv_remI (value1, value2);
1249 PUSHI (res);
1251 NEXT_INSN;
1253 insn_lrem:
1255 SAVE_PC();
1256 jlong value2 = POPL();
1257 jlong value1 = POPL();
1258 jlong res = _Jv_remJ (value1, value2);
1259 PUSHL (res);
1261 NEXT_INSN;
1263 insn_frem:
1265 jfloat value2 = POPF();
1266 jfloat value1 = POPF();
1267 jfloat res = __ieee754_fmod (value1, value2);
1268 PUSHF (res);
1270 NEXT_INSN;
1272 insn_drem:
1274 jdouble value2 = POPD();
1275 jdouble value1 = POPD();
1276 jdouble res = __ieee754_fmod (value1, value2);
1277 PUSHD (res);
1279 NEXT_INSN;
1281 insn_ineg:
1283 jint value = POPI();
1284 PUSHI (value * -1);
1286 NEXT_INSN;
1288 insn_lneg:
1290 jlong value = POPL();
1291 PUSHL (value * -1);
1293 NEXT_INSN;
1295 insn_fneg:
1297 jfloat value = POPF();
1298 PUSHF (value * -1);
1300 NEXT_INSN;
1302 insn_dneg:
1304 jdouble value = POPD();
1305 PUSHD (value * -1);
1307 NEXT_INSN;
1309 insn_ishl:
1311 jint shift = (POPI() & 0x1f);
1312 jint value = POPI();
1313 PUSHI (value << shift);
1315 NEXT_INSN;
1317 insn_lshl:
1319 jint shift = (POPI() & 0x3f);
1320 jlong value = POPL();
1321 PUSHL (value << shift);
1323 NEXT_INSN;
1325 insn_ishr:
1327 jint shift = (POPI() & 0x1f);
1328 jint value = POPI();
1329 PUSHI (value >> shift);
1331 NEXT_INSN;
1333 insn_lshr:
1335 jint shift = (POPI() & 0x3f);
1336 jlong value = POPL();
1337 PUSHL (value >> shift);
1339 NEXT_INSN;
1341 insn_iushr:
1343 jint shift = (POPI() & 0x1f);
1344 _Jv_uint value = (_Jv_uint) POPI();
1345 PUSHI ((jint) (value >> shift));
1347 NEXT_INSN;
1349 insn_lushr:
1351 jint shift = (POPI() & 0x3f);
1352 _Jv_ulong value = (_Jv_ulong) POPL();
1353 PUSHL ((jlong) (value >> shift));
1355 NEXT_INSN;
1357 insn_iand:
1358 BINOPI (&);
1359 NEXT_INSN;
1361 insn_land:
1362 BINOPL (&);
1363 NEXT_INSN;
1365 insn_ior:
1366 BINOPI (|);
1367 NEXT_INSN;
1369 insn_lor:
1370 BINOPL (|);
1371 NEXT_INSN;
1373 insn_ixor:
1374 BINOPI (^);
1375 NEXT_INSN;
1377 insn_lxor:
1378 BINOPL (^);
1379 NEXT_INSN;
1381 insn_iinc:
1383 jint index = GET1U ();
1384 jint amount = GET1S ();
1385 locals[index].i += amount;
1387 NEXT_INSN;
1389 insn_i2l:
1390 {jlong value = POPI(); PUSHL (value);}
1391 NEXT_INSN;
1393 insn_i2f:
1394 {jfloat value = POPI(); PUSHF (value);}
1395 NEXT_INSN;
1397 insn_i2d:
1398 {jdouble value = POPI(); PUSHD (value);}
1399 NEXT_INSN;
1401 insn_l2i:
1402 {jint value = POPL(); PUSHI (value);}
1403 NEXT_INSN;
1405 insn_l2f:
1406 {jfloat value = POPL(); PUSHF (value);}
1407 NEXT_INSN;
1409 insn_l2d:
1410 {jdouble value = POPL(); PUSHD (value);}
1411 NEXT_INSN;
1413 insn_f2i:
1415 using namespace java::lang;
1416 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1417 PUSHI(value);
1419 NEXT_INSN;
1421 insn_f2l:
1423 using namespace java::lang;
1424 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1425 PUSHL(value);
1427 NEXT_INSN;
1429 insn_f2d:
1430 { jdouble value = POPF (); PUSHD(value); }
1431 NEXT_INSN;
1433 insn_d2i:
1435 using namespace java::lang;
1436 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1437 PUSHI(value);
1439 NEXT_INSN;
1441 insn_d2l:
1443 using namespace java::lang;
1444 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1445 PUSHL(value);
1447 NEXT_INSN;
1449 insn_d2f:
1450 { jfloat value = POPD (); PUSHF(value); }
1451 NEXT_INSN;
1453 insn_i2b:
1454 { jbyte value = POPI (); PUSHI(value); }
1455 NEXT_INSN;
1457 insn_i2c:
1458 { jchar value = POPI (); PUSHI(value); }
1459 NEXT_INSN;
1461 insn_i2s:
1462 { jshort value = POPI (); PUSHI(value); }
1463 NEXT_INSN;
1465 insn_lcmp:
1467 jlong value2 = POPL ();
1468 jlong value1 = POPL ();
1469 if (value1 > value2)
1470 { PUSHI (1); }
1471 else if (value1 == value2)
1472 { PUSHI (0); }
1473 else
1474 { PUSHI (-1); }
1476 NEXT_INSN;
1478 insn_fcmpl:
1479 tmpval = -1;
1480 goto fcmp;
1482 insn_fcmpg:
1483 tmpval = 1;
1485 fcmp:
1487 jfloat value2 = POPF ();
1488 jfloat value1 = POPF ();
1489 if (value1 > value2)
1490 PUSHI (1);
1491 else if (value1 == value2)
1492 PUSHI (0);
1493 else if (value1 < value2)
1494 PUSHI (-1);
1495 else
1496 PUSHI (tmpval);
1498 NEXT_INSN;
1500 insn_dcmpl:
1501 tmpval = -1;
1502 goto dcmp;
1504 insn_dcmpg:
1505 tmpval = 1;
1507 dcmp:
1509 jdouble value2 = POPD ();
1510 jdouble value1 = POPD ();
1511 if (value1 > value2)
1512 PUSHI (1);
1513 else if (value1 == value2)
1514 PUSHI (0);
1515 else if (value1 < value2)
1516 PUSHI (-1);
1517 else
1518 PUSHI (tmpval);
1520 NEXT_INSN;
1522 insn_ifeq:
1524 if (POPI() == 0)
1525 TAKE_GOTO;
1526 else
1527 SKIP_GOTO;
1529 NEXT_INSN;
1531 insn_ifne:
1533 if (POPI() != 0)
1534 TAKE_GOTO;
1535 else
1536 SKIP_GOTO;
1538 NEXT_INSN;
1540 insn_iflt:
1542 if (POPI() < 0)
1543 TAKE_GOTO;
1544 else
1545 SKIP_GOTO;
1547 NEXT_INSN;
1549 insn_ifge:
1551 if (POPI() >= 0)
1552 TAKE_GOTO;
1553 else
1554 SKIP_GOTO;
1556 NEXT_INSN;
1558 insn_ifgt:
1560 if (POPI() > 0)
1561 TAKE_GOTO;
1562 else
1563 SKIP_GOTO;
1565 NEXT_INSN;
1567 insn_ifle:
1569 if (POPI() <= 0)
1570 TAKE_GOTO;
1571 else
1572 SKIP_GOTO;
1574 NEXT_INSN;
1576 insn_if_icmpeq:
1578 jint value2 = POPI();
1579 jint value1 = POPI();
1580 if (value1 == value2)
1581 TAKE_GOTO;
1582 else
1583 SKIP_GOTO;
1585 NEXT_INSN;
1587 insn_if_icmpne:
1589 jint value2 = POPI();
1590 jint value1 = POPI();
1591 if (value1 != value2)
1592 TAKE_GOTO;
1593 else
1594 SKIP_GOTO;
1596 NEXT_INSN;
1598 insn_if_icmplt:
1600 jint value2 = POPI();
1601 jint value1 = POPI();
1602 if (value1 < value2)
1603 TAKE_GOTO;
1604 else
1605 SKIP_GOTO;
1607 NEXT_INSN;
1609 insn_if_icmpge:
1611 jint value2 = POPI();
1612 jint value1 = POPI();
1613 if (value1 >= value2)
1614 TAKE_GOTO;
1615 else
1616 SKIP_GOTO;
1618 NEXT_INSN;
1620 insn_if_icmpgt:
1622 jint value2 = POPI();
1623 jint value1 = POPI();
1624 if (value1 > value2)
1625 TAKE_GOTO;
1626 else
1627 SKIP_GOTO;
1629 NEXT_INSN;
1631 insn_if_icmple:
1633 jint value2 = POPI();
1634 jint value1 = POPI();
1635 if (value1 <= value2)
1636 TAKE_GOTO;
1637 else
1638 SKIP_GOTO;
1640 NEXT_INSN;
1642 insn_if_acmpeq:
1644 jobject value2 = POPA();
1645 jobject value1 = POPA();
1646 if (value1 == value2)
1647 TAKE_GOTO;
1648 else
1649 SKIP_GOTO;
1651 NEXT_INSN;
1653 insn_if_acmpne:
1655 jobject value2 = POPA();
1656 jobject value1 = POPA();
1657 if (value1 != value2)
1658 TAKE_GOTO;
1659 else
1660 SKIP_GOTO;
1662 NEXT_INSN;
1664 insn_goto_w:
1665 #ifndef DIRECT_THREADED
1666 // For direct threaded, goto and goto_w are the same.
1667 pc = pc - 1 + get4 (pc);
1668 NEXT_INSN;
1669 #endif /* DIRECT_THREADED */
1670 insn_goto:
1671 TAKE_GOTO;
1672 NEXT_INSN;
1674 insn_jsr_w:
1675 #ifndef DIRECT_THREADED
1676 // For direct threaded, jsr and jsr_w are the same.
1678 pc_t next = pc - 1 + get4 (pc);
1679 pc += 4;
1680 PUSHA ((jobject) pc);
1681 pc = next;
1683 NEXT_INSN;
1684 #endif /* DIRECT_THREADED */
1685 insn_jsr:
1687 pc_t next = GOTO_VAL();
1688 SKIP_GOTO;
1689 PUSHA ((jobject) pc);
1690 pc = next;
1692 NEXT_INSN;
1694 insn_ret:
1696 jint index = GET1U ();
1697 pc = (pc_t) PEEKA (index);
1699 NEXT_INSN;
1701 insn_tableswitch:
1703 #ifdef DIRECT_THREADED
1704 void *def = (pc++)->datum;
1706 int index = POPI();
1708 jint low = INTVAL ();
1709 jint high = INTVAL ();
1711 if (index < low || index > high)
1712 pc = (insn_slot *) def;
1713 else
1714 pc = (insn_slot *) ((pc + index - low)->datum);
1715 #else
1716 pc_t base_pc = pc - 1;
1717 int index = POPI ();
1719 pc_t base = (pc_t) meth->bytecode ();
1720 while ((pc - base) % 4 != 0)
1721 ++pc;
1723 jint def = get4 (pc);
1724 jint low = get4 (pc + 4);
1725 jint high = get4 (pc + 8);
1726 if (index < low || index > high)
1727 pc = base_pc + def;
1728 else
1729 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1730 #endif /* DIRECT_THREADED */
1732 NEXT_INSN;
1734 insn_lookupswitch:
1736 #ifdef DIRECT_THREADED
1737 void *def = (pc++)->insn;
1739 int index = POPI();
1741 jint npairs = INTVAL ();
1743 int max = npairs - 1;
1744 int min = 0;
1746 // Simple binary search...
1747 while (min < max)
1749 int half = (min + max) / 2;
1750 int match = pc[2 * half].int_val;
1752 if (index == match)
1754 // Found it.
1755 pc = (insn_slot *) pc[2 * half + 1].datum;
1756 NEXT_INSN;
1758 else if (index < match)
1759 // We can use HALF - 1 here because we check again on
1760 // loop exit.
1761 max = half - 1;
1762 else
1763 // We can use HALF + 1 here because we check again on
1764 // loop exit.
1765 min = half + 1;
1767 if (index == pc[2 * min].int_val)
1768 pc = (insn_slot *) pc[2 * min + 1].datum;
1769 else
1770 pc = (insn_slot *) def;
1771 #else
1772 unsigned char *base_pc = pc-1;
1773 int index = POPI();
1775 unsigned char* base = meth->bytecode ();
1776 while ((pc-base) % 4 != 0)
1777 ++pc;
1779 jint def = get4 (pc);
1780 jint npairs = get4 (pc+4);
1782 int max = npairs-1;
1783 int min = 0;
1785 // Simple binary search...
1786 while (min < max)
1788 int half = (min+max)/2;
1789 int match = get4 (pc+ 4*(2 + 2*half));
1791 if (index == match)
1792 min = max = half;
1793 else if (index < match)
1794 // We can use HALF - 1 here because we check again on
1795 // loop exit.
1796 max = half - 1;
1797 else
1798 // We can use HALF + 1 here because we check again on
1799 // loop exit.
1800 min = half + 1;
1803 if (index == get4 (pc+ 4*(2 + 2*min)))
1804 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1805 else
1806 pc = base_pc + def;
1807 #endif /* DIRECT_THREADED */
1809 NEXT_INSN;
1811 insn_areturn:
1812 *(jobject *) retp = POPA ();
1813 return;
1815 insn_lreturn:
1816 *(jlong *) retp = POPL ();
1817 return;
1819 insn_freturn:
1820 *(jfloat *) retp = POPF ();
1821 return;
1823 insn_dreturn:
1824 *(jdouble *) retp = POPD ();
1825 return;
1827 insn_ireturn:
1828 *(jint *) retp = POPI ();
1829 return;
1831 insn_return:
1832 return;
1834 insn_getstatic:
1836 jint fieldref_index = GET2U ();
1837 SAVE_PC(); // Constant pool resolution could throw.
1838 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1839 _Jv_Field *field = pool_data[fieldref_index].field;
1841 if ((field->flags & Modifier::STATIC) == 0)
1842 throw_incompatible_class_change_error
1843 (JvNewStringLatin1 ("field no longer static"));
1845 jclass type = field->type;
1847 // We rewrite the instruction once we discover what it refers
1848 // to.
1849 void *newinsn = NULL;
1850 if (type->isPrimitive ())
1852 switch (type->size_in_bytes)
1854 case 1:
1855 PUSHI (*field->u.byte_addr);
1856 newinsn = AMPAMP (getstatic_resolved_1);
1857 break;
1859 case 2:
1860 if (type == JvPrimClass (char))
1862 PUSHI (*field->u.char_addr);
1863 newinsn = AMPAMP (getstatic_resolved_char);
1865 else
1867 PUSHI (*field->u.short_addr);
1868 newinsn = AMPAMP (getstatic_resolved_short);
1870 break;
1872 case 4:
1873 PUSHI(*field->u.int_addr);
1874 newinsn = AMPAMP (getstatic_resolved_4);
1875 break;
1877 case 8:
1878 PUSHL(*field->u.long_addr);
1879 newinsn = AMPAMP (getstatic_resolved_8);
1880 break;
1883 else
1885 PUSHA(*field->u.object_addr);
1886 newinsn = AMPAMP (getstatic_resolved_obj);
1889 #ifdef DIRECT_THREADED
1890 REWRITE_INSN (newinsn, datum, field->u.addr);
1891 #endif /* DIRECT_THREADED */
1893 NEXT_INSN;
1895 #ifdef DIRECT_THREADED
1896 getstatic_resolved_1:
1897 PUSHI (*(jbyte *) AVAL ());
1898 NEXT_INSN;
1900 getstatic_resolved_char:
1901 PUSHI (*(jchar *) AVAL ());
1902 NEXT_INSN;
1904 getstatic_resolved_short:
1905 PUSHI (*(jshort *) AVAL ());
1906 NEXT_INSN;
1908 getstatic_resolved_4:
1909 PUSHI (*(jint *) AVAL ());
1910 NEXT_INSN;
1912 getstatic_resolved_8:
1913 PUSHL (*(jlong *) AVAL ());
1914 NEXT_INSN;
1916 getstatic_resolved_obj:
1917 PUSHA (*(jobject *) AVAL ());
1918 NEXT_INSN;
1919 #endif /* DIRECT_THREADED */
1921 insn_getfield:
1923 SAVE_PC();
1924 jint fieldref_index = GET2U ();
1925 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1926 _Jv_Field *field = pool_data[fieldref_index].field;
1928 if ((field->flags & Modifier::STATIC) != 0)
1929 throw_incompatible_class_change_error
1930 (JvNewStringLatin1 ("field is static"));
1932 jclass type = field->type;
1933 jint field_offset = field->u.boffset;
1935 jobject obj = POPA();
1936 NULLCHECK(obj);
1938 void *newinsn = NULL;
1939 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1940 if (type->isPrimitive ())
1942 switch (type->size_in_bytes)
1944 case 1:
1945 PUSHI (val->byte_value);
1946 newinsn = AMPAMP (getfield_resolved_1);
1947 break;
1949 case 2:
1950 if (type == JvPrimClass (char))
1952 PUSHI (val->char_value);
1953 newinsn = AMPAMP (getfield_resolved_char);
1955 else
1957 PUSHI (val->short_value);
1958 newinsn = AMPAMP (getfield_resolved_short);
1960 break;
1962 case 4:
1963 PUSHI (val->int_value);
1964 newinsn = AMPAMP (getfield_resolved_4);
1965 break;
1967 case 8:
1968 PUSHL (val->long_value);
1969 newinsn = AMPAMP (getfield_resolved_8);
1970 break;
1973 else
1975 PUSHA (val->object_value);
1976 newinsn = AMPAMP (getfield_resolved_obj);
1979 #ifdef DIRECT_THREADED
1980 REWRITE_INSN (newinsn, int_val, field_offset);
1981 #endif /* DIRECT_THREADED */
1983 NEXT_INSN;
1985 #ifdef DIRECT_THREADED
1986 getfield_resolved_1:
1988 char *obj = (char *) POPA ();
1989 NULLCHECK (obj);
1990 PUSHI (*(jbyte *) (obj + INTVAL ()));
1992 NEXT_INSN;
1994 getfield_resolved_char:
1996 char *obj = (char *) POPA ();
1997 NULLCHECK (obj);
1998 PUSHI (*(jchar *) (obj + INTVAL ()));
2000 NEXT_INSN;
2002 getfield_resolved_short:
2004 char *obj = (char *) POPA ();
2005 NULLCHECK (obj);
2006 PUSHI (*(jshort *) (obj + INTVAL ()));
2008 NEXT_INSN;
2010 getfield_resolved_4:
2012 char *obj = (char *) POPA ();
2013 NULLCHECK (obj);
2014 PUSHI (*(jint *) (obj + INTVAL ()));
2016 NEXT_INSN;
2018 getfield_resolved_8:
2020 char *obj = (char *) POPA ();
2021 NULLCHECK (obj);
2022 PUSHL (*(jlong *) (obj + INTVAL ()));
2024 NEXT_INSN;
2026 getfield_resolved_obj:
2028 char *obj = (char *) POPA ();
2029 NULLCHECK (obj);
2030 PUSHA (*(jobject *) (obj + INTVAL ()));
2032 NEXT_INSN;
2033 #endif /* DIRECT_THREADED */
2035 insn_putstatic:
2037 SAVE_PC();
2038 jint fieldref_index = GET2U ();
2039 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2040 _Jv_Field *field = pool_data[fieldref_index].field;
2042 jclass type = field->type;
2044 // ResolvePoolEntry cannot check this
2045 if ((field->flags & Modifier::STATIC) == 0)
2046 throw_incompatible_class_change_error
2047 (JvNewStringLatin1 ("field no longer static"));
2049 void *newinsn = NULL;
2050 if (type->isPrimitive ())
2052 switch (type->size_in_bytes)
2054 case 1:
2056 jint value = POPI();
2057 *field->u.byte_addr = value;
2058 newinsn = AMPAMP (putstatic_resolved_1);
2059 break;
2062 case 2:
2064 jint value = POPI();
2065 *field->u.char_addr = value;
2066 newinsn = AMPAMP (putstatic_resolved_2);
2067 break;
2070 case 4:
2072 jint value = POPI();
2073 *field->u.int_addr = value;
2074 newinsn = AMPAMP (putstatic_resolved_4);
2075 break;
2078 case 8:
2080 jlong value = POPL();
2081 *field->u.long_addr = value;
2082 newinsn = AMPAMP (putstatic_resolved_8);
2083 break;
2087 else
2089 jobject value = POPA();
2090 *field->u.object_addr = value;
2091 newinsn = AMPAMP (putstatic_resolved_obj);
2094 #ifdef DIRECT_THREADED
2095 REWRITE_INSN (newinsn, datum, field->u.addr);
2096 #endif /* DIRECT_THREADED */
2098 NEXT_INSN;
2100 #ifdef DIRECT_THREADED
2101 putstatic_resolved_1:
2102 *(jbyte *) AVAL () = POPI ();
2103 NEXT_INSN;
2105 putstatic_resolved_2:
2106 *(jchar *) AVAL () = POPI ();
2107 NEXT_INSN;
2109 putstatic_resolved_4:
2110 *(jint *) AVAL () = POPI ();
2111 NEXT_INSN;
2113 putstatic_resolved_8:
2114 *(jlong *) AVAL () = POPL ();
2115 NEXT_INSN;
2117 putstatic_resolved_obj:
2118 *(jobject *) AVAL () = POPA ();
2119 NEXT_INSN;
2120 #endif /* DIRECT_THREADED */
2122 insn_putfield:
2124 SAVE_PC();
2125 jint fieldref_index = GET2U ();
2126 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2127 _Jv_Field *field = pool_data[fieldref_index].field;
2129 jclass type = field->type;
2131 if ((field->flags & Modifier::STATIC) != 0)
2132 throw_incompatible_class_change_error
2133 (JvNewStringLatin1 ("field is static"));
2135 jint field_offset = field->u.boffset;
2137 void *newinsn = NULL;
2138 if (type->isPrimitive ())
2140 switch (type->size_in_bytes)
2142 case 1:
2144 jint value = POPI();
2145 jobject obj = POPA();
2146 NULLCHECK(obj);
2147 *(jbyte*) ((char*)obj + field_offset) = value;
2148 newinsn = AMPAMP (putfield_resolved_1);
2149 break;
2152 case 2:
2154 jint value = POPI();
2155 jobject obj = POPA();
2156 NULLCHECK(obj);
2157 *(jchar*) ((char*)obj + field_offset) = value;
2158 newinsn = AMPAMP (putfield_resolved_2);
2159 break;
2162 case 4:
2164 jint value = POPI();
2165 jobject obj = POPA();
2166 NULLCHECK(obj);
2167 *(jint*) ((char*)obj + field_offset) = value;
2168 newinsn = AMPAMP (putfield_resolved_4);
2169 break;
2172 case 8:
2174 jlong value = POPL();
2175 jobject obj = POPA();
2176 NULLCHECK(obj);
2177 *(jlong*) ((char*)obj + field_offset) = value;
2178 newinsn = AMPAMP (putfield_resolved_8);
2179 break;
2183 else
2185 jobject value = POPA();
2186 jobject obj = POPA();
2187 NULLCHECK(obj);
2188 *(jobject*) ((char*)obj + field_offset) = value;
2189 newinsn = AMPAMP (putfield_resolved_obj);
2192 #ifdef DIRECT_THREADED
2193 REWRITE_INSN (newinsn, int_val, field_offset);
2194 #endif /* DIRECT_THREADED */
2196 NEXT_INSN;
2198 #ifdef DIRECT_THREADED
2199 putfield_resolved_1:
2201 jint val = POPI ();
2202 char *obj = (char *) POPA ();
2203 NULLCHECK (obj);
2204 *(jbyte *) (obj + INTVAL ()) = val;
2206 NEXT_INSN;
2208 putfield_resolved_2:
2210 jint val = POPI ();
2211 char *obj = (char *) POPA ();
2212 NULLCHECK (obj);
2213 *(jchar *) (obj + INTVAL ()) = val;
2215 NEXT_INSN;
2217 putfield_resolved_4:
2219 jint val = POPI ();
2220 char *obj = (char *) POPA ();
2221 NULLCHECK (obj);
2222 *(jint *) (obj + INTVAL ()) = val;
2224 NEXT_INSN;
2226 putfield_resolved_8:
2228 jlong val = POPL ();
2229 char *obj = (char *) POPA ();
2230 NULLCHECK (obj);
2231 *(jlong *) (obj + INTVAL ()) = val;
2233 NEXT_INSN;
2235 putfield_resolved_obj:
2237 jobject val = POPA ();
2238 char *obj = (char *) POPA ();
2239 NULLCHECK (obj);
2240 *(jobject *) (obj + INTVAL ()) = val;
2242 NEXT_INSN;
2243 #endif /* DIRECT_THREADED */
2245 insn_invokespecial:
2247 SAVE_PC();
2248 int index = GET2U ();
2250 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2251 index)).rmethod;
2253 sp -= rmeth->stack_item_count;
2255 // We don't use NULLCHECK here because we can't rely on that
2256 // working for <init>. So instead we do an explicit test.
2257 if (! sp[0].o)
2259 SAVE_PC();
2260 throw_null_pointer_exception ();
2263 fun = (void (*)()) rmeth->method->ncode;
2265 #ifdef DIRECT_THREADED
2266 // Rewrite instruction so that we use a faster pre-resolved
2267 // method.
2268 REWRITE_INSN (&&invokespecial_resolved, datum, rmeth);
2269 #endif /* DIRECT_THREADED */
2271 goto perform_invoke;
2273 #ifdef DIRECT_THREADED
2274 invokespecial_resolved:
2276 SAVE_PC();
2277 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2278 sp -= rmeth->stack_item_count;
2279 // We don't use NULLCHECK here because we can't rely on that
2280 // working for <init>. So instead we do an explicit test.
2281 if (! sp[0].o)
2283 throw_null_pointer_exception ();
2285 fun = (void (*)()) rmeth->method->ncode;
2287 goto perform_invoke;
2288 #endif /* DIRECT_THREADED */
2290 insn_invokestatic:
2292 SAVE_PC();
2293 int index = GET2U ();
2295 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2296 index)).rmethod;
2298 sp -= rmeth->stack_item_count;
2300 fun = (void (*)()) rmeth->method->ncode;
2302 #ifdef DIRECT_THREADED
2303 // Rewrite instruction so that we use a faster pre-resolved
2304 // method.
2305 REWRITE_INSN (&&invokestatic_resolved, datum, rmeth);
2306 #endif /* DIRECT_THREADED */
2308 goto perform_invoke;
2310 #ifdef DIRECT_THREADED
2311 invokestatic_resolved:
2313 SAVE_PC();
2314 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2315 sp -= rmeth->stack_item_count;
2316 fun = (void (*)()) rmeth->method->ncode;
2318 goto perform_invoke;
2319 #endif /* DIRECT_THREADED */
2321 insn_invokeinterface:
2323 SAVE_PC();
2324 int index = GET2U ();
2326 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2327 index)).rmethod;
2329 sp -= rmeth->stack_item_count;
2331 jobject rcv = sp[0].o;
2333 NULLCHECK (rcv);
2335 fun = (void (*)())
2336 _Jv_LookupInterfaceMethod (rcv->getClass (),
2337 rmeth->method->name,
2338 rmeth->method->signature);
2340 #ifdef DIRECT_THREADED
2341 // Rewrite instruction so that we use a faster pre-resolved
2342 // method.
2343 REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth);
2344 #else
2345 // Skip dummy bytes.
2346 pc += 2;
2347 #endif /* DIRECT_THREADED */
2349 goto perform_invoke;
2351 #ifdef DIRECT_THREADED
2352 invokeinterface_resolved:
2354 SAVE_PC();
2355 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2356 sp -= rmeth->stack_item_count;
2357 jobject rcv = sp[0].o;
2358 NULLCHECK (rcv);
2359 fun = (void (*)())
2360 _Jv_LookupInterfaceMethod (rcv->getClass (),
2361 rmeth->method->name,
2362 rmeth->method->signature);
2364 goto perform_invoke;
2365 #endif /* DIRECT_THREADED */
2367 insn_new:
2369 SAVE_PC();
2370 int index = GET2U ();
2371 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2372 index)).clazz;
2373 /* VM spec, section 3.11.5 */
2374 if ((klass->getModifiers() & Modifier::ABSTRACT)
2375 || klass->isInterface())
2377 jthrowable t = new java::lang::InstantiationException;
2378 INTERP_REPORT_EXCEPTION (t);
2379 throw t;
2381 jobject res = _Jv_AllocObject (klass);
2382 PUSHA (res);
2384 #ifdef DIRECT_THREADED
2385 REWRITE_INSN (&&new_resolved, datum, klass);
2386 #endif /* DIRECT_THREADED */
2388 NEXT_INSN;
2390 #ifdef DIRECT_THREADED
2391 new_resolved:
2393 jclass klass = (jclass) AVAL ();
2394 jobject res = _Jv_AllocObject (klass);
2395 PUSHA (res);
2397 NEXT_INSN;
2398 #endif /* DIRECT_THREADED */
2400 insn_newarray:
2402 int atype = GET1U ();
2403 int size = POPI();
2404 jobject result = _Jv_NewArray (atype, size);
2405 PUSHA (result);
2407 NEXT_INSN;
2409 insn_anewarray:
2411 SAVE_PC();
2412 int index = GET2U ();
2413 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2414 index)).clazz;
2415 int size = POPI();
2416 jobject result = _Jv_NewObjectArray (size, klass, 0);
2417 PUSHA (result);
2419 #ifdef DIRECT_THREADED
2420 REWRITE_INSN (&&anewarray_resolved, datum, klass);
2421 #endif /* DIRECT_THREADED */
2423 NEXT_INSN;
2425 #ifdef DIRECT_THREADED
2426 anewarray_resolved:
2428 jclass klass = (jclass) AVAL ();
2429 int size = POPI ();
2430 jobject result = _Jv_NewObjectArray (size, klass, 0);
2431 PUSHA (result);
2433 NEXT_INSN;
2434 #endif /* DIRECT_THREADED */
2436 insn_arraylength:
2438 __JArray *arr = (__JArray*)POPA();
2439 NULLARRAYCHECK (arr);
2440 PUSHI (arr->length);
2442 NEXT_INSN;
2444 insn_athrow:
2446 jobject value = POPA();
2447 jthrowable t = static_cast<jthrowable> (value);
2448 INTERP_REPORT_EXCEPTION (t);
2449 throw t;
2451 NEXT_INSN;
2453 insn_checkcast:
2455 SAVE_PC();
2456 jobject value = POPA();
2457 jint index = GET2U ();
2458 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2459 index)).clazz;
2461 value = (jobject) _Jv_CheckCast (to, value);
2463 PUSHA (value);
2465 #ifdef DIRECT_THREADED
2466 REWRITE_INSN (&&checkcast_resolved, datum, to);
2467 #endif /* DIRECT_THREADED */
2469 NEXT_INSN;
2471 #ifdef DIRECT_THREADED
2472 checkcast_resolved:
2474 SAVE_PC();
2475 jobject value = POPA ();
2476 jclass to = (jclass) AVAL ();
2477 value = (jobject) _Jv_CheckCast (to, value);
2478 PUSHA (value);
2480 NEXT_INSN;
2481 #endif /* DIRECT_THREADED */
2483 insn_instanceof:
2485 SAVE_PC();
2486 jobject value = POPA();
2487 jint index = GET2U ();
2488 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2489 index)).clazz;
2490 PUSHI (to->isInstance (value));
2492 #ifdef DIRECT_THREADED
2493 REWRITE_INSN (&&instanceof_resolved, datum, to);
2494 #endif /* DIRECT_THREADED */
2496 NEXT_INSN;
2498 #ifdef DIRECT_THREADED
2499 instanceof_resolved:
2501 jobject value = POPA ();
2502 jclass to = (jclass) AVAL ();
2503 PUSHI (to->isInstance (value));
2505 NEXT_INSN;
2506 #endif /* DIRECT_THREADED */
2508 insn_monitorenter:
2510 jobject value = POPA();
2511 NULLCHECK(value);
2512 _Jv_MonitorEnter (value);
2514 NEXT_INSN;
2516 insn_monitorexit:
2518 jobject value = POPA();
2519 NULLCHECK(value);
2520 _Jv_MonitorExit (value);
2522 NEXT_INSN;
2524 insn_ifnull:
2526 jobject val = POPA();
2527 if (val == NULL)
2528 TAKE_GOTO;
2529 else
2530 SKIP_GOTO;
2532 NEXT_INSN;
2534 insn_ifnonnull:
2536 jobject val = POPA();
2537 if (val != NULL)
2538 TAKE_GOTO;
2539 else
2540 SKIP_GOTO;
2542 NEXT_INSN;
2544 insn_multianewarray:
2546 SAVE_PC();
2547 int kind_index = GET2U ();
2548 int dim = GET1U ();
2550 jclass type
2551 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2552 kind_index)).clazz;
2553 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2555 for (int i = dim - 1; i >= 0; i--)
2557 sizes[i] = POPI ();
2560 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2562 PUSHA (res);
2564 NEXT_INSN;
2566 #ifndef DIRECT_THREADED
2567 insn_wide:
2569 jint the_mod_op = get1u (pc++);
2570 jint wide = get2u (pc); pc += 2;
2572 switch (the_mod_op)
2574 case op_istore:
2575 STOREI (wide);
2576 NEXT_INSN;
2578 case op_fstore:
2579 STOREF (wide);
2580 NEXT_INSN;
2582 case op_astore:
2583 STOREA (wide);
2584 NEXT_INSN;
2586 case op_lload:
2587 LOADL (wide);
2588 NEXT_INSN;
2590 case op_dload:
2591 LOADD (wide);
2592 NEXT_INSN;
2594 case op_iload:
2595 LOADI (wide);
2596 NEXT_INSN;
2598 case op_fload:
2599 LOADF (wide);
2600 NEXT_INSN;
2602 case op_aload:
2603 LOADA (wide);
2604 NEXT_INSN;
2606 case op_lstore:
2607 STOREL (wide);
2608 NEXT_INSN;
2610 case op_dstore:
2611 STORED (wide);
2612 NEXT_INSN;
2614 case op_ret:
2615 pc = (unsigned char*) PEEKA (wide);
2616 NEXT_INSN;
2618 case op_iinc:
2620 jint amount = get2s (pc); pc += 2;
2621 jint value = PEEKI (wide);
2622 POKEI (wide, value+amount);
2624 NEXT_INSN;
2626 default:
2627 throw_internal_error ("illegal bytecode modified by wide");
2631 #endif /* DIRECT_THREADED */
2633 insn_breakpoint:
2635 using namespace ::java::lang;
2636 jmethodID method = meth->self;
2637 jlocation location = meth->insn_index (pc - 1);
2639 using namespace gnu::gcj::jvmti;
2640 Breakpoint *bp
2641 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2642 location);
2643 JvAssert (bp != NULL);
2645 // Save the insn here since the breakpoint could be removed
2646 // before the JVMTI notification returns.
2647 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2649 bp->execute ();
2651 // Continue execution
2652 #ifdef DIRECT_THREADED
2653 goto *(opc->insn);
2654 #else
2655 goto *(insn_target[*opc]);
2656 #endif
2659 catch (java::lang::Throwable *ex)
2661 // Check if the exception is handled and, if so, set the pc to the start
2662 // of the appropriate catch block.
2663 if (meth->check_handler (&pc, meth, ex))
2665 sp = stack;
2666 sp++->o = ex; // Push exception.
2667 #ifdef DEBUG
2668 if (JVMTI_REQUESTED_EVENT (ExceptionCatch))
2670 using namespace gnu::gcj::jvmti;
2671 jlong catch_meth = reinterpret_cast<jlong> (meth->get_method ());
2672 jlong catch_loc = meth->insn_index (pc);
2673 _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH, thread,
2674 _Jv_GetCurrentJNIEnv (), catch_meth,
2675 catch_loc, ex);
2677 #endif
2678 NEXT_INSN;
2681 // No handler, so re-throw.
2682 throw ex;