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 #ifdef DIRECT_THREADED
33 ThreadCountAdjuster adj (meth, &frame_desc);
34 #endif // DIRECT_THREADED
36 _Jv_word stack[meth->max_stack];
39 _Jv_word locals[meth->max_locals];
42 // This is the information needed to get and set local variables with
43 // proper type checking.
44 frame_desc.locals = locals;
45 char locals_type[meth->max_locals];
46 frame_desc.locals_type = locals_type;
48 // Set all slots as invalid until they are written to.
49 memset (locals_type, 'x', meth->max_locals);
51 // We need to set the local variable types for the method arguments since
52 // they are valid at invocation.
54 _Jv_Method *method = meth->get_method ();
57 // If the method is non-static, we need to set the type for the "this" pointer.
58 if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
62 // Set the "this" pointer for this frame.
63 _Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args);
64 frame_desc.obj_ptr = this_ptr[0].o;
67 frame_desc.locals_type[0] = 'o';
71 // Now parse the method signature to set the types of the other arguments.
72 int sig_len = method->signature->len ();
73 char *signature = method->signature->chars ();
74 for (int i = 1; signature[i] != ')' && i <= sig_len; i++)
76 if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C'
77 || signature[i] == 'S' || signature[i] == 'I')
79 frame_desc.locals_type[type_ctr] = 'i';
83 else if (signature[i] == 'F')
85 frame_desc.locals_type[type_ctr] = 'f';
89 else if (signature[i] == 'J')
91 frame_desc.locals_type[type_ctr] = 'l';
92 frame_desc.locals_type[type_ctr+1] = 'x';
96 else if (signature[i] == 'D')
98 frame_desc.locals_type[type_ctr] = 'd';
99 frame_desc.locals_type[type_ctr+1] = 'x';
103 else if (signature[i] == 'L')
105 frame_desc.locals_type[type_ctr] = 'o';
107 while (signature[i] != ';')
111 else if (signature[i] == '[')
113 frame_desc.locals_type[type_ctr] = 'o';
116 // Ignore multi-dimensional arrays.
117 while (signature[i] == '[')
120 // Check for an object array
121 if (signature[i] == 'L')
123 while (signature[i] != ';')
129 #endif /* __GCJ_DEBUG */
131 #define INSN_LABEL(op) &&insn_##op
133 static const void *const insn_target[] =
136 INSN_LABEL(aconst_null),
137 INSN_LABEL(iconst_m1),
138 INSN_LABEL(iconst_0),
139 INSN_LABEL(iconst_1),
140 INSN_LABEL(iconst_2),
141 INSN_LABEL(iconst_3),
142 INSN_LABEL(iconst_4),
143 INSN_LABEL(iconst_5),
144 INSN_LABEL(lconst_0),
145 INSN_LABEL(lconst_1),
146 INSN_LABEL(fconst_0),
147 INSN_LABEL(fconst_1),
148 INSN_LABEL(fconst_2),
149 INSN_LABEL(dconst_0),
150 INSN_LABEL(dconst_1),
194 INSN_LABEL(istore_0),
195 INSN_LABEL(istore_1),
196 INSN_LABEL(istore_2),
197 INSN_LABEL(istore_3),
198 INSN_LABEL(lstore_0),
199 INSN_LABEL(lstore_1),
200 INSN_LABEL(lstore_2),
201 INSN_LABEL(lstore_3),
202 INSN_LABEL(fstore_0),
203 INSN_LABEL(fstore_1),
204 INSN_LABEL(fstore_2),
205 INSN_LABEL(fstore_3),
206 INSN_LABEL(dstore_0),
207 INSN_LABEL(dstore_1),
208 INSN_LABEL(dstore_2),
209 INSN_LABEL(dstore_3),
210 INSN_LABEL(astore_0),
211 INSN_LABEL(astore_1),
212 INSN_LABEL(astore_2),
213 INSN_LABEL(astore_3),
294 INSN_LABEL(if_icmpeq),
295 INSN_LABEL(if_icmpne),
296 INSN_LABEL(if_icmplt),
297 INSN_LABEL(if_icmpge),
298 INSN_LABEL(if_icmpgt),
299 INSN_LABEL(if_icmple),
300 INSN_LABEL(if_acmpeq),
301 INSN_LABEL(if_acmpne),
305 INSN_LABEL(tableswitch),
306 INSN_LABEL(lookupswitch),
313 INSN_LABEL(getstatic),
314 INSN_LABEL(putstatic),
315 INSN_LABEL(getfield),
316 INSN_LABEL(putfield),
317 INSN_LABEL(invokevirtual),
318 INSN_LABEL(invokespecial),
319 INSN_LABEL(invokestatic),
320 INSN_LABEL(invokeinterface),
321 INSN_LABEL(breakpoint),
323 INSN_LABEL(newarray),
324 INSN_LABEL(anewarray),
325 INSN_LABEL(arraylength),
327 INSN_LABEL(checkcast),
328 INSN_LABEL(instanceof),
329 INSN_LABEL(monitorenter),
330 INSN_LABEL(monitorexit),
331 #ifdef DIRECT_THREADED
336 INSN_LABEL(multianewarray),
338 INSN_LABEL(ifnonnull),
341 #ifdef DIRECT_THREADED
342 INSN_LABEL (ldc_class)
348 #ifdef DIRECT_THREADED
356 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
358 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
359 jmethodID method = meth->self; \
360 jlocation loc = meth->insn_index (insn); \
361 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
364 goto *(insn->insn); \
368 // We fail to rewrite a breakpoint if there is another thread
369 // currently executing this method. This is a bug, but there's
370 // nothing else we can do that doesn't cause a data race.
372 #define REWRITE_INSN(INSN,SLOT,VALUE) \
375 _Jv_MutexLock (&rewrite_insn_mutex); \
376 if (meth->thread_count <= 1) \
378 if (pc[-2].insn == breakpoint_insn->insn) \
380 using namespace ::gnu::gcj::jvmti; \
381 jlocation location = meth->insn_index (pc - 2); \
382 _Jv_RewriteBreakpointInsn (meth->self, location, (pc_t) INSN); \
385 pc[-2].insn = INSN; \
387 pc[-1].SLOT = VALUE; \
389 _Jv_MutexUnlock (&rewrite_insn_mutex); \
393 #undef INTERP_REPORT_EXCEPTION
394 #define INTERP_REPORT_EXCEPTION(Jthrowable) REPORT_EXCEPTION (Jthrowable)
395 #else // !__GCJ_DEBUG
397 #define NEXT_INSN goto *((pc++)->insn)
399 // Rewriting a multi-word instruction in the presence of multiple
400 // threads is a data race if a thread reads part of an instruction
401 // while some other thread is rewriting that instruction. We detect
402 // more than one thread executing a method and don't rewrite the
403 // instruction. A thread entering a method blocks on
404 // rewrite_insn_mutex until the write is complete.
405 #define REWRITE_INSN(INSN,SLOT,VALUE) \
407 _Jv_MutexLock (&rewrite_insn_mutex); \
408 if (meth->thread_count <= 1) \
410 pc[-2].insn = INSN; \
411 pc[-1].SLOT = VALUE; \
413 _Jv_MutexUnlock (&rewrite_insn_mutex); \
417 #undef INTERP_REPORT_EXCEPTION
418 #define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */
419 #endif // !__GCJ_DEBUG
421 #define INTVAL() ((pc++)->int_val)
422 #define AVAL() ((pc++)->datum)
424 #define GET1S() INTVAL ()
425 #define GET2S() INTVAL ()
426 #define GET1U() INTVAL ()
427 #define GET2U() INTVAL ()
428 #define AVAL1U() AVAL ()
429 #define AVAL2U() AVAL ()
430 #define AVAL2UP() AVAL ()
431 #define SKIP_GOTO ++pc
432 #define GOTO_VAL() (insn_slot *) pc->datum
433 #define PCVAL(unionval) unionval.p
434 #define AMPAMP(label) &&label
436 // Compile if we must. NOTE: Double-check locking.
437 if (meth->prepared == NULL)
439 _Jv_MutexLock (&compile_mutex);
440 if (meth->prepared == NULL)
441 meth->compile (insn_target);
442 _Jv_MutexUnlock (&compile_mutex);
445 // If we're only compiling, stop here
449 pc = (insn_slot *) meth->prepared;
457 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
459 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
460 jmethodID method = meth->self; \
461 jlocation loc = meth->insn_index (pc); \
462 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
465 goto *(insn_target[*pc++])
467 #define NEXT_INSN goto *(insn_target[*pc++])
470 #define GET1S() get1s (pc++)
471 #define GET2S() (pc += 2, get2s (pc- 2))
472 #define GET1U() get1u (pc++)
473 #define GET2U() (pc += 2, get2u (pc - 2))
474 // Note that these could be more efficient when not handling 'ldc
477 ({ int index = get1u (pc++); \
478 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
480 ({ int index = get2u (pc); pc += 2; \
481 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
482 // Note that we don't need to resolve the pool entry here as class
483 // constants are never wide.
484 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
485 #define SKIP_GOTO pc += 2
486 #define GOTO_VAL() pc - 1 + get2s (pc)
487 #define PCVAL(unionval) unionval.i
488 #define AMPAMP(label) NULL
490 pc = meth->bytecode ();
492 #endif /* DIRECT_THREADED */
494 #define TAKE_GOTO pc = GOTO_VAL ()
496 /* Go straight at it! the ffi raw format matches the internal
497 stack representation exactly. At least, that's the idea.
499 memcpy ((void*) locals, (void*) args, meth->args_raw_size);
501 _Jv_word *pool_data = meth->defining_class->constants.data;
503 /* These three are temporaries for common code used by several
506 _Jv_ResolvedMethod* rmeth;
511 // We keep nop around. It is used if we're interpreting the
512 // bytecodes and not doing direct threading.
516 /* The first few instructions here are ordered according to their
517 frequency, in the hope that this will improve code locality a
520 insn_aload_0: // 0x2a
528 insn_iload_1: // 0x1b
532 insn_invokevirtual: // 0xb6
535 int index = GET2U ();
537 /* _Jv_Linker::resolve_pool_entry returns immediately if the
538 * value already is resolved. If we want to clutter up the
539 * code here to gain a little performance, then we can check
540 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
541 * directly. For now, I don't think it is worth it. */
543 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
546 sp -= rmeth->stack_item_count;
548 if (rmeth->method->accflags & Modifier::FINAL)
550 // We can't rely on NULLCHECK working if the method is final.
552 throw_null_pointer_exception ();
554 // Final methods might not appear in the vtable.
555 fun = (void (*)()) rmeth->method->ncode;
560 jobject rcv = sp[0].o;
561 _Jv_VTable *table = *(_Jv_VTable**) rcv;
562 fun = (void (*)()) table->get_method (rmeth->method->index);
565 #ifdef DIRECT_THREADED
566 // Rewrite instruction so that we use a faster pre-resolved
568 REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth);
569 #endif /* DIRECT_THREADED */
573 #ifdef DIRECT_THREADED
574 invokevirtual_resolved:
577 rmeth = (_Jv_ResolvedMethod *) AVAL ();
578 sp -= rmeth->stack_item_count;
580 if (rmeth->method->accflags & Modifier::FINAL)
582 // We can't rely on NULLCHECK working if the method is final.
584 throw_null_pointer_exception ();
586 // Final methods might not appear in the vtable.
587 fun = (void (*)()) rmeth->method->ncode;
592 jobject rcv = sp[0].o;
593 _Jv_VTable *table = *(_Jv_VTable**) rcv;
594 fun = (void (*)()) table->get_method (rmeth->method->index);
598 #endif /* DIRECT_THREADED */
602 /* here goes the magic again... */
603 ffi_cif *cif = &rmeth->cif;
604 INTERP_FFI_RAW_TYPE *raw = (INTERP_FFI_RAW_TYPE *) sp;
608 #if FFI_NATIVE_RAW_API
609 /* We assume that this is only implemented if it's correct */
610 /* to use it here. On a 64 bit machine, it never is. */
611 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
613 ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
616 int rtype = cif->rtype->type;
618 /* the likelyhood of object, int, or void return is very high,
619 * so those are checked before the switch */
620 if (rtype == FFI_TYPE_POINTER)
622 PUSHA (rvalue.object_value);
624 else if (rtype == FFI_TYPE_SINT32)
626 PUSHI (rvalue.int_value);
628 else if (rtype == FFI_TYPE_VOID)
637 PUSHI ((jbyte)(rvalue.int_value & 0xff));
640 case FFI_TYPE_SINT16:
641 PUSHI ((jshort)(rvalue.int_value & 0xffff));
644 case FFI_TYPE_UINT16:
645 PUSHI (rvalue.int_value & 0xffff);
649 PUSHF (rvalue.float_value);
652 case FFI_TYPE_DOUBLE:
653 PUSHD (rvalue.double_value);
656 case FFI_TYPE_SINT64:
657 PUSHL (rvalue.long_value);
661 throw_internal_error ("unknown return type in invokeXXX");
728 // For direct threaded, bipush and sipush are the same.
729 #ifndef DIRECT_THREADED
732 #endif /* DIRECT_THREADED */
738 // For direct threaded, ldc and ldc_w are the same.
739 #ifndef DIRECT_THREADED
740 PUSHA ((jobject) AVAL1U ());
742 #endif /* DIRECT_THREADED */
744 PUSHA ((jobject) AVAL2U ());
747 #ifdef DIRECT_THREADED
748 // For direct threaded we have a separate 'ldc class' operation.
752 // We could rewrite the instruction at this point.
753 int index = INTVAL ();
754 jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
759 #endif /* DIRECT_THREADED */
763 void *where = AVAL2UP ();
764 memcpy (sp, where, 2*sizeof (_Jv_word));
860 jintArray arr = (jintArray) POPA();
861 NULLARRAYCHECK (arr);
862 ARRAYBOUNDSCHECK (arr, index);
863 PUSHI( elements(arr)[index] );
870 jlongArray arr = (jlongArray) POPA();
871 NULLARRAYCHECK (arr);
872 ARRAYBOUNDSCHECK (arr, index);
873 PUSHL( elements(arr)[index] );
880 jfloatArray arr = (jfloatArray) POPA();
881 NULLARRAYCHECK (arr);
882 ARRAYBOUNDSCHECK (arr, index);
883 PUSHF( elements(arr)[index] );
890 jdoubleArray arr = (jdoubleArray) POPA();
891 NULLARRAYCHECK (arr);
892 ARRAYBOUNDSCHECK (arr, index);
893 PUSHD( elements(arr)[index] );
900 jobjectArray arr = (jobjectArray) POPA();
901 NULLARRAYCHECK (arr);
902 ARRAYBOUNDSCHECK (arr, index);
903 PUSHA( elements(arr)[index] );
910 jbyteArray arr = (jbyteArray) POPA();
911 NULLARRAYCHECK (arr);
912 ARRAYBOUNDSCHECK (arr, index);
913 PUSHI( elements(arr)[index] );
920 jcharArray arr = (jcharArray) POPA();
921 NULLARRAYCHECK (arr);
922 ARRAYBOUNDSCHECK (arr, index);
923 PUSHI( elements(arr)[index] );
930 jshortArray arr = (jshortArray) POPA();
931 NULLARRAYCHECK (arr);
932 ARRAYBOUNDSCHECK (arr, index);
933 PUSHI( elements(arr)[index] );
1039 jint value = POPI();
1040 jint index = POPI();
1041 jintArray arr = (jintArray) POPA();
1042 NULLARRAYCHECK (arr);
1043 ARRAYBOUNDSCHECK (arr, index);
1044 elements(arr)[index] = value;
1050 jlong value = POPL();
1051 jint index = POPI();
1052 jlongArray arr = (jlongArray) POPA();
1053 NULLARRAYCHECK (arr);
1054 ARRAYBOUNDSCHECK (arr, index);
1055 elements(arr)[index] = value;
1061 jfloat value = POPF();
1062 jint index = POPI();
1063 jfloatArray arr = (jfloatArray) POPA();
1064 NULLARRAYCHECK (arr);
1065 ARRAYBOUNDSCHECK (arr, index);
1066 elements(arr)[index] = value;
1072 jdouble value = POPD();
1073 jint index = POPI();
1074 jdoubleArray arr = (jdoubleArray) POPA();
1075 NULLARRAYCHECK (arr);
1076 ARRAYBOUNDSCHECK (arr, index);
1077 elements(arr)[index] = value;
1083 jobject value = POPA();
1084 jint index = POPI();
1085 jobjectArray arr = (jobjectArray) POPA();
1086 NULLARRAYCHECK (arr);
1087 ARRAYBOUNDSCHECK (arr, index);
1088 _Jv_CheckArrayStore (arr, value);
1089 elements(arr)[index] = value;
1095 jbyte value = (jbyte) POPI();
1096 jint index = POPI();
1097 jbyteArray arr = (jbyteArray) POPA();
1098 NULLARRAYCHECK (arr);
1099 ARRAYBOUNDSCHECK (arr, index);
1100 elements(arr)[index] = value;
1106 jchar value = (jchar) POPI();
1107 jint index = POPI();
1108 jcharArray arr = (jcharArray) POPA();
1109 NULLARRAYCHECK (arr);
1110 ARRAYBOUNDSCHECK (arr, index);
1111 elements(arr)[index] = value;
1117 jshort value = (jshort) POPI();
1118 jint index = POPI();
1119 jshortArray arr = (jshortArray) POPA();
1120 NULLARRAYCHECK (arr);
1121 ARRAYBOUNDSCHECK (arr, index);
1122 elements(arr)[index] = value;
1140 dupx (sp, 1, 1); sp+=1;
1144 dupx (sp, 1, 2); sp+=1;
1154 dupx (sp, 2, 1); sp+=2;
1158 dupx (sp, 2, 2); sp+=2;
1163 jobject tmp1 = POPA();
1164 jobject tmp2 = POPA();
1221 jint value2 = POPI();
1222 jint value1 = POPI();
1223 jint res = _Jv_divI (value1, value2);
1231 jlong value2 = POPL();
1232 jlong value1 = POPL();
1233 jlong res = _Jv_divJ (value1, value2);
1240 jfloat value2 = POPF();
1241 jfloat value1 = POPF();
1242 jfloat res = value1 / value2;
1249 jdouble value2 = POPD();
1250 jdouble value1 = POPD();
1251 jdouble res = value1 / value2;
1259 jint value2 = POPI();
1260 jint value1 = POPI();
1261 jint res = _Jv_remI (value1, value2);
1269 jlong value2 = POPL();
1270 jlong value1 = POPL();
1271 jlong res = _Jv_remJ (value1, value2);
1278 jfloat value2 = POPF();
1279 jfloat value1 = POPF();
1280 jfloat res = __ieee754_fmod (value1, value2);
1287 jdouble value2 = POPD();
1288 jdouble value1 = POPD();
1289 jdouble res = __ieee754_fmod (value1, value2);
1296 jint value = POPI();
1303 jlong value = POPL();
1310 jfloat value = POPF();
1317 jdouble value = POPD();
1324 jint shift = (POPI() & 0x1f);
1325 jint value = POPI();
1326 PUSHI (value << shift);
1332 jint shift = (POPI() & 0x3f);
1333 jlong value = POPL();
1334 PUSHL (value << shift);
1340 jint shift = (POPI() & 0x1f);
1341 jint value = POPI();
1342 PUSHI (value >> shift);
1348 jint shift = (POPI() & 0x3f);
1349 jlong value = POPL();
1350 PUSHL (value >> shift);
1356 jint shift = (POPI() & 0x1f);
1357 _Jv_uint value = (_Jv_uint) POPI();
1358 PUSHI ((jint) (value >> shift));
1364 jint shift = (POPI() & 0x3f);
1365 _Jv_ulong value = (_Jv_ulong) POPL();
1366 PUSHL ((jlong) (value >> shift));
1396 jint index = GET1U ();
1397 jint amount = GET1S ();
1398 locals[index].i += amount;
1403 {jlong value = POPI(); PUSHL (value);}
1407 {jfloat value = POPI(); PUSHF (value);}
1411 {jdouble value = POPI(); PUSHD (value);}
1415 {jint value = POPL(); PUSHI (value);}
1419 {jfloat value = POPL(); PUSHF (value);}
1423 {jdouble value = POPL(); PUSHD (value);}
1428 using namespace java::lang;
1429 jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1436 using namespace java::lang;
1437 jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
1443 { jdouble value = POPF (); PUSHD(value); }
1448 using namespace java::lang;
1449 jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
1456 using namespace java::lang;
1457 jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
1463 { jfloat value = POPD (); PUSHF(value); }
1467 { jbyte value = POPI (); PUSHI(value); }
1471 { jchar value = POPI (); PUSHI(value); }
1475 { jshort value = POPI (); PUSHI(value); }
1480 jlong value2 = POPL ();
1481 jlong value1 = POPL ();
1482 if (value1 > value2)
1484 else if (value1 == value2)
1500 jfloat value2 = POPF ();
1501 jfloat value1 = POPF ();
1502 if (value1 > value2)
1504 else if (value1 == value2)
1506 else if (value1 < value2)
1522 jdouble value2 = POPD ();
1523 jdouble value1 = POPD ();
1524 if (value1 > value2)
1526 else if (value1 == value2)
1528 else if (value1 < value2)
1591 jint value2 = POPI();
1592 jint value1 = POPI();
1593 if (value1 == value2)
1602 jint value2 = POPI();
1603 jint value1 = POPI();
1604 if (value1 != value2)
1613 jint value2 = POPI();
1614 jint value1 = POPI();
1615 if (value1 < value2)
1624 jint value2 = POPI();
1625 jint value1 = POPI();
1626 if (value1 >= value2)
1635 jint value2 = POPI();
1636 jint value1 = POPI();
1637 if (value1 > value2)
1646 jint value2 = POPI();
1647 jint value1 = POPI();
1648 if (value1 <= value2)
1657 jobject value2 = POPA();
1658 jobject value1 = POPA();
1659 if (value1 == value2)
1668 jobject value2 = POPA();
1669 jobject value1 = POPA();
1670 if (value1 != value2)
1678 #ifndef DIRECT_THREADED
1679 // For direct threaded, goto and goto_w are the same.
1680 pc = pc - 1 + get4 (pc);
1682 #endif /* DIRECT_THREADED */
1688 #ifndef DIRECT_THREADED
1689 // For direct threaded, jsr and jsr_w are the same.
1691 pc_t next = pc - 1 + get4 (pc);
1693 PUSHA ((jobject) pc);
1697 #endif /* DIRECT_THREADED */
1700 pc_t next = GOTO_VAL();
1702 PUSHA ((jobject) pc);
1709 jint index = GET1U ();
1710 pc = (pc_t) PEEKA (index);
1716 #ifdef DIRECT_THREADED
1717 void *def = (pc++)->datum;
1721 jint low = INTVAL ();
1722 jint high = INTVAL ();
1724 if (index < low || index > high)
1725 pc = (insn_slot *) def;
1727 pc = (insn_slot *) ((pc + index - low)->datum);
1729 pc_t base_pc = pc - 1;
1730 int index = POPI ();
1732 pc_t base = (pc_t) meth->bytecode ();
1733 while ((pc - base) % 4 != 0)
1736 jint def = get4 (pc);
1737 jint low = get4 (pc + 4);
1738 jint high = get4 (pc + 8);
1739 if (index < low || index > high)
1742 pc = base_pc + get4 (pc + 4 * (index - low + 3));
1743 #endif /* DIRECT_THREADED */
1749 #ifdef DIRECT_THREADED
1750 void *def = (pc++)->insn;
1754 jint npairs = INTVAL ();
1756 int max = npairs - 1;
1759 // Simple binary search...
1762 int half = (min + max) / 2;
1763 int match = pc[2 * half].int_val;
1768 pc = (insn_slot *) pc[2 * half + 1].datum;
1771 else if (index < match)
1772 // We can use HALF - 1 here because we check again on
1776 // We can use HALF + 1 here because we check again on
1780 if (index == pc[2 * min].int_val)
1781 pc = (insn_slot *) pc[2 * min + 1].datum;
1783 pc = (insn_slot *) def;
1785 unsigned char *base_pc = pc-1;
1788 unsigned char* base = meth->bytecode ();
1789 while ((pc-base) % 4 != 0)
1792 jint def = get4 (pc);
1793 jint npairs = get4 (pc+4);
1798 // Simple binary search...
1801 int half = (min+max)/2;
1802 int match = get4 (pc+ 4*(2 + 2*half));
1806 else if (index < match)
1807 // We can use HALF - 1 here because we check again on
1811 // We can use HALF + 1 here because we check again on
1816 if (index == get4 (pc+ 4*(2 + 2*min)))
1817 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1820 #endif /* DIRECT_THREADED */
1825 *(jobject *) retp = POPA ();
1829 *(jlong *) retp = POPL ();
1833 *(jfloat *) retp = POPF ();
1837 *(jdouble *) retp = POPD ();
1841 *(jint *) retp = POPI ();
1849 jint fieldref_index = GET2U ();
1850 SAVE_PC(); // Constant pool resolution could throw.
1851 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1852 _Jv_Field *field = pool_data[fieldref_index].field;
1854 if ((field->flags & Modifier::STATIC) == 0)
1855 throw_incompatible_class_change_error
1856 (JvNewStringLatin1 ("field no longer static"));
1858 jclass type = field->type;
1860 // We rewrite the instruction once we discover what it refers
1862 void *newinsn = NULL;
1863 if (type->isPrimitive ())
1865 switch (type->size_in_bytes)
1868 PUSHI (*field->u.byte_addr);
1869 newinsn = AMPAMP (getstatic_resolved_1);
1873 if (type == JvPrimClass (char))
1875 PUSHI (*field->u.char_addr);
1876 newinsn = AMPAMP (getstatic_resolved_char);
1880 PUSHI (*field->u.short_addr);
1881 newinsn = AMPAMP (getstatic_resolved_short);
1886 PUSHI(*field->u.int_addr);
1887 newinsn = AMPAMP (getstatic_resolved_4);
1891 PUSHL(*field->u.long_addr);
1892 newinsn = AMPAMP (getstatic_resolved_8);
1898 PUSHA(*field->u.object_addr);
1899 newinsn = AMPAMP (getstatic_resolved_obj);
1902 #ifdef DIRECT_THREADED
1903 REWRITE_INSN (newinsn, datum, field->u.addr);
1904 #endif /* DIRECT_THREADED */
1908 #ifdef DIRECT_THREADED
1909 getstatic_resolved_1:
1910 PUSHI (*(jbyte *) AVAL ());
1913 getstatic_resolved_char:
1914 PUSHI (*(jchar *) AVAL ());
1917 getstatic_resolved_short:
1918 PUSHI (*(jshort *) AVAL ());
1921 getstatic_resolved_4:
1922 PUSHI (*(jint *) AVAL ());
1925 getstatic_resolved_8:
1926 PUSHL (*(jlong *) AVAL ());
1929 getstatic_resolved_obj:
1930 PUSHA (*(jobject *) AVAL ());
1932 #endif /* DIRECT_THREADED */
1937 jint fieldref_index = GET2U ();
1938 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
1939 _Jv_Field *field = pool_data[fieldref_index].field;
1941 if ((field->flags & Modifier::STATIC) != 0)
1942 throw_incompatible_class_change_error
1943 (JvNewStringLatin1 ("field is static"));
1945 jclass type = field->type;
1946 jint field_offset = field->u.boffset;
1948 jobject obj = POPA();
1951 void *newinsn = NULL;
1952 _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
1953 if (type->isPrimitive ())
1955 switch (type->size_in_bytes)
1958 PUSHI (val->byte_value);
1959 newinsn = AMPAMP (getfield_resolved_1);
1963 if (type == JvPrimClass (char))
1965 PUSHI (val->char_value);
1966 newinsn = AMPAMP (getfield_resolved_char);
1970 PUSHI (val->short_value);
1971 newinsn = AMPAMP (getfield_resolved_short);
1976 PUSHI (val->int_value);
1977 newinsn = AMPAMP (getfield_resolved_4);
1981 PUSHL (val->long_value);
1982 newinsn = AMPAMP (getfield_resolved_8);
1988 PUSHA (val->object_value);
1989 newinsn = AMPAMP (getfield_resolved_obj);
1992 #ifdef DIRECT_THREADED
1993 REWRITE_INSN (newinsn, int_val, field_offset);
1994 #endif /* DIRECT_THREADED */
1998 #ifdef DIRECT_THREADED
1999 getfield_resolved_1:
2001 char *obj = (char *) POPA ();
2003 PUSHI (*(jbyte *) (obj + INTVAL ()));
2007 getfield_resolved_char:
2009 char *obj = (char *) POPA ();
2011 PUSHI (*(jchar *) (obj + INTVAL ()));
2015 getfield_resolved_short:
2017 char *obj = (char *) POPA ();
2019 PUSHI (*(jshort *) (obj + INTVAL ()));
2023 getfield_resolved_4:
2025 char *obj = (char *) POPA ();
2027 PUSHI (*(jint *) (obj + INTVAL ()));
2031 getfield_resolved_8:
2033 char *obj = (char *) POPA ();
2035 PUSHL (*(jlong *) (obj + INTVAL ()));
2039 getfield_resolved_obj:
2041 char *obj = (char *) POPA ();
2043 PUSHA (*(jobject *) (obj + INTVAL ()));
2046 #endif /* DIRECT_THREADED */
2051 jint fieldref_index = GET2U ();
2052 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2053 _Jv_Field *field = pool_data[fieldref_index].field;
2055 jclass type = field->type;
2057 // ResolvePoolEntry cannot check this
2058 if ((field->flags & Modifier::STATIC) == 0)
2059 throw_incompatible_class_change_error
2060 (JvNewStringLatin1 ("field no longer static"));
2062 void *newinsn = NULL;
2063 if (type->isPrimitive ())
2065 switch (type->size_in_bytes)
2069 jint value = POPI();
2070 *field->u.byte_addr = value;
2071 newinsn = AMPAMP (putstatic_resolved_1);
2077 jint value = POPI();
2078 *field->u.char_addr = value;
2079 newinsn = AMPAMP (putstatic_resolved_2);
2085 jint value = POPI();
2086 *field->u.int_addr = value;
2087 newinsn = AMPAMP (putstatic_resolved_4);
2093 jlong value = POPL();
2094 *field->u.long_addr = value;
2095 newinsn = AMPAMP (putstatic_resolved_8);
2102 jobject value = POPA();
2103 *field->u.object_addr = value;
2104 newinsn = AMPAMP (putstatic_resolved_obj);
2107 #ifdef DIRECT_THREADED
2108 REWRITE_INSN (newinsn, datum, field->u.addr);
2109 #endif /* DIRECT_THREADED */
2113 #ifdef DIRECT_THREADED
2114 putstatic_resolved_1:
2115 *(jbyte *) AVAL () = POPI ();
2118 putstatic_resolved_2:
2119 *(jchar *) AVAL () = POPI ();
2122 putstatic_resolved_4:
2123 *(jint *) AVAL () = POPI ();
2126 putstatic_resolved_8:
2127 *(jlong *) AVAL () = POPL ();
2130 putstatic_resolved_obj:
2131 *(jobject *) AVAL () = POPA ();
2133 #endif /* DIRECT_THREADED */
2138 jint fieldref_index = GET2U ();
2139 _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
2140 _Jv_Field *field = pool_data[fieldref_index].field;
2142 jclass type = field->type;
2144 if ((field->flags & Modifier::STATIC) != 0)
2145 throw_incompatible_class_change_error
2146 (JvNewStringLatin1 ("field is static"));
2148 jint field_offset = field->u.boffset;
2150 void *newinsn = NULL;
2151 if (type->isPrimitive ())
2153 switch (type->size_in_bytes)
2157 jint value = POPI();
2158 jobject obj = POPA();
2160 *(jbyte*) ((char*)obj + field_offset) = value;
2161 newinsn = AMPAMP (putfield_resolved_1);
2167 jint value = POPI();
2168 jobject obj = POPA();
2170 *(jchar*) ((char*)obj + field_offset) = value;
2171 newinsn = AMPAMP (putfield_resolved_2);
2177 jint value = POPI();
2178 jobject obj = POPA();
2180 *(jint*) ((char*)obj + field_offset) = value;
2181 newinsn = AMPAMP (putfield_resolved_4);
2187 jlong value = POPL();
2188 jobject obj = POPA();
2190 *(jlong*) ((char*)obj + field_offset) = value;
2191 newinsn = AMPAMP (putfield_resolved_8);
2198 jobject value = POPA();
2199 jobject obj = POPA();
2201 *(jobject*) ((char*)obj + field_offset) = value;
2202 newinsn = AMPAMP (putfield_resolved_obj);
2205 #ifdef DIRECT_THREADED
2206 REWRITE_INSN (newinsn, int_val, field_offset);
2207 #endif /* DIRECT_THREADED */
2211 #ifdef DIRECT_THREADED
2212 putfield_resolved_1:
2215 char *obj = (char *) POPA ();
2217 *(jbyte *) (obj + INTVAL ()) = val;
2221 putfield_resolved_2:
2224 char *obj = (char *) POPA ();
2226 *(jchar *) (obj + INTVAL ()) = val;
2230 putfield_resolved_4:
2233 char *obj = (char *) POPA ();
2235 *(jint *) (obj + INTVAL ()) = val;
2239 putfield_resolved_8:
2241 jlong val = POPL ();
2242 char *obj = (char *) POPA ();
2244 *(jlong *) (obj + INTVAL ()) = val;
2248 putfield_resolved_obj:
2250 jobject val = POPA ();
2251 char *obj = (char *) POPA ();
2253 *(jobject *) (obj + INTVAL ()) = val;
2256 #endif /* DIRECT_THREADED */
2261 int index = GET2U ();
2263 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2266 sp -= rmeth->stack_item_count;
2268 // We don't use NULLCHECK here because we can't rely on that
2269 // working for <init>. So instead we do an explicit test.
2273 throw_null_pointer_exception ();
2276 fun = (void (*)()) rmeth->method->ncode;
2278 #ifdef DIRECT_THREADED
2279 // Rewrite instruction so that we use a faster pre-resolved
2281 REWRITE_INSN (&&invokespecial_resolved, datum, rmeth);
2282 #endif /* DIRECT_THREADED */
2284 goto perform_invoke;
2286 #ifdef DIRECT_THREADED
2287 invokespecial_resolved:
2290 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2291 sp -= rmeth->stack_item_count;
2292 // We don't use NULLCHECK here because we can't rely on that
2293 // working for <init>. So instead we do an explicit test.
2296 throw_null_pointer_exception ();
2298 fun = (void (*)()) rmeth->method->ncode;
2300 goto perform_invoke;
2301 #endif /* DIRECT_THREADED */
2306 int index = GET2U ();
2308 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2311 sp -= rmeth->stack_item_count;
2313 fun = (void (*)()) rmeth->method->ncode;
2315 #ifdef DIRECT_THREADED
2316 // Rewrite instruction so that we use a faster pre-resolved
2318 REWRITE_INSN (&&invokestatic_resolved, datum, rmeth);
2319 #endif /* DIRECT_THREADED */
2321 goto perform_invoke;
2323 #ifdef DIRECT_THREADED
2324 invokestatic_resolved:
2327 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2328 sp -= rmeth->stack_item_count;
2329 fun = (void (*)()) rmeth->method->ncode;
2331 goto perform_invoke;
2332 #endif /* DIRECT_THREADED */
2334 insn_invokeinterface:
2337 int index = GET2U ();
2339 rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2342 sp -= rmeth->stack_item_count;
2344 jobject rcv = sp[0].o;
2349 _Jv_LookupInterfaceMethod (rcv->getClass (),
2350 rmeth->method->name,
2351 rmeth->method->signature);
2353 #ifdef DIRECT_THREADED
2354 // Rewrite instruction so that we use a faster pre-resolved
2356 REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth);
2358 // Skip dummy bytes.
2360 #endif /* DIRECT_THREADED */
2362 goto perform_invoke;
2364 #ifdef DIRECT_THREADED
2365 invokeinterface_resolved:
2368 rmeth = (_Jv_ResolvedMethod *) AVAL ();
2369 sp -= rmeth->stack_item_count;
2370 jobject rcv = sp[0].o;
2373 _Jv_LookupInterfaceMethod (rcv->getClass (),
2374 rmeth->method->name,
2375 rmeth->method->signature);
2377 goto perform_invoke;
2378 #endif /* DIRECT_THREADED */
2383 int index = GET2U ();
2384 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2386 /* VM spec, section 3.11.5 */
2387 if ((klass->getModifiers() & Modifier::ABSTRACT)
2388 || klass->isInterface())
2390 jthrowable t = new java::lang::InstantiationException;
2391 INTERP_REPORT_EXCEPTION (t);
2394 jobject res = _Jv_AllocObject (klass);
2397 #ifdef DIRECT_THREADED
2398 REWRITE_INSN (&&new_resolved, datum, klass);
2399 #endif /* DIRECT_THREADED */
2403 #ifdef DIRECT_THREADED
2406 jclass klass = (jclass) AVAL ();
2407 jobject res = _Jv_AllocObject (klass);
2411 #endif /* DIRECT_THREADED */
2415 int atype = GET1U ();
2417 jobject result = _Jv_NewArray (atype, size);
2425 int index = GET2U ();
2426 jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2429 jobject result = _Jv_NewObjectArray (size, klass, 0);
2432 #ifdef DIRECT_THREADED
2433 REWRITE_INSN (&&anewarray_resolved, datum, klass);
2434 #endif /* DIRECT_THREADED */
2438 #ifdef DIRECT_THREADED
2441 jclass klass = (jclass) AVAL ();
2443 jobject result = _Jv_NewObjectArray (size, klass, 0);
2447 #endif /* DIRECT_THREADED */
2451 __JArray *arr = (__JArray*)POPA();
2452 NULLARRAYCHECK (arr);
2453 PUSHI (arr->length);
2459 jobject value = POPA();
2460 jthrowable t = static_cast<jthrowable> (value);
2461 INTERP_REPORT_EXCEPTION (t);
2469 jobject value = POPA();
2470 jint index = GET2U ();
2471 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2474 value = (jobject) _Jv_CheckCast (to, value);
2478 #ifdef DIRECT_THREADED
2479 REWRITE_INSN (&&checkcast_resolved, datum, to);
2480 #endif /* DIRECT_THREADED */
2484 #ifdef DIRECT_THREADED
2488 jobject value = POPA ();
2489 jclass to = (jclass) AVAL ();
2490 value = (jobject) _Jv_CheckCast (to, value);
2494 #endif /* DIRECT_THREADED */
2499 jobject value = POPA();
2500 jint index = GET2U ();
2501 jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2503 PUSHI (to->isInstance (value));
2505 #ifdef DIRECT_THREADED
2506 REWRITE_INSN (&&instanceof_resolved, datum, to);
2507 #endif /* DIRECT_THREADED */
2511 #ifdef DIRECT_THREADED
2512 instanceof_resolved:
2514 jobject value = POPA ();
2515 jclass to = (jclass) AVAL ();
2516 PUSHI (to->isInstance (value));
2519 #endif /* DIRECT_THREADED */
2523 jobject value = POPA();
2525 _Jv_MonitorEnter (value);
2531 jobject value = POPA();
2533 _Jv_MonitorExit (value);
2539 jobject val = POPA();
2549 jobject val = POPA();
2557 insn_multianewarray:
2560 int kind_index = GET2U ();
2564 = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
2566 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim);
2568 for (int i = dim - 1; i >= 0; i--)
2573 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2579 #ifndef DIRECT_THREADED
2582 jint the_mod_op = get1u (pc++);
2583 jint wide = get2u (pc); pc += 2;
2628 pc = (unsigned char*) PEEKA (wide);
2633 jint amount = get2s (pc); pc += 2;
2634 jint value = PEEKI (wide);
2635 POKEI (wide, value+amount);
2640 throw_internal_error ("illegal bytecode modified by wide");
2644 #endif /* DIRECT_THREADED */
2648 using namespace ::java::lang;
2649 jmethodID method = meth->self;
2650 jlocation location = meth->insn_index (pc - 1);
2652 using namespace gnu::gcj::jvmti;
2654 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
2656 JvAssert (bp != NULL);
2658 // Save the insn here since the breakpoint could be removed
2659 // before the JVMTI notification returns.
2660 pc_t opc = reinterpret_cast<pc_t> (bp->getInsn ());
2664 // Continue execution
2665 #ifdef DIRECT_THREADED
2668 goto *(insn_target[*opc]);
2672 catch (java::lang::Throwable *ex)
2674 // Check if the exception is handled and, if so, set the pc to the start
2675 // of the appropriate catch block.
2676 if (meth->check_handler (&pc, meth, ex))
2679 sp++->o = ex; // Push exception.
2681 if (JVMTI_REQUESTED_EVENT (ExceptionCatch))
2683 using namespace gnu::gcj::jvmti;
2684 jlong catch_meth = reinterpret_cast<jlong> (meth->get_method ());
2685 jlong catch_loc = meth->insn_index (pc);
2686 _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH, thread,
2687 _Jv_GetCurrentJNIEnv (), catch_meth,
2694 // No handler, so re-throw.