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
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;
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
24 java::lang::Thread *thread = java::lang::Thread::currentThread();
27 _Jv_InterpFrame frame_desc (meth, thread, NULL, &pc);
29 _Jv_InterpFrame frame_desc (meth, thread);
32 _Jv_word stack[meth->max_stack];
35 _Jv_word locals[meth->max_locals];
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 ();
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)
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';
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';
79 else if (signature[i] == 'F')
81 frame_desc.locals_type[type_ctr] = 'f';
85 else if (signature[i] == 'J')
87 frame_desc.locals_type[type_ctr] = 'l';
88 frame_desc.locals_type[type_ctr+1] = 'x';
92 else if (signature[i] == 'D')
94 frame_desc.locals_type[type_ctr] = 'd';
95 frame_desc.locals_type[type_ctr+1] = 'x';
99 else if (signature[i] == 'L')
101 frame_desc.locals_type[type_ctr] = 'o';
103 while (signature[i] != ';')
107 else if (signature[i] == '[')
109 frame_desc.locals_type[type_ctr] = 'o';
112 // Ignore multi-dimensional arrays.
113 while (signature[i] == '[')
116 // Check for an object array
117 if (signature[i] == 'L')
119 while (signature[i] != ';')
127 #define INSN_LABEL(op) &&insn_##op
129 static const void *const insn_target[] =
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),
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),
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),
301 INSN_LABEL(tableswitch),
302 INSN_LABEL(lookupswitch),
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),
319 INSN_LABEL(newarray),
320 INSN_LABEL(anewarray),
321 INSN_LABEL(arraylength),
323 INSN_LABEL(checkcast),
324 INSN_LABEL(instanceof),
325 INSN_LABEL(monitorenter),
326 INSN_LABEL(monitorexit),
327 #ifdef DIRECT_THREADED
332 INSN_LABEL(multianewarray),
334 INSN_LABEL(ifnonnull),
337 #ifdef DIRECT_THREADED
338 INSN_LABEL (ldc_class)
344 #ifdef DIRECT_THREADED
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, \
360 goto *(insn->insn); \
365 #define REWRITE_INSN(INSN,SLOT,VALUE) \
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); \
374 pc[-2].insn = INSN; \
376 pc[-1].SLOT = VALUE; \
382 #define NEXT_INSN goto *((pc++)->insn)
383 #define REWRITE_INSN(INSN,SLOT,VALUE) \
385 pc[-2].insn = INSN; \
386 pc[-1].SLOT = VALUE; \
391 #define INTVAL() ((pc++)->int_val)
392 #define AVAL() ((pc++)->datum)
394 #define GET1S() INTVAL ()
395 #define GET2S() INTVAL ()
396 #define GET1U() INTVAL ()
397 #define GET2U() INTVAL ()
398 #define AVAL1U() AVAL ()
399 #define AVAL2U() AVAL ()
400 #define AVAL2UP() AVAL ()
401 #define SKIP_GOTO ++pc
402 #define GOTO_VAL() (insn_slot *) pc->datum
403 #define PCVAL(unionval) unionval.p
404 #define AMPAMP(label) &&label
406 // Compile if we must. NOTE: Double-check locking.
407 if (meth->prepared == NULL)
409 _Jv_MutexLock (&compile_mutex);
410 if (meth->prepared == NULL)
411 meth->compile (insn_target);
412 _Jv_MutexUnlock (&compile_mutex);
415 // If we're only compiling, stop here
419 pc = (insn_slot *) meth->prepared;
427 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
429 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
430 jmethodID method = meth->self; \
431 jlocation loc = meth->insn_index (pc); \
432 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
435 goto *(insn_target[*pc++])
437 #define NEXT_INSN goto *(insn_target[*pc++])
440 #define GET1S() get1s (pc++)
441 #define GET2S() (pc += 2, get2s (pc- 2))
442 #define GET1U() get1u (pc++)
443 #define GET2U() (pc += 2, get2u (pc - 2))
444 // Note that these could be more efficient when not handling 'ldc
447 ({ int index = get1u (pc++); \
448 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
450 ({ int index = get2u (pc); pc += 2; \
451 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
452 // Note that we don't need to resolve the pool entry here as class
453 // constants are never wide.
454 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
455 #define SKIP_GOTO pc += 2
456 #define GOTO_VAL() pc - 1 + get2s (pc)
457 #define PCVAL(unionval) unionval.i
458 #define AMPAMP(label) NULL
460 pc = meth->bytecode ();
462 #endif /* DIRECT_THREADED */
464 #define TAKE_GOTO pc = GOTO_VAL ()
466 /* Go straight at it! the ffi raw format matches the internal
467 stack representation exactly. At least, that's the idea.
469 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
471 _Jv_word *pool_data = meth->defining_class->constants.data;
473 /* These three are temporaries for common code used by several
476 _Jv_ResolvedMethod* rmeth;
481 // We keep nop around. It is used if we're interpreting the
482 // bytecodes and not doing direct threading.
486 /* The first few instructions here are ordered according to their
487 frequency, in the hope that this will improve code locality a
490 insn_aload_0: // 0x2a
498 insn_iload_1: // 0x1b
502 insn_invokevirtual: // 0xb6
505 int index = GET2U ();
507 /* _Jv_Linker::resolve_pool_entry returns immediately if the
508 * value already is resolved. If we want to clutter up the
509 * code here to gain a little performance, then we can check
510 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
511 * directly. For now, I don't think it is worth it. */
513 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
516 sp -= rmeth->stack_item_count;
518 if (rmeth->method->accflags & Modifier::FINAL)
520 // We can't rely on NULLCHECK working if the method is final.
522 throw_null_pointer_exception ();
524 // Final methods might not appear in the vtable.
525 fun = (void (*)()) rmeth->method->ncode;
530 jobject rcv = sp[0].o;
531 _Jv_VTable *table = *(_Jv_VTable**) rcv;
532 fun = (void (*)()) table->get_method (rmeth->method->index);
535 #ifdef DIRECT_THREADED
536 // Rewrite instruction so that we use a faster pre-resolved
538 REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth);
539 #endif /* DIRECT_THREADED */
543 #ifdef DIRECT_THREADED
544 invokevirtual_resolved:
547 rmeth = (_Jv_ResolvedMethod *) AVAL ();
548 sp -= rmeth->stack_item_count;
550 if (rmeth->method->accflags & Modifier::FINAL)
552 // We can't rely on NULLCHECK working if the method is final.
554 throw_null_pointer_exception ();
556 // Final methods might not appear in the vtable.
557 fun = (void (*)()) rmeth->method->ncode;
561 jobject rcv = sp[0].o;
562 _Jv_VTable *table = *(_Jv_VTable**) rcv;
563 fun = (void (*)()) table->get_method (rmeth->method->index);
567 #endif /* DIRECT_THREADED */
571 /* here goes the magic again... */
572 ffi_cif *cif = &rmeth->cif;
573 ffi_raw *raw = (ffi_raw*) sp;
577 #if FFI_NATIVE_RAW_API
578 /* We assume that this is only implemented if it's correct */
579 /* to use it here. On a 64 bit machine, it never is. */
580 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
582 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
585 int rtype = cif->rtype->type;
587 /* the likelyhood of object, int, or void return is very high,
588 * so those are checked before the switch */
589 if (rtype == FFI_TYPE_POINTER)
591 PUSHA (rvalue.object_value);
593 else if (rtype == FFI_TYPE_SINT32)
595 PUSHI (rvalue.int_value);
597 else if (rtype == FFI_TYPE_VOID)
606 PUSHI ((jbyte)(rvalue.int_value & 0xff));
609 case FFI_TYPE_SINT16:
610 PUSHI ((jshort)(rvalue.int_value & 0xffff));
613 case FFI_TYPE_UINT16:
614 PUSHI (rvalue.int_value & 0xffff);
618 PUSHF (rvalue.float_value);
621 case FFI_TYPE_DOUBLE:
622 PUSHD (rvalue.double_value);
625 case FFI_TYPE_SINT64:
626 PUSHL (rvalue.long_value);
630 throw_internal_error ("unknown return type in invokeXXX");
697 // For direct threaded, bipush and sipush are the same.
698 #ifndef DIRECT_THREADED
701 #endif /* DIRECT_THREADED */
707 // For direct threaded, ldc and ldc_w are the same.
708 #ifndef DIRECT_THREADED
709 PUSHA ((jobject) AVAL1U ());
711 #endif /* DIRECT_THREADED */
713 PUSHA ((jobject) AVAL2U ());
716 #ifdef DIRECT_THREADED
717 // For direct threaded we have a separate 'ldc class' operation.
721 // We could rewrite the instruction at this point.
722 int index = INTVAL ();
723 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
728 #endif /* DIRECT_THREADED */
732 void *where = AVAL2UP ();
733 memcpy (sp, where, 2*sizeof (_Jv_word));
829 jintArray arr = (jintArray) POPA();
830 NULLARRAYCHECK (arr);
831 ARRAYBOUNDSCHECK (arr, index);
832 PUSHI( elements(arr)[index] );
839 jlongArray arr = (jlongArray) POPA();
840 NULLARRAYCHECK (arr);
841 ARRAYBOUNDSCHECK (arr, index);
842 PUSHL( elements(arr)[index] );
849 jfloatArray arr = (jfloatArray) POPA();
850 NULLARRAYCHECK (arr);
851 ARRAYBOUNDSCHECK (arr, index);
852 PUSHF( elements(arr)[index] );
859 jdoubleArray arr = (jdoubleArray) POPA();
860 NULLARRAYCHECK (arr);
861 ARRAYBOUNDSCHECK (arr, index);
862 PUSHD( elements(arr)[index] );
869 jobjectArray arr = (jobjectArray) POPA();
870 NULLARRAYCHECK (arr);
871 ARRAYBOUNDSCHECK (arr, index);
872 PUSHA( elements(arr)[index] );
879 jbyteArray arr = (jbyteArray) POPA();
880 NULLARRAYCHECK (arr);
881 ARRAYBOUNDSCHECK (arr, index);
882 PUSHI( elements(arr)[index] );
889 jcharArray arr = (jcharArray) POPA();
890 NULLARRAYCHECK (arr);
891 ARRAYBOUNDSCHECK (arr, index);
892 PUSHI( elements(arr)[index] );
899 jshortArray arr = (jshortArray) POPA();
900 NULLARRAYCHECK (arr);
901 ARRAYBOUNDSCHECK (arr, index);
902 PUSHI( elements(arr)[index] );
1008 jint value = POPI();
1009 jint index = POPI();
1010 jintArray arr = (jintArray) POPA();
1011 NULLARRAYCHECK (arr);
1012 ARRAYBOUNDSCHECK (arr, index);
1013 elements(arr)[index] = value;
1019 jlong value = POPL();
1020 jint index = POPI();
1021 jlongArray arr = (jlongArray) POPA();
1022 NULLARRAYCHECK (arr);
1023 ARRAYBOUNDSCHECK (arr, index);
1024 elements(arr)[index] = value;
1030 jfloat value = POPF();
1031 jint index = POPI();
1032 jfloatArray arr = (jfloatArray) POPA();
1033 NULLARRAYCHECK (arr);
1034 ARRAYBOUNDSCHECK (arr, index);
1035 elements(arr)[index] = value;
1041 jdouble value = POPD();
1042 jint index = POPI();
1043 jdoubleArray arr = (jdoubleArray) POPA();
1044 NULLARRAYCHECK (arr);
1045 ARRAYBOUNDSCHECK (arr, index);
1046 elements(arr)[index] = value;
1052 jobject value = POPA();
1053 jint index = POPI();
1054 jobjectArray arr = (jobjectArray) POPA();
1055 NULLARRAYCHECK (arr);
1056 ARRAYBOUNDSCHECK (arr, index);
1057 _Jv_CheckArrayStore (arr, value);
1058 elements(arr)[index] = value;
1064 jbyte value = (jbyte) POPI();
1065 jint index = POPI();
1066 jbyteArray arr = (jbyteArray) POPA();
1067 NULLARRAYCHECK (arr);
1068 ARRAYBOUNDSCHECK (arr, index);
1069 elements(arr)[index] = value;
1075 jchar value = (jchar) POPI();
1076 jint index = POPI();
1077 jcharArray arr = (jcharArray) POPA();
1078 NULLARRAYCHECK (arr);
1079 ARRAYBOUNDSCHECK (arr, index);
1080 elements(arr)[index] = value;
1086 jshort value = (jshort) POPI();
1087 jint index = POPI();
1088 jshortArray arr = (jshortArray) POPA();
1089 NULLARRAYCHECK (arr);
1090 ARRAYBOUNDSCHECK (arr, index);
1091 elements(arr)[index] = value;
1109 dupx (sp, 1, 1); sp+=1;
1113 dupx (sp, 1, 2); sp+=1;
1123 dupx (sp, 2, 1); sp+=2;
1127 dupx (sp, 2, 2); sp+=2;
1132 jobject tmp1 = POPA();
1133 jobject tmp2 = POPA();
1190 jint value2 = POPI();
1191 jint value1 = POPI();
1192 jint res = _Jv_divI (value1, value2);
1200 jlong value2 = POPL();
1201 jlong value1 = POPL();
1202 jlong res = _Jv_divJ (value1, value2);
1209 jfloat value2 = POPF();
1210 jfloat value1 = POPF();
1211 jfloat res = value1 / value2;
1218 jdouble value2 = POPD();
1219 jdouble value1 = POPD();
1220 jdouble res = value1 / value2;
1228 jint value2 = POPI();
1229 jint value1 = POPI();
1230 jint res = _Jv_remI (value1, value2);
1238 jlong value2 = POPL();
1239 jlong value1 = POPL();
1240 jlong res = _Jv_remJ (value1, value2);
1247 jfloat value2 = POPF();
1248 jfloat value1 = POPF();
1249 jfloat res = __ieee754_fmod (value1, value2);
1256 jdouble value2 = POPD();
1257 jdouble value1 = POPD();
1258 jdouble res = __ieee754_fmod (value1, value2);
1265 jint value = POPI();
1272 jlong value = POPL();
1279 jfloat value = POPF();
1286 jdouble value = POPD();
1293 jint shift = (POPI() & 0x1f);
1294 jint value = POPI();
1295 PUSHI (value << shift);
1301 jint shift = (POPI() & 0x3f);
1302 jlong value = POPL();
1303 PUSHL (value << shift);
1309 jint shift = (POPI() & 0x1f);
1310 jint value = POPI();
1311 PUSHI (value >> shift);
1317 jint shift = (POPI() & 0x3f);
1318 jlong value = POPL();
1319 PUSHL (value >> shift);
1325 jint shift = (POPI() & 0x1f);
1326 _Jv_uint value = (_Jv_uint) POPI();
1327 PUSHI ((jint) (value >> shift));
1333 jint shift = (POPI() & 0x3f);
1334 _Jv_ulong value = (_Jv_ulong) POPL();
1335 PUSHL ((jlong) (value >> shift));
1365 jint index = GET1U ();
1366 jint amount = GET1S ();
1367 locals[index].i += amount;
1372 {jlong value = POPI(); PUSHL (value);}
1376 {jfloat value = POPI(); PUSHF (value);}
1380 {jdouble value = POPI(); PUSHD (value);}
1384 {jint value = POPL(); PUSHI (value);}
1388 {jfloat value = POPL(); PUSHF (value);}
1392 {jdouble value = POPL(); PUSHD (value);}
1397 using namespace java::lang;
1398 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1405 using namespace java::lang;
1406 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1412 { jdouble value = POPF (); PUSHD(value); }
1417 using namespace java::lang;
1418 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1425 using namespace java::lang;
1426 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1432 { jfloat value = POPD (); PUSHF(value); }
1436 { jbyte value = POPI (); PUSHI(value); }
1440 { jchar value = POPI (); PUSHI(value); }
1444 { jshort value = POPI (); PUSHI(value); }
1449 jlong value2 = POPL ();
1450 jlong value1 = POPL ();
1451 if (value1 > value2)
1453 else if (value1 == value2)
1469 jfloat value2 = POPF ();
1470 jfloat value1 = POPF ();
1471 if (value1 > value2)
1473 else if (value1 == value2)
1475 else if (value1 < value2)
1491 jdouble value2 = POPD ();
1492 jdouble value1 = POPD ();
1493 if (value1 > value2)
1495 else if (value1 == value2)
1497 else if (value1 < value2)
1560 jint value2 = POPI();
1561 jint value1 = POPI();
1562 if (value1 == value2)
1571 jint value2 = POPI();
1572 jint value1 = POPI();
1573 if (value1 != value2)
1582 jint value2 = POPI();
1583 jint value1 = POPI();
1584 if (value1 < value2)
1593 jint value2 = POPI();
1594 jint value1 = POPI();
1595 if (value1 >= value2)
1604 jint value2 = POPI();
1605 jint value1 = POPI();
1606 if (value1 > value2)
1615 jint value2 = POPI();
1616 jint value1 = POPI();
1617 if (value1 <= value2)
1626 jobject value2 = POPA();
1627 jobject value1 = POPA();
1628 if (value1 == value2)
1637 jobject value2 = POPA();
1638 jobject value1 = POPA();
1639 if (value1 != value2)
1647 #ifndef DIRECT_THREADED
1648 // For direct threaded, goto and goto_w are the same.
1649 pc = pc - 1 + get4 (pc);
1651 #endif /* DIRECT_THREADED */
1657 #ifndef DIRECT_THREADED
1658 // For direct threaded, jsr and jsr_w are the same.
1660 pc_t next = pc - 1 + get4 (pc);
1662 PUSHA ((jobject) pc);
1666 #endif /* DIRECT_THREADED */
1669 pc_t next = GOTO_VAL();
1671 PUSHA ((jobject) pc);
1678 jint index = GET1U ();
1679 pc = (pc_t) PEEKA (index);
1685 #ifdef DIRECT_THREADED
1686 void *def = (pc++)->datum;
1690 jint low = INTVAL ();
1691 jint high = INTVAL ();
1693 if (index < low || index > high)
1694 pc = (insn_slot *) def;
1696 pc = (insn_slot *) ((pc + index - low)->datum);
1698 pc_t base_pc = pc - 1;
1699 int index = POPI ();
1701 pc_t base = (pc_t) meth->bytecode ();
1702 while ((pc - base) % 4 != 0)
1705 jint def = get4 (pc);
1706 jint low = get4 (pc + 4);
1707 jint high = get4 (pc + 8);
1708 if (index < low || index > high)
1711 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1712 #endif /* DIRECT_THREADED */
1718 #ifdef DIRECT_THREADED
1719 void *def = (pc++)->insn;
1723 jint npairs = INTVAL ();
1725 int max = npairs - 1;
1728 // Simple binary search...
1731 int half = (min + max) / 2;
1732 int match = pc[2 * half].int_val;
1737 pc = (insn_slot *) pc[2 * half + 1].datum;
1740 else if (index < match)
1741 // We can use HALF - 1 here because we check again on
1745 // We can use HALF + 1 here because we check again on
1749 if (index == pc[2 * min].int_val)
1750 pc = (insn_slot *) pc[2 * min + 1].datum;
1752 pc = (insn_slot *) def;
1754 unsigned char *base_pc = pc-1;
1757 unsigned char* base = meth->bytecode ();
1758 while ((pc-base) % 4 != 0)
1761 jint def = get4 (pc);
1762 jint npairs = get4 (pc+4);
1767 // Simple binary search...
1770 int half = (min+max)/2;
1771 int match = get4 (pc+ 4*(2 + 2*half));
1775 else if (index < match)
1776 // We can use HALF - 1 here because we check again on
1780 // We can use HALF + 1 here because we check again on
1785 if (index == get4 (pc+ 4*(2 + 2*min)))
1786 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1789 #endif /* DIRECT_THREADED */
1794 *(jobject *) retp = POPA ();
1798 *(jlong *) retp = POPL ();
1802 *(jfloat *) retp = POPF ();
1806 *(jdouble *) retp = POPD ();
1810 *(jint *) retp = POPI ();
1818 jint fieldref_index = GET2U ();
1819 SAVE_PC(); // Constant pool resolution could throw.
1820 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1821 _Jv_Field *field = pool_data[fieldref_index].field;
1823 if ((field->flags & Modifier::STATIC) == 0)
1824 throw_incompatible_class_change_error
1825 (JvNewStringLatin1 ("field no longer static"));
1827 jclass type = field->type;
1829 // We rewrite the instruction once we discover what it refers
1831 void *newinsn = NULL;
1832 if (type->isPrimitive ())
1834 switch (type->size_in_bytes)
1837 PUSHI (*field->u.byte_addr);
1838 newinsn = AMPAMP (getstatic_resolved_1);
1842 if (type == JvPrimClass (char))
1844 PUSHI (*field->u.char_addr);
1845 newinsn = AMPAMP (getstatic_resolved_char);
1849 PUSHI (*field->u.short_addr);
1850 newinsn = AMPAMP (getstatic_resolved_short);
1855 PUSHI(*field->u.int_addr);
1856 newinsn = AMPAMP (getstatic_resolved_4);
1860 PUSHL(*field->u.long_addr);
1861 newinsn = AMPAMP (getstatic_resolved_8);
1867 PUSHA(*field->u.object_addr);
1868 newinsn = AMPAMP (getstatic_resolved_obj);
1871 #ifdef DIRECT_THREADED
1872 REWRITE_INSN (newinsn, datum, field->u.addr);
1873 #endif /* DIRECT_THREADED */
1877 #ifdef DIRECT_THREADED
1878 getstatic_resolved_1:
1879 PUSHI (*(jbyte *) AVAL ());
1882 getstatic_resolved_char:
1883 PUSHI (*(jchar *) AVAL ());
1886 getstatic_resolved_short:
1887 PUSHI (*(jshort *) AVAL ());
1890 getstatic_resolved_4:
1891 PUSHI (*(jint *) AVAL ());
1894 getstatic_resolved_8:
1895 PUSHL (*(jlong *) AVAL ());
1898 getstatic_resolved_obj:
1899 PUSHA (*(jobject *) AVAL ());
1901 #endif /* DIRECT_THREADED */
1906 jint fieldref_index = GET2U ();
1907 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1908 _Jv_Field *field = pool_data[fieldref_index].field;
1910 if ((field->flags & Modifier::STATIC) != 0)
1911 throw_incompatible_class_change_error
1912 (JvNewStringLatin1 ("field is static"));
1914 jclass type = field->type;
1915 jint field_offset = field->u.boffset;
1917 jobject obj = POPA();
1920 void *newinsn = NULL;
1921 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1922 if (type->isPrimitive ())
1924 switch (type->size_in_bytes)
1927 PUSHI (val->byte_value);
1928 newinsn = AMPAMP (getfield_resolved_1);
1932 if (type == JvPrimClass (char))
1934 PUSHI (val->char_value);
1935 newinsn = AMPAMP (getfield_resolved_char);
1939 PUSHI (val->short_value);
1940 newinsn = AMPAMP (getfield_resolved_short);
1945 PUSHI (val->int_value);
1946 newinsn = AMPAMP (getfield_resolved_4);
1950 PUSHL (val->long_value);
1951 newinsn = AMPAMP (getfield_resolved_8);
1957 PUSHA (val->object_value);
1958 newinsn = AMPAMP (getfield_resolved_obj);
1961 #ifdef DIRECT_THREADED
1962 REWRITE_INSN (newinsn, int_val, field_offset);
1963 #endif /* DIRECT_THREADED */
1967 #ifdef DIRECT_THREADED
1968 getfield_resolved_1:
1970 char *obj = (char *) POPA ();
1972 PUSHI (*(jbyte *) (obj + INTVAL ()));
1976 getfield_resolved_char:
1978 char *obj = (char *) POPA ();
1980 PUSHI (*(jchar *) (obj + INTVAL ()));
1984 getfield_resolved_short:
1986 char *obj = (char *) POPA ();
1988 PUSHI (*(jshort *) (obj + INTVAL ()));
1992 getfield_resolved_4:
1994 char *obj = (char *) POPA ();
1996 PUSHI (*(jint *) (obj + INTVAL ()));
2000 getfield_resolved_8:
2002 char *obj = (char *) POPA ();
2004 PUSHL (*(jlong *) (obj + INTVAL ()));
2008 getfield_resolved_obj:
2010 char *obj = (char *) POPA ();
2012 PUSHA (*(jobject *) (obj + INTVAL ()));
2015 #endif /* DIRECT_THREADED */
2020 jint fieldref_index = GET2U ();
2021 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2022 _Jv_Field *field = pool_data[fieldref_index].field;
2024 jclass type = field->type;
2026 // ResolvePoolEntry cannot check this
2027 if ((field->flags & Modifier::STATIC) == 0)
2028 throw_incompatible_class_change_error
2029 (JvNewStringLatin1 ("field no longer static"));
2031 void *newinsn = NULL;
2032 if (type->isPrimitive ())
2034 switch (type->size_in_bytes)
2038 jint value = POPI();
2039 *field->u.byte_addr = value;
2040 newinsn = AMPAMP (putstatic_resolved_1);
2046 jint value = POPI();
2047 *field->u.char_addr = value;
2048 newinsn = AMPAMP (putstatic_resolved_2);
2054 jint value = POPI();
2055 *field->u.int_addr = value;
2056 newinsn = AMPAMP (putstatic_resolved_4);
2062 jlong value = POPL();
2063 *field->u.long_addr = value;
2064 newinsn = AMPAMP (putstatic_resolved_8);
2071 jobject value = POPA();
2072 *field->u.object_addr = value;
2073 newinsn = AMPAMP (putstatic_resolved_obj);
2076 #ifdef DIRECT_THREADED
2077 REWRITE_INSN (newinsn, datum, field->u.addr);
2078 #endif /* DIRECT_THREADED */
2082 #ifdef DIRECT_THREADED
2083 putstatic_resolved_1:
2084 *(jbyte *) AVAL () = POPI ();
2087 putstatic_resolved_2:
2088 *(jchar *) AVAL () = POPI ();
2091 putstatic_resolved_4:
2092 *(jint *) AVAL () = POPI ();
2095 putstatic_resolved_8:
2096 *(jlong *) AVAL () = POPL ();
2099 putstatic_resolved_obj:
2100 *(jobject *) AVAL () = POPA ();
2102 #endif /* DIRECT_THREADED */
2107 jint fieldref_index = GET2U ();
2108 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2109 _Jv_Field *field = pool_data[fieldref_index].field;
2111 jclass type = field->type;
2113 if ((field->flags & Modifier::STATIC) != 0)
2114 throw_incompatible_class_change_error
2115 (JvNewStringLatin1 ("field is static"));
2117 jint field_offset = field->u.boffset;
2119 void *newinsn = NULL;
2120 if (type->isPrimitive ())
2122 switch (type->size_in_bytes)
2126 jint value = POPI();
2127 jobject obj = POPA();
2129 *(jbyte*) ((char*)obj + field_offset) = value;
2130 newinsn = AMPAMP (putfield_resolved_1);
2136 jint value = POPI();
2137 jobject obj = POPA();
2139 *(jchar*) ((char*)obj + field_offset) = value;
2140 newinsn = AMPAMP (putfield_resolved_2);
2146 jint value = POPI();
2147 jobject obj = POPA();
2149 *(jint*) ((char*)obj + field_offset) = value;
2150 newinsn = AMPAMP (putfield_resolved_4);
2156 jlong value = POPL();
2157 jobject obj = POPA();
2159 *(jlong*) ((char*)obj + field_offset) = value;
2160 newinsn = AMPAMP (putfield_resolved_8);
2167 jobject value = POPA();
2168 jobject obj = POPA();
2170 *(jobject*) ((char*)obj + field_offset) = value;
2171 newinsn = AMPAMP (putfield_resolved_obj);
2174 #ifdef DIRECT_THREADED
2175 REWRITE_INSN (newinsn, int_val, field_offset);
2176 #endif /* DIRECT_THREADED */
2180 #ifdef DIRECT_THREADED
2181 putfield_resolved_1:
2184 char *obj = (char *) POPA ();
2186 *(jbyte *) (obj + INTVAL ()) = val;
2190 putfield_resolved_2:
2193 char *obj = (char *) POPA ();
2195 *(jchar *) (obj + INTVAL ()) = val;
2199 putfield_resolved_4:
2202 char *obj = (char *) POPA ();
2204 *(jint *) (obj + INTVAL ()) = val;
2208 putfield_resolved_8:
2210 jlong val = POPL ();
2211 char *obj = (char *) POPA ();
2213 *(jlong *) (obj + INTVAL ()) = val;
2217 putfield_resolved_obj:
2219 jobject val = POPA ();
2220 char *obj = (char *) POPA ();
2222 *(jobject *) (obj + INTVAL ()) = val;
2225 #endif /* DIRECT_THREADED */
2230 int index = GET2U ();
2232 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2235 sp -= rmeth->stack_item_count;
2237 // We don't use NULLCHECK here because we can't rely on that
2238 // working for <init>. So instead we do an explicit test.
2242 throw_null_pointer_exception ();
2245 fun = (void (*)()) rmeth->method->ncode;
2247 #ifdef DIRECT_THREADED
2248 // Rewrite instruction so that we use a faster pre-resolved
2250 REWRITE_INSN (&&invokespecial_resolved, datum, rmeth);
2251 #endif /* DIRECT_THREADED */
2253 goto perform_invoke;
2255 #ifdef DIRECT_THREADED
2256 invokespecial_resolved:
2259 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2260 sp -= rmeth->stack_item_count;
2261 // We don't use NULLCHECK here because we can't rely on that
2262 // working for <init>. So instead we do an explicit test.
2265 throw_null_pointer_exception ();
2267 fun = (void (*)()) rmeth->method->ncode;
2269 goto perform_invoke;
2270 #endif /* DIRECT_THREADED */
2275 int index = GET2U ();
2277 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2280 sp -= rmeth->stack_item_count;
2282 fun = (void (*)()) rmeth->method->ncode;
2284 #ifdef DIRECT_THREADED
2285 // Rewrite instruction so that we use a faster pre-resolved
2287 REWRITE_INSN (&&invokestatic_resolved, datum, rmeth);
2288 #endif /* DIRECT_THREADED */
2290 goto perform_invoke;
2292 #ifdef DIRECT_THREADED
2293 invokestatic_resolved:
2296 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2297 sp -= rmeth->stack_item_count;
2298 fun = (void (*)()) rmeth->method->ncode;
2300 goto perform_invoke;
2301 #endif /* DIRECT_THREADED */
2303 insn_invokeinterface:
2306 int index = GET2U ();
2308 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2311 sp -= rmeth->stack_item_count;
2313 jobject rcv = sp[0].o;
2318 _Jv_LookupInterfaceMethod (rcv->getClass (),
2319 rmeth->method->name,
2320 rmeth->method->signature);
2322 #ifdef DIRECT_THREADED
2323 // Rewrite instruction so that we use a faster pre-resolved
2325 REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth);
2327 // Skip dummy bytes.
2329 #endif /* DIRECT_THREADED */
2331 goto perform_invoke;
2333 #ifdef DIRECT_THREADED
2334 invokeinterface_resolved:
2337 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2338 sp -= rmeth->stack_item_count;
2339 jobject rcv = sp[0].o;
2342 _Jv_LookupInterfaceMethod (rcv->getClass (),
2343 rmeth->method->name,
2344 rmeth->method->signature);
2346 goto perform_invoke;
2347 #endif /* DIRECT_THREADED */
2352 int index = GET2U ();
2353 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2355 /* VM spec, section 3.11.5 */
2356 if ((klass->getModifiers() & Modifier::ABSTRACT)
2357 || klass->isInterface())
2358 throw new java::lang::InstantiationException;
2359 jobject res = _Jv_AllocObject (klass);
2362 #ifdef DIRECT_THREADED
2363 REWRITE_INSN (&&new_resolved, datum, klass);
2364 #endif /* DIRECT_THREADED */
2368 #ifdef DIRECT_THREADED
2371 jclass klass = (jclass) AVAL ();
2372 jobject res = _Jv_AllocObject (klass);
2376 #endif /* DIRECT_THREADED */
2380 int atype = GET1U ();
2382 jobject result = _Jv_NewArray (atype, size);
2390 int index = GET2U ();
2391 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2394 jobject result = _Jv_NewObjectArray (size, klass, 0);
2397 #ifdef DIRECT_THREADED
2398 REWRITE_INSN (&&anewarray_resolved, datum, klass);
2399 #endif /* DIRECT_THREADED */
2403 #ifdef DIRECT_THREADED
2406 jclass klass = (jclass) AVAL ();
2408 jobject result = _Jv_NewObjectArray (size, klass, 0);
2412 #endif /* DIRECT_THREADED */
2416 __JArray *arr = (__JArray*)POPA();
2417 NULLARRAYCHECK (arr);
2418 PUSHI (arr->length);
2424 jobject value = POPA();
2425 throw static_cast<jthrowable>(value);
2432 jobject value = POPA();
2433 jint index = GET2U ();
2434 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2437 value = (jobject) _Jv_CheckCast (to, value);
2441 #ifdef DIRECT_THREADED
2442 REWRITE_INSN (&&checkcast_resolved, datum, to);
2443 #endif /* DIRECT_THREADED */
2447 #ifdef DIRECT_THREADED
2451 jobject value = POPA ();
2452 jclass to = (jclass) AVAL ();
2453 value = (jobject) _Jv_CheckCast (to, value);
2457 #endif /* DIRECT_THREADED */
2462 jobject value = POPA();
2463 jint index = GET2U ();
2464 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2466 PUSHI (to->isInstance (value));
2468 #ifdef DIRECT_THREADED
2469 REWRITE_INSN (&&instanceof_resolved, datum, to);
2470 #endif /* DIRECT_THREADED */
2474 #ifdef DIRECT_THREADED
2475 instanceof_resolved:
2477 jobject value = POPA ();
2478 jclass to = (jclass) AVAL ();
2479 PUSHI (to->isInstance (value));
2482 #endif /* DIRECT_THREADED */
2486 jobject value = POPA();
2488 _Jv_MonitorEnter (value);
2494 jobject value = POPA();
2496 _Jv_MonitorExit (value);
2502 jobject val = POPA();
2512 jobject val = POPA();
2520 insn_multianewarray:
2523 int kind_index = GET2U ();
2527 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2529 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2531 for (int i = dim - 1; i >= 0; i--)
2536 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2542 #ifndef DIRECT_THREADED
2545 jint the_mod_op = get1u (pc++);
2546 jint wide = get2u (pc); pc += 2;
2591 pc = (unsigned char*) PEEKA (wide);
2596 jint amount = get2s (pc); pc += 2;
2597 jint value = PEEKI (wide);
2598 POKEI (wide, value+amount);
2603 throw_internal_error ("illegal bytecode modified by wide");
2607 #endif /* DIRECT_THREADED */
2611 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2613 // Send JVMTI notification
2614 using namespace ::java::lang;
2615 jmethodID method = meth->self;
2616 jlocation location = meth->insn_index (pc - 1);
2617 Thread *thread = Thread::currentThread ();
2618 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2620 // Save the insn here since the breakpoint could be removed
2621 // before the JVMTI notification returns.
2622 using namespace gnu::gcj::jvmti;
2624 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2626 JvAssert (bp != NULL);
2627 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2629 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2632 // Continue execution
2633 #ifdef DIRECT_THREADED
2636 goto *(insn_target[*opc]);
2640 catch (java::lang::Throwable *ex)
2643 // This needs to be done before the pc is changed.
2644 jlong throw_loc = meth->insn_index (pc);
2646 // Check if the exception is handled and, if so, set the pc to the start
2647 // of the appropriate catch block.
2648 if (meth->check_handler (&pc, meth, ex))
2651 sp++->o = ex; // Push exception.
2653 if (JVMTI_REQUESTED_EVENT (Exception))
2655 using namespace gnu::gcj::jvmti;
2656 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2657 jlong catch_loc = meth->insn_index (pc);
2658 ExceptionEvent::postExceptionEvent (thread, throw_meth,
2659 throw_loc, ex, throw_meth,
2666 if (JVMTI_REQUESTED_EVENT (Exception))
2668 using namespace gnu::gcj::jvmti;
2669 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2670 ExceptionEvent::postExceptionEvent (thread, throw_meth, throw_loc,
2674 // No handler, so re-throw.