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; \
380 #undef INTERP_REPORT_EXCEPTION
381 #define INTERP_REPORT_EXCEPTION(Jthrowable) REPORT_EXCEPTION (Jthrowable)
384 #define NEXT_INSN goto *((pc++)->insn)
386 // REWRITE_INSN does nothing.
388 // Rewriting a multi-word instruction in the presence of multiple
389 // threads leads to a data race if a thread reads part of an
390 // instruction while some other thread is rewriting that instruction.
391 // For example, an invokespecial instruction may be rewritten to
392 // invokespecial_resolved and its operand changed from an index to a
393 // pointer while another thread is executing invokespecial. This
394 // other thread then reads the pointer that is now the operand of
395 // invokespecial_resolved and tries to use it as an index.
397 // Fixing this requires either spinlocks, a more elaborate data
398 // structure, or even per-thread allocated pages. It's clear from the
399 // locking in meth->compile below that the presence of multiple
400 // threads was contemplated when this code was written, but the full
401 // consequences were not fully appreciated.
402 #define REWRITE_INSN(INSN,SLOT,VALUE)
404 #undef INTERP_REPORT_EXCEPTION
405 #define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */
408 #define INTVAL() ((pc++)->int_val)
409 #define AVAL() ((pc++)->datum)
411 #define GET1S() INTVAL ()
412 #define GET2S() INTVAL ()
413 #define GET1U() INTVAL ()
414 #define GET2U() INTVAL ()
415 #define AVAL1U() AVAL ()
416 #define AVAL2U() AVAL ()
417 #define AVAL2UP() AVAL ()
418 #define SKIP_GOTO ++pc
419 #define GOTO_VAL() (insn_slot *) pc->datum
420 #define PCVAL(unionval) unionval.p
421 #define AMPAMP(label) &&label
423 // Compile if we must. NOTE: Double-check locking.
424 if (meth->prepared == NULL)
426 _Jv_MutexLock (&compile_mutex);
427 if (meth->prepared == NULL)
428 meth->compile (insn_target);
429 _Jv_MutexUnlock (&compile_mutex);
432 // If we're only compiling, stop here
436 pc = (insn_slot *) meth->prepared;
444 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
446 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
447 jmethodID method = meth->self; \
448 jlocation loc = meth->insn_index (pc); \
449 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
452 goto *(insn_target[*pc++])
454 #define NEXT_INSN goto *(insn_target[*pc++])
457 #define GET1S() get1s (pc++)
458 #define GET2S() (pc += 2, get2s (pc- 2))
459 #define GET1U() get1u (pc++)
460 #define GET2U() (pc += 2, get2u (pc - 2))
461 // Note that these could be more efficient when not handling 'ldc
464 ({ int index = get1u (pc++); \
465 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
467 ({ int index = get2u (pc); pc += 2; \
468 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
469 // Note that we don't need to resolve the pool entry here as class
470 // constants are never wide.
471 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
472 #define SKIP_GOTO pc += 2
473 #define GOTO_VAL() pc - 1 + get2s (pc)
474 #define PCVAL(unionval) unionval.i
475 #define AMPAMP(label) NULL
477 pc = meth->bytecode ();
479 #endif /* DIRECT_THREADED */
481 #define TAKE_GOTO pc = GOTO_VAL ()
483 /* Go straight at it! the ffi raw format matches the internal
484 stack representation exactly. At least, that's the idea.
486 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
488 _Jv_word *pool_data = meth->defining_class->constants.data;
490 /* These three are temporaries for common code used by several
493 _Jv_ResolvedMethod* rmeth;
498 // We keep nop around. It is used if we're interpreting the
499 // bytecodes and not doing direct threading.
503 /* The first few instructions here are ordered according to their
504 frequency, in the hope that this will improve code locality a
507 insn_aload_0: // 0x2a
515 insn_iload_1: // 0x1b
519 insn_invokevirtual: // 0xb6
522 int index = GET2U ();
524 /* _Jv_Linker::resolve_pool_entry returns immediately if the
525 * value already is resolved. If we want to clutter up the
526 * code here to gain a little performance, then we can check
527 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
528 * directly. For now, I don't think it is worth it. */
530 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
533 sp -= rmeth->stack_item_count;
535 if (rmeth->method->accflags & Modifier::FINAL)
537 // We can't rely on NULLCHECK working if the method is final.
539 throw_null_pointer_exception ();
541 // Final methods might not appear in the vtable.
542 fun = (void (*)()) rmeth->method->ncode;
547 jobject rcv = sp[0].o;
548 _Jv_VTable *table = *(_Jv_VTable**) rcv;
549 fun = (void (*)()) table->get_method (rmeth->method->index);
552 #ifdef DIRECT_THREADED
553 // Rewrite instruction so that we use a faster pre-resolved
555 REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth);
556 #endif /* DIRECT_THREADED */
560 #ifdef DIRECT_THREADED
561 invokevirtual_resolved:
564 rmeth = (_Jv_ResolvedMethod *) AVAL ();
565 sp -= rmeth->stack_item_count;
567 if (rmeth->method->accflags & Modifier::FINAL)
569 // We can't rely on NULLCHECK working if the method is final.
571 throw_null_pointer_exception ();
573 // Final methods might not appear in the vtable.
574 fun = (void (*)()) rmeth->method->ncode;
579 jobject rcv = sp[0].o;
580 _Jv_VTable *table = *(_Jv_VTable**) rcv;
581 fun = (void (*)()) table->get_method (rmeth->method->index);
585 #endif /* DIRECT_THREADED */
589 /* here goes the magic again... */
590 ffi_cif *cif = &rmeth->cif;
591 INTERP_FFI_RAW_TYPE *raw = (INTERP_FFI_RAW_TYPE *) sp;
595 #if FFI_NATIVE_RAW_API
596 /* We assume that this is only implemented if it's correct */
597 /* to use it here. On a 64 bit machine, it never is. */
598 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
600 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
603 int rtype = cif->rtype->type;
605 /* the likelyhood of object, int, or void return is very high,
606 * so those are checked before the switch */
607 if (rtype == FFI_TYPE_POINTER)
609 PUSHA (rvalue.object_value);
611 else if (rtype == FFI_TYPE_SINT32)
613 PUSHI (rvalue.int_value);
615 else if (rtype == FFI_TYPE_VOID)
624 PUSHI ((jbyte)(rvalue.int_value & 0xff));
627 case FFI_TYPE_SINT16:
628 PUSHI ((jshort)(rvalue.int_value & 0xffff));
631 case FFI_TYPE_UINT16:
632 PUSHI (rvalue.int_value & 0xffff);
636 PUSHF (rvalue.float_value);
639 case FFI_TYPE_DOUBLE:
640 PUSHD (rvalue.double_value);
643 case FFI_TYPE_SINT64:
644 PUSHL (rvalue.long_value);
648 throw_internal_error ("unknown return type in invokeXXX");
715 // For direct threaded, bipush and sipush are the same.
716 #ifndef DIRECT_THREADED
719 #endif /* DIRECT_THREADED */
725 // For direct threaded, ldc and ldc_w are the same.
726 #ifndef DIRECT_THREADED
727 PUSHA ((jobject) AVAL1U ());
729 #endif /* DIRECT_THREADED */
731 PUSHA ((jobject) AVAL2U ());
734 #ifdef DIRECT_THREADED
735 // For direct threaded we have a separate 'ldc class' operation.
739 // We could rewrite the instruction at this point.
740 int index = INTVAL ();
741 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
746 #endif /* DIRECT_THREADED */
750 void *where = AVAL2UP ();
751 memcpy (sp, where, 2*sizeof (_Jv_word));
847 jintArray arr = (jintArray) POPA();
848 NULLARRAYCHECK (arr);
849 ARRAYBOUNDSCHECK (arr, index);
850 PUSHI( elements(arr)[index] );
857 jlongArray arr = (jlongArray) POPA();
858 NULLARRAYCHECK (arr);
859 ARRAYBOUNDSCHECK (arr, index);
860 PUSHL( elements(arr)[index] );
867 jfloatArray arr = (jfloatArray) POPA();
868 NULLARRAYCHECK (arr);
869 ARRAYBOUNDSCHECK (arr, index);
870 PUSHF( elements(arr)[index] );
877 jdoubleArray arr = (jdoubleArray) POPA();
878 NULLARRAYCHECK (arr);
879 ARRAYBOUNDSCHECK (arr, index);
880 PUSHD( elements(arr)[index] );
887 jobjectArray arr = (jobjectArray) POPA();
888 NULLARRAYCHECK (arr);
889 ARRAYBOUNDSCHECK (arr, index);
890 PUSHA( elements(arr)[index] );
897 jbyteArray arr = (jbyteArray) POPA();
898 NULLARRAYCHECK (arr);
899 ARRAYBOUNDSCHECK (arr, index);
900 PUSHI( elements(arr)[index] );
907 jcharArray arr = (jcharArray) POPA();
908 NULLARRAYCHECK (arr);
909 ARRAYBOUNDSCHECK (arr, index);
910 PUSHI( elements(arr)[index] );
917 jshortArray arr = (jshortArray) POPA();
918 NULLARRAYCHECK (arr);
919 ARRAYBOUNDSCHECK (arr, index);
920 PUSHI( elements(arr)[index] );
1026 jint value = POPI();
1027 jint index = POPI();
1028 jintArray arr = (jintArray) POPA();
1029 NULLARRAYCHECK (arr);
1030 ARRAYBOUNDSCHECK (arr, index);
1031 elements(arr)[index] = value;
1037 jlong value = POPL();
1038 jint index = POPI();
1039 jlongArray arr = (jlongArray) POPA();
1040 NULLARRAYCHECK (arr);
1041 ARRAYBOUNDSCHECK (arr, index);
1042 elements(arr)[index] = value;
1048 jfloat value = POPF();
1049 jint index = POPI();
1050 jfloatArray arr = (jfloatArray) POPA();
1051 NULLARRAYCHECK (arr);
1052 ARRAYBOUNDSCHECK (arr, index);
1053 elements(arr)[index] = value;
1059 jdouble value = POPD();
1060 jint index = POPI();
1061 jdoubleArray arr = (jdoubleArray) POPA();
1062 NULLARRAYCHECK (arr);
1063 ARRAYBOUNDSCHECK (arr, index);
1064 elements(arr)[index] = value;
1070 jobject value = POPA();
1071 jint index = POPI();
1072 jobjectArray arr = (jobjectArray) POPA();
1073 NULLARRAYCHECK (arr);
1074 ARRAYBOUNDSCHECK (arr, index);
1075 _Jv_CheckArrayStore (arr, value);
1076 elements(arr)[index] = value;
1082 jbyte value = (jbyte) POPI();
1083 jint index = POPI();
1084 jbyteArray arr = (jbyteArray) POPA();
1085 NULLARRAYCHECK (arr);
1086 ARRAYBOUNDSCHECK (arr, index);
1087 elements(arr)[index] = value;
1093 jchar value = (jchar) POPI();
1094 jint index = POPI();
1095 jcharArray arr = (jcharArray) POPA();
1096 NULLARRAYCHECK (arr);
1097 ARRAYBOUNDSCHECK (arr, index);
1098 elements(arr)[index] = value;
1104 jshort value = (jshort) POPI();
1105 jint index = POPI();
1106 jshortArray arr = (jshortArray) POPA();
1107 NULLARRAYCHECK (arr);
1108 ARRAYBOUNDSCHECK (arr, index);
1109 elements(arr)[index] = value;
1127 dupx (sp, 1, 1); sp+=1;
1131 dupx (sp, 1, 2); sp+=1;
1141 dupx (sp, 2, 1); sp+=2;
1145 dupx (sp, 2, 2); sp+=2;
1150 jobject tmp1 = POPA();
1151 jobject tmp2 = POPA();
1208 jint value2 = POPI();
1209 jint value1 = POPI();
1210 jint res = _Jv_divI (value1, value2);
1218 jlong value2 = POPL();
1219 jlong value1 = POPL();
1220 jlong res = _Jv_divJ (value1, value2);
1227 jfloat value2 = POPF();
1228 jfloat value1 = POPF();
1229 jfloat res = value1 / value2;
1236 jdouble value2 = POPD();
1237 jdouble value1 = POPD();
1238 jdouble res = value1 / value2;
1246 jint value2 = POPI();
1247 jint value1 = POPI();
1248 jint res = _Jv_remI (value1, value2);
1256 jlong value2 = POPL();
1257 jlong value1 = POPL();
1258 jlong res = _Jv_remJ (value1, value2);
1265 jfloat value2 = POPF();
1266 jfloat value1 = POPF();
1267 jfloat res = __ieee754_fmod (value1, value2);
1274 jdouble value2 = POPD();
1275 jdouble value1 = POPD();
1276 jdouble res = __ieee754_fmod (value1, value2);
1283 jint value = POPI();
1290 jlong value = POPL();
1297 jfloat value = POPF();
1304 jdouble value = POPD();
1311 jint shift = (POPI() & 0x1f);
1312 jint value = POPI();
1313 PUSHI (value << shift);
1319 jint shift = (POPI() & 0x3f);
1320 jlong value = POPL();
1321 PUSHL (value << shift);
1327 jint shift = (POPI() & 0x1f);
1328 jint value = POPI();
1329 PUSHI (value >> shift);
1335 jint shift = (POPI() & 0x3f);
1336 jlong value = POPL();
1337 PUSHL (value >> shift);
1343 jint shift = (POPI() & 0x1f);
1344 _Jv_uint value = (_Jv_uint) POPI();
1345 PUSHI ((jint) (value >> shift));
1351 jint shift = (POPI() & 0x3f);
1352 _Jv_ulong value = (_Jv_ulong) POPL();
1353 PUSHL ((jlong) (value >> shift));
1383 jint index = GET1U ();
1384 jint amount = GET1S ();
1385 locals[index].i += amount;
1390 {jlong value = POPI(); PUSHL (value);}
1394 {jfloat value = POPI(); PUSHF (value);}
1398 {jdouble value = POPI(); PUSHD (value);}
1402 {jint value = POPL(); PUSHI (value);}
1406 {jfloat value = POPL(); PUSHF (value);}
1410 {jdouble value = POPL(); PUSHD (value);}
1415 using namespace java::lang;
1416 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1423 using namespace java::lang;
1424 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1430 { jdouble value = POPF (); PUSHD(value); }
1435 using namespace java::lang;
1436 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1443 using namespace java::lang;
1444 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1450 { jfloat value = POPD (); PUSHF(value); }
1454 { jbyte value = POPI (); PUSHI(value); }
1458 { jchar value = POPI (); PUSHI(value); }
1462 { jshort value = POPI (); PUSHI(value); }
1467 jlong value2 = POPL ();
1468 jlong value1 = POPL ();
1469 if (value1 > value2)
1471 else if (value1 == value2)
1487 jfloat value2 = POPF ();
1488 jfloat value1 = POPF ();
1489 if (value1 > value2)
1491 else if (value1 == value2)
1493 else if (value1 < value2)
1509 jdouble value2 = POPD ();
1510 jdouble value1 = POPD ();
1511 if (value1 > value2)
1513 else if (value1 == value2)
1515 else if (value1 < value2)
1578 jint value2 = POPI();
1579 jint value1 = POPI();
1580 if (value1 == value2)
1589 jint value2 = POPI();
1590 jint value1 = POPI();
1591 if (value1 != value2)
1600 jint value2 = POPI();
1601 jint value1 = POPI();
1602 if (value1 < value2)
1611 jint value2 = POPI();
1612 jint value1 = POPI();
1613 if (value1 >= value2)
1622 jint value2 = POPI();
1623 jint value1 = POPI();
1624 if (value1 > value2)
1633 jint value2 = POPI();
1634 jint value1 = POPI();
1635 if (value1 <= value2)
1644 jobject value2 = POPA();
1645 jobject value1 = POPA();
1646 if (value1 == value2)
1655 jobject value2 = POPA();
1656 jobject value1 = POPA();
1657 if (value1 != value2)
1665 #ifndef DIRECT_THREADED
1666 // For direct threaded, goto and goto_w are the same.
1667 pc = pc - 1 + get4 (pc);
1669 #endif /* DIRECT_THREADED */
1675 #ifndef DIRECT_THREADED
1676 // For direct threaded, jsr and jsr_w are the same.
1678 pc_t next = pc - 1 + get4 (pc);
1680 PUSHA ((jobject) pc);
1684 #endif /* DIRECT_THREADED */
1687 pc_t next = GOTO_VAL();
1689 PUSHA ((jobject) pc);
1696 jint index = GET1U ();
1697 pc = (pc_t) PEEKA (index);
1703 #ifdef DIRECT_THREADED
1704 void *def = (pc++)->datum;
1708 jint low = INTVAL ();
1709 jint high = INTVAL ();
1711 if (index < low || index > high)
1712 pc = (insn_slot *) def;
1714 pc = (insn_slot *) ((pc + index - low)->datum);
1716 pc_t base_pc = pc - 1;
1717 int index = POPI ();
1719 pc_t base = (pc_t) meth->bytecode ();
1720 while ((pc - base) % 4 != 0)
1723 jint def = get4 (pc);
1724 jint low = get4 (pc + 4);
1725 jint high = get4 (pc + 8);
1726 if (index < low || index > high)
1729 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1730 #endif /* DIRECT_THREADED */
1736 #ifdef DIRECT_THREADED
1737 void *def = (pc++)->insn;
1741 jint npairs = INTVAL ();
1743 int max = npairs - 1;
1746 // Simple binary search...
1749 int half = (min + max) / 2;
1750 int match = pc[2 * half].int_val;
1755 pc = (insn_slot *) pc[2 * half + 1].datum;
1758 else if (index < match)
1759 // We can use HALF - 1 here because we check again on
1763 // We can use HALF + 1 here because we check again on
1767 if (index == pc[2 * min].int_val)
1768 pc = (insn_slot *) pc[2 * min + 1].datum;
1770 pc = (insn_slot *) def;
1772 unsigned char *base_pc = pc-1;
1775 unsigned char* base = meth->bytecode ();
1776 while ((pc-base) % 4 != 0)
1779 jint def = get4 (pc);
1780 jint npairs = get4 (pc+4);
1785 // Simple binary search...
1788 int half = (min+max)/2;
1789 int match = get4 (pc+ 4*(2 + 2*half));
1793 else if (index < match)
1794 // We can use HALF - 1 here because we check again on
1798 // We can use HALF + 1 here because we check again on
1803 if (index == get4 (pc+ 4*(2 + 2*min)))
1804 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1807 #endif /* DIRECT_THREADED */
1812 *(jobject *) retp = POPA ();
1816 *(jlong *) retp = POPL ();
1820 *(jfloat *) retp = POPF ();
1824 *(jdouble *) retp = POPD ();
1828 *(jint *) retp = POPI ();
1836 jint fieldref_index = GET2U ();
1837 SAVE_PC(); // Constant pool resolution could throw.
1838 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1839 _Jv_Field *field = pool_data[fieldref_index].field;
1841 if ((field->flags & Modifier::STATIC) == 0)
1842 throw_incompatible_class_change_error
1843 (JvNewStringLatin1 ("field no longer static"));
1845 jclass type = field->type;
1847 // We rewrite the instruction once we discover what it refers
1849 void *newinsn = NULL;
1850 if (type->isPrimitive ())
1852 switch (type->size_in_bytes)
1855 PUSHI (*field->u.byte_addr);
1856 newinsn = AMPAMP (getstatic_resolved_1);
1860 if (type == JvPrimClass (char))
1862 PUSHI (*field->u.char_addr);
1863 newinsn = AMPAMP (getstatic_resolved_char);
1867 PUSHI (*field->u.short_addr);
1868 newinsn = AMPAMP (getstatic_resolved_short);
1873 PUSHI(*field->u.int_addr);
1874 newinsn = AMPAMP (getstatic_resolved_4);
1878 PUSHL(*field->u.long_addr);
1879 newinsn = AMPAMP (getstatic_resolved_8);
1885 PUSHA(*field->u.object_addr);
1886 newinsn = AMPAMP (getstatic_resolved_obj);
1889 #ifdef DIRECT_THREADED
1890 REWRITE_INSN (newinsn, datum, field->u.addr);
1891 #endif /* DIRECT_THREADED */
1895 #ifdef DIRECT_THREADED
1896 getstatic_resolved_1:
1897 PUSHI (*(jbyte *) AVAL ());
1900 getstatic_resolved_char:
1901 PUSHI (*(jchar *) AVAL ());
1904 getstatic_resolved_short:
1905 PUSHI (*(jshort *) AVAL ());
1908 getstatic_resolved_4:
1909 PUSHI (*(jint *) AVAL ());
1912 getstatic_resolved_8:
1913 PUSHL (*(jlong *) AVAL ());
1916 getstatic_resolved_obj:
1917 PUSHA (*(jobject *) AVAL ());
1919 #endif /* DIRECT_THREADED */
1924 jint fieldref_index = GET2U ();
1925 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1926 _Jv_Field *field = pool_data[fieldref_index].field;
1928 if ((field->flags & Modifier::STATIC) != 0)
1929 throw_incompatible_class_change_error
1930 (JvNewStringLatin1 ("field is static"));
1932 jclass type = field->type;
1933 jint field_offset = field->u.boffset;
1935 jobject obj = POPA();
1938 void *newinsn = NULL;
1939 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1940 if (type->isPrimitive ())
1942 switch (type->size_in_bytes)
1945 PUSHI (val->byte_value);
1946 newinsn = AMPAMP (getfield_resolved_1);
1950 if (type == JvPrimClass (char))
1952 PUSHI (val->char_value);
1953 newinsn = AMPAMP (getfield_resolved_char);
1957 PUSHI (val->short_value);
1958 newinsn = AMPAMP (getfield_resolved_short);
1963 PUSHI (val->int_value);
1964 newinsn = AMPAMP (getfield_resolved_4);
1968 PUSHL (val->long_value);
1969 newinsn = AMPAMP (getfield_resolved_8);
1975 PUSHA (val->object_value);
1976 newinsn = AMPAMP (getfield_resolved_obj);
1979 #ifdef DIRECT_THREADED
1980 REWRITE_INSN (newinsn, int_val, field_offset);
1981 #endif /* DIRECT_THREADED */
1985 #ifdef DIRECT_THREADED
1986 getfield_resolved_1:
1988 char *obj = (char *) POPA ();
1990 PUSHI (*(jbyte *) (obj + INTVAL ()));
1994 getfield_resolved_char:
1996 char *obj = (char *) POPA ();
1998 PUSHI (*(jchar *) (obj + INTVAL ()));
2002 getfield_resolved_short:
2004 char *obj = (char *) POPA ();
2006 PUSHI (*(jshort *) (obj + INTVAL ()));
2010 getfield_resolved_4:
2012 char *obj = (char *) POPA ();
2014 PUSHI (*(jint *) (obj + INTVAL ()));
2018 getfield_resolved_8:
2020 char *obj = (char *) POPA ();
2022 PUSHL (*(jlong *) (obj + INTVAL ()));
2026 getfield_resolved_obj:
2028 char *obj = (char *) POPA ();
2030 PUSHA (*(jobject *) (obj + INTVAL ()));
2033 #endif /* DIRECT_THREADED */
2038 jint fieldref_index = GET2U ();
2039 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2040 _Jv_Field *field = pool_data[fieldref_index].field;
2042 jclass type = field->type;
2044 // ResolvePoolEntry cannot check this
2045 if ((field->flags & Modifier::STATIC) == 0)
2046 throw_incompatible_class_change_error
2047 (JvNewStringLatin1 ("field no longer static"));
2049 void *newinsn = NULL;
2050 if (type->isPrimitive ())
2052 switch (type->size_in_bytes)
2056 jint value = POPI();
2057 *field->u.byte_addr = value;
2058 newinsn = AMPAMP (putstatic_resolved_1);
2064 jint value = POPI();
2065 *field->u.char_addr = value;
2066 newinsn = AMPAMP (putstatic_resolved_2);
2072 jint value = POPI();
2073 *field->u.int_addr = value;
2074 newinsn = AMPAMP (putstatic_resolved_4);
2080 jlong value = POPL();
2081 *field->u.long_addr = value;
2082 newinsn = AMPAMP (putstatic_resolved_8);
2089 jobject value = POPA();
2090 *field->u.object_addr = value;
2091 newinsn = AMPAMP (putstatic_resolved_obj);
2094 #ifdef DIRECT_THREADED
2095 REWRITE_INSN (newinsn, datum, field->u.addr);
2096 #endif /* DIRECT_THREADED */
2100 #ifdef DIRECT_THREADED
2101 putstatic_resolved_1:
2102 *(jbyte *) AVAL () = POPI ();
2105 putstatic_resolved_2:
2106 *(jchar *) AVAL () = POPI ();
2109 putstatic_resolved_4:
2110 *(jint *) AVAL () = POPI ();
2113 putstatic_resolved_8:
2114 *(jlong *) AVAL () = POPL ();
2117 putstatic_resolved_obj:
2118 *(jobject *) AVAL () = POPA ();
2120 #endif /* DIRECT_THREADED */
2125 jint fieldref_index = GET2U ();
2126 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2127 _Jv_Field *field = pool_data[fieldref_index].field;
2129 jclass type = field->type;
2131 if ((field->flags & Modifier::STATIC) != 0)
2132 throw_incompatible_class_change_error
2133 (JvNewStringLatin1 ("field is static"));
2135 jint field_offset = field->u.boffset;
2137 void *newinsn = NULL;
2138 if (type->isPrimitive ())
2140 switch (type->size_in_bytes)
2144 jint value = POPI();
2145 jobject obj = POPA();
2147 *(jbyte*) ((char*)obj + field_offset) = value;
2148 newinsn = AMPAMP (putfield_resolved_1);
2154 jint value = POPI();
2155 jobject obj = POPA();
2157 *(jchar*) ((char*)obj + field_offset) = value;
2158 newinsn = AMPAMP (putfield_resolved_2);
2164 jint value = POPI();
2165 jobject obj = POPA();
2167 *(jint*) ((char*)obj + field_offset) = value;
2168 newinsn = AMPAMP (putfield_resolved_4);
2174 jlong value = POPL();
2175 jobject obj = POPA();
2177 *(jlong*) ((char*)obj + field_offset) = value;
2178 newinsn = AMPAMP (putfield_resolved_8);
2185 jobject value = POPA();
2186 jobject obj = POPA();
2188 *(jobject*) ((char*)obj + field_offset) = value;
2189 newinsn = AMPAMP (putfield_resolved_obj);
2192 #ifdef DIRECT_THREADED
2193 REWRITE_INSN (newinsn, int_val, field_offset);
2194 #endif /* DIRECT_THREADED */
2198 #ifdef DIRECT_THREADED
2199 putfield_resolved_1:
2202 char *obj = (char *) POPA ();
2204 *(jbyte *) (obj + INTVAL ()) = val;
2208 putfield_resolved_2:
2211 char *obj = (char *) POPA ();
2213 *(jchar *) (obj + INTVAL ()) = val;
2217 putfield_resolved_4:
2220 char *obj = (char *) POPA ();
2222 *(jint *) (obj + INTVAL ()) = val;
2226 putfield_resolved_8:
2228 jlong val = POPL ();
2229 char *obj = (char *) POPA ();
2231 *(jlong *) (obj + INTVAL ()) = val;
2235 putfield_resolved_obj:
2237 jobject val = POPA ();
2238 char *obj = (char *) POPA ();
2240 *(jobject *) (obj + INTVAL ()) = val;
2243 #endif /* DIRECT_THREADED */
2248 int index = GET2U ();
2250 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2253 sp -= rmeth->stack_item_count;
2255 // We don't use NULLCHECK here because we can't rely on that
2256 // working for <init>. So instead we do an explicit test.
2260 throw_null_pointer_exception ();
2263 fun = (void (*)()) rmeth->method->ncode;
2265 #ifdef DIRECT_THREADED
2266 // Rewrite instruction so that we use a faster pre-resolved
2268 REWRITE_INSN (&&invokespecial_resolved, datum, rmeth);
2269 #endif /* DIRECT_THREADED */
2271 goto perform_invoke;
2273 #ifdef DIRECT_THREADED
2274 invokespecial_resolved:
2277 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2278 sp -= rmeth->stack_item_count;
2279 // We don't use NULLCHECK here because we can't rely on that
2280 // working for <init>. So instead we do an explicit test.
2283 throw_null_pointer_exception ();
2285 fun = (void (*)()) rmeth->method->ncode;
2287 goto perform_invoke;
2288 #endif /* DIRECT_THREADED */
2293 int index = GET2U ();
2295 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2298 sp -= rmeth->stack_item_count;
2300 fun = (void (*)()) rmeth->method->ncode;
2302 #ifdef DIRECT_THREADED
2303 // Rewrite instruction so that we use a faster pre-resolved
2305 REWRITE_INSN (&&invokestatic_resolved, datum, rmeth);
2306 #endif /* DIRECT_THREADED */
2308 goto perform_invoke;
2310 #ifdef DIRECT_THREADED
2311 invokestatic_resolved:
2314 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2315 sp -= rmeth->stack_item_count;
2316 fun = (void (*)()) rmeth->method->ncode;
2318 goto perform_invoke;
2319 #endif /* DIRECT_THREADED */
2321 insn_invokeinterface:
2324 int index = GET2U ();
2326 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2329 sp -= rmeth->stack_item_count;
2331 jobject rcv = sp[0].o;
2336 _Jv_LookupInterfaceMethod (rcv->getClass (),
2337 rmeth->method->name,
2338 rmeth->method->signature);
2340 #ifdef DIRECT_THREADED
2341 // Rewrite instruction so that we use a faster pre-resolved
2343 REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth);
2345 // Skip dummy bytes.
2347 #endif /* DIRECT_THREADED */
2349 goto perform_invoke;
2351 #ifdef DIRECT_THREADED
2352 invokeinterface_resolved:
2355 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2356 sp -= rmeth->stack_item_count;
2357 jobject rcv = sp[0].o;
2360 _Jv_LookupInterfaceMethod (rcv->getClass (),
2361 rmeth->method->name,
2362 rmeth->method->signature);
2364 goto perform_invoke;
2365 #endif /* DIRECT_THREADED */
2370 int index = GET2U ();
2371 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2373 /* VM spec, section 3.11.5 */
2374 if ((klass->getModifiers() & Modifier::ABSTRACT)
2375 || klass->isInterface())
2377 jthrowable t = new java::lang::InstantiationException;
2378 INTERP_REPORT_EXCEPTION (t);
2381 jobject res = _Jv_AllocObject (klass);
2384 #ifdef DIRECT_THREADED
2385 REWRITE_INSN (&&new_resolved, datum, klass);
2386 #endif /* DIRECT_THREADED */
2390 #ifdef DIRECT_THREADED
2393 jclass klass = (jclass) AVAL ();
2394 jobject res = _Jv_AllocObject (klass);
2398 #endif /* DIRECT_THREADED */
2402 int atype = GET1U ();
2404 jobject result = _Jv_NewArray (atype, size);
2412 int index = GET2U ();
2413 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2416 jobject result = _Jv_NewObjectArray (size, klass, 0);
2419 #ifdef DIRECT_THREADED
2420 REWRITE_INSN (&&anewarray_resolved, datum, klass);
2421 #endif /* DIRECT_THREADED */
2425 #ifdef DIRECT_THREADED
2428 jclass klass = (jclass) AVAL ();
2430 jobject result = _Jv_NewObjectArray (size, klass, 0);
2434 #endif /* DIRECT_THREADED */
2438 __JArray *arr = (__JArray*)POPA();
2439 NULLARRAYCHECK (arr);
2440 PUSHI (arr->length);
2446 jobject value = POPA();
2447 jthrowable t = static_cast<jthrowable> (value);
2448 INTERP_REPORT_EXCEPTION (t);
2456 jobject value = POPA();
2457 jint index = GET2U ();
2458 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2461 value = (jobject) _Jv_CheckCast (to, value);
2465 #ifdef DIRECT_THREADED
2466 REWRITE_INSN (&&checkcast_resolved, datum, to);
2467 #endif /* DIRECT_THREADED */
2471 #ifdef DIRECT_THREADED
2475 jobject value = POPA ();
2476 jclass to = (jclass) AVAL ();
2477 value = (jobject) _Jv_CheckCast (to, value);
2481 #endif /* DIRECT_THREADED */
2486 jobject value = POPA();
2487 jint index = GET2U ();
2488 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2490 PUSHI (to->isInstance (value));
2492 #ifdef DIRECT_THREADED
2493 REWRITE_INSN (&&instanceof_resolved, datum, to);
2494 #endif /* DIRECT_THREADED */
2498 #ifdef DIRECT_THREADED
2499 instanceof_resolved:
2501 jobject value = POPA ();
2502 jclass to = (jclass) AVAL ();
2503 PUSHI (to->isInstance (value));
2506 #endif /* DIRECT_THREADED */
2510 jobject value = POPA();
2512 _Jv_MonitorEnter (value);
2518 jobject value = POPA();
2520 _Jv_MonitorExit (value);
2526 jobject val = POPA();
2536 jobject val = POPA();
2544 insn_multianewarray:
2547 int kind_index = GET2U ();
2551 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2553 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2555 for (int i = dim - 1; i >= 0; i--)
2560 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2566 #ifndef DIRECT_THREADED
2569 jint the_mod_op = get1u (pc++);
2570 jint wide = get2u (pc); pc += 2;
2615 pc = (unsigned char*) PEEKA (wide);
2620 jint amount = get2s (pc); pc += 2;
2621 jint value = PEEKI (wide);
2622 POKEI (wide, value+amount);
2627 throw_internal_error ("illegal bytecode modified by wide");
2631 #endif /* DIRECT_THREADED */
2635 using namespace ::java::lang;
2636 jmethodID method = meth->self;
2637 jlocation location = meth->insn_index (pc - 1);
2639 using namespace gnu::gcj::jvmti;
2641 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2643 JvAssert (bp != NULL);
2645 // Save the insn here since the breakpoint could be removed
2646 // before the JVMTI notification returns.
2647 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2651 // Continue execution
2652 #ifdef DIRECT_THREADED
2655 goto *(insn_target[*opc]);
2659 catch (java::lang::Throwable *ex)
2661 // Check if the exception is handled and, if so, set the pc to the start
2662 // of the appropriate catch block.
2663 if (meth->check_handler (&pc, meth, ex))
2666 sp++->o = ex; // Push exception.
2668 if (JVMTI_REQUESTED_EVENT (ExceptionCatch))
2670 using namespace gnu::gcj::jvmti;
2671 jlong catch_meth = reinterpret_cast<jlong> (meth->get_method ());
2672 jlong catch_loc = meth->insn_index (pc);
2673 _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH, thread,
2674 _Jv_GetCurrentJNIEnv (), catch_meth,
2681 // No handler, so re-throw.