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
;
16 // FRAME_DESC registers this particular invocation as the top-most
17 // interpreter frame. This lets the stack tracing code (for
18 // Throwable) print information about the method being interpreted
19 // rather than about the interpreter itself. FRAME_DESC has a
20 // destructor so it cleans up automatically when the interpreter
22 java::lang::Thread
*thread
= java::lang::Thread::currentThread();
23 _Jv_InterpFrame
frame_desc (meth
, thread
);
25 _Jv_word stack
[meth
->max_stack
];
28 _Jv_word locals
[meth
->max_locals
];
30 #define INSN_LABEL(op) &&insn_##op
32 static const void *const insn_target
[] =
35 INSN_LABEL(aconst_null
),
36 INSN_LABEL(iconst_m1
),
100 INSN_LABEL(lstore_3
),
101 INSN_LABEL(fstore_0
),
102 INSN_LABEL(fstore_1
),
103 INSN_LABEL(fstore_2
),
104 INSN_LABEL(fstore_3
),
105 INSN_LABEL(dstore_0
),
106 INSN_LABEL(dstore_1
),
107 INSN_LABEL(dstore_2
),
108 INSN_LABEL(dstore_3
),
109 INSN_LABEL(astore_0
),
110 INSN_LABEL(astore_1
),
111 INSN_LABEL(astore_2
),
112 INSN_LABEL(astore_3
),
193 INSN_LABEL(if_icmpeq
),
194 INSN_LABEL(if_icmpne
),
195 INSN_LABEL(if_icmplt
),
196 INSN_LABEL(if_icmpge
),
197 INSN_LABEL(if_icmpgt
),
198 INSN_LABEL(if_icmple
),
199 INSN_LABEL(if_acmpeq
),
200 INSN_LABEL(if_acmpne
),
204 INSN_LABEL(tableswitch
),
205 INSN_LABEL(lookupswitch
),
212 INSN_LABEL(getstatic
),
213 INSN_LABEL(putstatic
),
214 INSN_LABEL(getfield
),
215 INSN_LABEL(putfield
),
216 INSN_LABEL(invokevirtual
),
217 INSN_LABEL(invokespecial
),
218 INSN_LABEL(invokestatic
),
219 INSN_LABEL(invokeinterface
),
220 INSN_LABEL(breakpoint
),
222 INSN_LABEL(newarray
),
223 INSN_LABEL(anewarray
),
224 INSN_LABEL(arraylength
),
226 INSN_LABEL(checkcast
),
227 INSN_LABEL(instanceof
),
228 INSN_LABEL(monitorenter
),
229 INSN_LABEL(monitorexit
),
230 #ifdef DIRECT_THREADED
235 INSN_LABEL(multianewarray
),
237 INSN_LABEL(ifnonnull
),
240 #ifdef DIRECT_THREADED
241 INSN_LABEL (ldc_class
)
249 #ifdef DIRECT_THREADED
256 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
258 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
259 jmethodID method = meth->self; \
260 jlocation loc = meth->insn_index (pc); \
261 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
264 goto *((pc++)->insn); \
269 #define NEXT_INSN goto *((pc++)->insn)
272 #define INTVAL() ((pc++)->int_val)
273 #define AVAL() ((pc++)->datum)
275 #define GET1S() INTVAL ()
276 #define GET2S() INTVAL ()
277 #define GET1U() INTVAL ()
278 #define GET2U() INTVAL ()
279 #define AVAL1U() AVAL ()
280 #define AVAL2U() AVAL ()
281 #define AVAL2UP() AVAL ()
282 #define SKIP_GOTO ++pc
283 #define GOTO_VAL() (insn_slot *) pc->datum
284 #define PCVAL(unionval) unionval.p
285 #define AMPAMP(label) &&label
287 // Compile if we must. NOTE: Double-check locking.
288 if (meth
->prepared
== NULL
)
290 _Jv_MutexLock (&compile_mutex
);
291 if (meth
->prepared
== NULL
)
292 meth
->compile (insn_target
);
293 _Jv_MutexUnlock (&compile_mutex
);
296 // If we're only compiling, stop here
300 pc
= (insn_slot
*) meth
->prepared
;
308 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
310 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
311 jmethodID method = meth->self; \
312 jlocation loc = meth->insn_index (pc); \
313 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
316 goto *(insn_target[*pc++])
318 #define NEXT_INSN goto *(insn_target[*pc++])
321 #define GET1S() get1s (pc++)
322 #define GET2S() (pc += 2, get2s (pc- 2))
323 #define GET1U() get1u (pc++)
324 #define GET2U() (pc += 2, get2u (pc - 2))
325 // Note that these could be more efficient when not handling 'ldc
328 ({ int index = get1u (pc++); \
329 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
331 ({ int index = get2u (pc); pc += 2; \
332 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
333 // Note that we don't need to resolve the pool entry here as class
334 // constants are never wide.
335 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
336 #define SKIP_GOTO pc += 2
337 #define GOTO_VAL() pc - 1 + get2s (pc)
338 #define PCVAL(unionval) unionval.i
339 #define AMPAMP(label) NULL
341 pc
= meth
->bytecode ();
343 #endif /* DIRECT_THREADED */
345 #define TAKE_GOTO pc = GOTO_VAL ()
347 /* Go straight at it! the ffi raw format matches the internal
348 stack representation exactly. At least, that's the idea.
350 memcpy ((void*) locals
, (void*) args
, meth
->args_raw_size
);
352 _Jv_word
*pool_data
= meth
->defining_class
->constants
.data
;
354 /* These three are temporaries for common code used by several
357 _Jv_ResolvedMethod
* rmeth
;
362 // We keep nop around. It is used if we're interpreting the
363 // bytecodes and not doing direct threading.
367 /* The first few instructions here are ordered according to their
368 frequency, in the hope that this will improve code locality a
371 insn_aload_0
: // 0x2a
379 insn_iload_1
: // 0x1b
383 insn_invokevirtual
: // 0xb6
386 int index
= GET2U ();
388 /* _Jv_Linker::resolve_pool_entry returns immediately if the
389 * value already is resolved. If we want to clutter up the
390 * code here to gain a little performance, then we can check
391 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
392 * directly. For now, I don't think it is worth it. */
394 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
397 sp
-= rmeth
->stack_item_count
;
399 if (rmeth
->method
->accflags
& Modifier::FINAL
)
401 // We can't rely on NULLCHECK working if the method is final.
403 throw_null_pointer_exception ();
405 // Final methods might not appear in the vtable.
406 fun
= (void (*)()) rmeth
->method
->ncode
;
411 jobject rcv
= sp
[0].o
;
412 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
413 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
416 #ifdef DIRECT_THREADED
417 // Rewrite instruction so that we use a faster pre-resolved
419 pc
[-2].insn
= &&invokevirtual_resolved
;
420 pc
[-1].datum
= rmeth
;
421 #endif /* DIRECT_THREADED */
425 #ifdef DIRECT_THREADED
426 invokevirtual_resolved
:
429 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
430 sp
-= rmeth
->stack_item_count
;
432 if (rmeth
->method
->accflags
& Modifier::FINAL
)
434 // We can't rely on NULLCHECK working if the method is final.
436 throw_null_pointer_exception ();
438 // Final methods might not appear in the vtable.
439 fun
= (void (*)()) rmeth
->method
->ncode
;
443 jobject rcv
= sp
[0].o
;
444 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
445 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
449 #endif /* DIRECT_THREADED */
453 /* here goes the magic again... */
454 ffi_cif
*cif
= &rmeth
->cif
;
455 ffi_raw
*raw
= (ffi_raw
*) sp
;
459 #if FFI_NATIVE_RAW_API
460 /* We assume that this is only implemented if it's correct */
461 /* to use it here. On a 64 bit machine, it never is. */
462 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
464 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
467 int rtype
= cif
->rtype
->type
;
469 /* the likelyhood of object, int, or void return is very high,
470 * so those are checked before the switch */
471 if (rtype
== FFI_TYPE_POINTER
)
473 PUSHA (rvalue
.object_value
);
475 else if (rtype
== FFI_TYPE_SINT32
)
477 PUSHI (rvalue
.int_value
);
479 else if (rtype
== FFI_TYPE_VOID
)
488 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
491 case FFI_TYPE_SINT16
:
492 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
495 case FFI_TYPE_UINT16
:
496 PUSHI (rvalue
.int_value
& 0xffff);
500 PUSHF (rvalue
.float_value
);
503 case FFI_TYPE_DOUBLE
:
504 PUSHD (rvalue
.double_value
);
507 case FFI_TYPE_SINT64
:
508 PUSHL (rvalue
.long_value
);
512 throw_internal_error ("unknown return type in invokeXXX");
579 // For direct threaded, bipush and sipush are the same.
580 #ifndef DIRECT_THREADED
583 #endif /* DIRECT_THREADED */
589 // For direct threaded, ldc and ldc_w are the same.
590 #ifndef DIRECT_THREADED
591 PUSHA ((jobject
) AVAL1U ());
593 #endif /* DIRECT_THREADED */
595 PUSHA ((jobject
) AVAL2U ());
598 #ifdef DIRECT_THREADED
599 // For direct threaded we have a separate 'ldc class' operation.
603 // We could rewrite the instruction at this point.
604 int index
= INTVAL ();
605 jobject k
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
610 #endif /* DIRECT_THREADED */
614 void *where
= AVAL2UP ();
615 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
711 jintArray arr
= (jintArray
) POPA();
712 NULLARRAYCHECK (arr
);
713 ARRAYBOUNDSCHECK (arr
, index
);
714 PUSHI( elements(arr
)[index
] );
721 jlongArray arr
= (jlongArray
) POPA();
722 NULLARRAYCHECK (arr
);
723 ARRAYBOUNDSCHECK (arr
, index
);
724 PUSHL( elements(arr
)[index
] );
731 jfloatArray arr
= (jfloatArray
) POPA();
732 NULLARRAYCHECK (arr
);
733 ARRAYBOUNDSCHECK (arr
, index
);
734 PUSHF( elements(arr
)[index
] );
741 jdoubleArray arr
= (jdoubleArray
) POPA();
742 NULLARRAYCHECK (arr
);
743 ARRAYBOUNDSCHECK (arr
, index
);
744 PUSHD( elements(arr
)[index
] );
751 jobjectArray arr
= (jobjectArray
) POPA();
752 NULLARRAYCHECK (arr
);
753 ARRAYBOUNDSCHECK (arr
, index
);
754 PUSHA( elements(arr
)[index
] );
761 jbyteArray arr
= (jbyteArray
) POPA();
762 NULLARRAYCHECK (arr
);
763 ARRAYBOUNDSCHECK (arr
, index
);
764 PUSHI( elements(arr
)[index
] );
771 jcharArray arr
= (jcharArray
) POPA();
772 NULLARRAYCHECK (arr
);
773 ARRAYBOUNDSCHECK (arr
, index
);
774 PUSHI( elements(arr
)[index
] );
781 jshortArray arr
= (jshortArray
) POPA();
782 NULLARRAYCHECK (arr
);
783 ARRAYBOUNDSCHECK (arr
, index
);
784 PUSHI( elements(arr
)[index
] );
892 jintArray arr
= (jintArray
) POPA();
893 NULLARRAYCHECK (arr
);
894 ARRAYBOUNDSCHECK (arr
, index
);
895 elements(arr
)[index
] = value
;
901 jlong value
= POPL();
903 jlongArray arr
= (jlongArray
) POPA();
904 NULLARRAYCHECK (arr
);
905 ARRAYBOUNDSCHECK (arr
, index
);
906 elements(arr
)[index
] = value
;
912 jfloat value
= POPF();
914 jfloatArray arr
= (jfloatArray
) POPA();
915 NULLARRAYCHECK (arr
);
916 ARRAYBOUNDSCHECK (arr
, index
);
917 elements(arr
)[index
] = value
;
923 jdouble value
= POPD();
925 jdoubleArray arr
= (jdoubleArray
) POPA();
926 NULLARRAYCHECK (arr
);
927 ARRAYBOUNDSCHECK (arr
, index
);
928 elements(arr
)[index
] = value
;
934 jobject value
= POPA();
936 jobjectArray arr
= (jobjectArray
) POPA();
937 NULLARRAYCHECK (arr
);
938 ARRAYBOUNDSCHECK (arr
, index
);
939 _Jv_CheckArrayStore (arr
, value
);
940 elements(arr
)[index
] = value
;
946 jbyte value
= (jbyte
) POPI();
948 jbyteArray arr
= (jbyteArray
) POPA();
949 NULLARRAYCHECK (arr
);
950 ARRAYBOUNDSCHECK (arr
, index
);
951 elements(arr
)[index
] = value
;
957 jchar value
= (jchar
) POPI();
959 jcharArray arr
= (jcharArray
) POPA();
960 NULLARRAYCHECK (arr
);
961 ARRAYBOUNDSCHECK (arr
, index
);
962 elements(arr
)[index
] = value
;
968 jshort value
= (jshort
) POPI();
970 jshortArray arr
= (jshortArray
) POPA();
971 NULLARRAYCHECK (arr
);
972 ARRAYBOUNDSCHECK (arr
, index
);
973 elements(arr
)[index
] = value
;
991 dupx (sp
, 1, 1); sp
+=1;
995 dupx (sp
, 1, 2); sp
+=1;
1005 dupx (sp
, 2, 1); sp
+=2;
1009 dupx (sp
, 2, 2); sp
+=2;
1014 jobject tmp1
= POPA();
1015 jobject tmp2
= POPA();
1072 jint value2
= POPI();
1073 jint value1
= POPI();
1074 jint res
= _Jv_divI (value1
, value2
);
1082 jlong value2
= POPL();
1083 jlong value1
= POPL();
1084 jlong res
= _Jv_divJ (value1
, value2
);
1091 jfloat value2
= POPF();
1092 jfloat value1
= POPF();
1093 jfloat res
= value1
/ value2
;
1100 jdouble value2
= POPD();
1101 jdouble value1
= POPD();
1102 jdouble res
= value1
/ value2
;
1110 jint value2
= POPI();
1111 jint value1
= POPI();
1112 jint res
= _Jv_remI (value1
, value2
);
1120 jlong value2
= POPL();
1121 jlong value1
= POPL();
1122 jlong res
= _Jv_remJ (value1
, value2
);
1129 jfloat value2
= POPF();
1130 jfloat value1
= POPF();
1131 jfloat res
= __ieee754_fmod (value1
, value2
);
1138 jdouble value2
= POPD();
1139 jdouble value1
= POPD();
1140 jdouble res
= __ieee754_fmod (value1
, value2
);
1147 jint value
= POPI();
1154 jlong value
= POPL();
1161 jfloat value
= POPF();
1168 jdouble value
= POPD();
1175 jint shift
= (POPI() & 0x1f);
1176 jint value
= POPI();
1177 PUSHI (value
<< shift
);
1183 jint shift
= (POPI() & 0x3f);
1184 jlong value
= POPL();
1185 PUSHL (value
<< shift
);
1191 jint shift
= (POPI() & 0x1f);
1192 jint value
= POPI();
1193 PUSHI (value
>> shift
);
1199 jint shift
= (POPI() & 0x3f);
1200 jlong value
= POPL();
1201 PUSHL (value
>> shift
);
1207 jint shift
= (POPI() & 0x1f);
1208 _Jv_uint value
= (_Jv_uint
) POPI();
1209 PUSHI ((jint
) (value
>> shift
));
1215 jint shift
= (POPI() & 0x3f);
1216 _Jv_ulong value
= (_Jv_ulong
) POPL();
1217 PUSHL ((jlong
) (value
>> shift
));
1247 jint index
= GET1U ();
1248 jint amount
= GET1S ();
1249 locals
[index
].i
+= amount
;
1254 {jlong value
= POPI(); PUSHL (value
);}
1258 {jfloat value
= POPI(); PUSHF (value
);}
1262 {jdouble value
= POPI(); PUSHD (value
);}
1266 {jint value
= POPL(); PUSHI (value
);}
1270 {jfloat value
= POPL(); PUSHF (value
);}
1274 {jdouble value
= POPL(); PUSHD (value
);}
1279 using namespace java::lang
;
1280 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1287 using namespace java::lang
;
1288 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1294 { jdouble value
= POPF (); PUSHD(value
); }
1299 using namespace java::lang
;
1300 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1307 using namespace java::lang
;
1308 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1314 { jfloat value
= POPD (); PUSHF(value
); }
1318 { jbyte value
= POPI (); PUSHI(value
); }
1322 { jchar value
= POPI (); PUSHI(value
); }
1326 { jshort value
= POPI (); PUSHI(value
); }
1331 jlong value2
= POPL ();
1332 jlong value1
= POPL ();
1333 if (value1
> value2
)
1335 else if (value1
== value2
)
1351 jfloat value2
= POPF ();
1352 jfloat value1
= POPF ();
1353 if (value1
> value2
)
1355 else if (value1
== value2
)
1357 else if (value1
< value2
)
1373 jdouble value2
= POPD ();
1374 jdouble value1
= POPD ();
1375 if (value1
> value2
)
1377 else if (value1
== value2
)
1379 else if (value1
< value2
)
1442 jint value2
= POPI();
1443 jint value1
= POPI();
1444 if (value1
== value2
)
1453 jint value2
= POPI();
1454 jint value1
= POPI();
1455 if (value1
!= value2
)
1464 jint value2
= POPI();
1465 jint value1
= POPI();
1466 if (value1
< value2
)
1475 jint value2
= POPI();
1476 jint value1
= POPI();
1477 if (value1
>= value2
)
1486 jint value2
= POPI();
1487 jint value1
= POPI();
1488 if (value1
> value2
)
1497 jint value2
= POPI();
1498 jint value1
= POPI();
1499 if (value1
<= value2
)
1508 jobject value2
= POPA();
1509 jobject value1
= POPA();
1510 if (value1
== value2
)
1519 jobject value2
= POPA();
1520 jobject value1
= POPA();
1521 if (value1
!= value2
)
1529 #ifndef DIRECT_THREADED
1530 // For direct threaded, goto and goto_w are the same.
1531 pc
= pc
- 1 + get4 (pc
);
1533 #endif /* DIRECT_THREADED */
1539 #ifndef DIRECT_THREADED
1540 // For direct threaded, jsr and jsr_w are the same.
1542 pc_t next
= pc
- 1 + get4 (pc
);
1544 PUSHA ((jobject
) pc
);
1548 #endif /* DIRECT_THREADED */
1551 pc_t next
= GOTO_VAL();
1553 PUSHA ((jobject
) pc
);
1560 jint index
= GET1U ();
1561 pc
= (pc_t
) PEEKA (index
);
1567 #ifdef DIRECT_THREADED
1568 void *def
= (pc
++)->datum
;
1572 jint low
= INTVAL ();
1573 jint high
= INTVAL ();
1575 if (index
< low
|| index
> high
)
1576 pc
= (insn_slot
*) def
;
1578 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
1580 pc_t base_pc
= pc
- 1;
1581 int index
= POPI ();
1583 pc_t base
= (pc_t
) meth
->bytecode ();
1584 while ((pc
- base
) % 4 != 0)
1587 jint def
= get4 (pc
);
1588 jint low
= get4 (pc
+ 4);
1589 jint high
= get4 (pc
+ 8);
1590 if (index
< low
|| index
> high
)
1593 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
1594 #endif /* DIRECT_THREADED */
1600 #ifdef DIRECT_THREADED
1601 void *def
= (pc
++)->insn
;
1605 jint npairs
= INTVAL ();
1607 int max
= npairs
- 1;
1610 // Simple binary search...
1613 int half
= (min
+ max
) / 2;
1614 int match
= pc
[2 * half
].int_val
;
1619 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
1622 else if (index
< match
)
1623 // We can use HALF - 1 here because we check again on
1627 // We can use HALF + 1 here because we check again on
1631 if (index
== pc
[2 * min
].int_val
)
1632 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
1634 pc
= (insn_slot
*) def
;
1636 unsigned char *base_pc
= pc
-1;
1639 unsigned char* base
= meth
->bytecode ();
1640 while ((pc
-base
) % 4 != 0)
1643 jint def
= get4 (pc
);
1644 jint npairs
= get4 (pc
+4);
1649 // Simple binary search...
1652 int half
= (min
+max
)/2;
1653 int match
= get4 (pc
+ 4*(2 + 2*half
));
1657 else if (index
< match
)
1658 // We can use HALF - 1 here because we check again on
1662 // We can use HALF + 1 here because we check again on
1667 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1668 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1671 #endif /* DIRECT_THREADED */
1676 *(jobject
*) retp
= POPA ();
1680 *(jlong
*) retp
= POPL ();
1684 *(jfloat
*) retp
= POPF ();
1688 *(jdouble
*) retp
= POPD ();
1692 *(jint
*) retp
= POPI ();
1700 jint fieldref_index
= GET2U ();
1701 SAVE_PC(); // Constant pool resolution could throw.
1702 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1703 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1705 if ((field
->flags
& Modifier::STATIC
) == 0)
1706 throw_incompatible_class_change_error
1707 (JvNewStringLatin1 ("field no longer static"));
1709 jclass type
= field
->type
;
1711 // We rewrite the instruction once we discover what it refers
1713 void *newinsn
= NULL
;
1714 if (type
->isPrimitive ())
1716 switch (type
->size_in_bytes
)
1719 PUSHI (*field
->u
.byte_addr
);
1720 newinsn
= AMPAMP (getstatic_resolved_1
);
1724 if (type
== JvPrimClass (char))
1726 PUSHI (*field
->u
.char_addr
);
1727 newinsn
= AMPAMP (getstatic_resolved_char
);
1731 PUSHI (*field
->u
.short_addr
);
1732 newinsn
= AMPAMP (getstatic_resolved_short
);
1737 PUSHI(*field
->u
.int_addr
);
1738 newinsn
= AMPAMP (getstatic_resolved_4
);
1742 PUSHL(*field
->u
.long_addr
);
1743 newinsn
= AMPAMP (getstatic_resolved_8
);
1749 PUSHA(*field
->u
.object_addr
);
1750 newinsn
= AMPAMP (getstatic_resolved_obj
);
1753 #ifdef DIRECT_THREADED
1754 pc
[-2].insn
= newinsn
;
1755 pc
[-1].datum
= field
->u
.addr
;
1756 #endif /* DIRECT_THREADED */
1760 #ifdef DIRECT_THREADED
1761 getstatic_resolved_1
:
1762 PUSHI (*(jbyte
*) AVAL ());
1765 getstatic_resolved_char
:
1766 PUSHI (*(jchar
*) AVAL ());
1769 getstatic_resolved_short
:
1770 PUSHI (*(jshort
*) AVAL ());
1773 getstatic_resolved_4
:
1774 PUSHI (*(jint
*) AVAL ());
1777 getstatic_resolved_8
:
1778 PUSHL (*(jlong
*) AVAL ());
1781 getstatic_resolved_obj
:
1782 PUSHA (*(jobject
*) AVAL ());
1784 #endif /* DIRECT_THREADED */
1789 jint fieldref_index
= GET2U ();
1790 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1791 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1793 if ((field
->flags
& Modifier::STATIC
) != 0)
1794 throw_incompatible_class_change_error
1795 (JvNewStringLatin1 ("field is static"));
1797 jclass type
= field
->type
;
1798 jint field_offset
= field
->u
.boffset
;
1800 jobject obj
= POPA();
1803 void *newinsn
= NULL
;
1804 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
1805 if (type
->isPrimitive ())
1807 switch (type
->size_in_bytes
)
1810 PUSHI (val
->byte_value
);
1811 newinsn
= AMPAMP (getfield_resolved_1
);
1815 if (type
== JvPrimClass (char))
1817 PUSHI (val
->char_value
);
1818 newinsn
= AMPAMP (getfield_resolved_char
);
1822 PUSHI (val
->short_value
);
1823 newinsn
= AMPAMP (getfield_resolved_short
);
1828 PUSHI (val
->int_value
);
1829 newinsn
= AMPAMP (getfield_resolved_4
);
1833 PUSHL (val
->long_value
);
1834 newinsn
= AMPAMP (getfield_resolved_8
);
1840 PUSHA (val
->object_value
);
1841 newinsn
= AMPAMP (getfield_resolved_obj
);
1844 #ifdef DIRECT_THREADED
1845 pc
[-2].insn
= newinsn
;
1846 pc
[-1].int_val
= field_offset
;
1847 #endif /* DIRECT_THREADED */
1851 #ifdef DIRECT_THREADED
1852 getfield_resolved_1
:
1854 char *obj
= (char *) POPA ();
1856 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
1860 getfield_resolved_char
:
1862 char *obj
= (char *) POPA ();
1864 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
1868 getfield_resolved_short
:
1870 char *obj
= (char *) POPA ();
1872 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
1876 getfield_resolved_4
:
1878 char *obj
= (char *) POPA ();
1880 PUSHI (*(jint
*) (obj
+ INTVAL ()));
1884 getfield_resolved_8
:
1886 char *obj
= (char *) POPA ();
1888 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
1892 getfield_resolved_obj
:
1894 char *obj
= (char *) POPA ();
1896 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
1899 #endif /* DIRECT_THREADED */
1904 jint fieldref_index
= GET2U ();
1905 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1906 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1908 jclass type
= field
->type
;
1910 // ResolvePoolEntry cannot check this
1911 if ((field
->flags
& Modifier::STATIC
) == 0)
1912 throw_incompatible_class_change_error
1913 (JvNewStringLatin1 ("field no longer static"));
1915 void *newinsn
= NULL
;
1916 if (type
->isPrimitive ())
1918 switch (type
->size_in_bytes
)
1922 jint value
= POPI();
1923 *field
->u
.byte_addr
= value
;
1924 newinsn
= AMPAMP (putstatic_resolved_1
);
1930 jint value
= POPI();
1931 *field
->u
.char_addr
= value
;
1932 newinsn
= AMPAMP (putstatic_resolved_2
);
1938 jint value
= POPI();
1939 *field
->u
.int_addr
= value
;
1940 newinsn
= AMPAMP (putstatic_resolved_4
);
1946 jlong value
= POPL();
1947 *field
->u
.long_addr
= value
;
1948 newinsn
= AMPAMP (putstatic_resolved_8
);
1955 jobject value
= POPA();
1956 *field
->u
.object_addr
= value
;
1957 newinsn
= AMPAMP (putstatic_resolved_obj
);
1960 #ifdef DIRECT_THREADED
1961 pc
[-2].insn
= newinsn
;
1962 pc
[-1].datum
= field
->u
.addr
;
1963 #endif /* DIRECT_THREADED */
1967 #ifdef DIRECT_THREADED
1968 putstatic_resolved_1
:
1969 *(jbyte
*) AVAL () = POPI ();
1972 putstatic_resolved_2
:
1973 *(jchar
*) AVAL () = POPI ();
1976 putstatic_resolved_4
:
1977 *(jint
*) AVAL () = POPI ();
1980 putstatic_resolved_8
:
1981 *(jlong
*) AVAL () = POPL ();
1984 putstatic_resolved_obj
:
1985 *(jobject
*) AVAL () = POPA ();
1987 #endif /* DIRECT_THREADED */
1992 jint fieldref_index
= GET2U ();
1993 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1994 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1996 jclass type
= field
->type
;
1998 if ((field
->flags
& Modifier::STATIC
) != 0)
1999 throw_incompatible_class_change_error
2000 (JvNewStringLatin1 ("field is static"));
2002 jint field_offset
= field
->u
.boffset
;
2004 void *newinsn
= NULL
;
2005 if (type
->isPrimitive ())
2007 switch (type
->size_in_bytes
)
2011 jint value
= POPI();
2012 jobject obj
= POPA();
2014 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2015 newinsn
= AMPAMP (putfield_resolved_1
);
2021 jint value
= POPI();
2022 jobject obj
= POPA();
2024 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2025 newinsn
= AMPAMP (putfield_resolved_2
);
2031 jint value
= POPI();
2032 jobject obj
= POPA();
2034 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2035 newinsn
= AMPAMP (putfield_resolved_4
);
2041 jlong value
= POPL();
2042 jobject obj
= POPA();
2044 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2045 newinsn
= AMPAMP (putfield_resolved_8
);
2052 jobject value
= POPA();
2053 jobject obj
= POPA();
2055 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2056 newinsn
= AMPAMP (putfield_resolved_obj
);
2059 #ifdef DIRECT_THREADED
2060 pc
[-2].insn
= newinsn
;
2061 pc
[-1].int_val
= field_offset
;
2062 #endif /* DIRECT_THREADED */
2066 #ifdef DIRECT_THREADED
2067 putfield_resolved_1
:
2070 char *obj
= (char *) POPA ();
2072 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2076 putfield_resolved_2
:
2079 char *obj
= (char *) POPA ();
2081 *(jchar
*) (obj
+ INTVAL ()) = val
;
2085 putfield_resolved_4
:
2088 char *obj
= (char *) POPA ();
2090 *(jint
*) (obj
+ INTVAL ()) = val
;
2094 putfield_resolved_8
:
2096 jlong val
= POPL ();
2097 char *obj
= (char *) POPA ();
2099 *(jlong
*) (obj
+ INTVAL ()) = val
;
2103 putfield_resolved_obj
:
2105 jobject val
= POPA ();
2106 char *obj
= (char *) POPA ();
2108 *(jobject
*) (obj
+ INTVAL ()) = val
;
2111 #endif /* DIRECT_THREADED */
2116 int index
= GET2U ();
2118 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2121 sp
-= rmeth
->stack_item_count
;
2123 // We don't use NULLCHECK here because we can't rely on that
2124 // working for <init>. So instead we do an explicit test.
2128 throw_null_pointer_exception ();
2131 fun
= (void (*)()) rmeth
->method
->ncode
;
2133 #ifdef DIRECT_THREADED
2134 // Rewrite instruction so that we use a faster pre-resolved
2136 pc
[-2].insn
= &&invokespecial_resolved
;
2137 pc
[-1].datum
= rmeth
;
2138 #endif /* DIRECT_THREADED */
2140 goto perform_invoke
;
2142 #ifdef DIRECT_THREADED
2143 invokespecial_resolved
:
2146 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2147 sp
-= rmeth
->stack_item_count
;
2148 // We don't use NULLCHECK here because we can't rely on that
2149 // working for <init>. So instead we do an explicit test.
2152 throw_null_pointer_exception ();
2154 fun
= (void (*)()) rmeth
->method
->ncode
;
2156 goto perform_invoke
;
2157 #endif /* DIRECT_THREADED */
2162 int index
= GET2U ();
2164 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2167 sp
-= rmeth
->stack_item_count
;
2169 fun
= (void (*)()) rmeth
->method
->ncode
;
2171 #ifdef DIRECT_THREADED
2172 // Rewrite instruction so that we use a faster pre-resolved
2174 pc
[-2].insn
= &&invokestatic_resolved
;
2175 pc
[-1].datum
= rmeth
;
2176 #endif /* DIRECT_THREADED */
2178 goto perform_invoke
;
2180 #ifdef DIRECT_THREADED
2181 invokestatic_resolved
:
2184 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2185 sp
-= rmeth
->stack_item_count
;
2186 fun
= (void (*)()) rmeth
->method
->ncode
;
2188 goto perform_invoke
;
2189 #endif /* DIRECT_THREADED */
2191 insn_invokeinterface
:
2194 int index
= GET2U ();
2196 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2199 sp
-= rmeth
->stack_item_count
;
2201 jobject rcv
= sp
[0].o
;
2206 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2207 rmeth
->method
->name
,
2208 rmeth
->method
->signature
);
2210 #ifdef DIRECT_THREADED
2211 // Rewrite instruction so that we use a faster pre-resolved
2213 pc
[-2].insn
= &&invokeinterface_resolved
;
2214 pc
[-1].datum
= rmeth
;
2216 // Skip dummy bytes.
2218 #endif /* DIRECT_THREADED */
2220 goto perform_invoke
;
2222 #ifdef DIRECT_THREADED
2223 invokeinterface_resolved
:
2226 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2227 sp
-= rmeth
->stack_item_count
;
2228 jobject rcv
= sp
[0].o
;
2231 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2232 rmeth
->method
->name
,
2233 rmeth
->method
->signature
);
2235 goto perform_invoke
;
2236 #endif /* DIRECT_THREADED */
2241 int index
= GET2U ();
2242 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2244 /* VM spec, section 3.11.5 */
2245 if ((klass
->getModifiers() & Modifier::ABSTRACT
)
2246 || klass
->isInterface())
2247 throw new java::lang::InstantiationException
;
2248 jobject res
= _Jv_AllocObject (klass
);
2251 #ifdef DIRECT_THREADED
2252 pc
[-2].insn
= &&new_resolved
;
2253 pc
[-1].datum
= klass
;
2254 #endif /* DIRECT_THREADED */
2258 #ifdef DIRECT_THREADED
2261 jclass klass
= (jclass
) AVAL ();
2262 jobject res
= _Jv_AllocObject (klass
);
2266 #endif /* DIRECT_THREADED */
2270 int atype
= GET1U ();
2272 jobject result
= _Jv_NewArray (atype
, size
);
2280 int index
= GET2U ();
2281 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2284 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2287 #ifdef DIRECT_THREADED
2288 pc
[-2].insn
= &&anewarray_resolved
;
2289 pc
[-1].datum
= klass
;
2290 #endif /* DIRECT_THREADED */
2294 #ifdef DIRECT_THREADED
2297 jclass klass
= (jclass
) AVAL ();
2299 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2303 #endif /* DIRECT_THREADED */
2307 __JArray
*arr
= (__JArray
*)POPA();
2308 NULLARRAYCHECK (arr
);
2309 PUSHI (arr
->length
);
2315 jobject value
= POPA();
2316 throw static_cast<jthrowable
>(value
);
2323 jobject value
= POPA();
2324 jint index
= GET2U ();
2325 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2328 value
= (jobject
) _Jv_CheckCast (to
, value
);
2332 #ifdef DIRECT_THREADED
2333 pc
[-2].insn
= &&checkcast_resolved
;
2335 #endif /* DIRECT_THREADED */
2339 #ifdef DIRECT_THREADED
2343 jobject value
= POPA ();
2344 jclass to
= (jclass
) AVAL ();
2345 value
= (jobject
) _Jv_CheckCast (to
, value
);
2349 #endif /* DIRECT_THREADED */
2354 jobject value
= POPA();
2355 jint index
= GET2U ();
2356 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2358 PUSHI (to
->isInstance (value
));
2360 #ifdef DIRECT_THREADED
2361 pc
[-2].insn
= &&instanceof_resolved
;
2363 #endif /* DIRECT_THREADED */
2367 #ifdef DIRECT_THREADED
2368 instanceof_resolved
:
2370 jobject value
= POPA ();
2371 jclass to
= (jclass
) AVAL ();
2372 PUSHI (to
->isInstance (value
));
2375 #endif /* DIRECT_THREADED */
2379 jobject value
= POPA();
2381 _Jv_MonitorEnter (value
);
2387 jobject value
= POPA();
2389 _Jv_MonitorExit (value
);
2395 jobject val
= POPA();
2405 jobject val
= POPA();
2413 insn_multianewarray
:
2416 int kind_index
= GET2U ();
2420 = (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2422 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2424 for (int i
= dim
- 1; i
>= 0; i
--)
2429 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2435 #ifndef DIRECT_THREADED
2438 jint the_mod_op
= get1u (pc
++);
2439 jint wide
= get2u (pc
); pc
+= 2;
2484 pc
= (unsigned char*) PEEKA (wide
);
2489 jint amount
= get2s (pc
); pc
+= 2;
2490 jint value
= PEEKI (wide
);
2491 POKEI (wide
, value
+amount
);
2496 throw_internal_error ("illegal bytecode modified by wide");
2500 #endif /* DIRECT_THREADED */
2504 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint
));
2506 // Send JVMTI notification
2507 using namespace ::java::lang
;
2508 jmethodID method
= meth
->self
;
2509 jlocation location
= meth
->insn_index (pc
- 1);
2510 Thread
*thread
= Thread::currentThread ();
2511 JNIEnv
*jni_env
= _Jv_GetCurrentJNIEnv ();
2513 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT
, thread
, jni_env
,
2516 // Continue execution
2517 using namespace gnu::gcj::jvmti
;
2519 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong
> (method
),
2521 JvAssert (bp
!= NULL
);
2523 pc_t opc
= reinterpret_cast<pc_t
> (bp
->getInsn ());
2525 #ifdef DIRECT_THREADED
2528 goto *(insn_target
[*opc
]);
2532 catch (java::lang::Throwable
*ex
)
2534 #ifdef DIRECT_THREADED
2535 void *logical_pc
= (void *) ((insn_slot
*) pc
- 1);
2537 int logical_pc
= pc
- 1 - meth
->bytecode ();
2539 _Jv_InterpException
*exc
= meth
->exceptions ();
2540 jclass exc_class
= ex
->getClass ();
2542 for (int i
= 0; i
< meth
->exc_count
; i
++)
2544 if (PCVAL (exc
[i
].start_pc
) <= logical_pc
2545 && logical_pc
< PCVAL (exc
[i
].end_pc
))
2547 #ifdef DIRECT_THREADED
2548 jclass handler
= (jclass
) exc
[i
].handler_type
.p
;
2550 jclass handler
= NULL
;
2551 if (exc
[i
].handler_type
.i
!= 0)
2552 handler
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2553 exc
[i
].handler_type
.i
)).clazz
;
2554 #endif /* DIRECT_THREADED */
2556 if (handler
== NULL
|| handler
->isAssignableFrom (exc_class
))
2559 #ifdef DIRECT_THREADED
2560 pc
= (insn_slot
*) exc
[i
].handler_pc
.p
;
2562 pc
= meth
->bytecode () + exc
[i
].handler_pc
.i
;
2563 #endif /* DIRECT_THREADED */
2565 sp
++->o
= ex
; // Push exception.
2571 // No handler, so re-throw.