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 *(ffi_arg
*) 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.