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)
385 #define REWRITE_INSN(INSN,SLOT,VALUE) \
387 pc[-2].insn = INSN; \
388 pc[-1].SLOT = VALUE; \
392 #undef INTERP_REPORT_EXCEPTION
393 #define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */
396 #define INTVAL() ((pc++)->int_val)
397 #define AVAL() ((pc++)->datum)
399 #define GET1S() INTVAL ()
400 #define GET2S() INTVAL ()
401 #define GET1U() INTVAL ()
402 #define GET2U() INTVAL ()
403 #define AVAL1U() AVAL ()
404 #define AVAL2U() AVAL ()
405 #define AVAL2UP() AVAL ()
406 #define SKIP_GOTO ++pc
407 #define GOTO_VAL() (insn_slot *) pc->datum
408 #define PCVAL(unionval) unionval.p
409 #define AMPAMP(label) &&label
411 // Compile if we must. NOTE: Double-check locking.
412 if (meth
->prepared
== NULL
)
414 _Jv_MutexLock (&compile_mutex
);
415 if (meth
->prepared
== NULL
)
416 meth
->compile (insn_target
);
417 _Jv_MutexUnlock (&compile_mutex
);
420 // If we're only compiling, stop here
424 pc
= (insn_slot
*) meth
->prepared
;
432 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
434 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
435 jmethodID method = meth->self; \
436 jlocation loc = meth->insn_index (pc); \
437 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
440 goto *(insn_target[*pc++])
442 #define NEXT_INSN goto *(insn_target[*pc++])
445 #define GET1S() get1s (pc++)
446 #define GET2S() (pc += 2, get2s (pc- 2))
447 #define GET1U() get1u (pc++)
448 #define GET2U() (pc += 2, get2u (pc - 2))
449 // Note that these could be more efficient when not handling 'ldc
452 ({ int index = get1u (pc++); \
453 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
455 ({ int index = get2u (pc); pc += 2; \
456 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
457 // Note that we don't need to resolve the pool entry here as class
458 // constants are never wide.
459 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
460 #define SKIP_GOTO pc += 2
461 #define GOTO_VAL() pc - 1 + get2s (pc)
462 #define PCVAL(unionval) unionval.i
463 #define AMPAMP(label) NULL
465 pc
= meth
->bytecode ();
467 #endif /* DIRECT_THREADED */
469 #define TAKE_GOTO pc = GOTO_VAL ()
471 /* Go straight at it! the ffi raw format matches the internal
472 stack representation exactly. At least, that's the idea.
474 memcpy ((void*) locals
, (void*) args
, meth
->args_raw_size
);
476 _Jv_word
*pool_data
= meth
->defining_class
->constants
.data
;
478 /* These three are temporaries for common code used by several
481 _Jv_ResolvedMethod
* rmeth
;
486 // We keep nop around. It is used if we're interpreting the
487 // bytecodes and not doing direct threading.
491 /* The first few instructions here are ordered according to their
492 frequency, in the hope that this will improve code locality a
495 insn_aload_0
: // 0x2a
503 insn_iload_1
: // 0x1b
507 insn_invokevirtual
: // 0xb6
510 int index
= GET2U ();
512 /* _Jv_Linker::resolve_pool_entry returns immediately if the
513 * value already is resolved. If we want to clutter up the
514 * code here to gain a little performance, then we can check
515 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
516 * directly. For now, I don't think it is worth it. */
518 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
521 sp
-= rmeth
->stack_item_count
;
523 if (rmeth
->method
->accflags
& Modifier::FINAL
)
525 // We can't rely on NULLCHECK working if the method is final.
527 throw_null_pointer_exception ();
529 // Final methods might not appear in the vtable.
530 fun
= (void (*)()) rmeth
->method
->ncode
;
535 jobject rcv
= sp
[0].o
;
536 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
537 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
540 #ifdef DIRECT_THREADED
541 // Rewrite instruction so that we use a faster pre-resolved
543 REWRITE_INSN (&&invokevirtual_resolved
, datum
, rmeth
);
544 #endif /* DIRECT_THREADED */
548 #ifdef DIRECT_THREADED
549 invokevirtual_resolved
:
552 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
553 sp
-= rmeth
->stack_item_count
;
555 if (rmeth
->method
->accflags
& Modifier::FINAL
)
557 // We can't rely on NULLCHECK working if the method is final.
559 throw_null_pointer_exception ();
561 // Final methods might not appear in the vtable.
562 fun
= (void (*)()) rmeth
->method
->ncode
;
567 jobject rcv
= sp
[0].o
;
568 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
569 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
573 #endif /* DIRECT_THREADED */
577 /* here goes the magic again... */
578 ffi_cif
*cif
= &rmeth
->cif
;
579 INTERP_FFI_RAW_TYPE
*raw
= (INTERP_FFI_RAW_TYPE
*) sp
;
583 #if FFI_NATIVE_RAW_API
584 /* We assume that this is only implemented if it's correct */
585 /* to use it here. On a 64 bit machine, it never is. */
586 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
588 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
591 int rtype
= cif
->rtype
->type
;
593 /* the likelyhood of object, int, or void return is very high,
594 * so those are checked before the switch */
595 if (rtype
== FFI_TYPE_POINTER
)
597 PUSHA (rvalue
.object_value
);
599 else if (rtype
== FFI_TYPE_SINT32
)
601 PUSHI (rvalue
.int_value
);
603 else if (rtype
== FFI_TYPE_VOID
)
612 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
615 case FFI_TYPE_SINT16
:
616 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
619 case FFI_TYPE_UINT16
:
620 PUSHI (rvalue
.int_value
& 0xffff);
624 PUSHF (rvalue
.float_value
);
627 case FFI_TYPE_DOUBLE
:
628 PUSHD (rvalue
.double_value
);
631 case FFI_TYPE_SINT64
:
632 PUSHL (rvalue
.long_value
);
636 throw_internal_error ("unknown return type in invokeXXX");
703 // For direct threaded, bipush and sipush are the same.
704 #ifndef DIRECT_THREADED
707 #endif /* DIRECT_THREADED */
713 // For direct threaded, ldc and ldc_w are the same.
714 #ifndef DIRECT_THREADED
715 PUSHA ((jobject
) AVAL1U ());
717 #endif /* DIRECT_THREADED */
719 PUSHA ((jobject
) AVAL2U ());
722 #ifdef DIRECT_THREADED
723 // For direct threaded we have a separate 'ldc class' operation.
727 // We could rewrite the instruction at this point.
728 int index
= INTVAL ();
729 jobject k
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
734 #endif /* DIRECT_THREADED */
738 void *where
= AVAL2UP ();
739 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
835 jintArray arr
= (jintArray
) POPA();
836 NULLARRAYCHECK (arr
);
837 ARRAYBOUNDSCHECK (arr
, index
);
838 PUSHI( elements(arr
)[index
] );
845 jlongArray arr
= (jlongArray
) POPA();
846 NULLARRAYCHECK (arr
);
847 ARRAYBOUNDSCHECK (arr
, index
);
848 PUSHL( elements(arr
)[index
] );
855 jfloatArray arr
= (jfloatArray
) POPA();
856 NULLARRAYCHECK (arr
);
857 ARRAYBOUNDSCHECK (arr
, index
);
858 PUSHF( elements(arr
)[index
] );
865 jdoubleArray arr
= (jdoubleArray
) POPA();
866 NULLARRAYCHECK (arr
);
867 ARRAYBOUNDSCHECK (arr
, index
);
868 PUSHD( elements(arr
)[index
] );
875 jobjectArray arr
= (jobjectArray
) POPA();
876 NULLARRAYCHECK (arr
);
877 ARRAYBOUNDSCHECK (arr
, index
);
878 PUSHA( elements(arr
)[index
] );
885 jbyteArray arr
= (jbyteArray
) POPA();
886 NULLARRAYCHECK (arr
);
887 ARRAYBOUNDSCHECK (arr
, index
);
888 PUSHI( elements(arr
)[index
] );
895 jcharArray arr
= (jcharArray
) POPA();
896 NULLARRAYCHECK (arr
);
897 ARRAYBOUNDSCHECK (arr
, index
);
898 PUSHI( elements(arr
)[index
] );
905 jshortArray arr
= (jshortArray
) POPA();
906 NULLARRAYCHECK (arr
);
907 ARRAYBOUNDSCHECK (arr
, index
);
908 PUSHI( elements(arr
)[index
] );
1014 jint value
= POPI();
1015 jint index
= POPI();
1016 jintArray arr
= (jintArray
) POPA();
1017 NULLARRAYCHECK (arr
);
1018 ARRAYBOUNDSCHECK (arr
, index
);
1019 elements(arr
)[index
] = value
;
1025 jlong value
= POPL();
1026 jint index
= POPI();
1027 jlongArray arr
= (jlongArray
) POPA();
1028 NULLARRAYCHECK (arr
);
1029 ARRAYBOUNDSCHECK (arr
, index
);
1030 elements(arr
)[index
] = value
;
1036 jfloat value
= POPF();
1037 jint index
= POPI();
1038 jfloatArray arr
= (jfloatArray
) POPA();
1039 NULLARRAYCHECK (arr
);
1040 ARRAYBOUNDSCHECK (arr
, index
);
1041 elements(arr
)[index
] = value
;
1047 jdouble value
= POPD();
1048 jint index
= POPI();
1049 jdoubleArray arr
= (jdoubleArray
) POPA();
1050 NULLARRAYCHECK (arr
);
1051 ARRAYBOUNDSCHECK (arr
, index
);
1052 elements(arr
)[index
] = value
;
1058 jobject value
= POPA();
1059 jint index
= POPI();
1060 jobjectArray arr
= (jobjectArray
) POPA();
1061 NULLARRAYCHECK (arr
);
1062 ARRAYBOUNDSCHECK (arr
, index
);
1063 _Jv_CheckArrayStore (arr
, value
);
1064 elements(arr
)[index
] = value
;
1070 jbyte value
= (jbyte
) POPI();
1071 jint index
= POPI();
1072 jbyteArray arr
= (jbyteArray
) POPA();
1073 NULLARRAYCHECK (arr
);
1074 ARRAYBOUNDSCHECK (arr
, index
);
1075 elements(arr
)[index
] = value
;
1081 jchar value
= (jchar
) POPI();
1082 jint index
= POPI();
1083 jcharArray arr
= (jcharArray
) POPA();
1084 NULLARRAYCHECK (arr
);
1085 ARRAYBOUNDSCHECK (arr
, index
);
1086 elements(arr
)[index
] = value
;
1092 jshort value
= (jshort
) POPI();
1093 jint index
= POPI();
1094 jshortArray arr
= (jshortArray
) POPA();
1095 NULLARRAYCHECK (arr
);
1096 ARRAYBOUNDSCHECK (arr
, index
);
1097 elements(arr
)[index
] = value
;
1115 dupx (sp
, 1, 1); sp
+=1;
1119 dupx (sp
, 1, 2); sp
+=1;
1129 dupx (sp
, 2, 1); sp
+=2;
1133 dupx (sp
, 2, 2); sp
+=2;
1138 jobject tmp1
= POPA();
1139 jobject tmp2
= POPA();
1196 jint value2
= POPI();
1197 jint value1
= POPI();
1198 jint res
= _Jv_divI (value1
, value2
);
1206 jlong value2
= POPL();
1207 jlong value1
= POPL();
1208 jlong res
= _Jv_divJ (value1
, value2
);
1215 jfloat value2
= POPF();
1216 jfloat value1
= POPF();
1217 jfloat res
= value1
/ value2
;
1224 jdouble value2
= POPD();
1225 jdouble value1
= POPD();
1226 jdouble res
= value1
/ value2
;
1234 jint value2
= POPI();
1235 jint value1
= POPI();
1236 jint res
= _Jv_remI (value1
, value2
);
1244 jlong value2
= POPL();
1245 jlong value1
= POPL();
1246 jlong res
= _Jv_remJ (value1
, value2
);
1253 jfloat value2
= POPF();
1254 jfloat value1
= POPF();
1255 jfloat res
= __ieee754_fmod (value1
, value2
);
1262 jdouble value2
= POPD();
1263 jdouble value1
= POPD();
1264 jdouble res
= __ieee754_fmod (value1
, value2
);
1271 jint value
= POPI();
1278 jlong value
= POPL();
1285 jfloat value
= POPF();
1292 jdouble value
= POPD();
1299 jint shift
= (POPI() & 0x1f);
1300 jint value
= POPI();
1301 PUSHI (value
<< shift
);
1307 jint shift
= (POPI() & 0x3f);
1308 jlong value
= POPL();
1309 PUSHL (value
<< shift
);
1315 jint shift
= (POPI() & 0x1f);
1316 jint value
= POPI();
1317 PUSHI (value
>> shift
);
1323 jint shift
= (POPI() & 0x3f);
1324 jlong value
= POPL();
1325 PUSHL (value
>> shift
);
1331 jint shift
= (POPI() & 0x1f);
1332 _Jv_uint value
= (_Jv_uint
) POPI();
1333 PUSHI ((jint
) (value
>> shift
));
1339 jint shift
= (POPI() & 0x3f);
1340 _Jv_ulong value
= (_Jv_ulong
) POPL();
1341 PUSHL ((jlong
) (value
>> shift
));
1371 jint index
= GET1U ();
1372 jint amount
= GET1S ();
1373 locals
[index
].i
+= amount
;
1378 {jlong value
= POPI(); PUSHL (value
);}
1382 {jfloat value
= POPI(); PUSHF (value
);}
1386 {jdouble value
= POPI(); PUSHD (value
);}
1390 {jint value
= POPL(); PUSHI (value
);}
1394 {jfloat value
= POPL(); PUSHF (value
);}
1398 {jdouble value
= POPL(); PUSHD (value
);}
1403 using namespace java::lang
;
1404 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1411 using namespace java::lang
;
1412 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1418 { jdouble value
= POPF (); PUSHD(value
); }
1423 using namespace java::lang
;
1424 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1431 using namespace java::lang
;
1432 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1438 { jfloat value
= POPD (); PUSHF(value
); }
1442 { jbyte value
= POPI (); PUSHI(value
); }
1446 { jchar value
= POPI (); PUSHI(value
); }
1450 { jshort value
= POPI (); PUSHI(value
); }
1455 jlong value2
= POPL ();
1456 jlong value1
= POPL ();
1457 if (value1
> value2
)
1459 else if (value1
== value2
)
1475 jfloat value2
= POPF ();
1476 jfloat value1
= POPF ();
1477 if (value1
> value2
)
1479 else if (value1
== value2
)
1481 else if (value1
< value2
)
1497 jdouble value2
= POPD ();
1498 jdouble value1
= POPD ();
1499 if (value1
> value2
)
1501 else if (value1
== value2
)
1503 else if (value1
< value2
)
1566 jint value2
= POPI();
1567 jint value1
= POPI();
1568 if (value1
== value2
)
1577 jint value2
= POPI();
1578 jint value1
= POPI();
1579 if (value1
!= value2
)
1588 jint value2
= POPI();
1589 jint value1
= POPI();
1590 if (value1
< value2
)
1599 jint value2
= POPI();
1600 jint value1
= POPI();
1601 if (value1
>= value2
)
1610 jint value2
= POPI();
1611 jint value1
= POPI();
1612 if (value1
> value2
)
1621 jint value2
= POPI();
1622 jint value1
= POPI();
1623 if (value1
<= value2
)
1632 jobject value2
= POPA();
1633 jobject value1
= POPA();
1634 if (value1
== value2
)
1643 jobject value2
= POPA();
1644 jobject value1
= POPA();
1645 if (value1
!= value2
)
1653 #ifndef DIRECT_THREADED
1654 // For direct threaded, goto and goto_w are the same.
1655 pc
= pc
- 1 + get4 (pc
);
1657 #endif /* DIRECT_THREADED */
1663 #ifndef DIRECT_THREADED
1664 // For direct threaded, jsr and jsr_w are the same.
1666 pc_t next
= pc
- 1 + get4 (pc
);
1668 PUSHA ((jobject
) pc
);
1672 #endif /* DIRECT_THREADED */
1675 pc_t next
= GOTO_VAL();
1677 PUSHA ((jobject
) pc
);
1684 jint index
= GET1U ();
1685 pc
= (pc_t
) PEEKA (index
);
1691 #ifdef DIRECT_THREADED
1692 void *def
= (pc
++)->datum
;
1696 jint low
= INTVAL ();
1697 jint high
= INTVAL ();
1699 if (index
< low
|| index
> high
)
1700 pc
= (insn_slot
*) def
;
1702 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
1704 pc_t base_pc
= pc
- 1;
1705 int index
= POPI ();
1707 pc_t base
= (pc_t
) meth
->bytecode ();
1708 while ((pc
- base
) % 4 != 0)
1711 jint def
= get4 (pc
);
1712 jint low
= get4 (pc
+ 4);
1713 jint high
= get4 (pc
+ 8);
1714 if (index
< low
|| index
> high
)
1717 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
1718 #endif /* DIRECT_THREADED */
1724 #ifdef DIRECT_THREADED
1725 void *def
= (pc
++)->insn
;
1729 jint npairs
= INTVAL ();
1731 int max
= npairs
- 1;
1734 // Simple binary search...
1737 int half
= (min
+ max
) / 2;
1738 int match
= pc
[2 * half
].int_val
;
1743 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
1746 else if (index
< match
)
1747 // We can use HALF - 1 here because we check again on
1751 // We can use HALF + 1 here because we check again on
1755 if (index
== pc
[2 * min
].int_val
)
1756 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
1758 pc
= (insn_slot
*) def
;
1760 unsigned char *base_pc
= pc
-1;
1763 unsigned char* base
= meth
->bytecode ();
1764 while ((pc
-base
) % 4 != 0)
1767 jint def
= get4 (pc
);
1768 jint npairs
= get4 (pc
+4);
1773 // Simple binary search...
1776 int half
= (min
+max
)/2;
1777 int match
= get4 (pc
+ 4*(2 + 2*half
));
1781 else if (index
< match
)
1782 // We can use HALF - 1 here because we check again on
1786 // We can use HALF + 1 here because we check again on
1791 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1792 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1795 #endif /* DIRECT_THREADED */
1800 *(jobject
*) retp
= POPA ();
1804 *(jlong
*) retp
= POPL ();
1808 *(jfloat
*) retp
= POPF ();
1812 *(jdouble
*) retp
= POPD ();
1816 *(jint
*) retp
= POPI ();
1824 jint fieldref_index
= GET2U ();
1825 SAVE_PC(); // Constant pool resolution could throw.
1826 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1827 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1829 if ((field
->flags
& Modifier::STATIC
) == 0)
1830 throw_incompatible_class_change_error
1831 (JvNewStringLatin1 ("field no longer static"));
1833 jclass type
= field
->type
;
1835 // We rewrite the instruction once we discover what it refers
1837 void *newinsn
= NULL
;
1838 if (type
->isPrimitive ())
1840 switch (type
->size_in_bytes
)
1843 PUSHI (*field
->u
.byte_addr
);
1844 newinsn
= AMPAMP (getstatic_resolved_1
);
1848 if (type
== JvPrimClass (char))
1850 PUSHI (*field
->u
.char_addr
);
1851 newinsn
= AMPAMP (getstatic_resolved_char
);
1855 PUSHI (*field
->u
.short_addr
);
1856 newinsn
= AMPAMP (getstatic_resolved_short
);
1861 PUSHI(*field
->u
.int_addr
);
1862 newinsn
= AMPAMP (getstatic_resolved_4
);
1866 PUSHL(*field
->u
.long_addr
);
1867 newinsn
= AMPAMP (getstatic_resolved_8
);
1873 PUSHA(*field
->u
.object_addr
);
1874 newinsn
= AMPAMP (getstatic_resolved_obj
);
1877 #ifdef DIRECT_THREADED
1878 REWRITE_INSN (newinsn
, datum
, field
->u
.addr
);
1879 #endif /* DIRECT_THREADED */
1883 #ifdef DIRECT_THREADED
1884 getstatic_resolved_1
:
1885 PUSHI (*(jbyte
*) AVAL ());
1888 getstatic_resolved_char
:
1889 PUSHI (*(jchar
*) AVAL ());
1892 getstatic_resolved_short
:
1893 PUSHI (*(jshort
*) AVAL ());
1896 getstatic_resolved_4
:
1897 PUSHI (*(jint
*) AVAL ());
1900 getstatic_resolved_8
:
1901 PUSHL (*(jlong
*) AVAL ());
1904 getstatic_resolved_obj
:
1905 PUSHA (*(jobject
*) AVAL ());
1907 #endif /* DIRECT_THREADED */
1912 jint fieldref_index
= GET2U ();
1913 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1914 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1916 if ((field
->flags
& Modifier::STATIC
) != 0)
1917 throw_incompatible_class_change_error
1918 (JvNewStringLatin1 ("field is static"));
1920 jclass type
= field
->type
;
1921 jint field_offset
= field
->u
.boffset
;
1923 jobject obj
= POPA();
1926 void *newinsn
= NULL
;
1927 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
1928 if (type
->isPrimitive ())
1930 switch (type
->size_in_bytes
)
1933 PUSHI (val
->byte_value
);
1934 newinsn
= AMPAMP (getfield_resolved_1
);
1938 if (type
== JvPrimClass (char))
1940 PUSHI (val
->char_value
);
1941 newinsn
= AMPAMP (getfield_resolved_char
);
1945 PUSHI (val
->short_value
);
1946 newinsn
= AMPAMP (getfield_resolved_short
);
1951 PUSHI (val
->int_value
);
1952 newinsn
= AMPAMP (getfield_resolved_4
);
1956 PUSHL (val
->long_value
);
1957 newinsn
= AMPAMP (getfield_resolved_8
);
1963 PUSHA (val
->object_value
);
1964 newinsn
= AMPAMP (getfield_resolved_obj
);
1967 #ifdef DIRECT_THREADED
1968 REWRITE_INSN (newinsn
, int_val
, field_offset
);
1969 #endif /* DIRECT_THREADED */
1973 #ifdef DIRECT_THREADED
1974 getfield_resolved_1
:
1976 char *obj
= (char *) POPA ();
1978 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
1982 getfield_resolved_char
:
1984 char *obj
= (char *) POPA ();
1986 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
1990 getfield_resolved_short
:
1992 char *obj
= (char *) POPA ();
1994 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
1998 getfield_resolved_4
:
2000 char *obj
= (char *) POPA ();
2002 PUSHI (*(jint
*) (obj
+ INTVAL ()));
2006 getfield_resolved_8
:
2008 char *obj
= (char *) POPA ();
2010 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
2014 getfield_resolved_obj
:
2016 char *obj
= (char *) POPA ();
2018 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
2021 #endif /* DIRECT_THREADED */
2026 jint fieldref_index
= GET2U ();
2027 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
2028 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2030 jclass type
= field
->type
;
2032 // ResolvePoolEntry cannot check this
2033 if ((field
->flags
& Modifier::STATIC
) == 0)
2034 throw_incompatible_class_change_error
2035 (JvNewStringLatin1 ("field no longer static"));
2037 void *newinsn
= NULL
;
2038 if (type
->isPrimitive ())
2040 switch (type
->size_in_bytes
)
2044 jint value
= POPI();
2045 *field
->u
.byte_addr
= value
;
2046 newinsn
= AMPAMP (putstatic_resolved_1
);
2052 jint value
= POPI();
2053 *field
->u
.char_addr
= value
;
2054 newinsn
= AMPAMP (putstatic_resolved_2
);
2060 jint value
= POPI();
2061 *field
->u
.int_addr
= value
;
2062 newinsn
= AMPAMP (putstatic_resolved_4
);
2068 jlong value
= POPL();
2069 *field
->u
.long_addr
= value
;
2070 newinsn
= AMPAMP (putstatic_resolved_8
);
2077 jobject value
= POPA();
2078 *field
->u
.object_addr
= value
;
2079 newinsn
= AMPAMP (putstatic_resolved_obj
);
2082 #ifdef DIRECT_THREADED
2083 REWRITE_INSN (newinsn
, datum
, field
->u
.addr
);
2084 #endif /* DIRECT_THREADED */
2088 #ifdef DIRECT_THREADED
2089 putstatic_resolved_1
:
2090 *(jbyte
*) AVAL () = POPI ();
2093 putstatic_resolved_2
:
2094 *(jchar
*) AVAL () = POPI ();
2097 putstatic_resolved_4
:
2098 *(jint
*) AVAL () = POPI ();
2101 putstatic_resolved_8
:
2102 *(jlong
*) AVAL () = POPL ();
2105 putstatic_resolved_obj
:
2106 *(jobject
*) AVAL () = POPA ();
2108 #endif /* DIRECT_THREADED */
2113 jint fieldref_index
= GET2U ();
2114 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
2115 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2117 jclass type
= field
->type
;
2119 if ((field
->flags
& Modifier::STATIC
) != 0)
2120 throw_incompatible_class_change_error
2121 (JvNewStringLatin1 ("field is static"));
2123 jint field_offset
= field
->u
.boffset
;
2125 void *newinsn
= NULL
;
2126 if (type
->isPrimitive ())
2128 switch (type
->size_in_bytes
)
2132 jint value
= POPI();
2133 jobject obj
= POPA();
2135 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2136 newinsn
= AMPAMP (putfield_resolved_1
);
2142 jint value
= POPI();
2143 jobject obj
= POPA();
2145 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2146 newinsn
= AMPAMP (putfield_resolved_2
);
2152 jint value
= POPI();
2153 jobject obj
= POPA();
2155 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2156 newinsn
= AMPAMP (putfield_resolved_4
);
2162 jlong value
= POPL();
2163 jobject obj
= POPA();
2165 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2166 newinsn
= AMPAMP (putfield_resolved_8
);
2173 jobject value
= POPA();
2174 jobject obj
= POPA();
2176 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2177 newinsn
= AMPAMP (putfield_resolved_obj
);
2180 #ifdef DIRECT_THREADED
2181 REWRITE_INSN (newinsn
, int_val
, field_offset
);
2182 #endif /* DIRECT_THREADED */
2186 #ifdef DIRECT_THREADED
2187 putfield_resolved_1
:
2190 char *obj
= (char *) POPA ();
2192 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2196 putfield_resolved_2
:
2199 char *obj
= (char *) POPA ();
2201 *(jchar
*) (obj
+ INTVAL ()) = val
;
2205 putfield_resolved_4
:
2208 char *obj
= (char *) POPA ();
2210 *(jint
*) (obj
+ INTVAL ()) = val
;
2214 putfield_resolved_8
:
2216 jlong val
= POPL ();
2217 char *obj
= (char *) POPA ();
2219 *(jlong
*) (obj
+ INTVAL ()) = val
;
2223 putfield_resolved_obj
:
2225 jobject val
= POPA ();
2226 char *obj
= (char *) POPA ();
2228 *(jobject
*) (obj
+ INTVAL ()) = val
;
2231 #endif /* DIRECT_THREADED */
2236 int index
= GET2U ();
2238 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2241 sp
-= rmeth
->stack_item_count
;
2243 // We don't use NULLCHECK here because we can't rely on that
2244 // working for <init>. So instead we do an explicit test.
2248 throw_null_pointer_exception ();
2251 fun
= (void (*)()) rmeth
->method
->ncode
;
2253 #ifdef DIRECT_THREADED
2254 // Rewrite instruction so that we use a faster pre-resolved
2256 REWRITE_INSN (&&invokespecial_resolved
, datum
, rmeth
);
2257 #endif /* DIRECT_THREADED */
2259 goto perform_invoke
;
2261 #ifdef DIRECT_THREADED
2262 invokespecial_resolved
:
2265 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2266 sp
-= rmeth
->stack_item_count
;
2267 // We don't use NULLCHECK here because we can't rely on that
2268 // working for <init>. So instead we do an explicit test.
2271 throw_null_pointer_exception ();
2273 fun
= (void (*)()) rmeth
->method
->ncode
;
2275 goto perform_invoke
;
2276 #endif /* DIRECT_THREADED */
2281 int index
= GET2U ();
2283 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2286 sp
-= rmeth
->stack_item_count
;
2288 fun
= (void (*)()) rmeth
->method
->ncode
;
2290 #ifdef DIRECT_THREADED
2291 // Rewrite instruction so that we use a faster pre-resolved
2293 REWRITE_INSN (&&invokestatic_resolved
, datum
, rmeth
);
2294 #endif /* DIRECT_THREADED */
2296 goto perform_invoke
;
2298 #ifdef DIRECT_THREADED
2299 invokestatic_resolved
:
2302 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2303 sp
-= rmeth
->stack_item_count
;
2304 fun
= (void (*)()) rmeth
->method
->ncode
;
2306 goto perform_invoke
;
2307 #endif /* DIRECT_THREADED */
2309 insn_invokeinterface
:
2312 int index
= GET2U ();
2314 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2317 sp
-= rmeth
->stack_item_count
;
2319 jobject rcv
= sp
[0].o
;
2324 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2325 rmeth
->method
->name
,
2326 rmeth
->method
->signature
);
2328 #ifdef DIRECT_THREADED
2329 // Rewrite instruction so that we use a faster pre-resolved
2331 REWRITE_INSN (&&invokeinterface_resolved
, datum
, rmeth
);
2333 // Skip dummy bytes.
2335 #endif /* DIRECT_THREADED */
2337 goto perform_invoke
;
2339 #ifdef DIRECT_THREADED
2340 invokeinterface_resolved
:
2343 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2344 sp
-= rmeth
->stack_item_count
;
2345 jobject rcv
= sp
[0].o
;
2348 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2349 rmeth
->method
->name
,
2350 rmeth
->method
->signature
);
2352 goto perform_invoke
;
2353 #endif /* DIRECT_THREADED */
2358 int index
= GET2U ();
2359 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2361 /* VM spec, section 3.11.5 */
2362 if ((klass
->getModifiers() & Modifier::ABSTRACT
)
2363 || klass
->isInterface())
2365 jthrowable t
= new java::lang::InstantiationException
;
2366 INTERP_REPORT_EXCEPTION (t
);
2369 jobject res
= _Jv_AllocObject (klass
);
2372 #ifdef DIRECT_THREADED
2373 REWRITE_INSN (&&new_resolved
, datum
, klass
);
2374 #endif /* DIRECT_THREADED */
2378 #ifdef DIRECT_THREADED
2381 jclass klass
= (jclass
) AVAL ();
2382 jobject res
= _Jv_AllocObject (klass
);
2386 #endif /* DIRECT_THREADED */
2390 int atype
= GET1U ();
2392 jobject result
= _Jv_NewArray (atype
, size
);
2400 int index
= GET2U ();
2401 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2404 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2407 #ifdef DIRECT_THREADED
2408 REWRITE_INSN (&&anewarray_resolved
, datum
, klass
);
2409 #endif /* DIRECT_THREADED */
2413 #ifdef DIRECT_THREADED
2416 jclass klass
= (jclass
) AVAL ();
2418 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2422 #endif /* DIRECT_THREADED */
2426 __JArray
*arr
= (__JArray
*)POPA();
2427 NULLARRAYCHECK (arr
);
2428 PUSHI (arr
->length
);
2434 jobject value
= POPA();
2435 jthrowable t
= static_cast<jthrowable
> (value
);
2436 INTERP_REPORT_EXCEPTION (t
);
2444 jobject value
= POPA();
2445 jint index
= GET2U ();
2446 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2449 value
= (jobject
) _Jv_CheckCast (to
, value
);
2453 #ifdef DIRECT_THREADED
2454 REWRITE_INSN (&&checkcast_resolved
, datum
, to
);
2455 #endif /* DIRECT_THREADED */
2459 #ifdef DIRECT_THREADED
2463 jobject value
= POPA ();
2464 jclass to
= (jclass
) AVAL ();
2465 value
= (jobject
) _Jv_CheckCast (to
, value
);
2469 #endif /* DIRECT_THREADED */
2474 jobject value
= POPA();
2475 jint index
= GET2U ();
2476 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2478 PUSHI (to
->isInstance (value
));
2480 #ifdef DIRECT_THREADED
2481 REWRITE_INSN (&&instanceof_resolved
, datum
, to
);
2482 #endif /* DIRECT_THREADED */
2486 #ifdef DIRECT_THREADED
2487 instanceof_resolved
:
2489 jobject value
= POPA ();
2490 jclass to
= (jclass
) AVAL ();
2491 PUSHI (to
->isInstance (value
));
2494 #endif /* DIRECT_THREADED */
2498 jobject value
= POPA();
2500 _Jv_MonitorEnter (value
);
2506 jobject value
= POPA();
2508 _Jv_MonitorExit (value
);
2514 jobject val
= POPA();
2524 jobject val
= POPA();
2532 insn_multianewarray
:
2535 int kind_index
= GET2U ();
2539 = (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2541 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2543 for (int i
= dim
- 1; i
>= 0; i
--)
2548 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2554 #ifndef DIRECT_THREADED
2557 jint the_mod_op
= get1u (pc
++);
2558 jint wide
= get2u (pc
); pc
+= 2;
2603 pc
= (unsigned char*) PEEKA (wide
);
2608 jint amount
= get2s (pc
); pc
+= 2;
2609 jint value
= PEEKI (wide
);
2610 POKEI (wide
, value
+amount
);
2615 throw_internal_error ("illegal bytecode modified by wide");
2619 #endif /* DIRECT_THREADED */
2623 using namespace ::java::lang
;
2624 jmethodID method
= meth
->self
;
2625 jlocation location
= meth
->insn_index (pc
- 1);
2627 using namespace gnu::gcj::jvmti
;
2629 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong
> (method
),
2631 JvAssert (bp
!= NULL
);
2633 // Save the insn here since the breakpoint could be removed
2634 // before the JVMTI notification returns.
2635 pc_t opc
= reinterpret_cast<pc_t
> (bp
->getInsn ());
2639 // Continue execution
2640 #ifdef DIRECT_THREADED
2643 goto *(insn_target
[*opc
]);
2647 catch (java::lang::Throwable
*ex
)
2649 // Check if the exception is handled and, if so, set the pc to the start
2650 // of the appropriate catch block.
2651 if (meth
->check_handler (&pc
, meth
, ex
))
2654 sp
++->o
= ex
; // Push exception.
2656 if (JVMTI_REQUESTED_EVENT (ExceptionCatch
))
2658 using namespace gnu::gcj::jvmti
;
2659 jlong catch_meth
= reinterpret_cast<jlong
> (meth
->get_method ());
2660 jlong catch_loc
= meth
->insn_index (pc
);
2661 _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH
, thread
,
2662 _Jv_GetCurrentJNIEnv (), catch_meth
,
2669 // No handler, so re-throw.