2007-07-21 Christopher D. Rickett <crickett@lanl.gov>
[official-gcc.git] / libjava / interpret-run.cc
blob1eea57e1f9e19ce835ce24c3e51bfbf7697fcbc8
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)
385 #define REWRITE_INSN(INSN,SLOT,VALUE) \
386 do { \
387 pc[-2].insn = INSN; \
388 pc[-1].SLOT = VALUE; \
390 while (0)
392 #undef INTERP_REPORT_EXCEPTION
393 #define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */
394 #endif // !DEBUG
396 #define INTVAL() ((pc++)->int_val)
397 #define AVAL() ((pc++)->datum)
399 #define GET1S() INTVAL ()
400 #define GET2S() INTVAL ()
401 #define GET1U() INTVAL ()
402 #define GET2U() INTVAL ()
403 #define AVAL1U() AVAL ()
404 #define AVAL2U() AVAL ()
405 #define AVAL2UP() AVAL ()
406 #define SKIP_GOTO ++pc
407 #define GOTO_VAL() (insn_slot *) pc->datum
408 #define PCVAL(unionval) unionval.p
409 #define AMPAMP(label) &&label
411 // Compile if we must. NOTE: Double-check locking.
412 if (meth->prepared == NULL)
414 _Jv_MutexLock (&compile_mutex);
415 if (meth->prepared == NULL)
416 meth->compile (insn_target);
417 _Jv_MutexUnlock (&compile_mutex);
420 // If we're only compiling, stop here
421 if (args == NULL)
422 return;
424 pc = (insn_slot *) meth->prepared;
426 #else
428 #ifdef DEBUG
429 #define NEXT_INSN \
430 do \
432 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
434 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
435 jmethodID method = meth->self; \
436 jlocation loc = meth->insn_index (pc); \
437 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
438 env, method, loc); \
440 goto *(insn_target[*pc++])
441 #else
442 #define NEXT_INSN goto *(insn_target[*pc++])
443 #endif
445 #define GET1S() get1s (pc++)
446 #define GET2S() (pc += 2, get2s (pc- 2))
447 #define GET1U() get1u (pc++)
448 #define GET2U() (pc += 2, get2u (pc - 2))
449 // Note that these could be more efficient when not handling 'ldc
450 // class'.
451 #define AVAL1U() \
452 ({ int index = get1u (pc++); \
453 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
454 #define AVAL2U() \
455 ({ int index = get2u (pc); pc += 2; \
456 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
457 // Note that we don't need to resolve the pool entry here as class
458 // constants are never wide.
459 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
460 #define SKIP_GOTO pc += 2
461 #define GOTO_VAL() pc - 1 + get2s (pc)
462 #define PCVAL(unionval) unionval.i
463 #define AMPAMP(label) NULL
465 pc = meth->bytecode ();
467 #endif /* DIRECT_THREADED */
469 #define TAKE_GOTO pc = GOTO_VAL ()
471 /* Go straight at it! the ffi raw format matches the internal
472 stack representation exactly. At least, that's the idea.
474 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
476 _Jv_word *pool_data = meth->defining_class->constants.data;
478 /* These three are temporaries for common code used by several
479 instructions. */
480 void (*fun)();
481 _Jv_ResolvedMethod* rmeth;
482 int tmpval;
486 // We keep nop around. It is used if we're interpreting the
487 // bytecodes and not doing direct threading.
488 insn_nop:
489 NEXT_INSN;
491 /* The first few instructions here are ordered according to their
492 frequency, in the hope that this will improve code locality a
493 little. */
495 insn_aload_0: // 0x2a
496 LOADA (0);
497 NEXT_INSN;
499 insn_iload: // 0x15
500 LOADI (GET1U ());
501 NEXT_INSN;
503 insn_iload_1: // 0x1b
504 LOADI (1);
505 NEXT_INSN;
507 insn_invokevirtual: // 0xb6
509 SAVE_PC();
510 int index = GET2U ();
512 /* _Jv_Linker::resolve_pool_entry returns immediately if the
513 * value already is resolved. If we want to clutter up the
514 * code here to gain a little performance, then we can check
515 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
516 * directly. For now, I don't think it is worth it. */
518 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
519 index)).rmethod;
521 sp -= rmeth->stack_item_count;
523 if (rmeth->method->accflags & Modifier::FINAL)
525 // We can't rely on NULLCHECK working if the method is final.
526 if (! sp[0].o)
527 throw_null_pointer_exception ();
529 // Final methods might not appear in the vtable.
530 fun = (void (*)()) rmeth->method->ncode;
532 else
534 NULLCHECK (sp[0].o);
535 jobject rcv = sp[0].o;
536 _Jv_VTable *table = *(_Jv_VTable**) rcv;
537 fun = (void (*)()) table->get_method (rmeth->method->index);
540 #ifdef DIRECT_THREADED
541 // Rewrite instruction so that we use a faster pre-resolved
542 // method.
543 REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth);
544 #endif /* DIRECT_THREADED */
546 goto perform_invoke;
548 #ifdef DIRECT_THREADED
549 invokevirtual_resolved:
551 SAVE_PC();
552 rmeth = (_Jv_ResolvedMethod *) AVAL ();
553 sp -= rmeth->stack_item_count;
555 if (rmeth->method->accflags & Modifier::FINAL)
557 // We can't rely on NULLCHECK working if the method is final.
558 if (! sp[0].o)
559 throw_null_pointer_exception ();
561 // Final methods might not appear in the vtable.
562 fun = (void (*)()) rmeth->method->ncode;
564 else
566 jobject rcv = sp[0].o;
567 _Jv_VTable *table = *(_Jv_VTable**) rcv;
568 fun = (void (*)()) table->get_method (rmeth->method->index);
571 goto perform_invoke;
572 #endif /* DIRECT_THREADED */
574 perform_invoke:
576 /* here goes the magic again... */
577 ffi_cif *cif = &rmeth->cif;
578 ffi_raw *raw = (ffi_raw*) sp;
580 _Jv_value rvalue;
582 #if FFI_NATIVE_RAW_API
583 /* We assume that this is only implemented if it's correct */
584 /* to use it here. On a 64 bit machine, it never is. */
585 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
586 #else
587 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
588 #endif
590 int rtype = cif->rtype->type;
592 /* the likelyhood of object, int, or void return is very high,
593 * so those are checked before the switch */
594 if (rtype == FFI_TYPE_POINTER)
596 PUSHA (rvalue.object_value);
598 else if (rtype == FFI_TYPE_SINT32)
600 PUSHI (rvalue.int_value);
602 else if (rtype == FFI_TYPE_VOID)
604 /* skip */
606 else
608 switch (rtype)
610 case FFI_TYPE_SINT8:
611 PUSHI ((jbyte)(rvalue.int_value & 0xff));
612 break;
614 case FFI_TYPE_SINT16:
615 PUSHI ((jshort)(rvalue.int_value & 0xffff));
616 break;
618 case FFI_TYPE_UINT16:
619 PUSHI (rvalue.int_value & 0xffff);
620 break;
622 case FFI_TYPE_FLOAT:
623 PUSHF (rvalue.float_value);
624 break;
626 case FFI_TYPE_DOUBLE:
627 PUSHD (rvalue.double_value);
628 break;
630 case FFI_TYPE_SINT64:
631 PUSHL (rvalue.long_value);
632 break;
634 default:
635 throw_internal_error ("unknown return type in invokeXXX");
639 NEXT_INSN;
641 insn_aconst_null:
642 PUSHA (NULL);
643 NEXT_INSN;
645 insn_iconst_m1:
646 PUSHI (-1);
647 NEXT_INSN;
649 insn_iconst_0:
650 PUSHI (0);
651 NEXT_INSN;
653 insn_iconst_1:
654 PUSHI (1);
655 NEXT_INSN;
657 insn_iconst_2:
658 PUSHI (2);
659 NEXT_INSN;
661 insn_iconst_3:
662 PUSHI (3);
663 NEXT_INSN;
665 insn_iconst_4:
666 PUSHI (4);
667 NEXT_INSN;
669 insn_iconst_5:
670 PUSHI (5);
671 NEXT_INSN;
673 insn_lconst_0:
674 PUSHL (0);
675 NEXT_INSN;
677 insn_lconst_1:
678 PUSHL (1);
679 NEXT_INSN;
681 insn_fconst_0:
682 PUSHF (0);
683 NEXT_INSN;
685 insn_fconst_1:
686 PUSHF (1);
687 NEXT_INSN;
689 insn_fconst_2:
690 PUSHF (2);
691 NEXT_INSN;
693 insn_dconst_0:
694 PUSHD (0);
695 NEXT_INSN;
697 insn_dconst_1:
698 PUSHD (1);
699 NEXT_INSN;
701 insn_bipush:
702 // For direct threaded, bipush and sipush are the same.
703 #ifndef DIRECT_THREADED
704 PUSHI (GET1S ());
705 NEXT_INSN;
706 #endif /* DIRECT_THREADED */
707 insn_sipush:
708 PUSHI (GET2S ());
709 NEXT_INSN;
711 insn_ldc:
712 // For direct threaded, ldc and ldc_w are the same.
713 #ifndef DIRECT_THREADED
714 PUSHA ((jobject) AVAL1U ());
715 NEXT_INSN;
716 #endif /* DIRECT_THREADED */
717 insn_ldc_w:
718 PUSHA ((jobject) AVAL2U ());
719 NEXT_INSN;
721 #ifdef DIRECT_THREADED
722 // For direct threaded we have a separate 'ldc class' operation.
723 insn_ldc_class:
725 SAVE_PC();
726 // We could rewrite the instruction at this point.
727 int index = INTVAL ();
728 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
729 index)).o;
730 PUSHA (k);
732 NEXT_INSN;
733 #endif /* DIRECT_THREADED */
735 insn_ldc2_w:
737 void *where = AVAL2UP ();
738 memcpy (sp, where, 2*sizeof (_Jv_word));
739 sp += 2;
741 NEXT_INSN;
743 insn_lload:
744 LOADL (GET1U ());
745 NEXT_INSN;
747 insn_fload:
748 LOADF (GET1U ());
749 NEXT_INSN;
751 insn_dload:
752 LOADD (GET1U ());
753 NEXT_INSN;
755 insn_aload:
756 LOADA (GET1U ());
757 NEXT_INSN;
759 insn_iload_0:
760 LOADI (0);
761 NEXT_INSN;
763 insn_iload_2:
764 LOADI (2);
765 NEXT_INSN;
767 insn_iload_3:
768 LOADI (3);
769 NEXT_INSN;
771 insn_lload_0:
772 LOADL (0);
773 NEXT_INSN;
775 insn_lload_1:
776 LOADL (1);
777 NEXT_INSN;
779 insn_lload_2:
780 LOADL (2);
781 NEXT_INSN;
783 insn_lload_3:
784 LOADL (3);
785 NEXT_INSN;
787 insn_fload_0:
788 LOADF (0);
789 NEXT_INSN;
791 insn_fload_1:
792 LOADF (1);
793 NEXT_INSN;
795 insn_fload_2:
796 LOADF (2);
797 NEXT_INSN;
799 insn_fload_3:
800 LOADF (3);
801 NEXT_INSN;
803 insn_dload_0:
804 LOADD (0);
805 NEXT_INSN;
807 insn_dload_1:
808 LOADD (1);
809 NEXT_INSN;
811 insn_dload_2:
812 LOADD (2);
813 NEXT_INSN;
815 insn_dload_3:
816 LOADD (3);
817 NEXT_INSN;
819 insn_aload_1:
820 LOADA(1);
821 NEXT_INSN;
823 insn_aload_2:
824 LOADA(2);
825 NEXT_INSN;
827 insn_aload_3:
828 LOADA(3);
829 NEXT_INSN;
831 insn_iaload:
833 jint index = POPI();
834 jintArray arr = (jintArray) POPA();
835 NULLARRAYCHECK (arr);
836 ARRAYBOUNDSCHECK (arr, index);
837 PUSHI( elements(arr)[index] );
839 NEXT_INSN;
841 insn_laload:
843 jint index = POPI();
844 jlongArray arr = (jlongArray) POPA();
845 NULLARRAYCHECK (arr);
846 ARRAYBOUNDSCHECK (arr, index);
847 PUSHL( elements(arr)[index] );
849 NEXT_INSN;
851 insn_faload:
853 jint index = POPI();
854 jfloatArray arr = (jfloatArray) POPA();
855 NULLARRAYCHECK (arr);
856 ARRAYBOUNDSCHECK (arr, index);
857 PUSHF( elements(arr)[index] );
859 NEXT_INSN;
861 insn_daload:
863 jint index = POPI();
864 jdoubleArray arr = (jdoubleArray) POPA();
865 NULLARRAYCHECK (arr);
866 ARRAYBOUNDSCHECK (arr, index);
867 PUSHD( elements(arr)[index] );
869 NEXT_INSN;
871 insn_aaload:
873 jint index = POPI();
874 jobjectArray arr = (jobjectArray) POPA();
875 NULLARRAYCHECK (arr);
876 ARRAYBOUNDSCHECK (arr, index);
877 PUSHA( elements(arr)[index] );
879 NEXT_INSN;
881 insn_baload:
883 jint index = POPI();
884 jbyteArray arr = (jbyteArray) POPA();
885 NULLARRAYCHECK (arr);
886 ARRAYBOUNDSCHECK (arr, index);
887 PUSHI( elements(arr)[index] );
889 NEXT_INSN;
891 insn_caload:
893 jint index = POPI();
894 jcharArray arr = (jcharArray) POPA();
895 NULLARRAYCHECK (arr);
896 ARRAYBOUNDSCHECK (arr, index);
897 PUSHI( elements(arr)[index] );
899 NEXT_INSN;
901 insn_saload:
903 jint index = POPI();
904 jshortArray arr = (jshortArray) POPA();
905 NULLARRAYCHECK (arr);
906 ARRAYBOUNDSCHECK (arr, index);
907 PUSHI( elements(arr)[index] );
909 NEXT_INSN;
911 insn_istore:
912 STOREI (GET1U ());
913 NEXT_INSN;
915 insn_lstore:
916 STOREL (GET1U ());
917 NEXT_INSN;
919 insn_fstore:
920 STOREF (GET1U ());
921 NEXT_INSN;
923 insn_dstore:
924 STORED (GET1U ());
925 NEXT_INSN;
927 insn_astore:
928 STOREA (GET1U ());
929 NEXT_INSN;
931 insn_istore_0:
932 STOREI (0);
933 NEXT_INSN;
935 insn_istore_1:
936 STOREI (1);
937 NEXT_INSN;
939 insn_istore_2:
940 STOREI (2);
941 NEXT_INSN;
943 insn_istore_3:
944 STOREI (3);
945 NEXT_INSN;
947 insn_lstore_0:
948 STOREL (0);
949 NEXT_INSN;
951 insn_lstore_1:
952 STOREL (1);
953 NEXT_INSN;
955 insn_lstore_2:
956 STOREL (2);
957 NEXT_INSN;
959 insn_lstore_3:
960 STOREL (3);
961 NEXT_INSN;
963 insn_fstore_0:
964 STOREF (0);
965 NEXT_INSN;
967 insn_fstore_1:
968 STOREF (1);
969 NEXT_INSN;
971 insn_fstore_2:
972 STOREF (2);
973 NEXT_INSN;
975 insn_fstore_3:
976 STOREF (3);
977 NEXT_INSN;
979 insn_dstore_0:
980 STORED (0);
981 NEXT_INSN;
983 insn_dstore_1:
984 STORED (1);
985 NEXT_INSN;
987 insn_dstore_2:
988 STORED (2);
989 NEXT_INSN;
991 insn_dstore_3:
992 STORED (3);
993 NEXT_INSN;
995 insn_astore_0:
996 STOREA(0);
997 NEXT_INSN;
999 insn_astore_1:
1000 STOREA(1);
1001 NEXT_INSN;
1003 insn_astore_2:
1004 STOREA(2);
1005 NEXT_INSN;
1007 insn_astore_3:
1008 STOREA(3);
1009 NEXT_INSN;
1011 insn_iastore:
1013 jint value = POPI();
1014 jint index = POPI();
1015 jintArray arr = (jintArray) POPA();
1016 NULLARRAYCHECK (arr);
1017 ARRAYBOUNDSCHECK (arr, index);
1018 elements(arr)[index] = value;
1020 NEXT_INSN;
1022 insn_lastore:
1024 jlong value = POPL();
1025 jint index = POPI();
1026 jlongArray arr = (jlongArray) POPA();
1027 NULLARRAYCHECK (arr);
1028 ARRAYBOUNDSCHECK (arr, index);
1029 elements(arr)[index] = value;
1031 NEXT_INSN;
1033 insn_fastore:
1035 jfloat value = POPF();
1036 jint index = POPI();
1037 jfloatArray arr = (jfloatArray) POPA();
1038 NULLARRAYCHECK (arr);
1039 ARRAYBOUNDSCHECK (arr, index);
1040 elements(arr)[index] = value;
1042 NEXT_INSN;
1044 insn_dastore:
1046 jdouble value = POPD();
1047 jint index = POPI();
1048 jdoubleArray arr = (jdoubleArray) POPA();
1049 NULLARRAYCHECK (arr);
1050 ARRAYBOUNDSCHECK (arr, index);
1051 elements(arr)[index] = value;
1053 NEXT_INSN;
1055 insn_aastore:
1057 jobject value = POPA();
1058 jint index = POPI();
1059 jobjectArray arr = (jobjectArray) POPA();
1060 NULLARRAYCHECK (arr);
1061 ARRAYBOUNDSCHECK (arr, index);
1062 _Jv_CheckArrayStore (arr, value);
1063 elements(arr)[index] = value;
1065 NEXT_INSN;
1067 insn_bastore:
1069 jbyte value = (jbyte) POPI();
1070 jint index = POPI();
1071 jbyteArray arr = (jbyteArray) POPA();
1072 NULLARRAYCHECK (arr);
1073 ARRAYBOUNDSCHECK (arr, index);
1074 elements(arr)[index] = value;
1076 NEXT_INSN;
1078 insn_castore:
1080 jchar value = (jchar) POPI();
1081 jint index = POPI();
1082 jcharArray arr = (jcharArray) POPA();
1083 NULLARRAYCHECK (arr);
1084 ARRAYBOUNDSCHECK (arr, index);
1085 elements(arr)[index] = value;
1087 NEXT_INSN;
1089 insn_sastore:
1091 jshort value = (jshort) POPI();
1092 jint index = POPI();
1093 jshortArray arr = (jshortArray) POPA();
1094 NULLARRAYCHECK (arr);
1095 ARRAYBOUNDSCHECK (arr, index);
1096 elements(arr)[index] = value;
1098 NEXT_INSN;
1100 insn_pop:
1101 sp -= 1;
1102 NEXT_INSN;
1104 insn_pop2:
1105 sp -= 2;
1106 NEXT_INSN;
1108 insn_dup:
1109 sp[0] = sp[-1];
1110 sp += 1;
1111 NEXT_INSN;
1113 insn_dup_x1:
1114 dupx (sp, 1, 1); sp+=1;
1115 NEXT_INSN;
1117 insn_dup_x2:
1118 dupx (sp, 1, 2); sp+=1;
1119 NEXT_INSN;
1121 insn_dup2:
1122 sp[0] = sp[-2];
1123 sp[1] = sp[-1];
1124 sp += 2;
1125 NEXT_INSN;
1127 insn_dup2_x1:
1128 dupx (sp, 2, 1); sp+=2;
1129 NEXT_INSN;
1131 insn_dup2_x2:
1132 dupx (sp, 2, 2); sp+=2;
1133 NEXT_INSN;
1135 insn_swap:
1137 jobject tmp1 = POPA();
1138 jobject tmp2 = POPA();
1139 PUSHA (tmp1);
1140 PUSHA (tmp2);
1142 NEXT_INSN;
1144 insn_iadd:
1145 BINOPI(+);
1146 NEXT_INSN;
1148 insn_ladd:
1149 BINOPL(+);
1150 NEXT_INSN;
1152 insn_fadd:
1153 BINOPF(+);
1154 NEXT_INSN;
1156 insn_dadd:
1157 BINOPD(+);
1158 NEXT_INSN;
1160 insn_isub:
1161 BINOPI(-);
1162 NEXT_INSN;
1164 insn_lsub:
1165 BINOPL(-);
1166 NEXT_INSN;
1168 insn_fsub:
1169 BINOPF(-);
1170 NEXT_INSN;
1172 insn_dsub:
1173 BINOPD(-);
1174 NEXT_INSN;
1176 insn_imul:
1177 BINOPI(*);
1178 NEXT_INSN;
1180 insn_lmul:
1181 BINOPL(*);
1182 NEXT_INSN;
1184 insn_fmul:
1185 BINOPF(*);
1186 NEXT_INSN;
1188 insn_dmul:
1189 BINOPD(*);
1190 NEXT_INSN;
1192 insn_idiv:
1194 SAVE_PC();
1195 jint value2 = POPI();
1196 jint value1 = POPI();
1197 jint res = _Jv_divI (value1, value2);
1198 PUSHI (res);
1200 NEXT_INSN;
1202 insn_ldiv:
1204 SAVE_PC();
1205 jlong value2 = POPL();
1206 jlong value1 = POPL();
1207 jlong res = _Jv_divJ (value1, value2);
1208 PUSHL (res);
1210 NEXT_INSN;
1212 insn_fdiv:
1214 jfloat value2 = POPF();
1215 jfloat value1 = POPF();
1216 jfloat res = value1 / value2;
1217 PUSHF (res);
1219 NEXT_INSN;
1221 insn_ddiv:
1223 jdouble value2 = POPD();
1224 jdouble value1 = POPD();
1225 jdouble res = value1 / value2;
1226 PUSHD (res);
1228 NEXT_INSN;
1230 insn_irem:
1232 SAVE_PC();
1233 jint value2 = POPI();
1234 jint value1 = POPI();
1235 jint res = _Jv_remI (value1, value2);
1236 PUSHI (res);
1238 NEXT_INSN;
1240 insn_lrem:
1242 SAVE_PC();
1243 jlong value2 = POPL();
1244 jlong value1 = POPL();
1245 jlong res = _Jv_remJ (value1, value2);
1246 PUSHL (res);
1248 NEXT_INSN;
1250 insn_frem:
1252 jfloat value2 = POPF();
1253 jfloat value1 = POPF();
1254 jfloat res = __ieee754_fmod (value1, value2);
1255 PUSHF (res);
1257 NEXT_INSN;
1259 insn_drem:
1261 jdouble value2 = POPD();
1262 jdouble value1 = POPD();
1263 jdouble res = __ieee754_fmod (value1, value2);
1264 PUSHD (res);
1266 NEXT_INSN;
1268 insn_ineg:
1270 jint value = POPI();
1271 PUSHI (value * -1);
1273 NEXT_INSN;
1275 insn_lneg:
1277 jlong value = POPL();
1278 PUSHL (value * -1);
1280 NEXT_INSN;
1282 insn_fneg:
1284 jfloat value = POPF();
1285 PUSHF (value * -1);
1287 NEXT_INSN;
1289 insn_dneg:
1291 jdouble value = POPD();
1292 PUSHD (value * -1);
1294 NEXT_INSN;
1296 insn_ishl:
1298 jint shift = (POPI() & 0x1f);
1299 jint value = POPI();
1300 PUSHI (value << shift);
1302 NEXT_INSN;
1304 insn_lshl:
1306 jint shift = (POPI() & 0x3f);
1307 jlong value = POPL();
1308 PUSHL (value << shift);
1310 NEXT_INSN;
1312 insn_ishr:
1314 jint shift = (POPI() & 0x1f);
1315 jint value = POPI();
1316 PUSHI (value >> shift);
1318 NEXT_INSN;
1320 insn_lshr:
1322 jint shift = (POPI() & 0x3f);
1323 jlong value = POPL();
1324 PUSHL (value >> shift);
1326 NEXT_INSN;
1328 insn_iushr:
1330 jint shift = (POPI() & 0x1f);
1331 _Jv_uint value = (_Jv_uint) POPI();
1332 PUSHI ((jint) (value >> shift));
1334 NEXT_INSN;
1336 insn_lushr:
1338 jint shift = (POPI() & 0x3f);
1339 _Jv_ulong value = (_Jv_ulong) POPL();
1340 PUSHL ((jlong) (value >> shift));
1342 NEXT_INSN;
1344 insn_iand:
1345 BINOPI (&);
1346 NEXT_INSN;
1348 insn_land:
1349 BINOPL (&);
1350 NEXT_INSN;
1352 insn_ior:
1353 BINOPI (|);
1354 NEXT_INSN;
1356 insn_lor:
1357 BINOPL (|);
1358 NEXT_INSN;
1360 insn_ixor:
1361 BINOPI (^);
1362 NEXT_INSN;
1364 insn_lxor:
1365 BINOPL (^);
1366 NEXT_INSN;
1368 insn_iinc:
1370 jint index = GET1U ();
1371 jint amount = GET1S ();
1372 locals[index].i += amount;
1374 NEXT_INSN;
1376 insn_i2l:
1377 {jlong value = POPI(); PUSHL (value);}
1378 NEXT_INSN;
1380 insn_i2f:
1381 {jfloat value = POPI(); PUSHF (value);}
1382 NEXT_INSN;
1384 insn_i2d:
1385 {jdouble value = POPI(); PUSHD (value);}
1386 NEXT_INSN;
1388 insn_l2i:
1389 {jint value = POPL(); PUSHI (value);}
1390 NEXT_INSN;
1392 insn_l2f:
1393 {jfloat value = POPL(); PUSHF (value);}
1394 NEXT_INSN;
1396 insn_l2d:
1397 {jdouble value = POPL(); PUSHD (value);}
1398 NEXT_INSN;
1400 insn_f2i:
1402 using namespace java::lang;
1403 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1404 PUSHI(value);
1406 NEXT_INSN;
1408 insn_f2l:
1410 using namespace java::lang;
1411 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1412 PUSHL(value);
1414 NEXT_INSN;
1416 insn_f2d:
1417 { jdouble value = POPF (); PUSHD(value); }
1418 NEXT_INSN;
1420 insn_d2i:
1422 using namespace java::lang;
1423 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1424 PUSHI(value);
1426 NEXT_INSN;
1428 insn_d2l:
1430 using namespace java::lang;
1431 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1432 PUSHL(value);
1434 NEXT_INSN;
1436 insn_d2f:
1437 { jfloat value = POPD (); PUSHF(value); }
1438 NEXT_INSN;
1440 insn_i2b:
1441 { jbyte value = POPI (); PUSHI(value); }
1442 NEXT_INSN;
1444 insn_i2c:
1445 { jchar value = POPI (); PUSHI(value); }
1446 NEXT_INSN;
1448 insn_i2s:
1449 { jshort value = POPI (); PUSHI(value); }
1450 NEXT_INSN;
1452 insn_lcmp:
1454 jlong value2 = POPL ();
1455 jlong value1 = POPL ();
1456 if (value1 > value2)
1457 { PUSHI (1); }
1458 else if (value1 == value2)
1459 { PUSHI (0); }
1460 else
1461 { PUSHI (-1); }
1463 NEXT_INSN;
1465 insn_fcmpl:
1466 tmpval = -1;
1467 goto fcmp;
1469 insn_fcmpg:
1470 tmpval = 1;
1472 fcmp:
1474 jfloat value2 = POPF ();
1475 jfloat value1 = POPF ();
1476 if (value1 > value2)
1477 PUSHI (1);
1478 else if (value1 == value2)
1479 PUSHI (0);
1480 else if (value1 < value2)
1481 PUSHI (-1);
1482 else
1483 PUSHI (tmpval);
1485 NEXT_INSN;
1487 insn_dcmpl:
1488 tmpval = -1;
1489 goto dcmp;
1491 insn_dcmpg:
1492 tmpval = 1;
1494 dcmp:
1496 jdouble value2 = POPD ();
1497 jdouble value1 = POPD ();
1498 if (value1 > value2)
1499 PUSHI (1);
1500 else if (value1 == value2)
1501 PUSHI (0);
1502 else if (value1 < value2)
1503 PUSHI (-1);
1504 else
1505 PUSHI (tmpval);
1507 NEXT_INSN;
1509 insn_ifeq:
1511 if (POPI() == 0)
1512 TAKE_GOTO;
1513 else
1514 SKIP_GOTO;
1516 NEXT_INSN;
1518 insn_ifne:
1520 if (POPI() != 0)
1521 TAKE_GOTO;
1522 else
1523 SKIP_GOTO;
1525 NEXT_INSN;
1527 insn_iflt:
1529 if (POPI() < 0)
1530 TAKE_GOTO;
1531 else
1532 SKIP_GOTO;
1534 NEXT_INSN;
1536 insn_ifge:
1538 if (POPI() >= 0)
1539 TAKE_GOTO;
1540 else
1541 SKIP_GOTO;
1543 NEXT_INSN;
1545 insn_ifgt:
1547 if (POPI() > 0)
1548 TAKE_GOTO;
1549 else
1550 SKIP_GOTO;
1552 NEXT_INSN;
1554 insn_ifle:
1556 if (POPI() <= 0)
1557 TAKE_GOTO;
1558 else
1559 SKIP_GOTO;
1561 NEXT_INSN;
1563 insn_if_icmpeq:
1565 jint value2 = POPI();
1566 jint value1 = POPI();
1567 if (value1 == value2)
1568 TAKE_GOTO;
1569 else
1570 SKIP_GOTO;
1572 NEXT_INSN;
1574 insn_if_icmpne:
1576 jint value2 = POPI();
1577 jint value1 = POPI();
1578 if (value1 != value2)
1579 TAKE_GOTO;
1580 else
1581 SKIP_GOTO;
1583 NEXT_INSN;
1585 insn_if_icmplt:
1587 jint value2 = POPI();
1588 jint value1 = POPI();
1589 if (value1 < value2)
1590 TAKE_GOTO;
1591 else
1592 SKIP_GOTO;
1594 NEXT_INSN;
1596 insn_if_icmpge:
1598 jint value2 = POPI();
1599 jint value1 = POPI();
1600 if (value1 >= value2)
1601 TAKE_GOTO;
1602 else
1603 SKIP_GOTO;
1605 NEXT_INSN;
1607 insn_if_icmpgt:
1609 jint value2 = POPI();
1610 jint value1 = POPI();
1611 if (value1 > value2)
1612 TAKE_GOTO;
1613 else
1614 SKIP_GOTO;
1616 NEXT_INSN;
1618 insn_if_icmple:
1620 jint value2 = POPI();
1621 jint value1 = POPI();
1622 if (value1 <= value2)
1623 TAKE_GOTO;
1624 else
1625 SKIP_GOTO;
1627 NEXT_INSN;
1629 insn_if_acmpeq:
1631 jobject value2 = POPA();
1632 jobject value1 = POPA();
1633 if (value1 == value2)
1634 TAKE_GOTO;
1635 else
1636 SKIP_GOTO;
1638 NEXT_INSN;
1640 insn_if_acmpne:
1642 jobject value2 = POPA();
1643 jobject value1 = POPA();
1644 if (value1 != value2)
1645 TAKE_GOTO;
1646 else
1647 SKIP_GOTO;
1649 NEXT_INSN;
1651 insn_goto_w:
1652 #ifndef DIRECT_THREADED
1653 // For direct threaded, goto and goto_w are the same.
1654 pc = pc - 1 + get4 (pc);
1655 NEXT_INSN;
1656 #endif /* DIRECT_THREADED */
1657 insn_goto:
1658 TAKE_GOTO;
1659 NEXT_INSN;
1661 insn_jsr_w:
1662 #ifndef DIRECT_THREADED
1663 // For direct threaded, jsr and jsr_w are the same.
1665 pc_t next = pc - 1 + get4 (pc);
1666 pc += 4;
1667 PUSHA ((jobject) pc);
1668 pc = next;
1670 NEXT_INSN;
1671 #endif /* DIRECT_THREADED */
1672 insn_jsr:
1674 pc_t next = GOTO_VAL();
1675 SKIP_GOTO;
1676 PUSHA ((jobject) pc);
1677 pc = next;
1679 NEXT_INSN;
1681 insn_ret:
1683 jint index = GET1U ();
1684 pc = (pc_t) PEEKA (index);
1686 NEXT_INSN;
1688 insn_tableswitch:
1690 #ifdef DIRECT_THREADED
1691 void *def = (pc++)->datum;
1693 int index = POPI();
1695 jint low = INTVAL ();
1696 jint high = INTVAL ();
1698 if (index < low || index > high)
1699 pc = (insn_slot *) def;
1700 else
1701 pc = (insn_slot *) ((pc + index - low)->datum);
1702 #else
1703 pc_t base_pc = pc - 1;
1704 int index = POPI ();
1706 pc_t base = (pc_t) meth->bytecode ();
1707 while ((pc - base) % 4 != 0)
1708 ++pc;
1710 jint def = get4 (pc);
1711 jint low = get4 (pc + 4);
1712 jint high = get4 (pc + 8);
1713 if (index < low || index > high)
1714 pc = base_pc + def;
1715 else
1716 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1717 #endif /* DIRECT_THREADED */
1719 NEXT_INSN;
1721 insn_lookupswitch:
1723 #ifdef DIRECT_THREADED
1724 void *def = (pc++)->insn;
1726 int index = POPI();
1728 jint npairs = INTVAL ();
1730 int max = npairs - 1;
1731 int min = 0;
1733 // Simple binary search...
1734 while (min < max)
1736 int half = (min + max) / 2;
1737 int match = pc[2 * half].int_val;
1739 if (index == match)
1741 // Found it.
1742 pc = (insn_slot *) pc[2 * half + 1].datum;
1743 NEXT_INSN;
1745 else if (index < match)
1746 // We can use HALF - 1 here because we check again on
1747 // loop exit.
1748 max = half - 1;
1749 else
1750 // We can use HALF + 1 here because we check again on
1751 // loop exit.
1752 min = half + 1;
1754 if (index == pc[2 * min].int_val)
1755 pc = (insn_slot *) pc[2 * min + 1].datum;
1756 else
1757 pc = (insn_slot *) def;
1758 #else
1759 unsigned char *base_pc = pc-1;
1760 int index = POPI();
1762 unsigned char* base = meth->bytecode ();
1763 while ((pc-base) % 4 != 0)
1764 ++pc;
1766 jint def = get4 (pc);
1767 jint npairs = get4 (pc+4);
1769 int max = npairs-1;
1770 int min = 0;
1772 // Simple binary search...
1773 while (min < max)
1775 int half = (min+max)/2;
1776 int match = get4 (pc+ 4*(2 + 2*half));
1778 if (index == match)
1779 min = max = half;
1780 else if (index < match)
1781 // We can use HALF - 1 here because we check again on
1782 // loop exit.
1783 max = half - 1;
1784 else
1785 // We can use HALF + 1 here because we check again on
1786 // loop exit.
1787 min = half + 1;
1790 if (index == get4 (pc+ 4*(2 + 2*min)))
1791 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1792 else
1793 pc = base_pc + def;
1794 #endif /* DIRECT_THREADED */
1796 NEXT_INSN;
1798 insn_areturn:
1799 *(jobject *) retp = POPA ();
1800 return;
1802 insn_lreturn:
1803 *(jlong *) retp = POPL ();
1804 return;
1806 insn_freturn:
1807 *(jfloat *) retp = POPF ();
1808 return;
1810 insn_dreturn:
1811 *(jdouble *) retp = POPD ();
1812 return;
1814 insn_ireturn:
1815 *(jint *) retp = POPI ();
1816 return;
1818 insn_return:
1819 return;
1821 insn_getstatic:
1823 jint fieldref_index = GET2U ();
1824 SAVE_PC(); // Constant pool resolution could throw.
1825 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1826 _Jv_Field *field = pool_data[fieldref_index].field;
1828 if ((field->flags & Modifier::STATIC) == 0)
1829 throw_incompatible_class_change_error
1830 (JvNewStringLatin1 ("field no longer static"));
1832 jclass type = field->type;
1834 // We rewrite the instruction once we discover what it refers
1835 // to.
1836 void *newinsn = NULL;
1837 if (type->isPrimitive ())
1839 switch (type->size_in_bytes)
1841 case 1:
1842 PUSHI (*field->u.byte_addr);
1843 newinsn = AMPAMP (getstatic_resolved_1);
1844 break;
1846 case 2:
1847 if (type == JvPrimClass (char))
1849 PUSHI (*field->u.char_addr);
1850 newinsn = AMPAMP (getstatic_resolved_char);
1852 else
1854 PUSHI (*field->u.short_addr);
1855 newinsn = AMPAMP (getstatic_resolved_short);
1857 break;
1859 case 4:
1860 PUSHI(*field->u.int_addr);
1861 newinsn = AMPAMP (getstatic_resolved_4);
1862 break;
1864 case 8:
1865 PUSHL(*field->u.long_addr);
1866 newinsn = AMPAMP (getstatic_resolved_8);
1867 break;
1870 else
1872 PUSHA(*field->u.object_addr);
1873 newinsn = AMPAMP (getstatic_resolved_obj);
1876 #ifdef DIRECT_THREADED
1877 REWRITE_INSN (newinsn, datum, field->u.addr);
1878 #endif /* DIRECT_THREADED */
1880 NEXT_INSN;
1882 #ifdef DIRECT_THREADED
1883 getstatic_resolved_1:
1884 PUSHI (*(jbyte *) AVAL ());
1885 NEXT_INSN;
1887 getstatic_resolved_char:
1888 PUSHI (*(jchar *) AVAL ());
1889 NEXT_INSN;
1891 getstatic_resolved_short:
1892 PUSHI (*(jshort *) AVAL ());
1893 NEXT_INSN;
1895 getstatic_resolved_4:
1896 PUSHI (*(jint *) AVAL ());
1897 NEXT_INSN;
1899 getstatic_resolved_8:
1900 PUSHL (*(jlong *) AVAL ());
1901 NEXT_INSN;
1903 getstatic_resolved_obj:
1904 PUSHA (*(jobject *) AVAL ());
1905 NEXT_INSN;
1906 #endif /* DIRECT_THREADED */
1908 insn_getfield:
1910 SAVE_PC();
1911 jint fieldref_index = GET2U ();
1912 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1913 _Jv_Field *field = pool_data[fieldref_index].field;
1915 if ((field->flags & Modifier::STATIC) != 0)
1916 throw_incompatible_class_change_error
1917 (JvNewStringLatin1 ("field is static"));
1919 jclass type = field->type;
1920 jint field_offset = field->u.boffset;
1922 jobject obj = POPA();
1923 NULLCHECK(obj);
1925 void *newinsn = NULL;
1926 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1927 if (type->isPrimitive ())
1929 switch (type->size_in_bytes)
1931 case 1:
1932 PUSHI (val->byte_value);
1933 newinsn = AMPAMP (getfield_resolved_1);
1934 break;
1936 case 2:
1937 if (type == JvPrimClass (char))
1939 PUSHI (val->char_value);
1940 newinsn = AMPAMP (getfield_resolved_char);
1942 else
1944 PUSHI (val->short_value);
1945 newinsn = AMPAMP (getfield_resolved_short);
1947 break;
1949 case 4:
1950 PUSHI (val->int_value);
1951 newinsn = AMPAMP (getfield_resolved_4);
1952 break;
1954 case 8:
1955 PUSHL (val->long_value);
1956 newinsn = AMPAMP (getfield_resolved_8);
1957 break;
1960 else
1962 PUSHA (val->object_value);
1963 newinsn = AMPAMP (getfield_resolved_obj);
1966 #ifdef DIRECT_THREADED
1967 REWRITE_INSN (newinsn, int_val, field_offset);
1968 #endif /* DIRECT_THREADED */
1970 NEXT_INSN;
1972 #ifdef DIRECT_THREADED
1973 getfield_resolved_1:
1975 char *obj = (char *) POPA ();
1976 NULLCHECK (obj);
1977 PUSHI (*(jbyte *) (obj + INTVAL ()));
1979 NEXT_INSN;
1981 getfield_resolved_char:
1983 char *obj = (char *) POPA ();
1984 NULLCHECK (obj);
1985 PUSHI (*(jchar *) (obj + INTVAL ()));
1987 NEXT_INSN;
1989 getfield_resolved_short:
1991 char *obj = (char *) POPA ();
1992 NULLCHECK (obj);
1993 PUSHI (*(jshort *) (obj + INTVAL ()));
1995 NEXT_INSN;
1997 getfield_resolved_4:
1999 char *obj = (char *) POPA ();
2000 NULLCHECK (obj);
2001 PUSHI (*(jint *) (obj + INTVAL ()));
2003 NEXT_INSN;
2005 getfield_resolved_8:
2007 char *obj = (char *) POPA ();
2008 NULLCHECK (obj);
2009 PUSHL (*(jlong *) (obj + INTVAL ()));
2011 NEXT_INSN;
2013 getfield_resolved_obj:
2015 char *obj = (char *) POPA ();
2016 NULLCHECK (obj);
2017 PUSHA (*(jobject *) (obj + INTVAL ()));
2019 NEXT_INSN;
2020 #endif /* DIRECT_THREADED */
2022 insn_putstatic:
2024 SAVE_PC();
2025 jint fieldref_index = GET2U ();
2026 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2027 _Jv_Field *field = pool_data[fieldref_index].field;
2029 jclass type = field->type;
2031 // ResolvePoolEntry cannot check this
2032 if ((field->flags & Modifier::STATIC) == 0)
2033 throw_incompatible_class_change_error
2034 (JvNewStringLatin1 ("field no longer static"));
2036 void *newinsn = NULL;
2037 if (type->isPrimitive ())
2039 switch (type->size_in_bytes)
2041 case 1:
2043 jint value = POPI();
2044 *field->u.byte_addr = value;
2045 newinsn = AMPAMP (putstatic_resolved_1);
2046 break;
2049 case 2:
2051 jint value = POPI();
2052 *field->u.char_addr = value;
2053 newinsn = AMPAMP (putstatic_resolved_2);
2054 break;
2057 case 4:
2059 jint value = POPI();
2060 *field->u.int_addr = value;
2061 newinsn = AMPAMP (putstatic_resolved_4);
2062 break;
2065 case 8:
2067 jlong value = POPL();
2068 *field->u.long_addr = value;
2069 newinsn = AMPAMP (putstatic_resolved_8);
2070 break;
2074 else
2076 jobject value = POPA();
2077 *field->u.object_addr = value;
2078 newinsn = AMPAMP (putstatic_resolved_obj);
2081 #ifdef DIRECT_THREADED
2082 REWRITE_INSN (newinsn, datum, field->u.addr);
2083 #endif /* DIRECT_THREADED */
2085 NEXT_INSN;
2087 #ifdef DIRECT_THREADED
2088 putstatic_resolved_1:
2089 *(jbyte *) AVAL () = POPI ();
2090 NEXT_INSN;
2092 putstatic_resolved_2:
2093 *(jchar *) AVAL () = POPI ();
2094 NEXT_INSN;
2096 putstatic_resolved_4:
2097 *(jint *) AVAL () = POPI ();
2098 NEXT_INSN;
2100 putstatic_resolved_8:
2101 *(jlong *) AVAL () = POPL ();
2102 NEXT_INSN;
2104 putstatic_resolved_obj:
2105 *(jobject *) AVAL () = POPA ();
2106 NEXT_INSN;
2107 #endif /* DIRECT_THREADED */
2109 insn_putfield:
2111 SAVE_PC();
2112 jint fieldref_index = GET2U ();
2113 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2114 _Jv_Field *field = pool_data[fieldref_index].field;
2116 jclass type = field->type;
2118 if ((field->flags & Modifier::STATIC) != 0)
2119 throw_incompatible_class_change_error
2120 (JvNewStringLatin1 ("field is static"));
2122 jint field_offset = field->u.boffset;
2124 void *newinsn = NULL;
2125 if (type->isPrimitive ())
2127 switch (type->size_in_bytes)
2129 case 1:
2131 jint value = POPI();
2132 jobject obj = POPA();
2133 NULLCHECK(obj);
2134 *(jbyte*) ((char*)obj + field_offset) = value;
2135 newinsn = AMPAMP (putfield_resolved_1);
2136 break;
2139 case 2:
2141 jint value = POPI();
2142 jobject obj = POPA();
2143 NULLCHECK(obj);
2144 *(jchar*) ((char*)obj + field_offset) = value;
2145 newinsn = AMPAMP (putfield_resolved_2);
2146 break;
2149 case 4:
2151 jint value = POPI();
2152 jobject obj = POPA();
2153 NULLCHECK(obj);
2154 *(jint*) ((char*)obj + field_offset) = value;
2155 newinsn = AMPAMP (putfield_resolved_4);
2156 break;
2159 case 8:
2161 jlong value = POPL();
2162 jobject obj = POPA();
2163 NULLCHECK(obj);
2164 *(jlong*) ((char*)obj + field_offset) = value;
2165 newinsn = AMPAMP (putfield_resolved_8);
2166 break;
2170 else
2172 jobject value = POPA();
2173 jobject obj = POPA();
2174 NULLCHECK(obj);
2175 *(jobject*) ((char*)obj + field_offset) = value;
2176 newinsn = AMPAMP (putfield_resolved_obj);
2179 #ifdef DIRECT_THREADED
2180 REWRITE_INSN (newinsn, int_val, field_offset);
2181 #endif /* DIRECT_THREADED */
2183 NEXT_INSN;
2185 #ifdef DIRECT_THREADED
2186 putfield_resolved_1:
2188 jint val = POPI ();
2189 char *obj = (char *) POPA ();
2190 NULLCHECK (obj);
2191 *(jbyte *) (obj + INTVAL ()) = val;
2193 NEXT_INSN;
2195 putfield_resolved_2:
2197 jint val = POPI ();
2198 char *obj = (char *) POPA ();
2199 NULLCHECK (obj);
2200 *(jchar *) (obj + INTVAL ()) = val;
2202 NEXT_INSN;
2204 putfield_resolved_4:
2206 jint val = POPI ();
2207 char *obj = (char *) POPA ();
2208 NULLCHECK (obj);
2209 *(jint *) (obj + INTVAL ()) = val;
2211 NEXT_INSN;
2213 putfield_resolved_8:
2215 jlong val = POPL ();
2216 char *obj = (char *) POPA ();
2217 NULLCHECK (obj);
2218 *(jlong *) (obj + INTVAL ()) = val;
2220 NEXT_INSN;
2222 putfield_resolved_obj:
2224 jobject val = POPA ();
2225 char *obj = (char *) POPA ();
2226 NULLCHECK (obj);
2227 *(jobject *) (obj + INTVAL ()) = val;
2229 NEXT_INSN;
2230 #endif /* DIRECT_THREADED */
2232 insn_invokespecial:
2234 SAVE_PC();
2235 int index = GET2U ();
2237 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2238 index)).rmethod;
2240 sp -= rmeth->stack_item_count;
2242 // We don't use NULLCHECK here because we can't rely on that
2243 // working for <init>. So instead we do an explicit test.
2244 if (! sp[0].o)
2246 SAVE_PC();
2247 throw_null_pointer_exception ();
2250 fun = (void (*)()) rmeth->method->ncode;
2252 #ifdef DIRECT_THREADED
2253 // Rewrite instruction so that we use a faster pre-resolved
2254 // method.
2255 REWRITE_INSN (&&invokespecial_resolved, datum, rmeth);
2256 #endif /* DIRECT_THREADED */
2258 goto perform_invoke;
2260 #ifdef DIRECT_THREADED
2261 invokespecial_resolved:
2263 SAVE_PC();
2264 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2265 sp -= rmeth->stack_item_count;
2266 // We don't use NULLCHECK here because we can't rely on that
2267 // working for <init>. So instead we do an explicit test.
2268 if (! sp[0].o)
2270 throw_null_pointer_exception ();
2272 fun = (void (*)()) rmeth->method->ncode;
2274 goto perform_invoke;
2275 #endif /* DIRECT_THREADED */
2277 insn_invokestatic:
2279 SAVE_PC();
2280 int index = GET2U ();
2282 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2283 index)).rmethod;
2285 sp -= rmeth->stack_item_count;
2287 fun = (void (*)()) rmeth->method->ncode;
2289 #ifdef DIRECT_THREADED
2290 // Rewrite instruction so that we use a faster pre-resolved
2291 // method.
2292 REWRITE_INSN (&&invokestatic_resolved, datum, rmeth);
2293 #endif /* DIRECT_THREADED */
2295 goto perform_invoke;
2297 #ifdef DIRECT_THREADED
2298 invokestatic_resolved:
2300 SAVE_PC();
2301 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2302 sp -= rmeth->stack_item_count;
2303 fun = (void (*)()) rmeth->method->ncode;
2305 goto perform_invoke;
2306 #endif /* DIRECT_THREADED */
2308 insn_invokeinterface:
2310 SAVE_PC();
2311 int index = GET2U ();
2313 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2314 index)).rmethod;
2316 sp -= rmeth->stack_item_count;
2318 jobject rcv = sp[0].o;
2320 NULLCHECK (rcv);
2322 fun = (void (*)())
2323 _Jv_LookupInterfaceMethod (rcv->getClass (),
2324 rmeth->method->name,
2325 rmeth->method->signature);
2327 #ifdef DIRECT_THREADED
2328 // Rewrite instruction so that we use a faster pre-resolved
2329 // method.
2330 REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth);
2331 #else
2332 // Skip dummy bytes.
2333 pc += 2;
2334 #endif /* DIRECT_THREADED */
2336 goto perform_invoke;
2338 #ifdef DIRECT_THREADED
2339 invokeinterface_resolved:
2341 SAVE_PC();
2342 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2343 sp -= rmeth->stack_item_count;
2344 jobject rcv = sp[0].o;
2345 NULLCHECK (rcv);
2346 fun = (void (*)())
2347 _Jv_LookupInterfaceMethod (rcv->getClass (),
2348 rmeth->method->name,
2349 rmeth->method->signature);
2351 goto perform_invoke;
2352 #endif /* DIRECT_THREADED */
2354 insn_new:
2356 SAVE_PC();
2357 int index = GET2U ();
2358 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2359 index)).clazz;
2360 /* VM spec, section 3.11.5 */
2361 if ((klass->getModifiers() & Modifier::ABSTRACT)
2362 || klass->isInterface())
2364 jthrowable t = new java::lang::InstantiationException;
2365 INTERP_REPORT_EXCEPTION (t);
2366 throw t;
2368 jobject res = _Jv_AllocObject (klass);
2369 PUSHA (res);
2371 #ifdef DIRECT_THREADED
2372 REWRITE_INSN (&&new_resolved, datum, klass);
2373 #endif /* DIRECT_THREADED */
2375 NEXT_INSN;
2377 #ifdef DIRECT_THREADED
2378 new_resolved:
2380 jclass klass = (jclass) AVAL ();
2381 jobject res = _Jv_AllocObject (klass);
2382 PUSHA (res);
2384 NEXT_INSN;
2385 #endif /* DIRECT_THREADED */
2387 insn_newarray:
2389 int atype = GET1U ();
2390 int size = POPI();
2391 jobject result = _Jv_NewArray (atype, size);
2392 PUSHA (result);
2394 NEXT_INSN;
2396 insn_anewarray:
2398 SAVE_PC();
2399 int index = GET2U ();
2400 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2401 index)).clazz;
2402 int size = POPI();
2403 jobject result = _Jv_NewObjectArray (size, klass, 0);
2404 PUSHA (result);
2406 #ifdef DIRECT_THREADED
2407 REWRITE_INSN (&&anewarray_resolved, datum, klass);
2408 #endif /* DIRECT_THREADED */
2410 NEXT_INSN;
2412 #ifdef DIRECT_THREADED
2413 anewarray_resolved:
2415 jclass klass = (jclass) AVAL ();
2416 int size = POPI ();
2417 jobject result = _Jv_NewObjectArray (size, klass, 0);
2418 PUSHA (result);
2420 NEXT_INSN;
2421 #endif /* DIRECT_THREADED */
2423 insn_arraylength:
2425 __JArray *arr = (__JArray*)POPA();
2426 NULLARRAYCHECK (arr);
2427 PUSHI (arr->length);
2429 NEXT_INSN;
2431 insn_athrow:
2433 jobject value = POPA();
2434 jthrowable t = static_cast<jthrowable> (value);
2435 INTERP_REPORT_EXCEPTION (t);
2436 throw t;
2438 NEXT_INSN;
2440 insn_checkcast:
2442 SAVE_PC();
2443 jobject value = POPA();
2444 jint index = GET2U ();
2445 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2446 index)).clazz;
2448 value = (jobject) _Jv_CheckCast (to, value);
2450 PUSHA (value);
2452 #ifdef DIRECT_THREADED
2453 REWRITE_INSN (&&checkcast_resolved, datum, to);
2454 #endif /* DIRECT_THREADED */
2456 NEXT_INSN;
2458 #ifdef DIRECT_THREADED
2459 checkcast_resolved:
2461 SAVE_PC();
2462 jobject value = POPA ();
2463 jclass to = (jclass) AVAL ();
2464 value = (jobject) _Jv_CheckCast (to, value);
2465 PUSHA (value);
2467 NEXT_INSN;
2468 #endif /* DIRECT_THREADED */
2470 insn_instanceof:
2472 SAVE_PC();
2473 jobject value = POPA();
2474 jint index = GET2U ();
2475 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2476 index)).clazz;
2477 PUSHI (to->isInstance (value));
2479 #ifdef DIRECT_THREADED
2480 REWRITE_INSN (&&instanceof_resolved, datum, to);
2481 #endif /* DIRECT_THREADED */
2483 NEXT_INSN;
2485 #ifdef DIRECT_THREADED
2486 instanceof_resolved:
2488 jobject value = POPA ();
2489 jclass to = (jclass) AVAL ();
2490 PUSHI (to->isInstance (value));
2492 NEXT_INSN;
2493 #endif /* DIRECT_THREADED */
2495 insn_monitorenter:
2497 jobject value = POPA();
2498 NULLCHECK(value);
2499 _Jv_MonitorEnter (value);
2501 NEXT_INSN;
2503 insn_monitorexit:
2505 jobject value = POPA();
2506 NULLCHECK(value);
2507 _Jv_MonitorExit (value);
2509 NEXT_INSN;
2511 insn_ifnull:
2513 jobject val = POPA();
2514 if (val == NULL)
2515 TAKE_GOTO;
2516 else
2517 SKIP_GOTO;
2519 NEXT_INSN;
2521 insn_ifnonnull:
2523 jobject val = POPA();
2524 if (val != NULL)
2525 TAKE_GOTO;
2526 else
2527 SKIP_GOTO;
2529 NEXT_INSN;
2531 insn_multianewarray:
2533 SAVE_PC();
2534 int kind_index = GET2U ();
2535 int dim = GET1U ();
2537 jclass type
2538 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2539 kind_index)).clazz;
2540 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2542 for (int i = dim - 1; i >= 0; i--)
2544 sizes[i] = POPI ();
2547 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2549 PUSHA (res);
2551 NEXT_INSN;
2553 #ifndef DIRECT_THREADED
2554 insn_wide:
2556 jint the_mod_op = get1u (pc++);
2557 jint wide = get2u (pc); pc += 2;
2559 switch (the_mod_op)
2561 case op_istore:
2562 STOREI (wide);
2563 NEXT_INSN;
2565 case op_fstore:
2566 STOREF (wide);
2567 NEXT_INSN;
2569 case op_astore:
2570 STOREA (wide);
2571 NEXT_INSN;
2573 case op_lload:
2574 LOADL (wide);
2575 NEXT_INSN;
2577 case op_dload:
2578 LOADD (wide);
2579 NEXT_INSN;
2581 case op_iload:
2582 LOADI (wide);
2583 NEXT_INSN;
2585 case op_fload:
2586 LOADF (wide);
2587 NEXT_INSN;
2589 case op_aload:
2590 LOADA (wide);
2591 NEXT_INSN;
2593 case op_lstore:
2594 STOREL (wide);
2595 NEXT_INSN;
2597 case op_dstore:
2598 STORED (wide);
2599 NEXT_INSN;
2601 case op_ret:
2602 pc = (unsigned char*) PEEKA (wide);
2603 NEXT_INSN;
2605 case op_iinc:
2607 jint amount = get2s (pc); pc += 2;
2608 jint value = PEEKI (wide);
2609 POKEI (wide, value+amount);
2611 NEXT_INSN;
2613 default:
2614 throw_internal_error ("illegal bytecode modified by wide");
2618 #endif /* DIRECT_THREADED */
2620 insn_breakpoint:
2622 using namespace ::java::lang;
2623 jmethodID method = meth->self;
2624 jlocation location = meth->insn_index (pc - 1);
2626 using namespace gnu::gcj::jvmti;
2627 Breakpoint *bp
2628 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2629 location);
2630 JvAssert (bp != NULL);
2632 // Save the insn here since the breakpoint could be removed
2633 // before the JVMTI notification returns.
2634 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2636 bp->execute ();
2638 // Continue execution
2639 #ifdef DIRECT_THREADED
2640 goto *(opc->insn);
2641 #else
2642 goto *(insn_target[*opc]);
2643 #endif
2646 catch (java::lang::Throwable *ex)
2648 // Check if the exception is handled and, if so, set the pc to the start
2649 // of the appropriate catch block.
2650 if (meth->check_handler (&pc, meth, ex))
2652 sp = stack;
2653 sp++->o = ex; // Push exception.
2654 #ifdef DEBUG
2655 if (JVMTI_REQUESTED_EVENT (ExceptionCatch))
2657 using namespace gnu::gcj::jvmti;
2658 jlong catch_meth = reinterpret_cast<jlong> (meth->get_method ());
2659 jlong catch_loc = meth->insn_index (pc);
2660 _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH, thread,
2661 _Jv_GetCurrentJNIEnv (), catch_meth,
2662 catch_loc, ex);
2664 #endif
2665 NEXT_INSN;
2668 // No handler, so re-throw.
2669 throw ex;