1 // interpret-run.cc - Code to interpret bytecode
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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;
16 // FRAME_DESC registers this particular invocation as the top-most
17 // interpreter frame. This lets the stack tracing code (for
18 // Throwable) print information about the method being interpreted
19 // rather than about the interpreter itself. FRAME_DESC has a
20 // destructor so it cleans up automatically when the interpreter
22 java::lang::Thread *thread = java::lang::Thread::currentThread();
23 _Jv_InterpFrame frame_desc (meth, thread);
25 _Jv_word stack[meth->max_stack];
28 _Jv_word locals[meth->max_locals];
30 #define INSN_LABEL(op) &&insn_##op
32 static const void *const insn_target[] =
35 INSN_LABEL(aconst_null),
36 INSN_LABEL(iconst_m1),
100 INSN_LABEL(lstore_3),
101 INSN_LABEL(fstore_0),
102 INSN_LABEL(fstore_1),
103 INSN_LABEL(fstore_2),
104 INSN_LABEL(fstore_3),
105 INSN_LABEL(dstore_0),
106 INSN_LABEL(dstore_1),
107 INSN_LABEL(dstore_2),
108 INSN_LABEL(dstore_3),
109 INSN_LABEL(astore_0),
110 INSN_LABEL(astore_1),
111 INSN_LABEL(astore_2),
112 INSN_LABEL(astore_3),
193 INSN_LABEL(if_icmpeq),
194 INSN_LABEL(if_icmpne),
195 INSN_LABEL(if_icmplt),
196 INSN_LABEL(if_icmpge),
197 INSN_LABEL(if_icmpgt),
198 INSN_LABEL(if_icmple),
199 INSN_LABEL(if_acmpeq),
200 INSN_LABEL(if_acmpne),
204 INSN_LABEL(tableswitch),
205 INSN_LABEL(lookupswitch),
212 INSN_LABEL(getstatic),
213 INSN_LABEL(putstatic),
214 INSN_LABEL(getfield),
215 INSN_LABEL(putfield),
216 INSN_LABEL(invokevirtual),
217 INSN_LABEL(invokespecial),
218 INSN_LABEL(invokestatic),
219 INSN_LABEL(invokeinterface),
220 INSN_LABEL (breakpoint),
222 INSN_LABEL(newarray),
223 INSN_LABEL(anewarray),
224 INSN_LABEL(arraylength),
226 INSN_LABEL(checkcast),
227 INSN_LABEL(instanceof),
228 INSN_LABEL(monitorenter),
229 INSN_LABEL(monitorexit),
230 #ifdef DIRECT_THREADED
235 INSN_LABEL(multianewarray),
237 INSN_LABEL(ifnonnull),
240 #ifdef DIRECT_THREADED
241 INSN_LABEL (ldc_class)
249 #ifdef DIRECT_THREADED
251 #define NEXT_INSN goto *((pc++)->insn)
252 #define INTVAL() ((pc++)->int_val)
253 #define AVAL() ((pc++)->datum)
255 #define GET1S() INTVAL ()
256 #define GET2S() INTVAL ()
257 #define GET1U() INTVAL ()
258 #define GET2U() INTVAL ()
259 #define AVAL1U() AVAL ()
260 #define AVAL2U() AVAL ()
261 #define AVAL2UP() AVAL ()
262 #define SKIP_GOTO ++pc
263 #define GOTO_VAL() (insn_slot *) pc->datum
264 #define PCVAL(unionval) unionval.p
265 #define AMPAMP(label) &&label
267 // Compile if we must. NOTE: Double-check locking.
268 if (meth->prepared == NULL)
270 _Jv_MutexLock (&compile_mutex);
271 if (meth->prepared == NULL)
272 meth->compile (insn_target);
273 _Jv_MutexUnlock (&compile_mutex);
276 // If we're only compiling, stop here
280 pc = (insn_slot *) meth->prepared;
284 #define NEXT_INSN goto *(insn_target[*pc++])
286 #define GET1S() get1s (pc++)
287 #define GET2S() (pc += 2, get2s (pc- 2))
288 #define GET1U() get1u (pc++)
289 #define GET2U() (pc += 2, get2u (pc - 2))
290 // Note that these could be more efficient when not handling 'ldc
293 ({ int index = get1u (pc++); \
294 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
296 ({ int index = get2u (pc); pc += 2; \
297 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
298 // Note that we don't need to resolve the pool entry here as class
299 // constants are never wide.
300 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
301 #define SKIP_GOTO pc += 2
302 #define GOTO_VAL() pc - 1 + get2s (pc)
303 #define PCVAL(unionval) unionval.i
304 #define AMPAMP(label) NULL
306 pc = meth->bytecode ();
308 #endif /* DIRECT_THREADED */
310 #define TAKE_GOTO pc = GOTO_VAL ()
312 /* Go straight at it! the ffi raw format matches the internal
313 stack representation exactly. At least, that's the idea.
315 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
317 _Jv_word *pool_data = meth->defining_class->constants.data;
319 /* These three are temporaries for common code used by several
322 _Jv_ResolvedMethod* rmeth;
327 // We keep nop around. It is used if we're interpreting the
328 // bytecodes and not doing direct threading.
332 /* The first few instructions here are ordered according to their
333 frequency, in the hope that this will improve code locality a
336 insn_aload_0: // 0x2a
344 insn_iload_1: // 0x1b
348 insn_invokevirtual: // 0xb6
351 int index = GET2U ();
353 /* _Jv_Linker::resolve_pool_entry returns immediately if the
354 * value already is resolved. If we want to clutter up the
355 * code here to gain a little performance, then we can check
356 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
357 * directly. For now, I don't think it is worth it. */
359 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
362 sp -= rmeth->stack_item_count;
364 if (rmeth->method->accflags & Modifier::FINAL)
366 // We can't rely on NULLCHECK working if the method is final.
368 throw_null_pointer_exception ();
370 // Final methods might not appear in the vtable.
371 fun = (void (*)()) rmeth->method->ncode;
376 jobject rcv = sp[0].o;
377 _Jv_VTable *table = *(_Jv_VTable**) rcv;
378 fun = (void (*)()) table->get_method (rmeth->method->index);
381 #ifdef DIRECT_THREADED
382 // Rewrite instruction so that we use a faster pre-resolved
384 pc[-2].insn = &&invokevirtual_resolved;
385 pc[-1].datum = rmeth;
386 #endif /* DIRECT_THREADED */
390 #ifdef DIRECT_THREADED
391 invokevirtual_resolved:
394 rmeth = (_Jv_ResolvedMethod *) AVAL ();
395 sp -= rmeth->stack_item_count;
397 if (rmeth->method->accflags & Modifier::FINAL)
399 // We can't rely on NULLCHECK working if the method is final.
401 throw_null_pointer_exception ();
403 // Final methods might not appear in the vtable.
404 fun = (void (*)()) rmeth->method->ncode;
408 jobject rcv = sp[0].o;
409 _Jv_VTable *table = *(_Jv_VTable**) rcv;
410 fun = (void (*)()) table->get_method (rmeth->method->index);
414 #endif /* DIRECT_THREADED */
418 /* here goes the magic again... */
419 ffi_cif *cif = &rmeth->cif;
420 ffi_raw *raw = (ffi_raw*) sp;
424 #if FFI_NATIVE_RAW_API
425 /* We assume that this is only implemented if it's correct */
426 /* to use it here. On a 64 bit machine, it never is. */
427 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
429 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
432 int rtype = cif->rtype->type;
434 /* the likelyhood of object, int, or void return is very high,
435 * so those are checked before the switch */
436 if (rtype == FFI_TYPE_POINTER)
438 PUSHA (rvalue.object_value);
440 else if (rtype == FFI_TYPE_SINT32)
442 PUSHI (rvalue.int_value);
444 else if (rtype == FFI_TYPE_VOID)
453 PUSHI ((jbyte)(rvalue.int_value & 0xff));
456 case FFI_TYPE_SINT16:
457 PUSHI ((jshort)(rvalue.int_value & 0xffff));
460 case FFI_TYPE_UINT16:
461 PUSHI (rvalue.int_value & 0xffff);
465 PUSHF (rvalue.float_value);
468 case FFI_TYPE_DOUBLE:
469 PUSHD (rvalue.double_value);
472 case FFI_TYPE_SINT64:
473 PUSHL (rvalue.long_value);
477 throw_internal_error ("unknown return type in invokeXXX");
544 // For direct threaded, bipush and sipush are the same.
545 #ifndef DIRECT_THREADED
548 #endif /* DIRECT_THREADED */
554 // For direct threaded, ldc and ldc_w are the same.
555 #ifndef DIRECT_THREADED
556 PUSHA ((jobject) AVAL1U ());
558 #endif /* DIRECT_THREADED */
560 PUSHA ((jobject) AVAL2U ());
563 #ifdef DIRECT_THREADED
564 // For direct threaded we have a separate 'ldc class' operation.
568 // We could rewrite the instruction at this point.
569 int index = INTVAL ();
570 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
575 #endif /* DIRECT_THREADED */
579 void *where = AVAL2UP ();
580 memcpy (sp, where, 2*sizeof (_Jv_word));
676 jintArray arr = (jintArray) POPA();
677 NULLARRAYCHECK (arr);
678 ARRAYBOUNDSCHECK (arr, index);
679 PUSHI( elements(arr)[index] );
686 jlongArray arr = (jlongArray) POPA();
687 NULLARRAYCHECK (arr);
688 ARRAYBOUNDSCHECK (arr, index);
689 PUSHL( elements(arr)[index] );
696 jfloatArray arr = (jfloatArray) POPA();
697 NULLARRAYCHECK (arr);
698 ARRAYBOUNDSCHECK (arr, index);
699 PUSHF( elements(arr)[index] );
706 jdoubleArray arr = (jdoubleArray) POPA();
707 NULLARRAYCHECK (arr);
708 ARRAYBOUNDSCHECK (arr, index);
709 PUSHD( elements(arr)[index] );
716 jobjectArray arr = (jobjectArray) POPA();
717 NULLARRAYCHECK (arr);
718 ARRAYBOUNDSCHECK (arr, index);
719 PUSHA( elements(arr)[index] );
726 jbyteArray arr = (jbyteArray) POPA();
727 NULLARRAYCHECK (arr);
728 ARRAYBOUNDSCHECK (arr, index);
729 PUSHI( elements(arr)[index] );
736 jcharArray arr = (jcharArray) POPA();
737 NULLARRAYCHECK (arr);
738 ARRAYBOUNDSCHECK (arr, index);
739 PUSHI( elements(arr)[index] );
746 jshortArray arr = (jshortArray) POPA();
747 NULLARRAYCHECK (arr);
748 ARRAYBOUNDSCHECK (arr, index);
749 PUSHI( elements(arr)[index] );
857 jintArray arr = (jintArray) POPA();
858 NULLARRAYCHECK (arr);
859 ARRAYBOUNDSCHECK (arr, index);
860 elements(arr)[index] = value;
866 jlong value = POPL();
868 jlongArray arr = (jlongArray) POPA();
869 NULLARRAYCHECK (arr);
870 ARRAYBOUNDSCHECK (arr, index);
871 elements(arr)[index] = value;
877 jfloat value = POPF();
879 jfloatArray arr = (jfloatArray) POPA();
880 NULLARRAYCHECK (arr);
881 ARRAYBOUNDSCHECK (arr, index);
882 elements(arr)[index] = value;
888 jdouble value = POPD();
890 jdoubleArray arr = (jdoubleArray) POPA();
891 NULLARRAYCHECK (arr);
892 ARRAYBOUNDSCHECK (arr, index);
893 elements(arr)[index] = value;
899 jobject value = POPA();
901 jobjectArray arr = (jobjectArray) POPA();
902 NULLARRAYCHECK (arr);
903 ARRAYBOUNDSCHECK (arr, index);
904 _Jv_CheckArrayStore (arr, value);
905 elements(arr)[index] = value;
911 jbyte value = (jbyte) POPI();
913 jbyteArray arr = (jbyteArray) POPA();
914 NULLARRAYCHECK (arr);
915 ARRAYBOUNDSCHECK (arr, index);
916 elements(arr)[index] = value;
922 jchar value = (jchar) POPI();
924 jcharArray arr = (jcharArray) POPA();
925 NULLARRAYCHECK (arr);
926 ARRAYBOUNDSCHECK (arr, index);
927 elements(arr)[index] = value;
933 jshort value = (jshort) POPI();
935 jshortArray arr = (jshortArray) POPA();
936 NULLARRAYCHECK (arr);
937 ARRAYBOUNDSCHECK (arr, index);
938 elements(arr)[index] = value;
956 dupx (sp, 1, 1); sp+=1;
960 dupx (sp, 1, 2); sp+=1;
970 dupx (sp, 2, 1); sp+=2;
974 dupx (sp, 2, 2); sp+=2;
979 jobject tmp1 = POPA();
980 jobject tmp2 = POPA();
1037 jint value2 = POPI();
1038 jint value1 = POPI();
1039 jint res = _Jv_divI (value1, value2);
1047 jlong value2 = POPL();
1048 jlong value1 = POPL();
1049 jlong res = _Jv_divJ (value1, value2);
1056 jfloat value2 = POPF();
1057 jfloat value1 = POPF();
1058 jfloat res = value1 / value2;
1065 jdouble value2 = POPD();
1066 jdouble value1 = POPD();
1067 jdouble res = value1 / value2;
1075 jint value2 = POPI();
1076 jint value1 = POPI();
1077 jint res = _Jv_remI (value1, value2);
1085 jlong value2 = POPL();
1086 jlong value1 = POPL();
1087 jlong res = _Jv_remJ (value1, value2);
1094 jfloat value2 = POPF();
1095 jfloat value1 = POPF();
1096 jfloat res = __ieee754_fmod (value1, value2);
1103 jdouble value2 = POPD();
1104 jdouble value1 = POPD();
1105 jdouble res = __ieee754_fmod (value1, value2);
1112 jint value = POPI();
1119 jlong value = POPL();
1126 jfloat value = POPF();
1133 jdouble value = POPD();
1140 jint shift = (POPI() & 0x1f);
1141 jint value = POPI();
1142 PUSHI (value << shift);
1148 jint shift = (POPI() & 0x3f);
1149 jlong value = POPL();
1150 PUSHL (value << shift);
1156 jint shift = (POPI() & 0x1f);
1157 jint value = POPI();
1158 PUSHI (value >> shift);
1164 jint shift = (POPI() & 0x3f);
1165 jlong value = POPL();
1166 PUSHL (value >> shift);
1172 jint shift = (POPI() & 0x1f);
1173 _Jv_uint value = (_Jv_uint) POPI();
1174 PUSHI ((jint) (value >> shift));
1180 jint shift = (POPI() & 0x3f);
1181 _Jv_ulong value = (_Jv_ulong) POPL();
1182 PUSHL ((jlong) (value >> shift));
1212 jint index = GET1U ();
1213 jint amount = GET1S ();
1214 locals[index].i += amount;
1219 {jlong value = POPI(); PUSHL (value);}
1223 {jfloat value = POPI(); PUSHF (value);}
1227 {jdouble value = POPI(); PUSHD (value);}
1231 {jint value = POPL(); PUSHI (value);}
1235 {jfloat value = POPL(); PUSHF (value);}
1239 {jdouble value = POPL(); PUSHD (value);}
1244 using namespace java::lang;
1245 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1252 using namespace java::lang;
1253 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1259 { jdouble value = POPF (); PUSHD(value); }
1264 using namespace java::lang;
1265 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1272 using namespace java::lang;
1273 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1279 { jfloat value = POPD (); PUSHF(value); }
1283 { jbyte value = POPI (); PUSHI(value); }
1287 { jchar value = POPI (); PUSHI(value); }
1291 { jshort value = POPI (); PUSHI(value); }
1296 jlong value2 = POPL ();
1297 jlong value1 = POPL ();
1298 if (value1 > value2)
1300 else if (value1 == value2)
1316 jfloat value2 = POPF ();
1317 jfloat value1 = POPF ();
1318 if (value1 > value2)
1320 else if (value1 == value2)
1322 else if (value1 < value2)
1338 jdouble value2 = POPD ();
1339 jdouble value1 = POPD ();
1340 if (value1 > value2)
1342 else if (value1 == value2)
1344 else if (value1 < value2)
1407 jint value2 = POPI();
1408 jint value1 = POPI();
1409 if (value1 == value2)
1418 jint value2 = POPI();
1419 jint value1 = POPI();
1420 if (value1 != value2)
1429 jint value2 = POPI();
1430 jint value1 = POPI();
1431 if (value1 < value2)
1440 jint value2 = POPI();
1441 jint value1 = POPI();
1442 if (value1 >= value2)
1451 jint value2 = POPI();
1452 jint value1 = POPI();
1453 if (value1 > value2)
1462 jint value2 = POPI();
1463 jint value1 = POPI();
1464 if (value1 <= value2)
1473 jobject value2 = POPA();
1474 jobject value1 = POPA();
1475 if (value1 == value2)
1484 jobject value2 = POPA();
1485 jobject value1 = POPA();
1486 if (value1 != value2)
1494 #ifndef DIRECT_THREADED
1495 // For direct threaded, goto and goto_w are the same.
1496 pc = pc - 1 + get4 (pc);
1498 #endif /* DIRECT_THREADED */
1504 #ifndef DIRECT_THREADED
1505 // For direct threaded, jsr and jsr_w are the same.
1507 pc_t next = pc - 1 + get4 (pc);
1509 PUSHA ((jobject) pc);
1513 #endif /* DIRECT_THREADED */
1516 pc_t next = GOTO_VAL();
1518 PUSHA ((jobject) pc);
1525 jint index = GET1U ();
1526 pc = (pc_t) PEEKA (index);
1532 #ifdef DIRECT_THREADED
1533 void *def = (pc++)->datum;
1537 jint low = INTVAL ();
1538 jint high = INTVAL ();
1540 if (index < low || index > high)
1541 pc = (insn_slot *) def;
1543 pc = (insn_slot *) ((pc + index - low)->datum);
1545 pc_t base_pc = pc - 1;
1546 int index = POPI ();
1548 pc_t base = (pc_t) meth->bytecode ();
1549 while ((pc - base) % 4 != 0)
1552 jint def = get4 (pc);
1553 jint low = get4 (pc + 4);
1554 jint high = get4 (pc + 8);
1555 if (index < low || index > high)
1558 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1559 #endif /* DIRECT_THREADED */
1565 #ifdef DIRECT_THREADED
1566 void *def = (pc++)->insn;
1570 jint npairs = INTVAL ();
1572 int max = npairs - 1;
1575 // Simple binary search...
1578 int half = (min + max) / 2;
1579 int match = pc[2 * half].int_val;
1584 pc = (insn_slot *) pc[2 * half + 1].datum;
1587 else if (index < match)
1588 // We can use HALF - 1 here because we check again on
1592 // We can use HALF + 1 here because we check again on
1596 if (index == pc[2 * min].int_val)
1597 pc = (insn_slot *) pc[2 * min + 1].datum;
1599 pc = (insn_slot *) def;
1601 unsigned char *base_pc = pc-1;
1604 unsigned char* base = meth->bytecode ();
1605 while ((pc-base) % 4 != 0)
1608 jint def = get4 (pc);
1609 jint npairs = get4 (pc+4);
1614 // Simple binary search...
1617 int half = (min+max)/2;
1618 int match = get4 (pc+ 4*(2 + 2*half));
1622 else if (index < match)
1623 // We can use HALF - 1 here because we check again on
1627 // We can use HALF + 1 here because we check again on
1632 if (index == get4 (pc+ 4*(2 + 2*min)))
1633 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1636 #endif /* DIRECT_THREADED */
1641 *(jobject *) retp = POPA ();
1645 *(jlong *) retp = POPL ();
1649 *(jfloat *) retp = POPF ();
1653 *(jdouble *) retp = POPD ();
1657 *(jint *) retp = POPI ();
1665 jint fieldref_index = GET2U ();
1666 SAVE_PC(); // Constant pool resolution could throw.
1667 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1668 _Jv_Field *field = pool_data[fieldref_index].field;
1670 if ((field->flags & Modifier::STATIC) == 0)
1671 throw_incompatible_class_change_error
1672 (JvNewStringLatin1 ("field no longer static"));
1674 jclass type = field->type;
1676 // We rewrite the instruction once we discover what it refers
1678 void *newinsn = NULL;
1679 if (type->isPrimitive ())
1681 switch (type->size_in_bytes)
1684 PUSHI (*field->u.byte_addr);
1685 newinsn = AMPAMP (getstatic_resolved_1);
1689 if (type == JvPrimClass (char))
1691 PUSHI (*field->u.char_addr);
1692 newinsn = AMPAMP (getstatic_resolved_char);
1696 PUSHI (*field->u.short_addr);
1697 newinsn = AMPAMP (getstatic_resolved_short);
1702 PUSHI(*field->u.int_addr);
1703 newinsn = AMPAMP (getstatic_resolved_4);
1707 PUSHL(*field->u.long_addr);
1708 newinsn = AMPAMP (getstatic_resolved_8);
1714 PUSHA(*field->u.object_addr);
1715 newinsn = AMPAMP (getstatic_resolved_obj);
1718 #ifdef DIRECT_THREADED
1719 pc[-2].insn = newinsn;
1720 pc[-1].datum = field->u.addr;
1721 #endif /* DIRECT_THREADED */
1725 #ifdef DIRECT_THREADED
1726 getstatic_resolved_1:
1727 PUSHI (*(jbyte *) AVAL ());
1730 getstatic_resolved_char:
1731 PUSHI (*(jchar *) AVAL ());
1734 getstatic_resolved_short:
1735 PUSHI (*(jshort *) AVAL ());
1738 getstatic_resolved_4:
1739 PUSHI (*(jint *) AVAL ());
1742 getstatic_resolved_8:
1743 PUSHL (*(jlong *) AVAL ());
1746 getstatic_resolved_obj:
1747 PUSHA (*(jobject *) AVAL ());
1749 #endif /* DIRECT_THREADED */
1754 jint fieldref_index = GET2U ();
1755 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1756 _Jv_Field *field = pool_data[fieldref_index].field;
1758 if ((field->flags & Modifier::STATIC) != 0)
1759 throw_incompatible_class_change_error
1760 (JvNewStringLatin1 ("field is static"));
1762 jclass type = field->type;
1763 jint field_offset = field->u.boffset;
1765 jobject obj = POPA();
1768 void *newinsn = NULL;
1769 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1770 if (type->isPrimitive ())
1772 switch (type->size_in_bytes)
1775 PUSHI (val->byte_value);
1776 newinsn = AMPAMP (getfield_resolved_1);
1780 if (type == JvPrimClass (char))
1782 PUSHI (val->char_value);
1783 newinsn = AMPAMP (getfield_resolved_char);
1787 PUSHI (val->short_value);
1788 newinsn = AMPAMP (getfield_resolved_short);
1793 PUSHI (val->int_value);
1794 newinsn = AMPAMP (getfield_resolved_4);
1798 PUSHL (val->long_value);
1799 newinsn = AMPAMP (getfield_resolved_8);
1805 PUSHA (val->object_value);
1806 newinsn = AMPAMP (getfield_resolved_obj);
1809 #ifdef DIRECT_THREADED
1810 pc[-2].insn = newinsn;
1811 pc[-1].int_val = field_offset;
1812 #endif /* DIRECT_THREADED */
1816 #ifdef DIRECT_THREADED
1817 getfield_resolved_1:
1819 char *obj = (char *) POPA ();
1821 PUSHI (*(jbyte *) (obj + INTVAL ()));
1825 getfield_resolved_char:
1827 char *obj = (char *) POPA ();
1829 PUSHI (*(jchar *) (obj + INTVAL ()));
1833 getfield_resolved_short:
1835 char *obj = (char *) POPA ();
1837 PUSHI (*(jshort *) (obj + INTVAL ()));
1841 getfield_resolved_4:
1843 char *obj = (char *) POPA ();
1845 PUSHI (*(jint *) (obj + INTVAL ()));
1849 getfield_resolved_8:
1851 char *obj = (char *) POPA ();
1853 PUSHL (*(jlong *) (obj + INTVAL ()));
1857 getfield_resolved_obj:
1859 char *obj = (char *) POPA ();
1861 PUSHA (*(jobject *) (obj + INTVAL ()));
1864 #endif /* DIRECT_THREADED */
1869 jint fieldref_index = GET2U ();
1870 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1871 _Jv_Field *field = pool_data[fieldref_index].field;
1873 jclass type = field->type;
1875 // ResolvePoolEntry cannot check this
1876 if ((field->flags & Modifier::STATIC) == 0)
1877 throw_incompatible_class_change_error
1878 (JvNewStringLatin1 ("field no longer static"));
1880 void *newinsn = NULL;
1881 if (type->isPrimitive ())
1883 switch (type->size_in_bytes)
1887 jint value = POPI();
1888 *field->u.byte_addr = value;
1889 newinsn = AMPAMP (putstatic_resolved_1);
1895 jint value = POPI();
1896 *field->u.char_addr = value;
1897 newinsn = AMPAMP (putstatic_resolved_2);
1903 jint value = POPI();
1904 *field->u.int_addr = value;
1905 newinsn = AMPAMP (putstatic_resolved_4);
1911 jlong value = POPL();
1912 *field->u.long_addr = value;
1913 newinsn = AMPAMP (putstatic_resolved_8);
1920 jobject value = POPA();
1921 *field->u.object_addr = value;
1922 newinsn = AMPAMP (putstatic_resolved_obj);
1925 #ifdef DIRECT_THREADED
1926 pc[-2].insn = newinsn;
1927 pc[-1].datum = field->u.addr;
1928 #endif /* DIRECT_THREADED */
1932 #ifdef DIRECT_THREADED
1933 putstatic_resolved_1:
1934 *(jbyte *) AVAL () = POPI ();
1937 putstatic_resolved_2:
1938 *(jchar *) AVAL () = POPI ();
1941 putstatic_resolved_4:
1942 *(jint *) AVAL () = POPI ();
1945 putstatic_resolved_8:
1946 *(jlong *) AVAL () = POPL ();
1949 putstatic_resolved_obj:
1950 *(jobject *) AVAL () = POPA ();
1952 #endif /* DIRECT_THREADED */
1957 jint fieldref_index = GET2U ();
1958 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1959 _Jv_Field *field = pool_data[fieldref_index].field;
1961 jclass type = field->type;
1963 if ((field->flags & Modifier::STATIC) != 0)
1964 throw_incompatible_class_change_error
1965 (JvNewStringLatin1 ("field is static"));
1967 jint field_offset = field->u.boffset;
1969 void *newinsn = NULL;
1970 if (type->isPrimitive ())
1972 switch (type->size_in_bytes)
1976 jint value = POPI();
1977 jobject obj = POPA();
1979 *(jbyte*) ((char*)obj + field_offset) = value;
1980 newinsn = AMPAMP (putfield_resolved_1);
1986 jint value = POPI();
1987 jobject obj = POPA();
1989 *(jchar*) ((char*)obj + field_offset) = value;
1990 newinsn = AMPAMP (putfield_resolved_2);
1996 jint value = POPI();
1997 jobject obj = POPA();
1999 *(jint*) ((char*)obj + field_offset) = value;
2000 newinsn = AMPAMP (putfield_resolved_4);
2006 jlong value = POPL();
2007 jobject obj = POPA();
2009 *(jlong*) ((char*)obj + field_offset) = value;
2010 newinsn = AMPAMP (putfield_resolved_8);
2017 jobject value = POPA();
2018 jobject obj = POPA();
2020 *(jobject*) ((char*)obj + field_offset) = value;
2021 newinsn = AMPAMP (putfield_resolved_obj);
2024 #ifdef DIRECT_THREADED
2025 pc[-2].insn = newinsn;
2026 pc[-1].int_val = field_offset;
2027 #endif /* DIRECT_THREADED */
2031 #ifdef DIRECT_THREADED
2032 putfield_resolved_1:
2035 char *obj = (char *) POPA ();
2037 *(jbyte *) (obj + INTVAL ()) = val;
2041 putfield_resolved_2:
2044 char *obj = (char *) POPA ();
2046 *(jchar *) (obj + INTVAL ()) = val;
2050 putfield_resolved_4:
2053 char *obj = (char *) POPA ();
2055 *(jint *) (obj + INTVAL ()) = val;
2059 putfield_resolved_8:
2061 jlong val = POPL ();
2062 char *obj = (char *) POPA ();
2064 *(jlong *) (obj + INTVAL ()) = val;
2068 putfield_resolved_obj:
2070 jobject val = POPA ();
2071 char *obj = (char *) POPA ();
2073 *(jobject *) (obj + INTVAL ()) = val;
2076 #endif /* DIRECT_THREADED */
2081 int index = GET2U ();
2083 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2086 sp -= rmeth->stack_item_count;
2088 // We don't use NULLCHECK here because we can't rely on that
2089 // working for <init>. So instead we do an explicit test.
2093 throw_null_pointer_exception ();
2096 fun = (void (*)()) rmeth->method->ncode;
2098 #ifdef DIRECT_THREADED
2099 // Rewrite instruction so that we use a faster pre-resolved
2101 pc[-2].insn = &&invokespecial_resolved;
2102 pc[-1].datum = rmeth;
2103 #endif /* DIRECT_THREADED */
2105 goto perform_invoke;
2107 #ifdef DIRECT_THREADED
2108 invokespecial_resolved:
2111 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2112 sp -= rmeth->stack_item_count;
2113 // We don't use NULLCHECK here because we can't rely on that
2114 // working for <init>. So instead we do an explicit test.
2117 throw_null_pointer_exception ();
2119 fun = (void (*)()) rmeth->method->ncode;
2121 goto perform_invoke;
2122 #endif /* DIRECT_THREADED */
2127 int index = GET2U ();
2129 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2132 sp -= rmeth->stack_item_count;
2134 fun = (void (*)()) rmeth->method->ncode;
2136 #ifdef DIRECT_THREADED
2137 // Rewrite instruction so that we use a faster pre-resolved
2139 pc[-2].insn = &&invokestatic_resolved;
2140 pc[-1].datum = rmeth;
2141 #endif /* DIRECT_THREADED */
2143 goto perform_invoke;
2145 #ifdef DIRECT_THREADED
2146 invokestatic_resolved:
2149 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2150 sp -= rmeth->stack_item_count;
2151 fun = (void (*)()) rmeth->method->ncode;
2153 goto perform_invoke;
2154 #endif /* DIRECT_THREADED */
2156 insn_invokeinterface:
2159 int index = GET2U ();
2161 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2164 sp -= rmeth->stack_item_count;
2166 jobject rcv = sp[0].o;
2171 _Jv_LookupInterfaceMethod (rcv->getClass (),
2172 rmeth->method->name,
2173 rmeth->method->signature);
2175 #ifdef DIRECT_THREADED
2176 // Rewrite instruction so that we use a faster pre-resolved
2178 pc[-2].insn = &&invokeinterface_resolved;
2179 pc[-1].datum = rmeth;
2181 // Skip dummy bytes.
2183 #endif /* DIRECT_THREADED */
2185 goto perform_invoke;
2187 #ifdef DIRECT_THREADED
2188 invokeinterface_resolved:
2191 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2192 sp -= rmeth->stack_item_count;
2193 jobject rcv = sp[0].o;
2196 _Jv_LookupInterfaceMethod (rcv->getClass (),
2197 rmeth->method->name,
2198 rmeth->method->signature);
2200 goto perform_invoke;
2201 #endif /* DIRECT_THREADED */
2206 int index = GET2U ();
2207 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2209 /* VM spec, section 3.11.5 */
2210 if ((klass->getModifiers() & Modifier::ABSTRACT)
2211 || klass->isInterface())
2212 throw new java::lang::InstantiationException;
2213 jobject res = _Jv_AllocObject (klass);
2216 #ifdef DIRECT_THREADED
2217 pc[-2].insn = &&new_resolved;
2218 pc[-1].datum = klass;
2219 #endif /* DIRECT_THREADED */
2223 #ifdef DIRECT_THREADED
2226 jclass klass = (jclass) AVAL ();
2227 jobject res = _Jv_AllocObject (klass);
2231 #endif /* DIRECT_THREADED */
2235 int atype = GET1U ();
2237 jobject result = _Jv_NewArray (atype, size);
2245 int index = GET2U ();
2246 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2249 jobject result = _Jv_NewObjectArray (size, klass, 0);
2252 #ifdef DIRECT_THREADED
2253 pc[-2].insn = &&anewarray_resolved;
2254 pc[-1].datum = klass;
2255 #endif /* DIRECT_THREADED */
2259 #ifdef DIRECT_THREADED
2262 jclass klass = (jclass) AVAL ();
2264 jobject result = _Jv_NewObjectArray (size, klass, 0);
2268 #endif /* DIRECT_THREADED */
2272 __JArray *arr = (__JArray*)POPA();
2273 NULLARRAYCHECK (arr);
2274 PUSHI (arr->length);
2280 jobject value = POPA();
2281 throw static_cast<jthrowable>(value);
2288 jobject value = POPA();
2289 jint index = GET2U ();
2290 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2293 value = (jobject) _Jv_CheckCast (to, value);
2297 #ifdef DIRECT_THREADED
2298 pc[-2].insn = &&checkcast_resolved;
2300 #endif /* DIRECT_THREADED */
2304 #ifdef DIRECT_THREADED
2308 jobject value = POPA ();
2309 jclass to = (jclass) AVAL ();
2310 value = (jobject) _Jv_CheckCast (to, value);
2314 #endif /* DIRECT_THREADED */
2319 jobject value = POPA();
2320 jint index = GET2U ();
2321 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2323 PUSHI (to->isInstance (value));
2325 #ifdef DIRECT_THREADED
2326 pc[-2].insn = &&instanceof_resolved;
2328 #endif /* DIRECT_THREADED */
2332 #ifdef DIRECT_THREADED
2333 instanceof_resolved:
2335 jobject value = POPA ();
2336 jclass to = (jclass) AVAL ();
2337 PUSHI (to->isInstance (value));
2340 #endif /* DIRECT_THREADED */
2344 jobject value = POPA();
2346 _Jv_MonitorEnter (value);
2352 jobject value = POPA();
2354 _Jv_MonitorExit (value);
2360 jobject val = POPA();
2370 jobject val = POPA();
2378 insn_multianewarray:
2381 int kind_index = GET2U ();
2385 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2387 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2389 for (int i = dim - 1; i >= 0; i--)
2394 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2400 #ifndef DIRECT_THREADED
2403 jint the_mod_op = get1u (pc++);
2404 jint wide = get2u (pc); pc += 2;
2449 pc = (unsigned char*) PEEKA (wide);
2454 jint amount = get2s (pc); pc += 2;
2455 jint value = PEEKI (wide);
2456 POKEI (wide, value+amount);
2461 throw_internal_error ("illegal bytecode modified by wide");
2465 #endif /* DIRECT_THREADED */
2472 catch (java::lang::Throwable *ex)
2474 #ifdef DIRECT_THREADED
2475 void *logical_pc = (void *) ((insn_slot *) pc - 1);
2477 int logical_pc = pc - 1 - meth->bytecode ();
2479 _Jv_InterpException *exc = meth->exceptions ();
2480 jclass exc_class = ex->getClass ();
2482 for (int i = 0; i < meth->exc_count; i++)
2484 if (PCVAL (exc[i].start_pc) <= logical_pc
2485 && logical_pc < PCVAL (exc[i].end_pc))
2487 #ifdef DIRECT_THREADED
2488 jclass handler = (jclass) exc[i].handler_type.p;
2490 jclass handler = NULL;
2491 if (exc[i].handler_type.i != 0)
2492 handler = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2493 exc[i].handler_type.i)).clazz;
2494 #endif /* DIRECT_THREADED */
2496 if (handler == NULL || handler->isAssignableFrom (exc_class))
2499 #ifdef DIRECT_THREADED
2500 pc = (insn_slot *) exc[i].handler_pc.p;
2502 pc = meth->bytecode () + exc[i].handler_pc.i;
2503 #endif /* DIRECT_THREADED */
2505 sp++->o = ex; // Push exception.
2511 // No handler, so re-throw.