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
351 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
353 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
354 jmethodID method = meth->self; \
355 jlocation loc = meth->insn_index (pc); \
356 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
359 goto *((pc++)->insn); \
364 #define NEXT_INSN goto *((pc++)->insn)
367 #define INTVAL() ((pc++)->int_val)
368 #define AVAL() ((pc++)->datum)
370 #define GET1S() INTVAL ()
371 #define GET2S() INTVAL ()
372 #define GET1U() INTVAL ()
373 #define GET2U() INTVAL ()
374 #define AVAL1U() AVAL ()
375 #define AVAL2U() AVAL ()
376 #define AVAL2UP() AVAL ()
377 #define SKIP_GOTO ++pc
378 #define GOTO_VAL() (insn_slot *) pc->datum
379 #define PCVAL(unionval) unionval.p
380 #define AMPAMP(label) &&label
382 // Compile if we must. NOTE: Double-check locking.
383 if (meth->prepared == NULL)
385 _Jv_MutexLock (&compile_mutex);
386 if (meth->prepared == NULL)
387 meth->compile (insn_target);
388 _Jv_MutexUnlock (&compile_mutex);
391 // If we're only compiling, stop here
395 pc = (insn_slot *) meth->prepared;
403 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
405 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
406 jmethodID method = meth->self; \
407 jlocation loc = meth->insn_index (pc); \
408 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
411 goto *(insn_target[*pc++])
413 #define NEXT_INSN goto *(insn_target[*pc++])
416 #define GET1S() get1s (pc++)
417 #define GET2S() (pc += 2, get2s (pc- 2))
418 #define GET1U() get1u (pc++)
419 #define GET2U() (pc += 2, get2u (pc - 2))
420 // Note that these could be more efficient when not handling 'ldc
423 ({ int index = get1u (pc++); \
424 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
426 ({ int index = get2u (pc); pc += 2; \
427 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
428 // Note that we don't need to resolve the pool entry here as class
429 // constants are never wide.
430 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
431 #define SKIP_GOTO pc += 2
432 #define GOTO_VAL() pc - 1 + get2s (pc)
433 #define PCVAL(unionval) unionval.i
434 #define AMPAMP(label) NULL
436 pc = meth->bytecode ();
438 #endif /* DIRECT_THREADED */
440 #define TAKE_GOTO pc = GOTO_VAL ()
442 /* Go straight at it! the ffi raw format matches the internal
443 stack representation exactly. At least, that's the idea.
445 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
447 _Jv_word *pool_data = meth->defining_class->constants.data;
449 /* These three are temporaries for common code used by several
452 _Jv_ResolvedMethod* rmeth;
457 // We keep nop around. It is used if we're interpreting the
458 // bytecodes and not doing direct threading.
462 /* The first few instructions here are ordered according to their
463 frequency, in the hope that this will improve code locality a
466 insn_aload_0: // 0x2a
474 insn_iload_1: // 0x1b
478 insn_invokevirtual: // 0xb6
481 int index = GET2U ();
483 /* _Jv_Linker::resolve_pool_entry returns immediately if the
484 * value already is resolved. If we want to clutter up the
485 * code here to gain a little performance, then we can check
486 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
487 * directly. For now, I don't think it is worth it. */
489 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
492 sp -= rmeth->stack_item_count;
494 if (rmeth->method->accflags & Modifier::FINAL)
496 // We can't rely on NULLCHECK working if the method is final.
498 throw_null_pointer_exception ();
500 // Final methods might not appear in the vtable.
501 fun = (void (*)()) rmeth->method->ncode;
506 jobject rcv = sp[0].o;
507 _Jv_VTable *table = *(_Jv_VTable**) rcv;
508 fun = (void (*)()) table->get_method (rmeth->method->index);
511 #ifdef DIRECT_THREADED
512 // Rewrite instruction so that we use a faster pre-resolved
514 pc[-2].insn = &&invokevirtual_resolved;
515 pc[-1].datum = rmeth;
516 #endif /* DIRECT_THREADED */
520 #ifdef DIRECT_THREADED
521 invokevirtual_resolved:
524 rmeth = (_Jv_ResolvedMethod *) AVAL ();
525 sp -= rmeth->stack_item_count;
527 if (rmeth->method->accflags & Modifier::FINAL)
529 // We can't rely on NULLCHECK working if the method is final.
531 throw_null_pointer_exception ();
533 // Final methods might not appear in the vtable.
534 fun = (void (*)()) rmeth->method->ncode;
538 jobject rcv = sp[0].o;
539 _Jv_VTable *table = *(_Jv_VTable**) rcv;
540 fun = (void (*)()) table->get_method (rmeth->method->index);
544 #endif /* DIRECT_THREADED */
548 /* here goes the magic again... */
549 ffi_cif *cif = &rmeth->cif;
550 ffi_raw *raw = (ffi_raw*) sp;
554 #if FFI_NATIVE_RAW_API
555 /* We assume that this is only implemented if it's correct */
556 /* to use it here. On a 64 bit machine, it never is. */
557 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
559 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
562 int rtype = cif->rtype->type;
564 /* the likelyhood of object, int, or void return is very high,
565 * so those are checked before the switch */
566 if (rtype == FFI_TYPE_POINTER)
568 PUSHA (rvalue.object_value);
570 else if (rtype == FFI_TYPE_SINT32)
572 PUSHI (rvalue.int_value);
574 else if (rtype == FFI_TYPE_VOID)
583 PUSHI ((jbyte)(rvalue.int_value & 0xff));
586 case FFI_TYPE_SINT16:
587 PUSHI ((jshort)(rvalue.int_value & 0xffff));
590 case FFI_TYPE_UINT16:
591 PUSHI (rvalue.int_value & 0xffff);
595 PUSHF (rvalue.float_value);
598 case FFI_TYPE_DOUBLE:
599 PUSHD (rvalue.double_value);
602 case FFI_TYPE_SINT64:
603 PUSHL (rvalue.long_value);
607 throw_internal_error ("unknown return type in invokeXXX");
674 // For direct threaded, bipush and sipush are the same.
675 #ifndef DIRECT_THREADED
678 #endif /* DIRECT_THREADED */
684 // For direct threaded, ldc and ldc_w are the same.
685 #ifndef DIRECT_THREADED
686 PUSHA ((jobject) AVAL1U ());
688 #endif /* DIRECT_THREADED */
690 PUSHA ((jobject) AVAL2U ());
693 #ifdef DIRECT_THREADED
694 // For direct threaded we have a separate 'ldc class' operation.
698 // We could rewrite the instruction at this point.
699 int index = INTVAL ();
700 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
705 #endif /* DIRECT_THREADED */
709 void *where = AVAL2UP ();
710 memcpy (sp, where, 2*sizeof (_Jv_word));
806 jintArray arr = (jintArray) POPA();
807 NULLARRAYCHECK (arr);
808 ARRAYBOUNDSCHECK (arr, index);
809 PUSHI( elements(arr)[index] );
816 jlongArray arr = (jlongArray) POPA();
817 NULLARRAYCHECK (arr);
818 ARRAYBOUNDSCHECK (arr, index);
819 PUSHL( elements(arr)[index] );
826 jfloatArray arr = (jfloatArray) POPA();
827 NULLARRAYCHECK (arr);
828 ARRAYBOUNDSCHECK (arr, index);
829 PUSHF( elements(arr)[index] );
836 jdoubleArray arr = (jdoubleArray) POPA();
837 NULLARRAYCHECK (arr);
838 ARRAYBOUNDSCHECK (arr, index);
839 PUSHD( elements(arr)[index] );
846 jobjectArray arr = (jobjectArray) POPA();
847 NULLARRAYCHECK (arr);
848 ARRAYBOUNDSCHECK (arr, index);
849 PUSHA( elements(arr)[index] );
856 jbyteArray arr = (jbyteArray) POPA();
857 NULLARRAYCHECK (arr);
858 ARRAYBOUNDSCHECK (arr, index);
859 PUSHI( elements(arr)[index] );
866 jcharArray arr = (jcharArray) POPA();
867 NULLARRAYCHECK (arr);
868 ARRAYBOUNDSCHECK (arr, index);
869 PUSHI( elements(arr)[index] );
876 jshortArray arr = (jshortArray) POPA();
877 NULLARRAYCHECK (arr);
878 ARRAYBOUNDSCHECK (arr, index);
879 PUSHI( elements(arr)[index] );
987 jintArray arr = (jintArray) POPA();
988 NULLARRAYCHECK (arr);
989 ARRAYBOUNDSCHECK (arr, index);
990 elements(arr)[index] = value;
996 jlong value = POPL();
998 jlongArray arr = (jlongArray) POPA();
999 NULLARRAYCHECK (arr);
1000 ARRAYBOUNDSCHECK (arr, index);
1001 elements(arr)[index] = value;
1007 jfloat value = POPF();
1008 jint index = POPI();
1009 jfloatArray arr = (jfloatArray) POPA();
1010 NULLARRAYCHECK (arr);
1011 ARRAYBOUNDSCHECK (arr, index);
1012 elements(arr)[index] = value;
1018 jdouble value = POPD();
1019 jint index = POPI();
1020 jdoubleArray arr = (jdoubleArray) POPA();
1021 NULLARRAYCHECK (arr);
1022 ARRAYBOUNDSCHECK (arr, index);
1023 elements(arr)[index] = value;
1029 jobject value = POPA();
1030 jint index = POPI();
1031 jobjectArray arr = (jobjectArray) POPA();
1032 NULLARRAYCHECK (arr);
1033 ARRAYBOUNDSCHECK (arr, index);
1034 _Jv_CheckArrayStore (arr, value);
1035 elements(arr)[index] = value;
1041 jbyte value = (jbyte) POPI();
1042 jint index = POPI();
1043 jbyteArray arr = (jbyteArray) POPA();
1044 NULLARRAYCHECK (arr);
1045 ARRAYBOUNDSCHECK (arr, index);
1046 elements(arr)[index] = value;
1052 jchar value = (jchar) POPI();
1053 jint index = POPI();
1054 jcharArray arr = (jcharArray) POPA();
1055 NULLARRAYCHECK (arr);
1056 ARRAYBOUNDSCHECK (arr, index);
1057 elements(arr)[index] = value;
1063 jshort value = (jshort) POPI();
1064 jint index = POPI();
1065 jshortArray arr = (jshortArray) POPA();
1066 NULLARRAYCHECK (arr);
1067 ARRAYBOUNDSCHECK (arr, index);
1068 elements(arr)[index] = value;
1086 dupx (sp, 1, 1); sp+=1;
1090 dupx (sp, 1, 2); sp+=1;
1100 dupx (sp, 2, 1); sp+=2;
1104 dupx (sp, 2, 2); sp+=2;
1109 jobject tmp1 = POPA();
1110 jobject tmp2 = POPA();
1167 jint value2 = POPI();
1168 jint value1 = POPI();
1169 jint res = _Jv_divI (value1, value2);
1177 jlong value2 = POPL();
1178 jlong value1 = POPL();
1179 jlong res = _Jv_divJ (value1, value2);
1186 jfloat value2 = POPF();
1187 jfloat value1 = POPF();
1188 jfloat res = value1 / value2;
1195 jdouble value2 = POPD();
1196 jdouble value1 = POPD();
1197 jdouble res = value1 / value2;
1205 jint value2 = POPI();
1206 jint value1 = POPI();
1207 jint res = _Jv_remI (value1, value2);
1215 jlong value2 = POPL();
1216 jlong value1 = POPL();
1217 jlong res = _Jv_remJ (value1, value2);
1224 jfloat value2 = POPF();
1225 jfloat value1 = POPF();
1226 jfloat res = __ieee754_fmod (value1, value2);
1233 jdouble value2 = POPD();
1234 jdouble value1 = POPD();
1235 jdouble res = __ieee754_fmod (value1, value2);
1242 jint value = POPI();
1249 jlong value = POPL();
1256 jfloat value = POPF();
1263 jdouble value = POPD();
1270 jint shift = (POPI() & 0x1f);
1271 jint value = POPI();
1272 PUSHI (value << shift);
1278 jint shift = (POPI() & 0x3f);
1279 jlong value = POPL();
1280 PUSHL (value << shift);
1286 jint shift = (POPI() & 0x1f);
1287 jint value = POPI();
1288 PUSHI (value >> shift);
1294 jint shift = (POPI() & 0x3f);
1295 jlong value = POPL();
1296 PUSHL (value >> shift);
1302 jint shift = (POPI() & 0x1f);
1303 _Jv_uint value = (_Jv_uint) POPI();
1304 PUSHI ((jint) (value >> shift));
1310 jint shift = (POPI() & 0x3f);
1311 _Jv_ulong value = (_Jv_ulong) POPL();
1312 PUSHL ((jlong) (value >> shift));
1342 jint index = GET1U ();
1343 jint amount = GET1S ();
1344 locals[index].i += amount;
1349 {jlong value = POPI(); PUSHL (value);}
1353 {jfloat value = POPI(); PUSHF (value);}
1357 {jdouble value = POPI(); PUSHD (value);}
1361 {jint value = POPL(); PUSHI (value);}
1365 {jfloat value = POPL(); PUSHF (value);}
1369 {jdouble value = POPL(); PUSHD (value);}
1374 using namespace java::lang;
1375 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1382 using namespace java::lang;
1383 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1389 { jdouble value = POPF (); PUSHD(value); }
1394 using namespace java::lang;
1395 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1402 using namespace java::lang;
1403 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1409 { jfloat value = POPD (); PUSHF(value); }
1413 { jbyte value = POPI (); PUSHI(value); }
1417 { jchar value = POPI (); PUSHI(value); }
1421 { jshort value = POPI (); PUSHI(value); }
1426 jlong value2 = POPL ();
1427 jlong value1 = POPL ();
1428 if (value1 > value2)
1430 else if (value1 == value2)
1446 jfloat value2 = POPF ();
1447 jfloat value1 = POPF ();
1448 if (value1 > value2)
1450 else if (value1 == value2)
1452 else if (value1 < value2)
1468 jdouble value2 = POPD ();
1469 jdouble value1 = POPD ();
1470 if (value1 > value2)
1472 else if (value1 == value2)
1474 else if (value1 < value2)
1537 jint value2 = POPI();
1538 jint value1 = POPI();
1539 if (value1 == value2)
1548 jint value2 = POPI();
1549 jint value1 = POPI();
1550 if (value1 != value2)
1559 jint value2 = POPI();
1560 jint value1 = POPI();
1561 if (value1 < value2)
1570 jint value2 = POPI();
1571 jint value1 = POPI();
1572 if (value1 >= value2)
1581 jint value2 = POPI();
1582 jint value1 = POPI();
1583 if (value1 > value2)
1592 jint value2 = POPI();
1593 jint value1 = POPI();
1594 if (value1 <= value2)
1603 jobject value2 = POPA();
1604 jobject value1 = POPA();
1605 if (value1 == value2)
1614 jobject value2 = POPA();
1615 jobject value1 = POPA();
1616 if (value1 != value2)
1624 #ifndef DIRECT_THREADED
1625 // For direct threaded, goto and goto_w are the same.
1626 pc = pc - 1 + get4 (pc);
1628 #endif /* DIRECT_THREADED */
1634 #ifndef DIRECT_THREADED
1635 // For direct threaded, jsr and jsr_w are the same.
1637 pc_t next = pc - 1 + get4 (pc);
1639 PUSHA ((jobject) pc);
1643 #endif /* DIRECT_THREADED */
1646 pc_t next = GOTO_VAL();
1648 PUSHA ((jobject) pc);
1655 jint index = GET1U ();
1656 pc = (pc_t) PEEKA (index);
1662 #ifdef DIRECT_THREADED
1663 void *def = (pc++)->datum;
1667 jint low = INTVAL ();
1668 jint high = INTVAL ();
1670 if (index < low || index > high)
1671 pc = (insn_slot *) def;
1673 pc = (insn_slot *) ((pc + index - low)->datum);
1675 pc_t base_pc = pc - 1;
1676 int index = POPI ();
1678 pc_t base = (pc_t) meth->bytecode ();
1679 while ((pc - base) % 4 != 0)
1682 jint def = get4 (pc);
1683 jint low = get4 (pc + 4);
1684 jint high = get4 (pc + 8);
1685 if (index < low || index > high)
1688 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1689 #endif /* DIRECT_THREADED */
1695 #ifdef DIRECT_THREADED
1696 void *def = (pc++)->insn;
1700 jint npairs = INTVAL ();
1702 int max = npairs - 1;
1705 // Simple binary search...
1708 int half = (min + max) / 2;
1709 int match = pc[2 * half].int_val;
1714 pc = (insn_slot *) pc[2 * half + 1].datum;
1717 else if (index < match)
1718 // We can use HALF - 1 here because we check again on
1722 // We can use HALF + 1 here because we check again on
1726 if (index == pc[2 * min].int_val)
1727 pc = (insn_slot *) pc[2 * min + 1].datum;
1729 pc = (insn_slot *) def;
1731 unsigned char *base_pc = pc-1;
1734 unsigned char* base = meth->bytecode ();
1735 while ((pc-base) % 4 != 0)
1738 jint def = get4 (pc);
1739 jint npairs = get4 (pc+4);
1744 // Simple binary search...
1747 int half = (min+max)/2;
1748 int match = get4 (pc+ 4*(2 + 2*half));
1752 else if (index < match)
1753 // We can use HALF - 1 here because we check again on
1757 // We can use HALF + 1 here because we check again on
1762 if (index == get4 (pc+ 4*(2 + 2*min)))
1763 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1766 #endif /* DIRECT_THREADED */
1771 *(jobject *) retp = POPA ();
1775 *(jlong *) retp = POPL ();
1779 *(jfloat *) retp = POPF ();
1783 *(jdouble *) retp = POPD ();
1787 *(jint *) retp = POPI ();
1795 jint fieldref_index = GET2U ();
1796 SAVE_PC(); // Constant pool resolution could throw.
1797 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1798 _Jv_Field *field = pool_data[fieldref_index].field;
1800 if ((field->flags & Modifier::STATIC) == 0)
1801 throw_incompatible_class_change_error
1802 (JvNewStringLatin1 ("field no longer static"));
1804 jclass type = field->type;
1806 // We rewrite the instruction once we discover what it refers
1808 void *newinsn = NULL;
1809 if (type->isPrimitive ())
1811 switch (type->size_in_bytes)
1814 PUSHI (*field->u.byte_addr);
1815 newinsn = AMPAMP (getstatic_resolved_1);
1819 if (type == JvPrimClass (char))
1821 PUSHI (*field->u.char_addr);
1822 newinsn = AMPAMP (getstatic_resolved_char);
1826 PUSHI (*field->u.short_addr);
1827 newinsn = AMPAMP (getstatic_resolved_short);
1832 PUSHI(*field->u.int_addr);
1833 newinsn = AMPAMP (getstatic_resolved_4);
1837 PUSHL(*field->u.long_addr);
1838 newinsn = AMPAMP (getstatic_resolved_8);
1844 PUSHA(*field->u.object_addr);
1845 newinsn = AMPAMP (getstatic_resolved_obj);
1848 #ifdef DIRECT_THREADED
1849 pc[-2].insn = newinsn;
1850 pc[-1].datum = field->u.addr;
1851 #endif /* DIRECT_THREADED */
1855 #ifdef DIRECT_THREADED
1856 getstatic_resolved_1:
1857 PUSHI (*(jbyte *) AVAL ());
1860 getstatic_resolved_char:
1861 PUSHI (*(jchar *) AVAL ());
1864 getstatic_resolved_short:
1865 PUSHI (*(jshort *) AVAL ());
1868 getstatic_resolved_4:
1869 PUSHI (*(jint *) AVAL ());
1872 getstatic_resolved_8:
1873 PUSHL (*(jlong *) AVAL ());
1876 getstatic_resolved_obj:
1877 PUSHA (*(jobject *) AVAL ());
1879 #endif /* DIRECT_THREADED */
1884 jint fieldref_index = GET2U ();
1885 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1886 _Jv_Field *field = pool_data[fieldref_index].field;
1888 if ((field->flags & Modifier::STATIC) != 0)
1889 throw_incompatible_class_change_error
1890 (JvNewStringLatin1 ("field is static"));
1892 jclass type = field->type;
1893 jint field_offset = field->u.boffset;
1895 jobject obj = POPA();
1898 void *newinsn = NULL;
1899 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1900 if (type->isPrimitive ())
1902 switch (type->size_in_bytes)
1905 PUSHI (val->byte_value);
1906 newinsn = AMPAMP (getfield_resolved_1);
1910 if (type == JvPrimClass (char))
1912 PUSHI (val->char_value);
1913 newinsn = AMPAMP (getfield_resolved_char);
1917 PUSHI (val->short_value);
1918 newinsn = AMPAMP (getfield_resolved_short);
1923 PUSHI (val->int_value);
1924 newinsn = AMPAMP (getfield_resolved_4);
1928 PUSHL (val->long_value);
1929 newinsn = AMPAMP (getfield_resolved_8);
1935 PUSHA (val->object_value);
1936 newinsn = AMPAMP (getfield_resolved_obj);
1939 #ifdef DIRECT_THREADED
1940 pc[-2].insn = newinsn;
1941 pc[-1].int_val = field_offset;
1942 #endif /* DIRECT_THREADED */
1946 #ifdef DIRECT_THREADED
1947 getfield_resolved_1:
1949 char *obj = (char *) POPA ();
1951 PUSHI (*(jbyte *) (obj + INTVAL ()));
1955 getfield_resolved_char:
1957 char *obj = (char *) POPA ();
1959 PUSHI (*(jchar *) (obj + INTVAL ()));
1963 getfield_resolved_short:
1965 char *obj = (char *) POPA ();
1967 PUSHI (*(jshort *) (obj + INTVAL ()));
1971 getfield_resolved_4:
1973 char *obj = (char *) POPA ();
1975 PUSHI (*(jint *) (obj + INTVAL ()));
1979 getfield_resolved_8:
1981 char *obj = (char *) POPA ();
1983 PUSHL (*(jlong *) (obj + INTVAL ()));
1987 getfield_resolved_obj:
1989 char *obj = (char *) POPA ();
1991 PUSHA (*(jobject *) (obj + INTVAL ()));
1994 #endif /* DIRECT_THREADED */
1999 jint fieldref_index = GET2U ();
2000 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2001 _Jv_Field *field = pool_data[fieldref_index].field;
2003 jclass type = field->type;
2005 // ResolvePoolEntry cannot check this
2006 if ((field->flags & Modifier::STATIC) == 0)
2007 throw_incompatible_class_change_error
2008 (JvNewStringLatin1 ("field no longer static"));
2010 void *newinsn = NULL;
2011 if (type->isPrimitive ())
2013 switch (type->size_in_bytes)
2017 jint value = POPI();
2018 *field->u.byte_addr = value;
2019 newinsn = AMPAMP (putstatic_resolved_1);
2025 jint value = POPI();
2026 *field->u.char_addr = value;
2027 newinsn = AMPAMP (putstatic_resolved_2);
2033 jint value = POPI();
2034 *field->u.int_addr = value;
2035 newinsn = AMPAMP (putstatic_resolved_4);
2041 jlong value = POPL();
2042 *field->u.long_addr = value;
2043 newinsn = AMPAMP (putstatic_resolved_8);
2050 jobject value = POPA();
2051 *field->u.object_addr = value;
2052 newinsn = AMPAMP (putstatic_resolved_obj);
2055 #ifdef DIRECT_THREADED
2056 pc[-2].insn = newinsn;
2057 pc[-1].datum = field->u.addr;
2058 #endif /* DIRECT_THREADED */
2062 #ifdef DIRECT_THREADED
2063 putstatic_resolved_1:
2064 *(jbyte *) AVAL () = POPI ();
2067 putstatic_resolved_2:
2068 *(jchar *) AVAL () = POPI ();
2071 putstatic_resolved_4:
2072 *(jint *) AVAL () = POPI ();
2075 putstatic_resolved_8:
2076 *(jlong *) AVAL () = POPL ();
2079 putstatic_resolved_obj:
2080 *(jobject *) AVAL () = POPA ();
2082 #endif /* DIRECT_THREADED */
2087 jint fieldref_index = GET2U ();
2088 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2089 _Jv_Field *field = pool_data[fieldref_index].field;
2091 jclass type = field->type;
2093 if ((field->flags & Modifier::STATIC) != 0)
2094 throw_incompatible_class_change_error
2095 (JvNewStringLatin1 ("field is static"));
2097 jint field_offset = field->u.boffset;
2099 void *newinsn = NULL;
2100 if (type->isPrimitive ())
2102 switch (type->size_in_bytes)
2106 jint value = POPI();
2107 jobject obj = POPA();
2109 *(jbyte*) ((char*)obj + field_offset) = value;
2110 newinsn = AMPAMP (putfield_resolved_1);
2116 jint value = POPI();
2117 jobject obj = POPA();
2119 *(jchar*) ((char*)obj + field_offset) = value;
2120 newinsn = AMPAMP (putfield_resolved_2);
2126 jint value = POPI();
2127 jobject obj = POPA();
2129 *(jint*) ((char*)obj + field_offset) = value;
2130 newinsn = AMPAMP (putfield_resolved_4);
2136 jlong value = POPL();
2137 jobject obj = POPA();
2139 *(jlong*) ((char*)obj + field_offset) = value;
2140 newinsn = AMPAMP (putfield_resolved_8);
2147 jobject value = POPA();
2148 jobject obj = POPA();
2150 *(jobject*) ((char*)obj + field_offset) = value;
2151 newinsn = AMPAMP (putfield_resolved_obj);
2154 #ifdef DIRECT_THREADED
2155 pc[-2].insn = newinsn;
2156 pc[-1].int_val = field_offset;
2157 #endif /* DIRECT_THREADED */
2161 #ifdef DIRECT_THREADED
2162 putfield_resolved_1:
2165 char *obj = (char *) POPA ();
2167 *(jbyte *) (obj + INTVAL ()) = val;
2171 putfield_resolved_2:
2174 char *obj = (char *) POPA ();
2176 *(jchar *) (obj + INTVAL ()) = val;
2180 putfield_resolved_4:
2183 char *obj = (char *) POPA ();
2185 *(jint *) (obj + INTVAL ()) = val;
2189 putfield_resolved_8:
2191 jlong val = POPL ();
2192 char *obj = (char *) POPA ();
2194 *(jlong *) (obj + INTVAL ()) = val;
2198 putfield_resolved_obj:
2200 jobject val = POPA ();
2201 char *obj = (char *) POPA ();
2203 *(jobject *) (obj + INTVAL ()) = val;
2206 #endif /* DIRECT_THREADED */
2211 int index = GET2U ();
2213 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2216 sp -= rmeth->stack_item_count;
2218 // We don't use NULLCHECK here because we can't rely on that
2219 // working for <init>. So instead we do an explicit test.
2223 throw_null_pointer_exception ();
2226 fun = (void (*)()) rmeth->method->ncode;
2228 #ifdef DIRECT_THREADED
2229 // Rewrite instruction so that we use a faster pre-resolved
2231 pc[-2].insn = &&invokespecial_resolved;
2232 pc[-1].datum = rmeth;
2233 #endif /* DIRECT_THREADED */
2235 goto perform_invoke;
2237 #ifdef DIRECT_THREADED
2238 invokespecial_resolved:
2241 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2242 sp -= rmeth->stack_item_count;
2243 // We don't use NULLCHECK here because we can't rely on that
2244 // working for <init>. So instead we do an explicit test.
2247 throw_null_pointer_exception ();
2249 fun = (void (*)()) rmeth->method->ncode;
2251 goto perform_invoke;
2252 #endif /* DIRECT_THREADED */
2257 int index = GET2U ();
2259 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2262 sp -= rmeth->stack_item_count;
2264 fun = (void (*)()) rmeth->method->ncode;
2266 #ifdef DIRECT_THREADED
2267 // Rewrite instruction so that we use a faster pre-resolved
2269 pc[-2].insn = &&invokestatic_resolved;
2270 pc[-1].datum = rmeth;
2271 #endif /* DIRECT_THREADED */
2273 goto perform_invoke;
2275 #ifdef DIRECT_THREADED
2276 invokestatic_resolved:
2279 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2280 sp -= rmeth->stack_item_count;
2281 fun = (void (*)()) rmeth->method->ncode;
2283 goto perform_invoke;
2284 #endif /* DIRECT_THREADED */
2286 insn_invokeinterface:
2289 int index = GET2U ();
2291 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2294 sp -= rmeth->stack_item_count;
2296 jobject rcv = sp[0].o;
2301 _Jv_LookupInterfaceMethod (rcv->getClass (),
2302 rmeth->method->name,
2303 rmeth->method->signature);
2305 #ifdef DIRECT_THREADED
2306 // Rewrite instruction so that we use a faster pre-resolved
2308 pc[-2].insn = &&invokeinterface_resolved;
2309 pc[-1].datum = rmeth;
2311 // Skip dummy bytes.
2313 #endif /* DIRECT_THREADED */
2315 goto perform_invoke;
2317 #ifdef DIRECT_THREADED
2318 invokeinterface_resolved:
2321 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2322 sp -= rmeth->stack_item_count;
2323 jobject rcv = sp[0].o;
2326 _Jv_LookupInterfaceMethod (rcv->getClass (),
2327 rmeth->method->name,
2328 rmeth->method->signature);
2330 goto perform_invoke;
2331 #endif /* DIRECT_THREADED */
2336 int index = GET2U ();
2337 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2339 /* VM spec, section 3.11.5 */
2340 if ((klass->getModifiers() & Modifier::ABSTRACT)
2341 || klass->isInterface())
2342 throw new java::lang::InstantiationException;
2343 jobject res = _Jv_AllocObject (klass);
2346 #ifdef DIRECT_THREADED
2347 pc[-2].insn = &&new_resolved;
2348 pc[-1].datum = klass;
2349 #endif /* DIRECT_THREADED */
2353 #ifdef DIRECT_THREADED
2356 jclass klass = (jclass) AVAL ();
2357 jobject res = _Jv_AllocObject (klass);
2361 #endif /* DIRECT_THREADED */
2365 int atype = GET1U ();
2367 jobject result = _Jv_NewArray (atype, size);
2375 int index = GET2U ();
2376 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2379 jobject result = _Jv_NewObjectArray (size, klass, 0);
2382 #ifdef DIRECT_THREADED
2383 pc[-2].insn = &&anewarray_resolved;
2384 pc[-1].datum = klass;
2385 #endif /* DIRECT_THREADED */
2389 #ifdef DIRECT_THREADED
2392 jclass klass = (jclass) AVAL ();
2394 jobject result = _Jv_NewObjectArray (size, klass, 0);
2398 #endif /* DIRECT_THREADED */
2402 __JArray *arr = (__JArray*)POPA();
2403 NULLARRAYCHECK (arr);
2404 PUSHI (arr->length);
2410 jobject value = POPA();
2411 throw static_cast<jthrowable>(value);
2418 jobject value = POPA();
2419 jint index = GET2U ();
2420 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2423 value = (jobject) _Jv_CheckCast (to, value);
2427 #ifdef DIRECT_THREADED
2428 pc[-2].insn = &&checkcast_resolved;
2430 #endif /* DIRECT_THREADED */
2434 #ifdef DIRECT_THREADED
2438 jobject value = POPA ();
2439 jclass to = (jclass) AVAL ();
2440 value = (jobject) _Jv_CheckCast (to, value);
2444 #endif /* DIRECT_THREADED */
2449 jobject value = POPA();
2450 jint index = GET2U ();
2451 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2453 PUSHI (to->isInstance (value));
2455 #ifdef DIRECT_THREADED
2456 pc[-2].insn = &&instanceof_resolved;
2458 #endif /* DIRECT_THREADED */
2462 #ifdef DIRECT_THREADED
2463 instanceof_resolved:
2465 jobject value = POPA ();
2466 jclass to = (jclass) AVAL ();
2467 PUSHI (to->isInstance (value));
2470 #endif /* DIRECT_THREADED */
2474 jobject value = POPA();
2476 _Jv_MonitorEnter (value);
2482 jobject value = POPA();
2484 _Jv_MonitorExit (value);
2490 jobject val = POPA();
2500 jobject val = POPA();
2508 insn_multianewarray:
2511 int kind_index = GET2U ();
2515 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2517 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2519 for (int i = dim - 1; i >= 0; i--)
2524 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2530 #ifndef DIRECT_THREADED
2533 jint the_mod_op = get1u (pc++);
2534 jint wide = get2u (pc); pc += 2;
2579 pc = (unsigned char*) PEEKA (wide);
2584 jint amount = get2s (pc); pc += 2;
2585 jint value = PEEKI (wide);
2586 POKEI (wide, value+amount);
2591 throw_internal_error ("illegal bytecode modified by wide");
2595 #endif /* DIRECT_THREADED */
2599 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint));
2601 // Send JVMTI notification
2602 using namespace ::java::lang;
2603 jmethodID method = meth->self;
2604 jlocation location = meth->insn_index (pc - 1);
2605 Thread *thread = Thread::currentThread ();
2606 JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
2608 // Save the insn here since the breakpoint could be removed
2609 // before the JVMTI notification returns.
2610 using namespace gnu::gcj::jvmti;
2612 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2614 JvAssert (bp != NULL);
2615 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2617 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env,
2620 // Continue execution
2621 #ifdef DIRECT_THREADED
2624 goto *(insn_target[*opc]);
2628 catch (java::lang::Throwable *ex)
2631 // This needs to be done before the pc is changed.
2632 jlong throw_loc = meth->insn_index (pc);
2634 // Check if the exception is handled and, if so, set the pc to the start
2635 // of the appropriate catch block.
2636 if (meth->check_handler (&pc, meth, ex))
2639 sp++->o = ex; // Push exception.
2641 if (JVMTI_REQUESTED_EVENT (Exception))
2643 using namespace gnu::gcj::jvmti;
2644 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2645 jlong catch_loc = meth->insn_index (pc);
2646 ExceptionEvent::postExceptionEvent (thread, throw_meth,
2647 throw_loc, ex, throw_meth,
2654 if (JVMTI_REQUESTED_EVENT (Exception))
2656 using namespace gnu::gcj::jvmti;
2657 jlong throw_meth = reinterpret_cast<jlong> (meth->get_method ());
2658 ExceptionEvent::postExceptionEvent (thread, throw_meth, throw_loc,
2662 // No handler, so re-throw.