PR fortran/40539 Document LOGICAL representation
[official-gcc.git] / libjava / interpret-run.cc
bloba4c2d4dab43b614543070e7739661d1cfa21a54c
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 __GCJ_DEBUG
27 _Jv_InterpFrame frame_desc (meth, thread, NULL, &pc);
28 #else
29 _Jv_InterpFrame frame_desc (meth, thread);
30 #endif
32 #ifdef DIRECT_THREADED
33 ThreadCountAdjuster adj (meth, &frame_desc);
34 #endif // DIRECT_THREADED
36 _Jv_word stack[meth->max_stack];
37 _Jv_word *sp = stack;
39 _Jv_word locals[meth->max_locals];
41 #ifdef __GCJ_DEBUG
42 // This is the information needed to get and set local variables with
43 // proper type checking.
44 frame_desc.locals = locals;
45 char locals_type[meth->max_locals];
46 frame_desc.locals_type = locals_type;
48 // Set all slots as invalid until they are written to.
49 memset (locals_type, 'x', meth->max_locals);
51 // We need to set the local variable types for the method arguments since
52 // they are valid at invocation.
54 _Jv_Method *method = meth->get_method ();
55 int type_ctr = 0;
57 // If the method is non-static, we need to set the type for the "this" pointer.
58 if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
60 if (args)
62 // Set the "this" pointer for this frame.
63 _Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args);
64 frame_desc.obj_ptr = this_ptr[0].o;
67 frame_desc.locals_type[0] = 'o';
68 type_ctr++;
71 // Now parse the method signature to set the types of the other arguments.
72 int sig_len = method->signature->len ();
73 char *signature = method->signature->chars ();
74 for (int i = 1; signature[i] != ')' && i <= sig_len; i++)
76 if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C'
77 || signature[i] == 'S' || signature[i] == 'I')
79 frame_desc.locals_type[type_ctr] = 'i';
80 type_ctr++;
81 continue;
83 else if (signature[i] == 'F')
85 frame_desc.locals_type[type_ctr] = 'f';
86 type_ctr++;
87 continue;
89 else if (signature[i] == 'J')
91 frame_desc.locals_type[type_ctr] = 'l';
92 frame_desc.locals_type[type_ctr+1] = 'x';
93 type_ctr += 2;
94 continue;
96 else if (signature[i] == 'D')
98 frame_desc.locals_type[type_ctr] = 'd';
99 frame_desc.locals_type[type_ctr+1] = 'x';
100 type_ctr += 2;
101 continue;
103 else if (signature[i] == 'L')
105 frame_desc.locals_type[type_ctr] = 'o';
106 type_ctr++;
107 while (signature[i] != ';')
108 i++;
109 continue;
111 else if (signature[i] == '[')
113 frame_desc.locals_type[type_ctr] = 'o';
114 type_ctr++;
116 // Ignore multi-dimensional arrays.
117 while (signature[i] == '[')
118 i++;
120 // Check for an object array
121 if (signature[i] == 'L')
123 while (signature[i] != ';')
124 i++;
126 continue;
129 #endif /* __GCJ_DEBUG */
131 #define INSN_LABEL(op) &&insn_##op
133 static const void *const insn_target[] =
135 INSN_LABEL(nop),
136 INSN_LABEL(aconst_null),
137 INSN_LABEL(iconst_m1),
138 INSN_LABEL(iconst_0),
139 INSN_LABEL(iconst_1),
140 INSN_LABEL(iconst_2),
141 INSN_LABEL(iconst_3),
142 INSN_LABEL(iconst_4),
143 INSN_LABEL(iconst_5),
144 INSN_LABEL(lconst_0),
145 INSN_LABEL(lconst_1),
146 INSN_LABEL(fconst_0),
147 INSN_LABEL(fconst_1),
148 INSN_LABEL(fconst_2),
149 INSN_LABEL(dconst_0),
150 INSN_LABEL(dconst_1),
151 INSN_LABEL(bipush),
152 INSN_LABEL(sipush),
153 INSN_LABEL(ldc),
154 INSN_LABEL(ldc_w),
155 INSN_LABEL(ldc2_w),
156 INSN_LABEL(iload),
157 INSN_LABEL(lload),
158 INSN_LABEL(fload),
159 INSN_LABEL(dload),
160 INSN_LABEL(aload),
161 INSN_LABEL(iload_0),
162 INSN_LABEL(iload_1),
163 INSN_LABEL(iload_2),
164 INSN_LABEL(iload_3),
165 INSN_LABEL(lload_0),
166 INSN_LABEL(lload_1),
167 INSN_LABEL(lload_2),
168 INSN_LABEL(lload_3),
169 INSN_LABEL(fload_0),
170 INSN_LABEL(fload_1),
171 INSN_LABEL(fload_2),
172 INSN_LABEL(fload_3),
173 INSN_LABEL(dload_0),
174 INSN_LABEL(dload_1),
175 INSN_LABEL(dload_2),
176 INSN_LABEL(dload_3),
177 INSN_LABEL(aload_0),
178 INSN_LABEL(aload_1),
179 INSN_LABEL(aload_2),
180 INSN_LABEL(aload_3),
181 INSN_LABEL(iaload),
182 INSN_LABEL(laload),
183 INSN_LABEL(faload),
184 INSN_LABEL(daload),
185 INSN_LABEL(aaload),
186 INSN_LABEL(baload),
187 INSN_LABEL(caload),
188 INSN_LABEL(saload),
189 INSN_LABEL(istore),
190 INSN_LABEL(lstore),
191 INSN_LABEL(fstore),
192 INSN_LABEL(dstore),
193 INSN_LABEL(astore),
194 INSN_LABEL(istore_0),
195 INSN_LABEL(istore_1),
196 INSN_LABEL(istore_2),
197 INSN_LABEL(istore_3),
198 INSN_LABEL(lstore_0),
199 INSN_LABEL(lstore_1),
200 INSN_LABEL(lstore_2),
201 INSN_LABEL(lstore_3),
202 INSN_LABEL(fstore_0),
203 INSN_LABEL(fstore_1),
204 INSN_LABEL(fstore_2),
205 INSN_LABEL(fstore_3),
206 INSN_LABEL(dstore_0),
207 INSN_LABEL(dstore_1),
208 INSN_LABEL(dstore_2),
209 INSN_LABEL(dstore_3),
210 INSN_LABEL(astore_0),
211 INSN_LABEL(astore_1),
212 INSN_LABEL(astore_2),
213 INSN_LABEL(astore_3),
214 INSN_LABEL(iastore),
215 INSN_LABEL(lastore),
216 INSN_LABEL(fastore),
217 INSN_LABEL(dastore),
218 INSN_LABEL(aastore),
219 INSN_LABEL(bastore),
220 INSN_LABEL(castore),
221 INSN_LABEL(sastore),
222 INSN_LABEL(pop),
223 INSN_LABEL(pop2),
224 INSN_LABEL(dup),
225 INSN_LABEL(dup_x1),
226 INSN_LABEL(dup_x2),
227 INSN_LABEL(dup2),
228 INSN_LABEL(dup2_x1),
229 INSN_LABEL(dup2_x2),
230 INSN_LABEL(swap),
231 INSN_LABEL(iadd),
232 INSN_LABEL(ladd),
233 INSN_LABEL(fadd),
234 INSN_LABEL(dadd),
235 INSN_LABEL(isub),
236 INSN_LABEL(lsub),
237 INSN_LABEL(fsub),
238 INSN_LABEL(dsub),
239 INSN_LABEL(imul),
240 INSN_LABEL(lmul),
241 INSN_LABEL(fmul),
242 INSN_LABEL(dmul),
243 INSN_LABEL(idiv),
244 INSN_LABEL(ldiv),
245 INSN_LABEL(fdiv),
246 INSN_LABEL(ddiv),
247 INSN_LABEL(irem),
248 INSN_LABEL(lrem),
249 INSN_LABEL(frem),
250 INSN_LABEL(drem),
251 INSN_LABEL(ineg),
252 INSN_LABEL(lneg),
253 INSN_LABEL(fneg),
254 INSN_LABEL(dneg),
255 INSN_LABEL(ishl),
256 INSN_LABEL(lshl),
257 INSN_LABEL(ishr),
258 INSN_LABEL(lshr),
259 INSN_LABEL(iushr),
260 INSN_LABEL(lushr),
261 INSN_LABEL(iand),
262 INSN_LABEL(land),
263 INSN_LABEL(ior),
264 INSN_LABEL(lor),
265 INSN_LABEL(ixor),
266 INSN_LABEL(lxor),
267 INSN_LABEL(iinc),
268 INSN_LABEL(i2l),
269 INSN_LABEL(i2f),
270 INSN_LABEL(i2d),
271 INSN_LABEL(l2i),
272 INSN_LABEL(l2f),
273 INSN_LABEL(l2d),
274 INSN_LABEL(f2i),
275 INSN_LABEL(f2l),
276 INSN_LABEL(f2d),
277 INSN_LABEL(d2i),
278 INSN_LABEL(d2l),
279 INSN_LABEL(d2f),
280 INSN_LABEL(i2b),
281 INSN_LABEL(i2c),
282 INSN_LABEL(i2s),
283 INSN_LABEL(lcmp),
284 INSN_LABEL(fcmpl),
285 INSN_LABEL(fcmpg),
286 INSN_LABEL(dcmpl),
287 INSN_LABEL(dcmpg),
288 INSN_LABEL(ifeq),
289 INSN_LABEL(ifne),
290 INSN_LABEL(iflt),
291 INSN_LABEL(ifge),
292 INSN_LABEL(ifgt),
293 INSN_LABEL(ifle),
294 INSN_LABEL(if_icmpeq),
295 INSN_LABEL(if_icmpne),
296 INSN_LABEL(if_icmplt),
297 INSN_LABEL(if_icmpge),
298 INSN_LABEL(if_icmpgt),
299 INSN_LABEL(if_icmple),
300 INSN_LABEL(if_acmpeq),
301 INSN_LABEL(if_acmpne),
302 INSN_LABEL(goto),
303 INSN_LABEL(jsr),
304 INSN_LABEL(ret),
305 INSN_LABEL(tableswitch),
306 INSN_LABEL(lookupswitch),
307 INSN_LABEL(ireturn),
308 INSN_LABEL(lreturn),
309 INSN_LABEL(freturn),
310 INSN_LABEL(dreturn),
311 INSN_LABEL(areturn),
312 INSN_LABEL(return),
313 INSN_LABEL(getstatic),
314 INSN_LABEL(putstatic),
315 INSN_LABEL(getfield),
316 INSN_LABEL(putfield),
317 INSN_LABEL(invokevirtual),
318 INSN_LABEL(invokespecial),
319 INSN_LABEL(invokestatic),
320 INSN_LABEL(invokeinterface),
321 INSN_LABEL(breakpoint),
322 INSN_LABEL(new),
323 INSN_LABEL(newarray),
324 INSN_LABEL(anewarray),
325 INSN_LABEL(arraylength),
326 INSN_LABEL(athrow),
327 INSN_LABEL(checkcast),
328 INSN_LABEL(instanceof),
329 INSN_LABEL(monitorenter),
330 INSN_LABEL(monitorexit),
331 #ifdef DIRECT_THREADED
332 0, // wide
333 #else
334 INSN_LABEL(wide),
335 #endif
336 INSN_LABEL(multianewarray),
337 INSN_LABEL(ifnull),
338 INSN_LABEL(ifnonnull),
339 INSN_LABEL(goto_w),
340 INSN_LABEL(jsr_w),
341 #ifdef DIRECT_THREADED
342 INSN_LABEL (ldc_class)
343 #else
345 #endif
348 #ifdef DIRECT_THREADED
350 #ifdef __GCJ_DEBUG
351 #undef NEXT_INSN
352 #define NEXT_INSN \
353 do \
355 pc_t insn = pc++; \
356 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
358 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
359 jmethodID method = meth->self; \
360 jlocation loc = meth->insn_index (insn); \
361 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
362 env, method, loc); \
364 goto *(insn->insn); \
366 while (0)
368 // We fail to rewrite a breakpoint if there is another thread
369 // currently executing this method. This is a bug, but there's
370 // nothing else we can do that doesn't cause a data race.
371 #undef REWRITE_INSN
372 #define REWRITE_INSN(INSN,SLOT,VALUE) \
373 do \
375 _Jv_MutexLock (&rewrite_insn_mutex); \
376 if (meth->thread_count <= 1) \
378 if (pc[-2].insn == breakpoint_insn->insn) \
380 using namespace ::gnu::gcj::jvmti; \
381 jlocation location = meth->insn_index (pc - 2); \
382 _Jv_RewriteBreakpointInsn (meth->self, location, (pc_t) INSN); \
384 else \
385 pc[-2].insn = INSN; \
387 pc[-1].SLOT = VALUE; \
389 _Jv_MutexUnlock (&rewrite_insn_mutex); \
391 while (0)
393 #undef INTERP_REPORT_EXCEPTION
394 #define INTERP_REPORT_EXCEPTION(Jthrowable) REPORT_EXCEPTION (Jthrowable)
395 #else // !__GCJ_DEBUG
396 #undef NEXT_INSN
397 #define NEXT_INSN goto *((pc++)->insn)
399 // Rewriting a multi-word instruction in the presence of multiple
400 // threads is a data race if a thread reads part of an instruction
401 // while some other thread is rewriting that instruction. We detect
402 // more than one thread executing a method and don't rewrite the
403 // instruction. A thread entering a method blocks on
404 // rewrite_insn_mutex until the write is complete.
405 #define REWRITE_INSN(INSN,SLOT,VALUE) \
406 do { \
407 _Jv_MutexLock (&rewrite_insn_mutex); \
408 if (meth->thread_count <= 1) \
410 pc[-2].insn = INSN; \
411 pc[-1].SLOT = VALUE; \
413 _Jv_MutexUnlock (&rewrite_insn_mutex); \
415 while (0)
417 #undef INTERP_REPORT_EXCEPTION
418 #define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */
419 #endif // !__GCJ_DEBUG
421 #define INTVAL() ((pc++)->int_val)
422 #define AVAL() ((pc++)->datum)
424 #define GET1S() INTVAL ()
425 #define GET2S() INTVAL ()
426 #define GET1U() INTVAL ()
427 #define GET2U() INTVAL ()
428 #define AVAL1U() AVAL ()
429 #define AVAL2U() AVAL ()
430 #define AVAL2UP() AVAL ()
431 #define SKIP_GOTO ++pc
432 #define GOTO_VAL() (insn_slot *) pc->datum
433 #define PCVAL(unionval) unionval.p
434 #define AMPAMP(label) &&label
436 // Compile if we must. NOTE: Double-check locking.
437 if (meth->prepared == NULL)
439 _Jv_MutexLock (&compile_mutex);
440 if (meth->prepared == NULL)
441 meth->compile (insn_target);
442 _Jv_MutexUnlock (&compile_mutex);
445 // If we're only compiling, stop here
446 if (args == NULL)
447 return;
449 pc = (insn_slot *) meth->prepared;
451 #else
453 #ifdef __GCJ_DEBUG
454 #define NEXT_INSN \
455 do \
457 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
459 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
460 jmethodID method = meth->self; \
461 jlocation loc = meth->insn_index (pc); \
462 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
463 env, method, loc); \
465 goto *(insn_target[*pc++])
466 #else
467 #define NEXT_INSN goto *(insn_target[*pc++])
468 #endif
470 #define GET1S() get1s (pc++)
471 #define GET2S() (pc += 2, get2s (pc- 2))
472 #define GET1U() get1u (pc++)
473 #define GET2U() (pc += 2, get2u (pc - 2))
474 // Note that these could be more efficient when not handling 'ldc
475 // class'.
476 #define AVAL1U() \
477 ({ int index = get1u (pc++); \
478 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
479 #define AVAL2U() \
480 ({ int index = get2u (pc); pc += 2; \
481 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
482 // Note that we don't need to resolve the pool entry here as class
483 // constants are never wide.
484 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
485 #define SKIP_GOTO pc += 2
486 #define GOTO_VAL() pc - 1 + get2s (pc)
487 #define PCVAL(unionval) unionval.i
488 #define AMPAMP(label) NULL
490 pc = meth->bytecode ();
492 #endif /* DIRECT_THREADED */
494 #define TAKE_GOTO pc = GOTO_VAL ()
496 /* Go straight at it! the ffi raw format matches the internal
497 stack representation exactly. At least, that's the idea.
499 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
501 _Jv_word *pool_data = meth->defining_class->constants.data;
503 /* These three are temporaries for common code used by several
504 instructions. */
505 void (*fun)();
506 _Jv_ResolvedMethod* rmeth;
507 int tmpval;
511 // We keep nop around. It is used if we're interpreting the
512 // bytecodes and not doing direct threading.
513 insn_nop:
514 NEXT_INSN;
516 /* The first few instructions here are ordered according to their
517 frequency, in the hope that this will improve code locality a
518 little. */
520 insn_aload_0: // 0x2a
521 LOADA (0);
522 NEXT_INSN;
524 insn_iload: // 0x15
525 LOADI (GET1U ());
526 NEXT_INSN;
528 insn_iload_1: // 0x1b
529 LOADI (1);
530 NEXT_INSN;
532 insn_invokevirtual: // 0xb6
534 SAVE_PC();
535 int index = GET2U ();
537 /* _Jv_Linker::resolve_pool_entry returns immediately if the
538 * value already is resolved. If we want to clutter up the
539 * code here to gain a little performance, then we can check
540 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
541 * directly. For now, I don't think it is worth it. */
543 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
544 index)).rmethod;
546 sp -= rmeth->stack_item_count;
548 if (rmeth->method->accflags & Modifier::FINAL)
550 // We can't rely on NULLCHECK working if the method is final.
551 if (! sp[0].o)
552 throw_null_pointer_exception ();
554 // Final methods might not appear in the vtable.
555 fun = (void (*)()) rmeth->method->ncode;
557 else
559 NULLCHECK (sp[0].o);
560 jobject rcv = sp[0].o;
561 _Jv_VTable *table = *(_Jv_VTable**) rcv;
562 fun = (void (*)()) table->get_method (rmeth->method->index);
565 #ifdef DIRECT_THREADED
566 // Rewrite instruction so that we use a faster pre-resolved
567 // method.
568 REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth);
569 #endif /* DIRECT_THREADED */
571 goto perform_invoke;
573 #ifdef DIRECT_THREADED
574 invokevirtual_resolved:
576 SAVE_PC();
577 rmeth = (_Jv_ResolvedMethod *) AVAL ();
578 sp -= rmeth->stack_item_count;
580 if (rmeth->method->accflags & Modifier::FINAL)
582 // We can't rely on NULLCHECK working if the method is final.
583 if (! sp[0].o)
584 throw_null_pointer_exception ();
586 // Final methods might not appear in the vtable.
587 fun = (void (*)()) rmeth->method->ncode;
589 else
591 NULLCHECK (sp[0].o);
592 jobject rcv = sp[0].o;
593 _Jv_VTable *table = *(_Jv_VTable**) rcv;
594 fun = (void (*)()) table->get_method (rmeth->method->index);
597 goto perform_invoke;
598 #endif /* DIRECT_THREADED */
600 perform_invoke:
602 /* here goes the magic again... */
603 ffi_cif *cif = &rmeth->cif;
604 INTERP_FFI_RAW_TYPE *raw = (INTERP_FFI_RAW_TYPE *) sp;
606 _Jv_value rvalue;
608 #if FFI_NATIVE_RAW_API
609 /* We assume that this is only implemented if it's correct */
610 /* to use it here. On a 64 bit machine, it never is. */
611 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
612 #else
613 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
614 #endif
616 int rtype = cif->rtype->type;
618 /* the likelyhood of object, int, or void return is very high,
619 * so those are checked before the switch */
620 if (rtype == FFI_TYPE_POINTER)
622 PUSHA (rvalue.object_value);
624 else if (rtype == FFI_TYPE_SINT32)
626 PUSHI (rvalue.int_value);
628 else if (rtype == FFI_TYPE_VOID)
630 /* skip */
632 else
634 switch (rtype)
636 case FFI_TYPE_SINT8:
637 PUSHI ((jbyte)(rvalue.int_value & 0xff));
638 break;
640 case FFI_TYPE_SINT16:
641 PUSHI ((jshort)(rvalue.int_value & 0xffff));
642 break;
644 case FFI_TYPE_UINT16:
645 PUSHI (rvalue.int_value & 0xffff);
646 break;
648 case FFI_TYPE_FLOAT:
649 PUSHF (rvalue.float_value);
650 break;
652 case FFI_TYPE_DOUBLE:
653 PUSHD (rvalue.double_value);
654 break;
656 case FFI_TYPE_SINT64:
657 PUSHL (rvalue.long_value);
658 break;
660 default:
661 throw_internal_error ("unknown return type in invokeXXX");
665 NEXT_INSN;
667 insn_aconst_null:
668 PUSHA (NULL);
669 NEXT_INSN;
671 insn_iconst_m1:
672 PUSHI (-1);
673 NEXT_INSN;
675 insn_iconst_0:
676 PUSHI (0);
677 NEXT_INSN;
679 insn_iconst_1:
680 PUSHI (1);
681 NEXT_INSN;
683 insn_iconst_2:
684 PUSHI (2);
685 NEXT_INSN;
687 insn_iconst_3:
688 PUSHI (3);
689 NEXT_INSN;
691 insn_iconst_4:
692 PUSHI (4);
693 NEXT_INSN;
695 insn_iconst_5:
696 PUSHI (5);
697 NEXT_INSN;
699 insn_lconst_0:
700 PUSHL (0);
701 NEXT_INSN;
703 insn_lconst_1:
704 PUSHL (1);
705 NEXT_INSN;
707 insn_fconst_0:
708 PUSHF (0);
709 NEXT_INSN;
711 insn_fconst_1:
712 PUSHF (1);
713 NEXT_INSN;
715 insn_fconst_2:
716 PUSHF (2);
717 NEXT_INSN;
719 insn_dconst_0:
720 PUSHD (0);
721 NEXT_INSN;
723 insn_dconst_1:
724 PUSHD (1);
725 NEXT_INSN;
727 insn_bipush:
728 // For direct threaded, bipush and sipush are the same.
729 #ifndef DIRECT_THREADED
730 PUSHI (GET1S ());
731 NEXT_INSN;
732 #endif /* DIRECT_THREADED */
733 insn_sipush:
734 PUSHI (GET2S ());
735 NEXT_INSN;
737 insn_ldc:
738 // For direct threaded, ldc and ldc_w are the same.
739 #ifndef DIRECT_THREADED
740 PUSHA ((jobject) AVAL1U ());
741 NEXT_INSN;
742 #endif /* DIRECT_THREADED */
743 insn_ldc_w:
744 PUSHA ((jobject) AVAL2U ());
745 NEXT_INSN;
747 #ifdef DIRECT_THREADED
748 // For direct threaded we have a separate 'ldc class' operation.
749 insn_ldc_class:
751 SAVE_PC();
752 // We could rewrite the instruction at this point.
753 int index = INTVAL ();
754 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
755 index)).o;
756 PUSHA (k);
758 NEXT_INSN;
759 #endif /* DIRECT_THREADED */
761 insn_ldc2_w:
763 void *where = AVAL2UP ();
764 memcpy (sp, where, 2*sizeof (_Jv_word));
765 sp += 2;
767 NEXT_INSN;
769 insn_lload:
770 LOADL (GET1U ());
771 NEXT_INSN;
773 insn_fload:
774 LOADF (GET1U ());
775 NEXT_INSN;
777 insn_dload:
778 LOADD (GET1U ());
779 NEXT_INSN;
781 insn_aload:
782 LOADA (GET1U ());
783 NEXT_INSN;
785 insn_iload_0:
786 LOADI (0);
787 NEXT_INSN;
789 insn_iload_2:
790 LOADI (2);
791 NEXT_INSN;
793 insn_iload_3:
794 LOADI (3);
795 NEXT_INSN;
797 insn_lload_0:
798 LOADL (0);
799 NEXT_INSN;
801 insn_lload_1:
802 LOADL (1);
803 NEXT_INSN;
805 insn_lload_2:
806 LOADL (2);
807 NEXT_INSN;
809 insn_lload_3:
810 LOADL (3);
811 NEXT_INSN;
813 insn_fload_0:
814 LOADF (0);
815 NEXT_INSN;
817 insn_fload_1:
818 LOADF (1);
819 NEXT_INSN;
821 insn_fload_2:
822 LOADF (2);
823 NEXT_INSN;
825 insn_fload_3:
826 LOADF (3);
827 NEXT_INSN;
829 insn_dload_0:
830 LOADD (0);
831 NEXT_INSN;
833 insn_dload_1:
834 LOADD (1);
835 NEXT_INSN;
837 insn_dload_2:
838 LOADD (2);
839 NEXT_INSN;
841 insn_dload_3:
842 LOADD (3);
843 NEXT_INSN;
845 insn_aload_1:
846 LOADA(1);
847 NEXT_INSN;
849 insn_aload_2:
850 LOADA(2);
851 NEXT_INSN;
853 insn_aload_3:
854 LOADA(3);
855 NEXT_INSN;
857 insn_iaload:
859 jint index = POPI();
860 jintArray arr = (jintArray) POPA();
861 NULLARRAYCHECK (arr);
862 ARRAYBOUNDSCHECK (arr, index);
863 PUSHI( elements(arr)[index] );
865 NEXT_INSN;
867 insn_laload:
869 jint index = POPI();
870 jlongArray arr = (jlongArray) POPA();
871 NULLARRAYCHECK (arr);
872 ARRAYBOUNDSCHECK (arr, index);
873 PUSHL( elements(arr)[index] );
875 NEXT_INSN;
877 insn_faload:
879 jint index = POPI();
880 jfloatArray arr = (jfloatArray) POPA();
881 NULLARRAYCHECK (arr);
882 ARRAYBOUNDSCHECK (arr, index);
883 PUSHF( elements(arr)[index] );
885 NEXT_INSN;
887 insn_daload:
889 jint index = POPI();
890 jdoubleArray arr = (jdoubleArray) POPA();
891 NULLARRAYCHECK (arr);
892 ARRAYBOUNDSCHECK (arr, index);
893 PUSHD( elements(arr)[index] );
895 NEXT_INSN;
897 insn_aaload:
899 jint index = POPI();
900 jobjectArray arr = (jobjectArray) POPA();
901 NULLARRAYCHECK (arr);
902 ARRAYBOUNDSCHECK (arr, index);
903 PUSHA( elements(arr)[index] );
905 NEXT_INSN;
907 insn_baload:
909 jint index = POPI();
910 jbyteArray arr = (jbyteArray) POPA();
911 NULLARRAYCHECK (arr);
912 ARRAYBOUNDSCHECK (arr, index);
913 PUSHI( elements(arr)[index] );
915 NEXT_INSN;
917 insn_caload:
919 jint index = POPI();
920 jcharArray arr = (jcharArray) POPA();
921 NULLARRAYCHECK (arr);
922 ARRAYBOUNDSCHECK (arr, index);
923 PUSHI( elements(arr)[index] );
925 NEXT_INSN;
927 insn_saload:
929 jint index = POPI();
930 jshortArray arr = (jshortArray) POPA();
931 NULLARRAYCHECK (arr);
932 ARRAYBOUNDSCHECK (arr, index);
933 PUSHI( elements(arr)[index] );
935 NEXT_INSN;
937 insn_istore:
938 STOREI (GET1U ());
939 NEXT_INSN;
941 insn_lstore:
942 STOREL (GET1U ());
943 NEXT_INSN;
945 insn_fstore:
946 STOREF (GET1U ());
947 NEXT_INSN;
949 insn_dstore:
950 STORED (GET1U ());
951 NEXT_INSN;
953 insn_astore:
954 STOREA (GET1U ());
955 NEXT_INSN;
957 insn_istore_0:
958 STOREI (0);
959 NEXT_INSN;
961 insn_istore_1:
962 STOREI (1);
963 NEXT_INSN;
965 insn_istore_2:
966 STOREI (2);
967 NEXT_INSN;
969 insn_istore_3:
970 STOREI (3);
971 NEXT_INSN;
973 insn_lstore_0:
974 STOREL (0);
975 NEXT_INSN;
977 insn_lstore_1:
978 STOREL (1);
979 NEXT_INSN;
981 insn_lstore_2:
982 STOREL (2);
983 NEXT_INSN;
985 insn_lstore_3:
986 STOREL (3);
987 NEXT_INSN;
989 insn_fstore_0:
990 STOREF (0);
991 NEXT_INSN;
993 insn_fstore_1:
994 STOREF (1);
995 NEXT_INSN;
997 insn_fstore_2:
998 STOREF (2);
999 NEXT_INSN;
1001 insn_fstore_3:
1002 STOREF (3);
1003 NEXT_INSN;
1005 insn_dstore_0:
1006 STORED (0);
1007 NEXT_INSN;
1009 insn_dstore_1:
1010 STORED (1);
1011 NEXT_INSN;
1013 insn_dstore_2:
1014 STORED (2);
1015 NEXT_INSN;
1017 insn_dstore_3:
1018 STORED (3);
1019 NEXT_INSN;
1021 insn_astore_0:
1022 STOREA(0);
1023 NEXT_INSN;
1025 insn_astore_1:
1026 STOREA(1);
1027 NEXT_INSN;
1029 insn_astore_2:
1030 STOREA(2);
1031 NEXT_INSN;
1033 insn_astore_3:
1034 STOREA(3);
1035 NEXT_INSN;
1037 insn_iastore:
1039 jint value = POPI();
1040 jint index = POPI();
1041 jintArray arr = (jintArray) POPA();
1042 NULLARRAYCHECK (arr);
1043 ARRAYBOUNDSCHECK (arr, index);
1044 elements(arr)[index] = value;
1046 NEXT_INSN;
1048 insn_lastore:
1050 jlong value = POPL();
1051 jint index = POPI();
1052 jlongArray arr = (jlongArray) POPA();
1053 NULLARRAYCHECK (arr);
1054 ARRAYBOUNDSCHECK (arr, index);
1055 elements(arr)[index] = value;
1057 NEXT_INSN;
1059 insn_fastore:
1061 jfloat value = POPF();
1062 jint index = POPI();
1063 jfloatArray arr = (jfloatArray) POPA();
1064 NULLARRAYCHECK (arr);
1065 ARRAYBOUNDSCHECK (arr, index);
1066 elements(arr)[index] = value;
1068 NEXT_INSN;
1070 insn_dastore:
1072 jdouble value = POPD();
1073 jint index = POPI();
1074 jdoubleArray arr = (jdoubleArray) POPA();
1075 NULLARRAYCHECK (arr);
1076 ARRAYBOUNDSCHECK (arr, index);
1077 elements(arr)[index] = value;
1079 NEXT_INSN;
1081 insn_aastore:
1083 jobject value = POPA();
1084 jint index = POPI();
1085 jobjectArray arr = (jobjectArray) POPA();
1086 NULLARRAYCHECK (arr);
1087 ARRAYBOUNDSCHECK (arr, index);
1088 _Jv_CheckArrayStore (arr, value);
1089 elements(arr)[index] = value;
1091 NEXT_INSN;
1093 insn_bastore:
1095 jbyte value = (jbyte) POPI();
1096 jint index = POPI();
1097 jbyteArray arr = (jbyteArray) POPA();
1098 NULLARRAYCHECK (arr);
1099 ARRAYBOUNDSCHECK (arr, index);
1100 elements(arr)[index] = value;
1102 NEXT_INSN;
1104 insn_castore:
1106 jchar value = (jchar) POPI();
1107 jint index = POPI();
1108 jcharArray arr = (jcharArray) POPA();
1109 NULLARRAYCHECK (arr);
1110 ARRAYBOUNDSCHECK (arr, index);
1111 elements(arr)[index] = value;
1113 NEXT_INSN;
1115 insn_sastore:
1117 jshort value = (jshort) POPI();
1118 jint index = POPI();
1119 jshortArray arr = (jshortArray) POPA();
1120 NULLARRAYCHECK (arr);
1121 ARRAYBOUNDSCHECK (arr, index);
1122 elements(arr)[index] = value;
1124 NEXT_INSN;
1126 insn_pop:
1127 sp -= 1;
1128 NEXT_INSN;
1130 insn_pop2:
1131 sp -= 2;
1132 NEXT_INSN;
1134 insn_dup:
1135 sp[0] = sp[-1];
1136 sp += 1;
1137 NEXT_INSN;
1139 insn_dup_x1:
1140 dupx (sp, 1, 1); sp+=1;
1141 NEXT_INSN;
1143 insn_dup_x2:
1144 dupx (sp, 1, 2); sp+=1;
1145 NEXT_INSN;
1147 insn_dup2:
1148 sp[0] = sp[-2];
1149 sp[1] = sp[-1];
1150 sp += 2;
1151 NEXT_INSN;
1153 insn_dup2_x1:
1154 dupx (sp, 2, 1); sp+=2;
1155 NEXT_INSN;
1157 insn_dup2_x2:
1158 dupx (sp, 2, 2); sp+=2;
1159 NEXT_INSN;
1161 insn_swap:
1163 jobject tmp1 = POPA();
1164 jobject tmp2 = POPA();
1165 PUSHA (tmp1);
1166 PUSHA (tmp2);
1168 NEXT_INSN;
1170 insn_iadd:
1171 BINOPI(+);
1172 NEXT_INSN;
1174 insn_ladd:
1175 BINOPL(+);
1176 NEXT_INSN;
1178 insn_fadd:
1179 BINOPF(+);
1180 NEXT_INSN;
1182 insn_dadd:
1183 BINOPD(+);
1184 NEXT_INSN;
1186 insn_isub:
1187 BINOPI(-);
1188 NEXT_INSN;
1190 insn_lsub:
1191 BINOPL(-);
1192 NEXT_INSN;
1194 insn_fsub:
1195 BINOPF(-);
1196 NEXT_INSN;
1198 insn_dsub:
1199 BINOPD(-);
1200 NEXT_INSN;
1202 insn_imul:
1203 BINOPI(*);
1204 NEXT_INSN;
1206 insn_lmul:
1207 BINOPL(*);
1208 NEXT_INSN;
1210 insn_fmul:
1211 BINOPF(*);
1212 NEXT_INSN;
1214 insn_dmul:
1215 BINOPD(*);
1216 NEXT_INSN;
1218 insn_idiv:
1220 SAVE_PC();
1221 jint value2 = POPI();
1222 jint value1 = POPI();
1223 jint res = _Jv_divI (value1, value2);
1224 PUSHI (res);
1226 NEXT_INSN;
1228 insn_ldiv:
1230 SAVE_PC();
1231 jlong value2 = POPL();
1232 jlong value1 = POPL();
1233 jlong res = _Jv_divJ (value1, value2);
1234 PUSHL (res);
1236 NEXT_INSN;
1238 insn_fdiv:
1240 jfloat value2 = POPF();
1241 jfloat value1 = POPF();
1242 jfloat res = value1 / value2;
1243 PUSHF (res);
1245 NEXT_INSN;
1247 insn_ddiv:
1249 jdouble value2 = POPD();
1250 jdouble value1 = POPD();
1251 jdouble res = value1 / value2;
1252 PUSHD (res);
1254 NEXT_INSN;
1256 insn_irem:
1258 SAVE_PC();
1259 jint value2 = POPI();
1260 jint value1 = POPI();
1261 jint res = _Jv_remI (value1, value2);
1262 PUSHI (res);
1264 NEXT_INSN;
1266 insn_lrem:
1268 SAVE_PC();
1269 jlong value2 = POPL();
1270 jlong value1 = POPL();
1271 jlong res = _Jv_remJ (value1, value2);
1272 PUSHL (res);
1274 NEXT_INSN;
1276 insn_frem:
1278 jfloat value2 = POPF();
1279 jfloat value1 = POPF();
1280 jfloat res = __ieee754_fmod (value1, value2);
1281 PUSHF (res);
1283 NEXT_INSN;
1285 insn_drem:
1287 jdouble value2 = POPD();
1288 jdouble value1 = POPD();
1289 jdouble res = __ieee754_fmod (value1, value2);
1290 PUSHD (res);
1292 NEXT_INSN;
1294 insn_ineg:
1296 jint value = POPI();
1297 PUSHI (value * -1);
1299 NEXT_INSN;
1301 insn_lneg:
1303 jlong value = POPL();
1304 PUSHL (value * -1);
1306 NEXT_INSN;
1308 insn_fneg:
1310 jfloat value = POPF();
1311 PUSHF (value * -1);
1313 NEXT_INSN;
1315 insn_dneg:
1317 jdouble value = POPD();
1318 PUSHD (value * -1);
1320 NEXT_INSN;
1322 insn_ishl:
1324 jint shift = (POPI() & 0x1f);
1325 jint value = POPI();
1326 PUSHI (value << shift);
1328 NEXT_INSN;
1330 insn_lshl:
1332 jint shift = (POPI() & 0x3f);
1333 jlong value = POPL();
1334 PUSHL (value << shift);
1336 NEXT_INSN;
1338 insn_ishr:
1340 jint shift = (POPI() & 0x1f);
1341 jint value = POPI();
1342 PUSHI (value >> shift);
1344 NEXT_INSN;
1346 insn_lshr:
1348 jint shift = (POPI() & 0x3f);
1349 jlong value = POPL();
1350 PUSHL (value >> shift);
1352 NEXT_INSN;
1354 insn_iushr:
1356 jint shift = (POPI() & 0x1f);
1357 _Jv_uint value = (_Jv_uint) POPI();
1358 PUSHI ((jint) (value >> shift));
1360 NEXT_INSN;
1362 insn_lushr:
1364 jint shift = (POPI() & 0x3f);
1365 _Jv_ulong value = (_Jv_ulong) POPL();
1366 PUSHL ((jlong) (value >> shift));
1368 NEXT_INSN;
1370 insn_iand:
1371 BINOPI (&);
1372 NEXT_INSN;
1374 insn_land:
1375 BINOPL (&);
1376 NEXT_INSN;
1378 insn_ior:
1379 BINOPI (|);
1380 NEXT_INSN;
1382 insn_lor:
1383 BINOPL (|);
1384 NEXT_INSN;
1386 insn_ixor:
1387 BINOPI (^);
1388 NEXT_INSN;
1390 insn_lxor:
1391 BINOPL (^);
1392 NEXT_INSN;
1394 insn_iinc:
1396 jint index = GET1U ();
1397 jint amount = GET1S ();
1398 locals[index].i += amount;
1400 NEXT_INSN;
1402 insn_i2l:
1403 {jlong value = POPI(); PUSHL (value);}
1404 NEXT_INSN;
1406 insn_i2f:
1407 {jfloat value = POPI(); PUSHF (value);}
1408 NEXT_INSN;
1410 insn_i2d:
1411 {jdouble value = POPI(); PUSHD (value);}
1412 NEXT_INSN;
1414 insn_l2i:
1415 {jint value = POPL(); PUSHI (value);}
1416 NEXT_INSN;
1418 insn_l2f:
1419 {jfloat value = POPL(); PUSHF (value);}
1420 NEXT_INSN;
1422 insn_l2d:
1423 {jdouble value = POPL(); PUSHD (value);}
1424 NEXT_INSN;
1426 insn_f2i:
1428 using namespace java::lang;
1429 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1430 PUSHI(value);
1432 NEXT_INSN;
1434 insn_f2l:
1436 using namespace java::lang;
1437 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1438 PUSHL(value);
1440 NEXT_INSN;
1442 insn_f2d:
1443 { jdouble value = POPF (); PUSHD(value); }
1444 NEXT_INSN;
1446 insn_d2i:
1448 using namespace java::lang;
1449 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1450 PUSHI(value);
1452 NEXT_INSN;
1454 insn_d2l:
1456 using namespace java::lang;
1457 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1458 PUSHL(value);
1460 NEXT_INSN;
1462 insn_d2f:
1463 { jfloat value = POPD (); PUSHF(value); }
1464 NEXT_INSN;
1466 insn_i2b:
1467 { jbyte value = POPI (); PUSHI(value); }
1468 NEXT_INSN;
1470 insn_i2c:
1471 { jchar value = POPI (); PUSHI(value); }
1472 NEXT_INSN;
1474 insn_i2s:
1475 { jshort value = POPI (); PUSHI(value); }
1476 NEXT_INSN;
1478 insn_lcmp:
1480 jlong value2 = POPL ();
1481 jlong value1 = POPL ();
1482 if (value1 > value2)
1483 { PUSHI (1); }
1484 else if (value1 == value2)
1485 { PUSHI (0); }
1486 else
1487 { PUSHI (-1); }
1489 NEXT_INSN;
1491 insn_fcmpl:
1492 tmpval = -1;
1493 goto fcmp;
1495 insn_fcmpg:
1496 tmpval = 1;
1498 fcmp:
1500 jfloat value2 = POPF ();
1501 jfloat value1 = POPF ();
1502 if (value1 > value2)
1503 PUSHI (1);
1504 else if (value1 == value2)
1505 PUSHI (0);
1506 else if (value1 < value2)
1507 PUSHI (-1);
1508 else
1509 PUSHI (tmpval);
1511 NEXT_INSN;
1513 insn_dcmpl:
1514 tmpval = -1;
1515 goto dcmp;
1517 insn_dcmpg:
1518 tmpval = 1;
1520 dcmp:
1522 jdouble value2 = POPD ();
1523 jdouble value1 = POPD ();
1524 if (value1 > value2)
1525 PUSHI (1);
1526 else if (value1 == value2)
1527 PUSHI (0);
1528 else if (value1 < value2)
1529 PUSHI (-1);
1530 else
1531 PUSHI (tmpval);
1533 NEXT_INSN;
1535 insn_ifeq:
1537 if (POPI() == 0)
1538 TAKE_GOTO;
1539 else
1540 SKIP_GOTO;
1542 NEXT_INSN;
1544 insn_ifne:
1546 if (POPI() != 0)
1547 TAKE_GOTO;
1548 else
1549 SKIP_GOTO;
1551 NEXT_INSN;
1553 insn_iflt:
1555 if (POPI() < 0)
1556 TAKE_GOTO;
1557 else
1558 SKIP_GOTO;
1560 NEXT_INSN;
1562 insn_ifge:
1564 if (POPI() >= 0)
1565 TAKE_GOTO;
1566 else
1567 SKIP_GOTO;
1569 NEXT_INSN;
1571 insn_ifgt:
1573 if (POPI() > 0)
1574 TAKE_GOTO;
1575 else
1576 SKIP_GOTO;
1578 NEXT_INSN;
1580 insn_ifle:
1582 if (POPI() <= 0)
1583 TAKE_GOTO;
1584 else
1585 SKIP_GOTO;
1587 NEXT_INSN;
1589 insn_if_icmpeq:
1591 jint value2 = POPI();
1592 jint value1 = POPI();
1593 if (value1 == value2)
1594 TAKE_GOTO;
1595 else
1596 SKIP_GOTO;
1598 NEXT_INSN;
1600 insn_if_icmpne:
1602 jint value2 = POPI();
1603 jint value1 = POPI();
1604 if (value1 != value2)
1605 TAKE_GOTO;
1606 else
1607 SKIP_GOTO;
1609 NEXT_INSN;
1611 insn_if_icmplt:
1613 jint value2 = POPI();
1614 jint value1 = POPI();
1615 if (value1 < value2)
1616 TAKE_GOTO;
1617 else
1618 SKIP_GOTO;
1620 NEXT_INSN;
1622 insn_if_icmpge:
1624 jint value2 = POPI();
1625 jint value1 = POPI();
1626 if (value1 >= value2)
1627 TAKE_GOTO;
1628 else
1629 SKIP_GOTO;
1631 NEXT_INSN;
1633 insn_if_icmpgt:
1635 jint value2 = POPI();
1636 jint value1 = POPI();
1637 if (value1 > value2)
1638 TAKE_GOTO;
1639 else
1640 SKIP_GOTO;
1642 NEXT_INSN;
1644 insn_if_icmple:
1646 jint value2 = POPI();
1647 jint value1 = POPI();
1648 if (value1 <= value2)
1649 TAKE_GOTO;
1650 else
1651 SKIP_GOTO;
1653 NEXT_INSN;
1655 insn_if_acmpeq:
1657 jobject value2 = POPA();
1658 jobject value1 = POPA();
1659 if (value1 == value2)
1660 TAKE_GOTO;
1661 else
1662 SKIP_GOTO;
1664 NEXT_INSN;
1666 insn_if_acmpne:
1668 jobject value2 = POPA();
1669 jobject value1 = POPA();
1670 if (value1 != value2)
1671 TAKE_GOTO;
1672 else
1673 SKIP_GOTO;
1675 NEXT_INSN;
1677 insn_goto_w:
1678 #ifndef DIRECT_THREADED
1679 // For direct threaded, goto and goto_w are the same.
1680 pc = pc - 1 + get4 (pc);
1681 NEXT_INSN;
1682 #endif /* DIRECT_THREADED */
1683 insn_goto:
1684 TAKE_GOTO;
1685 NEXT_INSN;
1687 insn_jsr_w:
1688 #ifndef DIRECT_THREADED
1689 // For direct threaded, jsr and jsr_w are the same.
1691 pc_t next = pc - 1 + get4 (pc);
1692 pc += 4;
1693 PUSHA ((jobject) pc);
1694 pc = next;
1696 NEXT_INSN;
1697 #endif /* DIRECT_THREADED */
1698 insn_jsr:
1700 pc_t next = GOTO_VAL();
1701 SKIP_GOTO;
1702 PUSHA ((jobject) pc);
1703 pc = next;
1705 NEXT_INSN;
1707 insn_ret:
1709 jint index = GET1U ();
1710 pc = (pc_t) PEEKA (index);
1712 NEXT_INSN;
1714 insn_tableswitch:
1716 #ifdef DIRECT_THREADED
1717 void *def = (pc++)->datum;
1719 int index = POPI();
1721 jint low = INTVAL ();
1722 jint high = INTVAL ();
1724 if (index < low || index > high)
1725 pc = (insn_slot *) def;
1726 else
1727 pc = (insn_slot *) ((pc + index - low)->datum);
1728 #else
1729 pc_t base_pc = pc - 1;
1730 int index = POPI ();
1732 pc_t base = (pc_t) meth->bytecode ();
1733 while ((pc - base) % 4 != 0)
1734 ++pc;
1736 jint def = get4 (pc);
1737 jint low = get4 (pc + 4);
1738 jint high = get4 (pc + 8);
1739 if (index < low || index > high)
1740 pc = base_pc + def;
1741 else
1742 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1743 #endif /* DIRECT_THREADED */
1745 NEXT_INSN;
1747 insn_lookupswitch:
1749 #ifdef DIRECT_THREADED
1750 void *def = (pc++)->insn;
1752 int index = POPI();
1754 jint npairs = INTVAL ();
1756 int max = npairs - 1;
1757 int min = 0;
1759 // Simple binary search...
1760 while (min < max)
1762 int half = (min + max) / 2;
1763 int match = pc[2 * half].int_val;
1765 if (index == match)
1767 // Found it.
1768 pc = (insn_slot *) pc[2 * half + 1].datum;
1769 NEXT_INSN;
1771 else if (index < match)
1772 // We can use HALF - 1 here because we check again on
1773 // loop exit.
1774 max = half - 1;
1775 else
1776 // We can use HALF + 1 here because we check again on
1777 // loop exit.
1778 min = half + 1;
1780 if (index == pc[2 * min].int_val)
1781 pc = (insn_slot *) pc[2 * min + 1].datum;
1782 else
1783 pc = (insn_slot *) def;
1784 #else
1785 unsigned char *base_pc = pc-1;
1786 int index = POPI();
1788 unsigned char* base = meth->bytecode ();
1789 while ((pc-base) % 4 != 0)
1790 ++pc;
1792 jint def = get4 (pc);
1793 jint npairs = get4 (pc+4);
1795 int max = npairs-1;
1796 int min = 0;
1798 // Simple binary search...
1799 while (min < max)
1801 int half = (min+max)/2;
1802 int match = get4 (pc+ 4*(2 + 2*half));
1804 if (index == match)
1805 min = max = half;
1806 else if (index < match)
1807 // We can use HALF - 1 here because we check again on
1808 // loop exit.
1809 max = half - 1;
1810 else
1811 // We can use HALF + 1 here because we check again on
1812 // loop exit.
1813 min = half + 1;
1816 if (index == get4 (pc+ 4*(2 + 2*min)))
1817 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1818 else
1819 pc = base_pc + def;
1820 #endif /* DIRECT_THREADED */
1822 NEXT_INSN;
1824 insn_areturn:
1825 *(jobject *) retp = POPA ();
1826 return;
1828 insn_lreturn:
1829 *(jlong *) retp = POPL ();
1830 return;
1832 insn_freturn:
1833 *(jfloat *) retp = POPF ();
1834 return;
1836 insn_dreturn:
1837 *(jdouble *) retp = POPD ();
1838 return;
1840 insn_ireturn:
1841 *(jint *) retp = POPI ();
1842 return;
1844 insn_return:
1845 return;
1847 insn_getstatic:
1849 jint fieldref_index = GET2U ();
1850 SAVE_PC(); // Constant pool resolution could throw.
1851 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1852 _Jv_Field *field = pool_data[fieldref_index].field;
1854 if ((field->flags & Modifier::STATIC) == 0)
1855 throw_incompatible_class_change_error
1856 (JvNewStringLatin1 ("field no longer static"));
1858 jclass type = field->type;
1860 // We rewrite the instruction once we discover what it refers
1861 // to.
1862 void *newinsn = NULL;
1863 if (type->isPrimitive ())
1865 switch (type->size_in_bytes)
1867 case 1:
1868 PUSHI (*field->u.byte_addr);
1869 newinsn = AMPAMP (getstatic_resolved_1);
1870 break;
1872 case 2:
1873 if (type == JvPrimClass (char))
1875 PUSHI (*field->u.char_addr);
1876 newinsn = AMPAMP (getstatic_resolved_char);
1878 else
1880 PUSHI (*field->u.short_addr);
1881 newinsn = AMPAMP (getstatic_resolved_short);
1883 break;
1885 case 4:
1886 PUSHI(*field->u.int_addr);
1887 newinsn = AMPAMP (getstatic_resolved_4);
1888 break;
1890 case 8:
1891 PUSHL(*field->u.long_addr);
1892 newinsn = AMPAMP (getstatic_resolved_8);
1893 break;
1896 else
1898 PUSHA(*field->u.object_addr);
1899 newinsn = AMPAMP (getstatic_resolved_obj);
1902 #ifdef DIRECT_THREADED
1903 REWRITE_INSN (newinsn, datum, field->u.addr);
1904 #endif /* DIRECT_THREADED */
1906 NEXT_INSN;
1908 #ifdef DIRECT_THREADED
1909 getstatic_resolved_1:
1910 PUSHI (*(jbyte *) AVAL ());
1911 NEXT_INSN;
1913 getstatic_resolved_char:
1914 PUSHI (*(jchar *) AVAL ());
1915 NEXT_INSN;
1917 getstatic_resolved_short:
1918 PUSHI (*(jshort *) AVAL ());
1919 NEXT_INSN;
1921 getstatic_resolved_4:
1922 PUSHI (*(jint *) AVAL ());
1923 NEXT_INSN;
1925 getstatic_resolved_8:
1926 PUSHL (*(jlong *) AVAL ());
1927 NEXT_INSN;
1929 getstatic_resolved_obj:
1930 PUSHA (*(jobject *) AVAL ());
1931 NEXT_INSN;
1932 #endif /* DIRECT_THREADED */
1934 insn_getfield:
1936 SAVE_PC();
1937 jint fieldref_index = GET2U ();
1938 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1939 _Jv_Field *field = pool_data[fieldref_index].field;
1941 if ((field->flags & Modifier::STATIC) != 0)
1942 throw_incompatible_class_change_error
1943 (JvNewStringLatin1 ("field is static"));
1945 jclass type = field->type;
1946 jint field_offset = field->u.boffset;
1948 jobject obj = POPA();
1949 NULLCHECK(obj);
1951 void *newinsn = NULL;
1952 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1953 if (type->isPrimitive ())
1955 switch (type->size_in_bytes)
1957 case 1:
1958 PUSHI (val->byte_value);
1959 newinsn = AMPAMP (getfield_resolved_1);
1960 break;
1962 case 2:
1963 if (type == JvPrimClass (char))
1965 PUSHI (val->char_value);
1966 newinsn = AMPAMP (getfield_resolved_char);
1968 else
1970 PUSHI (val->short_value);
1971 newinsn = AMPAMP (getfield_resolved_short);
1973 break;
1975 case 4:
1976 PUSHI (val->int_value);
1977 newinsn = AMPAMP (getfield_resolved_4);
1978 break;
1980 case 8:
1981 PUSHL (val->long_value);
1982 newinsn = AMPAMP (getfield_resolved_8);
1983 break;
1986 else
1988 PUSHA (val->object_value);
1989 newinsn = AMPAMP (getfield_resolved_obj);
1992 #ifdef DIRECT_THREADED
1993 REWRITE_INSN (newinsn, int_val, field_offset);
1994 #endif /* DIRECT_THREADED */
1996 NEXT_INSN;
1998 #ifdef DIRECT_THREADED
1999 getfield_resolved_1:
2001 char *obj = (char *) POPA ();
2002 NULLCHECK (obj);
2003 PUSHI (*(jbyte *) (obj + INTVAL ()));
2005 NEXT_INSN;
2007 getfield_resolved_char:
2009 char *obj = (char *) POPA ();
2010 NULLCHECK (obj);
2011 PUSHI (*(jchar *) (obj + INTVAL ()));
2013 NEXT_INSN;
2015 getfield_resolved_short:
2017 char *obj = (char *) POPA ();
2018 NULLCHECK (obj);
2019 PUSHI (*(jshort *) (obj + INTVAL ()));
2021 NEXT_INSN;
2023 getfield_resolved_4:
2025 char *obj = (char *) POPA ();
2026 NULLCHECK (obj);
2027 PUSHI (*(jint *) (obj + INTVAL ()));
2029 NEXT_INSN;
2031 getfield_resolved_8:
2033 char *obj = (char *) POPA ();
2034 NULLCHECK (obj);
2035 PUSHL (*(jlong *) (obj + INTVAL ()));
2037 NEXT_INSN;
2039 getfield_resolved_obj:
2041 char *obj = (char *) POPA ();
2042 NULLCHECK (obj);
2043 PUSHA (*(jobject *) (obj + INTVAL ()));
2045 NEXT_INSN;
2046 #endif /* DIRECT_THREADED */
2048 insn_putstatic:
2050 SAVE_PC();
2051 jint fieldref_index = GET2U ();
2052 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2053 _Jv_Field *field = pool_data[fieldref_index].field;
2055 jclass type = field->type;
2057 // ResolvePoolEntry cannot check this
2058 if ((field->flags & Modifier::STATIC) == 0)
2059 throw_incompatible_class_change_error
2060 (JvNewStringLatin1 ("field no longer static"));
2062 void *newinsn = NULL;
2063 if (type->isPrimitive ())
2065 switch (type->size_in_bytes)
2067 case 1:
2069 jint value = POPI();
2070 *field->u.byte_addr = value;
2071 newinsn = AMPAMP (putstatic_resolved_1);
2072 break;
2075 case 2:
2077 jint value = POPI();
2078 *field->u.char_addr = value;
2079 newinsn = AMPAMP (putstatic_resolved_2);
2080 break;
2083 case 4:
2085 jint value = POPI();
2086 *field->u.int_addr = value;
2087 newinsn = AMPAMP (putstatic_resolved_4);
2088 break;
2091 case 8:
2093 jlong value = POPL();
2094 *field->u.long_addr = value;
2095 newinsn = AMPAMP (putstatic_resolved_8);
2096 break;
2100 else
2102 jobject value = POPA();
2103 *field->u.object_addr = value;
2104 newinsn = AMPAMP (putstatic_resolved_obj);
2107 #ifdef DIRECT_THREADED
2108 REWRITE_INSN (newinsn, datum, field->u.addr);
2109 #endif /* DIRECT_THREADED */
2111 NEXT_INSN;
2113 #ifdef DIRECT_THREADED
2114 putstatic_resolved_1:
2115 *(jbyte *) AVAL () = POPI ();
2116 NEXT_INSN;
2118 putstatic_resolved_2:
2119 *(jchar *) AVAL () = POPI ();
2120 NEXT_INSN;
2122 putstatic_resolved_4:
2123 *(jint *) AVAL () = POPI ();
2124 NEXT_INSN;
2126 putstatic_resolved_8:
2127 *(jlong *) AVAL () = POPL ();
2128 NEXT_INSN;
2130 putstatic_resolved_obj:
2131 *(jobject *) AVAL () = POPA ();
2132 NEXT_INSN;
2133 #endif /* DIRECT_THREADED */
2135 insn_putfield:
2137 SAVE_PC();
2138 jint fieldref_index = GET2U ();
2139 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2140 _Jv_Field *field = pool_data[fieldref_index].field;
2142 jclass type = field->type;
2144 if ((field->flags & Modifier::STATIC) != 0)
2145 throw_incompatible_class_change_error
2146 (JvNewStringLatin1 ("field is static"));
2148 jint field_offset = field->u.boffset;
2150 void *newinsn = NULL;
2151 if (type->isPrimitive ())
2153 switch (type->size_in_bytes)
2155 case 1:
2157 jint value = POPI();
2158 jobject obj = POPA();
2159 NULLCHECK(obj);
2160 *(jbyte*) ((char*)obj + field_offset) = value;
2161 newinsn = AMPAMP (putfield_resolved_1);
2162 break;
2165 case 2:
2167 jint value = POPI();
2168 jobject obj = POPA();
2169 NULLCHECK(obj);
2170 *(jchar*) ((char*)obj + field_offset) = value;
2171 newinsn = AMPAMP (putfield_resolved_2);
2172 break;
2175 case 4:
2177 jint value = POPI();
2178 jobject obj = POPA();
2179 NULLCHECK(obj);
2180 *(jint*) ((char*)obj + field_offset) = value;
2181 newinsn = AMPAMP (putfield_resolved_4);
2182 break;
2185 case 8:
2187 jlong value = POPL();
2188 jobject obj = POPA();
2189 NULLCHECK(obj);
2190 *(jlong*) ((char*)obj + field_offset) = value;
2191 newinsn = AMPAMP (putfield_resolved_8);
2192 break;
2196 else
2198 jobject value = POPA();
2199 jobject obj = POPA();
2200 NULLCHECK(obj);
2201 *(jobject*) ((char*)obj + field_offset) = value;
2202 newinsn = AMPAMP (putfield_resolved_obj);
2205 #ifdef DIRECT_THREADED
2206 REWRITE_INSN (newinsn, int_val, field_offset);
2207 #endif /* DIRECT_THREADED */
2209 NEXT_INSN;
2211 #ifdef DIRECT_THREADED
2212 putfield_resolved_1:
2214 jint val = POPI ();
2215 char *obj = (char *) POPA ();
2216 NULLCHECK (obj);
2217 *(jbyte *) (obj + INTVAL ()) = val;
2219 NEXT_INSN;
2221 putfield_resolved_2:
2223 jint val = POPI ();
2224 char *obj = (char *) POPA ();
2225 NULLCHECK (obj);
2226 *(jchar *) (obj + INTVAL ()) = val;
2228 NEXT_INSN;
2230 putfield_resolved_4:
2232 jint val = POPI ();
2233 char *obj = (char *) POPA ();
2234 NULLCHECK (obj);
2235 *(jint *) (obj + INTVAL ()) = val;
2237 NEXT_INSN;
2239 putfield_resolved_8:
2241 jlong val = POPL ();
2242 char *obj = (char *) POPA ();
2243 NULLCHECK (obj);
2244 *(jlong *) (obj + INTVAL ()) = val;
2246 NEXT_INSN;
2248 putfield_resolved_obj:
2250 jobject val = POPA ();
2251 char *obj = (char *) POPA ();
2252 NULLCHECK (obj);
2253 *(jobject *) (obj + INTVAL ()) = val;
2255 NEXT_INSN;
2256 #endif /* DIRECT_THREADED */
2258 insn_invokespecial:
2260 SAVE_PC();
2261 int index = GET2U ();
2263 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2264 index)).rmethod;
2266 sp -= rmeth->stack_item_count;
2268 // We don't use NULLCHECK here because we can't rely on that
2269 // working for <init>. So instead we do an explicit test.
2270 if (! sp[0].o)
2272 SAVE_PC();
2273 throw_null_pointer_exception ();
2276 fun = (void (*)()) rmeth->method->ncode;
2278 #ifdef DIRECT_THREADED
2279 // Rewrite instruction so that we use a faster pre-resolved
2280 // method.
2281 REWRITE_INSN (&&invokespecial_resolved, datum, rmeth);
2282 #endif /* DIRECT_THREADED */
2284 goto perform_invoke;
2286 #ifdef DIRECT_THREADED
2287 invokespecial_resolved:
2289 SAVE_PC();
2290 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2291 sp -= rmeth->stack_item_count;
2292 // We don't use NULLCHECK here because we can't rely on that
2293 // working for <init>. So instead we do an explicit test.
2294 if (! sp[0].o)
2296 throw_null_pointer_exception ();
2298 fun = (void (*)()) rmeth->method->ncode;
2300 goto perform_invoke;
2301 #endif /* DIRECT_THREADED */
2303 insn_invokestatic:
2305 SAVE_PC();
2306 int index = GET2U ();
2308 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2309 index)).rmethod;
2311 sp -= rmeth->stack_item_count;
2313 fun = (void (*)()) rmeth->method->ncode;
2315 #ifdef DIRECT_THREADED
2316 // Rewrite instruction so that we use a faster pre-resolved
2317 // method.
2318 REWRITE_INSN (&&invokestatic_resolved, datum, rmeth);
2319 #endif /* DIRECT_THREADED */
2321 goto perform_invoke;
2323 #ifdef DIRECT_THREADED
2324 invokestatic_resolved:
2326 SAVE_PC();
2327 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2328 sp -= rmeth->stack_item_count;
2329 fun = (void (*)()) rmeth->method->ncode;
2331 goto perform_invoke;
2332 #endif /* DIRECT_THREADED */
2334 insn_invokeinterface:
2336 SAVE_PC();
2337 int index = GET2U ();
2339 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2340 index)).rmethod;
2342 sp -= rmeth->stack_item_count;
2344 jobject rcv = sp[0].o;
2346 NULLCHECK (rcv);
2348 fun = (void (*)())
2349 _Jv_LookupInterfaceMethod (rcv->getClass (),
2350 rmeth->method->name,
2351 rmeth->method->signature);
2353 #ifdef DIRECT_THREADED
2354 // Rewrite instruction so that we use a faster pre-resolved
2355 // method.
2356 REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth);
2357 #else
2358 // Skip dummy bytes.
2359 pc += 2;
2360 #endif /* DIRECT_THREADED */
2362 goto perform_invoke;
2364 #ifdef DIRECT_THREADED
2365 invokeinterface_resolved:
2367 SAVE_PC();
2368 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2369 sp -= rmeth->stack_item_count;
2370 jobject rcv = sp[0].o;
2371 NULLCHECK (rcv);
2372 fun = (void (*)())
2373 _Jv_LookupInterfaceMethod (rcv->getClass (),
2374 rmeth->method->name,
2375 rmeth->method->signature);
2377 goto perform_invoke;
2378 #endif /* DIRECT_THREADED */
2380 insn_new:
2382 SAVE_PC();
2383 int index = GET2U ();
2384 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2385 index)).clazz;
2386 /* VM spec, section 3.11.5 */
2387 if ((klass->getModifiers() & Modifier::ABSTRACT)
2388 || klass->isInterface())
2390 jthrowable t = new java::lang::InstantiationException;
2391 INTERP_REPORT_EXCEPTION (t);
2392 throw t;
2394 jobject res = _Jv_AllocObject (klass);
2395 PUSHA (res);
2397 #ifdef DIRECT_THREADED
2398 REWRITE_INSN (&&new_resolved, datum, klass);
2399 #endif /* DIRECT_THREADED */
2401 NEXT_INSN;
2403 #ifdef DIRECT_THREADED
2404 new_resolved:
2406 jclass klass = (jclass) AVAL ();
2407 jobject res = _Jv_AllocObject (klass);
2408 PUSHA (res);
2410 NEXT_INSN;
2411 #endif /* DIRECT_THREADED */
2413 insn_newarray:
2415 int atype = GET1U ();
2416 int size = POPI();
2417 jobject result = _Jv_NewArray (atype, size);
2418 PUSHA (result);
2420 NEXT_INSN;
2422 insn_anewarray:
2424 SAVE_PC();
2425 int index = GET2U ();
2426 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2427 index)).clazz;
2428 int size = POPI();
2429 jobject result = _Jv_NewObjectArray (size, klass, 0);
2430 PUSHA (result);
2432 #ifdef DIRECT_THREADED
2433 REWRITE_INSN (&&anewarray_resolved, datum, klass);
2434 #endif /* DIRECT_THREADED */
2436 NEXT_INSN;
2438 #ifdef DIRECT_THREADED
2439 anewarray_resolved:
2441 jclass klass = (jclass) AVAL ();
2442 int size = POPI ();
2443 jobject result = _Jv_NewObjectArray (size, klass, 0);
2444 PUSHA (result);
2446 NEXT_INSN;
2447 #endif /* DIRECT_THREADED */
2449 insn_arraylength:
2451 __JArray *arr = (__JArray*)POPA();
2452 NULLARRAYCHECK (arr);
2453 PUSHI (arr->length);
2455 NEXT_INSN;
2457 insn_athrow:
2459 jobject value = POPA();
2460 jthrowable t = static_cast<jthrowable> (value);
2461 INTERP_REPORT_EXCEPTION (t);
2462 throw t;
2464 NEXT_INSN;
2466 insn_checkcast:
2468 SAVE_PC();
2469 jobject value = POPA();
2470 jint index = GET2U ();
2471 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2472 index)).clazz;
2474 value = (jobject) _Jv_CheckCast (to, value);
2476 PUSHA (value);
2478 #ifdef DIRECT_THREADED
2479 REWRITE_INSN (&&checkcast_resolved, datum, to);
2480 #endif /* DIRECT_THREADED */
2482 NEXT_INSN;
2484 #ifdef DIRECT_THREADED
2485 checkcast_resolved:
2487 SAVE_PC();
2488 jobject value = POPA ();
2489 jclass to = (jclass) AVAL ();
2490 value = (jobject) _Jv_CheckCast (to, value);
2491 PUSHA (value);
2493 NEXT_INSN;
2494 #endif /* DIRECT_THREADED */
2496 insn_instanceof:
2498 SAVE_PC();
2499 jobject value = POPA();
2500 jint index = GET2U ();
2501 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2502 index)).clazz;
2503 PUSHI (to->isInstance (value));
2505 #ifdef DIRECT_THREADED
2506 REWRITE_INSN (&&instanceof_resolved, datum, to);
2507 #endif /* DIRECT_THREADED */
2509 NEXT_INSN;
2511 #ifdef DIRECT_THREADED
2512 instanceof_resolved:
2514 jobject value = POPA ();
2515 jclass to = (jclass) AVAL ();
2516 PUSHI (to->isInstance (value));
2518 NEXT_INSN;
2519 #endif /* DIRECT_THREADED */
2521 insn_monitorenter:
2523 jobject value = POPA();
2524 NULLCHECK(value);
2525 _Jv_MonitorEnter (value);
2527 NEXT_INSN;
2529 insn_monitorexit:
2531 jobject value = POPA();
2532 NULLCHECK(value);
2533 _Jv_MonitorExit (value);
2535 NEXT_INSN;
2537 insn_ifnull:
2539 jobject val = POPA();
2540 if (val == NULL)
2541 TAKE_GOTO;
2542 else
2543 SKIP_GOTO;
2545 NEXT_INSN;
2547 insn_ifnonnull:
2549 jobject val = POPA();
2550 if (val != NULL)
2551 TAKE_GOTO;
2552 else
2553 SKIP_GOTO;
2555 NEXT_INSN;
2557 insn_multianewarray:
2559 SAVE_PC();
2560 int kind_index = GET2U ();
2561 int dim = GET1U ();
2563 jclass type
2564 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2565 kind_index)).clazz;
2566 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2568 for (int i = dim - 1; i >= 0; i--)
2570 sizes[i] = POPI ();
2573 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2575 PUSHA (res);
2577 NEXT_INSN;
2579 #ifndef DIRECT_THREADED
2580 insn_wide:
2582 jint the_mod_op = get1u (pc++);
2583 jint wide = get2u (pc); pc += 2;
2585 switch (the_mod_op)
2587 case op_istore:
2588 STOREI (wide);
2589 NEXT_INSN;
2591 case op_fstore:
2592 STOREF (wide);
2593 NEXT_INSN;
2595 case op_astore:
2596 STOREA (wide);
2597 NEXT_INSN;
2599 case op_lload:
2600 LOADL (wide);
2601 NEXT_INSN;
2603 case op_dload:
2604 LOADD (wide);
2605 NEXT_INSN;
2607 case op_iload:
2608 LOADI (wide);
2609 NEXT_INSN;
2611 case op_fload:
2612 LOADF (wide);
2613 NEXT_INSN;
2615 case op_aload:
2616 LOADA (wide);
2617 NEXT_INSN;
2619 case op_lstore:
2620 STOREL (wide);
2621 NEXT_INSN;
2623 case op_dstore:
2624 STORED (wide);
2625 NEXT_INSN;
2627 case op_ret:
2628 pc = (unsigned char*) PEEKA (wide);
2629 NEXT_INSN;
2631 case op_iinc:
2633 jint amount = get2s (pc); pc += 2;
2634 jint value = PEEKI (wide);
2635 POKEI (wide, value+amount);
2637 NEXT_INSN;
2639 default:
2640 throw_internal_error ("illegal bytecode modified by wide");
2644 #endif /* DIRECT_THREADED */
2646 insn_breakpoint:
2648 using namespace ::java::lang;
2649 jmethodID method = meth->self;
2650 jlocation location = meth->insn_index (pc - 1);
2652 using namespace gnu::gcj::jvmti;
2653 Breakpoint *bp
2654 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2655 location);
2656 JvAssert (bp != NULL);
2658 // Save the insn here since the breakpoint could be removed
2659 // before the JVMTI notification returns.
2660 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2662 bp->execute ();
2664 // Continue execution
2665 #ifdef DIRECT_THREADED
2666 goto *(opc->insn);
2667 #else
2668 goto *(insn_target[*opc]);
2669 #endif
2672 catch (java::lang::Throwable *ex)
2674 // Check if the exception is handled and, if so, set the pc to the start
2675 // of the appropriate catch block.
2676 if (meth->check_handler (&pc, meth, ex))
2678 sp = stack;
2679 sp++->o = ex; // Push exception.
2680 #ifdef __GCJ_DEBUG
2681 if (JVMTI_REQUESTED_EVENT (ExceptionCatch))
2683 using namespace gnu::gcj::jvmti;
2684 jlong catch_meth = reinterpret_cast<jlong> (meth->get_method ());
2685 jlong catch_loc = meth->insn_index (pc);
2686 _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH, thread,
2687 _Jv_GetCurrentJNIEnv (), catch_meth,
2688 catch_loc, ex);
2690 #endif
2691 NEXT_INSN;
2694 // No handler, so re-throw.
2695 throw ex;