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.