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
);
353 // Get the object pointer for this method, after checking that it is
355 _Jv_Method
*method
= meth
->get_method ();
357 if ((method
->accflags
& java::lang::reflect::Modifier::STATIC
) == 0)
358 frame_desc
.obj_ptr
= locals
[0].o
;
361 _Jv_word
*pool_data
= meth
->defining_class
->constants
.data
;
363 /* These three are temporaries for common code used by several
366 _Jv_ResolvedMethod
* rmeth
;
371 // We keep nop around. It is used if we're interpreting the
372 // bytecodes and not doing direct threading.
376 /* The first few instructions here are ordered according to their
377 frequency, in the hope that this will improve code locality a
380 insn_aload_0
: // 0x2a
388 insn_iload_1
: // 0x1b
392 insn_invokevirtual
: // 0xb6
395 int index
= GET2U ();
397 /* _Jv_Linker::resolve_pool_entry returns immediately if the
398 * value already is resolved. If we want to clutter up the
399 * code here to gain a little performance, then we can check
400 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
401 * directly. For now, I don't think it is worth it. */
403 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
406 sp
-= rmeth
->stack_item_count
;
408 if (rmeth
->method
->accflags
& Modifier::FINAL
)
410 // We can't rely on NULLCHECK working if the method is final.
412 throw_null_pointer_exception ();
414 // Final methods might not appear in the vtable.
415 fun
= (void (*)()) rmeth
->method
->ncode
;
420 jobject rcv
= sp
[0].o
;
421 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
422 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
425 #ifdef DIRECT_THREADED
426 // Rewrite instruction so that we use a faster pre-resolved
428 pc
[-2].insn
= &&invokevirtual_resolved
;
429 pc
[-1].datum
= rmeth
;
430 #endif /* DIRECT_THREADED */
434 #ifdef DIRECT_THREADED
435 invokevirtual_resolved
:
438 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
439 sp
-= rmeth
->stack_item_count
;
441 if (rmeth
->method
->accflags
& Modifier::FINAL
)
443 // We can't rely on NULLCHECK working if the method is final.
445 throw_null_pointer_exception ();
447 // Final methods might not appear in the vtable.
448 fun
= (void (*)()) rmeth
->method
->ncode
;
452 jobject rcv
= sp
[0].o
;
453 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
454 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
458 #endif /* DIRECT_THREADED */
462 /* here goes the magic again... */
463 ffi_cif
*cif
= &rmeth
->cif
;
464 ffi_raw
*raw
= (ffi_raw
*) sp
;
468 #if FFI_NATIVE_RAW_API
469 /* We assume that this is only implemented if it's correct */
470 /* to use it here. On a 64 bit machine, it never is. */
471 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
473 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
476 int rtype
= cif
->rtype
->type
;
478 /* the likelyhood of object, int, or void return is very high,
479 * so those are checked before the switch */
480 if (rtype
== FFI_TYPE_POINTER
)
482 PUSHA (rvalue
.object_value
);
484 else if (rtype
== FFI_TYPE_SINT32
)
486 PUSHI (rvalue
.int_value
);
488 else if (rtype
== FFI_TYPE_VOID
)
497 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
500 case FFI_TYPE_SINT16
:
501 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
504 case FFI_TYPE_UINT16
:
505 PUSHI (rvalue
.int_value
& 0xffff);
509 PUSHF (rvalue
.float_value
);
512 case FFI_TYPE_DOUBLE
:
513 PUSHD (rvalue
.double_value
);
516 case FFI_TYPE_SINT64
:
517 PUSHL (rvalue
.long_value
);
521 throw_internal_error ("unknown return type in invokeXXX");
588 // For direct threaded, bipush and sipush are the same.
589 #ifndef DIRECT_THREADED
592 #endif /* DIRECT_THREADED */
598 // For direct threaded, ldc and ldc_w are the same.
599 #ifndef DIRECT_THREADED
600 PUSHA ((jobject
) AVAL1U ());
602 #endif /* DIRECT_THREADED */
604 PUSHA ((jobject
) AVAL2U ());
607 #ifdef DIRECT_THREADED
608 // For direct threaded we have a separate 'ldc class' operation.
612 // We could rewrite the instruction at this point.
613 int index
= INTVAL ();
614 jobject k
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
619 #endif /* DIRECT_THREADED */
623 void *where
= AVAL2UP ();
624 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
720 jintArray arr
= (jintArray
) POPA();
721 NULLARRAYCHECK (arr
);
722 ARRAYBOUNDSCHECK (arr
, index
);
723 PUSHI( elements(arr
)[index
] );
730 jlongArray arr
= (jlongArray
) POPA();
731 NULLARRAYCHECK (arr
);
732 ARRAYBOUNDSCHECK (arr
, index
);
733 PUSHL( elements(arr
)[index
] );
740 jfloatArray arr
= (jfloatArray
) POPA();
741 NULLARRAYCHECK (arr
);
742 ARRAYBOUNDSCHECK (arr
, index
);
743 PUSHF( elements(arr
)[index
] );
750 jdoubleArray arr
= (jdoubleArray
) POPA();
751 NULLARRAYCHECK (arr
);
752 ARRAYBOUNDSCHECK (arr
, index
);
753 PUSHD( elements(arr
)[index
] );
760 jobjectArray arr
= (jobjectArray
) POPA();
761 NULLARRAYCHECK (arr
);
762 ARRAYBOUNDSCHECK (arr
, index
);
763 PUSHA( elements(arr
)[index
] );
770 jbyteArray arr
= (jbyteArray
) POPA();
771 NULLARRAYCHECK (arr
);
772 ARRAYBOUNDSCHECK (arr
, index
);
773 PUSHI( elements(arr
)[index
] );
780 jcharArray arr
= (jcharArray
) POPA();
781 NULLARRAYCHECK (arr
);
782 ARRAYBOUNDSCHECK (arr
, index
);
783 PUSHI( elements(arr
)[index
] );
790 jshortArray arr
= (jshortArray
) POPA();
791 NULLARRAYCHECK (arr
);
792 ARRAYBOUNDSCHECK (arr
, index
);
793 PUSHI( elements(arr
)[index
] );
901 jintArray arr
= (jintArray
) POPA();
902 NULLARRAYCHECK (arr
);
903 ARRAYBOUNDSCHECK (arr
, index
);
904 elements(arr
)[index
] = value
;
910 jlong value
= POPL();
912 jlongArray arr
= (jlongArray
) POPA();
913 NULLARRAYCHECK (arr
);
914 ARRAYBOUNDSCHECK (arr
, index
);
915 elements(arr
)[index
] = value
;
921 jfloat value
= POPF();
923 jfloatArray arr
= (jfloatArray
) POPA();
924 NULLARRAYCHECK (arr
);
925 ARRAYBOUNDSCHECK (arr
, index
);
926 elements(arr
)[index
] = value
;
932 jdouble value
= POPD();
934 jdoubleArray arr
= (jdoubleArray
) POPA();
935 NULLARRAYCHECK (arr
);
936 ARRAYBOUNDSCHECK (arr
, index
);
937 elements(arr
)[index
] = value
;
943 jobject value
= POPA();
945 jobjectArray arr
= (jobjectArray
) POPA();
946 NULLARRAYCHECK (arr
);
947 ARRAYBOUNDSCHECK (arr
, index
);
948 _Jv_CheckArrayStore (arr
, value
);
949 elements(arr
)[index
] = value
;
955 jbyte value
= (jbyte
) POPI();
957 jbyteArray arr
= (jbyteArray
) POPA();
958 NULLARRAYCHECK (arr
);
959 ARRAYBOUNDSCHECK (arr
, index
);
960 elements(arr
)[index
] = value
;
966 jchar value
= (jchar
) POPI();
968 jcharArray arr
= (jcharArray
) POPA();
969 NULLARRAYCHECK (arr
);
970 ARRAYBOUNDSCHECK (arr
, index
);
971 elements(arr
)[index
] = value
;
977 jshort value
= (jshort
) POPI();
979 jshortArray arr
= (jshortArray
) POPA();
980 NULLARRAYCHECK (arr
);
981 ARRAYBOUNDSCHECK (arr
, index
);
982 elements(arr
)[index
] = value
;
1000 dupx (sp
, 1, 1); sp
+=1;
1004 dupx (sp
, 1, 2); sp
+=1;
1014 dupx (sp
, 2, 1); sp
+=2;
1018 dupx (sp
, 2, 2); sp
+=2;
1023 jobject tmp1
= POPA();
1024 jobject tmp2
= POPA();
1081 jint value2
= POPI();
1082 jint value1
= POPI();
1083 jint res
= _Jv_divI (value1
, value2
);
1091 jlong value2
= POPL();
1092 jlong value1
= POPL();
1093 jlong res
= _Jv_divJ (value1
, value2
);
1100 jfloat value2
= POPF();
1101 jfloat value1
= POPF();
1102 jfloat res
= value1
/ value2
;
1109 jdouble value2
= POPD();
1110 jdouble value1
= POPD();
1111 jdouble res
= value1
/ value2
;
1119 jint value2
= POPI();
1120 jint value1
= POPI();
1121 jint res
= _Jv_remI (value1
, value2
);
1129 jlong value2
= POPL();
1130 jlong value1
= POPL();
1131 jlong res
= _Jv_remJ (value1
, value2
);
1138 jfloat value2
= POPF();
1139 jfloat value1
= POPF();
1140 jfloat res
= __ieee754_fmod (value1
, value2
);
1147 jdouble value2
= POPD();
1148 jdouble value1
= POPD();
1149 jdouble res
= __ieee754_fmod (value1
, value2
);
1156 jint value
= POPI();
1163 jlong value
= POPL();
1170 jfloat value
= POPF();
1177 jdouble value
= POPD();
1184 jint shift
= (POPI() & 0x1f);
1185 jint value
= POPI();
1186 PUSHI (value
<< shift
);
1192 jint shift
= (POPI() & 0x3f);
1193 jlong value
= POPL();
1194 PUSHL (value
<< shift
);
1200 jint shift
= (POPI() & 0x1f);
1201 jint value
= POPI();
1202 PUSHI (value
>> shift
);
1208 jint shift
= (POPI() & 0x3f);
1209 jlong value
= POPL();
1210 PUSHL (value
>> shift
);
1216 jint shift
= (POPI() & 0x1f);
1217 _Jv_uint value
= (_Jv_uint
) POPI();
1218 PUSHI ((jint
) (value
>> shift
));
1224 jint shift
= (POPI() & 0x3f);
1225 _Jv_ulong value
= (_Jv_ulong
) POPL();
1226 PUSHL ((jlong
) (value
>> shift
));
1256 jint index
= GET1U ();
1257 jint amount
= GET1S ();
1258 locals
[index
].i
+= amount
;
1263 {jlong value
= POPI(); PUSHL (value
);}
1267 {jfloat value
= POPI(); PUSHF (value
);}
1271 {jdouble value
= POPI(); PUSHD (value
);}
1275 {jint value
= POPL(); PUSHI (value
);}
1279 {jfloat value
= POPL(); PUSHF (value
);}
1283 {jdouble value
= POPL(); PUSHD (value
);}
1288 using namespace java::lang
;
1289 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1296 using namespace java::lang
;
1297 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1303 { jdouble value
= POPF (); PUSHD(value
); }
1308 using namespace java::lang
;
1309 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1316 using namespace java::lang
;
1317 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1323 { jfloat value
= POPD (); PUSHF(value
); }
1327 { jbyte value
= POPI (); PUSHI(value
); }
1331 { jchar value
= POPI (); PUSHI(value
); }
1335 { jshort value
= POPI (); PUSHI(value
); }
1340 jlong value2
= POPL ();
1341 jlong value1
= POPL ();
1342 if (value1
> value2
)
1344 else if (value1
== value2
)
1360 jfloat value2
= POPF ();
1361 jfloat value1
= POPF ();
1362 if (value1
> value2
)
1364 else if (value1
== value2
)
1366 else if (value1
< value2
)
1382 jdouble value2
= POPD ();
1383 jdouble value1
= POPD ();
1384 if (value1
> value2
)
1386 else if (value1
== value2
)
1388 else if (value1
< value2
)
1451 jint value2
= POPI();
1452 jint value1
= POPI();
1453 if (value1
== value2
)
1462 jint value2
= POPI();
1463 jint value1
= POPI();
1464 if (value1
!= value2
)
1473 jint value2
= POPI();
1474 jint value1
= POPI();
1475 if (value1
< value2
)
1484 jint value2
= POPI();
1485 jint value1
= POPI();
1486 if (value1
>= value2
)
1495 jint value2
= POPI();
1496 jint value1
= POPI();
1497 if (value1
> value2
)
1506 jint value2
= POPI();
1507 jint value1
= POPI();
1508 if (value1
<= value2
)
1517 jobject value2
= POPA();
1518 jobject value1
= POPA();
1519 if (value1
== value2
)
1528 jobject value2
= POPA();
1529 jobject value1
= POPA();
1530 if (value1
!= value2
)
1538 #ifndef DIRECT_THREADED
1539 // For direct threaded, goto and goto_w are the same.
1540 pc
= pc
- 1 + get4 (pc
);
1542 #endif /* DIRECT_THREADED */
1548 #ifndef DIRECT_THREADED
1549 // For direct threaded, jsr and jsr_w are the same.
1551 pc_t next
= pc
- 1 + get4 (pc
);
1553 PUSHA ((jobject
) pc
);
1557 #endif /* DIRECT_THREADED */
1560 pc_t next
= GOTO_VAL();
1562 PUSHA ((jobject
) pc
);
1569 jint index
= GET1U ();
1570 pc
= (pc_t
) PEEKA (index
);
1576 #ifdef DIRECT_THREADED
1577 void *def
= (pc
++)->datum
;
1581 jint low
= INTVAL ();
1582 jint high
= INTVAL ();
1584 if (index
< low
|| index
> high
)
1585 pc
= (insn_slot
*) def
;
1587 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
1589 pc_t base_pc
= pc
- 1;
1590 int index
= POPI ();
1592 pc_t base
= (pc_t
) meth
->bytecode ();
1593 while ((pc
- base
) % 4 != 0)
1596 jint def
= get4 (pc
);
1597 jint low
= get4 (pc
+ 4);
1598 jint high
= get4 (pc
+ 8);
1599 if (index
< low
|| index
> high
)
1602 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
1603 #endif /* DIRECT_THREADED */
1609 #ifdef DIRECT_THREADED
1610 void *def
= (pc
++)->insn
;
1614 jint npairs
= INTVAL ();
1616 int max
= npairs
- 1;
1619 // Simple binary search...
1622 int half
= (min
+ max
) / 2;
1623 int match
= pc
[2 * half
].int_val
;
1628 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
1631 else if (index
< match
)
1632 // We can use HALF - 1 here because we check again on
1636 // We can use HALF + 1 here because we check again on
1640 if (index
== pc
[2 * min
].int_val
)
1641 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
1643 pc
= (insn_slot
*) def
;
1645 unsigned char *base_pc
= pc
-1;
1648 unsigned char* base
= meth
->bytecode ();
1649 while ((pc
-base
) % 4 != 0)
1652 jint def
= get4 (pc
);
1653 jint npairs
= get4 (pc
+4);
1658 // Simple binary search...
1661 int half
= (min
+max
)/2;
1662 int match
= get4 (pc
+ 4*(2 + 2*half
));
1666 else if (index
< match
)
1667 // We can use HALF - 1 here because we check again on
1671 // We can use HALF + 1 here because we check again on
1676 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1677 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1680 #endif /* DIRECT_THREADED */
1685 *(jobject
*) retp
= POPA ();
1689 *(jlong
*) retp
= POPL ();
1693 *(jfloat
*) retp
= POPF ();
1697 *(jdouble
*) retp
= POPD ();
1701 *(jint
*) retp
= POPI ();
1709 jint fieldref_index
= GET2U ();
1710 SAVE_PC(); // Constant pool resolution could throw.
1711 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1712 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1714 if ((field
->flags
& Modifier::STATIC
) == 0)
1715 throw_incompatible_class_change_error
1716 (JvNewStringLatin1 ("field no longer static"));
1718 jclass type
= field
->type
;
1720 // We rewrite the instruction once we discover what it refers
1722 void *newinsn
= NULL
;
1723 if (type
->isPrimitive ())
1725 switch (type
->size_in_bytes
)
1728 PUSHI (*field
->u
.byte_addr
);
1729 newinsn
= AMPAMP (getstatic_resolved_1
);
1733 if (type
== JvPrimClass (char))
1735 PUSHI (*field
->u
.char_addr
);
1736 newinsn
= AMPAMP (getstatic_resolved_char
);
1740 PUSHI (*field
->u
.short_addr
);
1741 newinsn
= AMPAMP (getstatic_resolved_short
);
1746 PUSHI(*field
->u
.int_addr
);
1747 newinsn
= AMPAMP (getstatic_resolved_4
);
1751 PUSHL(*field
->u
.long_addr
);
1752 newinsn
= AMPAMP (getstatic_resolved_8
);
1758 PUSHA(*field
->u
.object_addr
);
1759 newinsn
= AMPAMP (getstatic_resolved_obj
);
1762 #ifdef DIRECT_THREADED
1763 pc
[-2].insn
= newinsn
;
1764 pc
[-1].datum
= field
->u
.addr
;
1765 #endif /* DIRECT_THREADED */
1769 #ifdef DIRECT_THREADED
1770 getstatic_resolved_1
:
1771 PUSHI (*(jbyte
*) AVAL ());
1774 getstatic_resolved_char
:
1775 PUSHI (*(jchar
*) AVAL ());
1778 getstatic_resolved_short
:
1779 PUSHI (*(jshort
*) AVAL ());
1782 getstatic_resolved_4
:
1783 PUSHI (*(jint
*) AVAL ());
1786 getstatic_resolved_8
:
1787 PUSHL (*(jlong
*) AVAL ());
1790 getstatic_resolved_obj
:
1791 PUSHA (*(jobject
*) AVAL ());
1793 #endif /* DIRECT_THREADED */
1798 jint fieldref_index
= GET2U ();
1799 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1800 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1802 if ((field
->flags
& Modifier::STATIC
) != 0)
1803 throw_incompatible_class_change_error
1804 (JvNewStringLatin1 ("field is static"));
1806 jclass type
= field
->type
;
1807 jint field_offset
= field
->u
.boffset
;
1809 jobject obj
= POPA();
1812 void *newinsn
= NULL
;
1813 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
1814 if (type
->isPrimitive ())
1816 switch (type
->size_in_bytes
)
1819 PUSHI (val
->byte_value
);
1820 newinsn
= AMPAMP (getfield_resolved_1
);
1824 if (type
== JvPrimClass (char))
1826 PUSHI (val
->char_value
);
1827 newinsn
= AMPAMP (getfield_resolved_char
);
1831 PUSHI (val
->short_value
);
1832 newinsn
= AMPAMP (getfield_resolved_short
);
1837 PUSHI (val
->int_value
);
1838 newinsn
= AMPAMP (getfield_resolved_4
);
1842 PUSHL (val
->long_value
);
1843 newinsn
= AMPAMP (getfield_resolved_8
);
1849 PUSHA (val
->object_value
);
1850 newinsn
= AMPAMP (getfield_resolved_obj
);
1853 #ifdef DIRECT_THREADED
1854 pc
[-2].insn
= newinsn
;
1855 pc
[-1].int_val
= field_offset
;
1856 #endif /* DIRECT_THREADED */
1860 #ifdef DIRECT_THREADED
1861 getfield_resolved_1
:
1863 char *obj
= (char *) POPA ();
1865 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
1869 getfield_resolved_char
:
1871 char *obj
= (char *) POPA ();
1873 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
1877 getfield_resolved_short
:
1879 char *obj
= (char *) POPA ();
1881 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
1885 getfield_resolved_4
:
1887 char *obj
= (char *) POPA ();
1889 PUSHI (*(jint
*) (obj
+ INTVAL ()));
1893 getfield_resolved_8
:
1895 char *obj
= (char *) POPA ();
1897 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
1901 getfield_resolved_obj
:
1903 char *obj
= (char *) POPA ();
1905 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
1908 #endif /* DIRECT_THREADED */
1913 jint fieldref_index
= GET2U ();
1914 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1915 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1917 jclass type
= field
->type
;
1919 // ResolvePoolEntry cannot check this
1920 if ((field
->flags
& Modifier::STATIC
) == 0)
1921 throw_incompatible_class_change_error
1922 (JvNewStringLatin1 ("field no longer static"));
1924 void *newinsn
= NULL
;
1925 if (type
->isPrimitive ())
1927 switch (type
->size_in_bytes
)
1931 jint value
= POPI();
1932 *field
->u
.byte_addr
= value
;
1933 newinsn
= AMPAMP (putstatic_resolved_1
);
1939 jint value
= POPI();
1940 *field
->u
.char_addr
= value
;
1941 newinsn
= AMPAMP (putstatic_resolved_2
);
1947 jint value
= POPI();
1948 *field
->u
.int_addr
= value
;
1949 newinsn
= AMPAMP (putstatic_resolved_4
);
1955 jlong value
= POPL();
1956 *field
->u
.long_addr
= value
;
1957 newinsn
= AMPAMP (putstatic_resolved_8
);
1964 jobject value
= POPA();
1965 *field
->u
.object_addr
= value
;
1966 newinsn
= AMPAMP (putstatic_resolved_obj
);
1969 #ifdef DIRECT_THREADED
1970 pc
[-2].insn
= newinsn
;
1971 pc
[-1].datum
= field
->u
.addr
;
1972 #endif /* DIRECT_THREADED */
1976 #ifdef DIRECT_THREADED
1977 putstatic_resolved_1
:
1978 *(jbyte
*) AVAL () = POPI ();
1981 putstatic_resolved_2
:
1982 *(jchar
*) AVAL () = POPI ();
1985 putstatic_resolved_4
:
1986 *(jint
*) AVAL () = POPI ();
1989 putstatic_resolved_8
:
1990 *(jlong
*) AVAL () = POPL ();
1993 putstatic_resolved_obj
:
1994 *(jobject
*) AVAL () = POPA ();
1996 #endif /* DIRECT_THREADED */
2001 jint fieldref_index
= GET2U ();
2002 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
2003 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2005 jclass type
= field
->type
;
2007 if ((field
->flags
& Modifier::STATIC
) != 0)
2008 throw_incompatible_class_change_error
2009 (JvNewStringLatin1 ("field is static"));
2011 jint field_offset
= field
->u
.boffset
;
2013 void *newinsn
= NULL
;
2014 if (type
->isPrimitive ())
2016 switch (type
->size_in_bytes
)
2020 jint value
= POPI();
2021 jobject obj
= POPA();
2023 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2024 newinsn
= AMPAMP (putfield_resolved_1
);
2030 jint value
= POPI();
2031 jobject obj
= POPA();
2033 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2034 newinsn
= AMPAMP (putfield_resolved_2
);
2040 jint value
= POPI();
2041 jobject obj
= POPA();
2043 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2044 newinsn
= AMPAMP (putfield_resolved_4
);
2050 jlong value
= POPL();
2051 jobject obj
= POPA();
2053 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2054 newinsn
= AMPAMP (putfield_resolved_8
);
2061 jobject value
= POPA();
2062 jobject obj
= POPA();
2064 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2065 newinsn
= AMPAMP (putfield_resolved_obj
);
2068 #ifdef DIRECT_THREADED
2069 pc
[-2].insn
= newinsn
;
2070 pc
[-1].int_val
= field_offset
;
2071 #endif /* DIRECT_THREADED */
2075 #ifdef DIRECT_THREADED
2076 putfield_resolved_1
:
2079 char *obj
= (char *) POPA ();
2081 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2085 putfield_resolved_2
:
2088 char *obj
= (char *) POPA ();
2090 *(jchar
*) (obj
+ INTVAL ()) = val
;
2094 putfield_resolved_4
:
2097 char *obj
= (char *) POPA ();
2099 *(jint
*) (obj
+ INTVAL ()) = val
;
2103 putfield_resolved_8
:
2105 jlong val
= POPL ();
2106 char *obj
= (char *) POPA ();
2108 *(jlong
*) (obj
+ INTVAL ()) = val
;
2112 putfield_resolved_obj
:
2114 jobject val
= POPA ();
2115 char *obj
= (char *) POPA ();
2117 *(jobject
*) (obj
+ INTVAL ()) = val
;
2120 #endif /* DIRECT_THREADED */
2125 int index
= GET2U ();
2127 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2130 sp
-= rmeth
->stack_item_count
;
2132 // We don't use NULLCHECK here because we can't rely on that
2133 // working for <init>. So instead we do an explicit test.
2137 throw_null_pointer_exception ();
2140 fun
= (void (*)()) rmeth
->method
->ncode
;
2142 #ifdef DIRECT_THREADED
2143 // Rewrite instruction so that we use a faster pre-resolved
2145 pc
[-2].insn
= &&invokespecial_resolved
;
2146 pc
[-1].datum
= rmeth
;
2147 #endif /* DIRECT_THREADED */
2149 goto perform_invoke
;
2151 #ifdef DIRECT_THREADED
2152 invokespecial_resolved
:
2155 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2156 sp
-= rmeth
->stack_item_count
;
2157 // We don't use NULLCHECK here because we can't rely on that
2158 // working for <init>. So instead we do an explicit test.
2161 throw_null_pointer_exception ();
2163 fun
= (void (*)()) rmeth
->method
->ncode
;
2165 goto perform_invoke
;
2166 #endif /* DIRECT_THREADED */
2171 int index
= GET2U ();
2173 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2176 sp
-= rmeth
->stack_item_count
;
2178 fun
= (void (*)()) rmeth
->method
->ncode
;
2180 #ifdef DIRECT_THREADED
2181 // Rewrite instruction so that we use a faster pre-resolved
2183 pc
[-2].insn
= &&invokestatic_resolved
;
2184 pc
[-1].datum
= rmeth
;
2185 #endif /* DIRECT_THREADED */
2187 goto perform_invoke
;
2189 #ifdef DIRECT_THREADED
2190 invokestatic_resolved
:
2193 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2194 sp
-= rmeth
->stack_item_count
;
2195 fun
= (void (*)()) rmeth
->method
->ncode
;
2197 goto perform_invoke
;
2198 #endif /* DIRECT_THREADED */
2200 insn_invokeinterface
:
2203 int index
= GET2U ();
2205 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2208 sp
-= rmeth
->stack_item_count
;
2210 jobject rcv
= sp
[0].o
;
2215 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2216 rmeth
->method
->name
,
2217 rmeth
->method
->signature
);
2219 #ifdef DIRECT_THREADED
2220 // Rewrite instruction so that we use a faster pre-resolved
2222 pc
[-2].insn
= &&invokeinterface_resolved
;
2223 pc
[-1].datum
= rmeth
;
2225 // Skip dummy bytes.
2227 #endif /* DIRECT_THREADED */
2229 goto perform_invoke
;
2231 #ifdef DIRECT_THREADED
2232 invokeinterface_resolved
:
2235 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2236 sp
-= rmeth
->stack_item_count
;
2237 jobject rcv
= sp
[0].o
;
2240 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2241 rmeth
->method
->name
,
2242 rmeth
->method
->signature
);
2244 goto perform_invoke
;
2245 #endif /* DIRECT_THREADED */
2250 int index
= GET2U ();
2251 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2253 /* VM spec, section 3.11.5 */
2254 if ((klass
->getModifiers() & Modifier::ABSTRACT
)
2255 || klass
->isInterface())
2256 throw new java::lang::InstantiationException
;
2257 jobject res
= _Jv_AllocObject (klass
);
2260 #ifdef DIRECT_THREADED
2261 pc
[-2].insn
= &&new_resolved
;
2262 pc
[-1].datum
= klass
;
2263 #endif /* DIRECT_THREADED */
2267 #ifdef DIRECT_THREADED
2270 jclass klass
= (jclass
) AVAL ();
2271 jobject res
= _Jv_AllocObject (klass
);
2275 #endif /* DIRECT_THREADED */
2279 int atype
= GET1U ();
2281 jobject result
= _Jv_NewArray (atype
, size
);
2289 int index
= GET2U ();
2290 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2293 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2296 #ifdef DIRECT_THREADED
2297 pc
[-2].insn
= &&anewarray_resolved
;
2298 pc
[-1].datum
= klass
;
2299 #endif /* DIRECT_THREADED */
2303 #ifdef DIRECT_THREADED
2306 jclass klass
= (jclass
) AVAL ();
2308 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2312 #endif /* DIRECT_THREADED */
2316 __JArray
*arr
= (__JArray
*)POPA();
2317 NULLARRAYCHECK (arr
);
2318 PUSHI (arr
->length
);
2324 jobject value
= POPA();
2325 throw static_cast<jthrowable
>(value
);
2332 jobject value
= POPA();
2333 jint index
= GET2U ();
2334 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2337 value
= (jobject
) _Jv_CheckCast (to
, value
);
2341 #ifdef DIRECT_THREADED
2342 pc
[-2].insn
= &&checkcast_resolved
;
2344 #endif /* DIRECT_THREADED */
2348 #ifdef DIRECT_THREADED
2352 jobject value
= POPA ();
2353 jclass to
= (jclass
) AVAL ();
2354 value
= (jobject
) _Jv_CheckCast (to
, value
);
2358 #endif /* DIRECT_THREADED */
2363 jobject value
= POPA();
2364 jint index
= GET2U ();
2365 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2367 PUSHI (to
->isInstance (value
));
2369 #ifdef DIRECT_THREADED
2370 pc
[-2].insn
= &&instanceof_resolved
;
2372 #endif /* DIRECT_THREADED */
2376 #ifdef DIRECT_THREADED
2377 instanceof_resolved
:
2379 jobject value
= POPA ();
2380 jclass to
= (jclass
) AVAL ();
2381 PUSHI (to
->isInstance (value
));
2384 #endif /* DIRECT_THREADED */
2388 jobject value
= POPA();
2390 _Jv_MonitorEnter (value
);
2396 jobject value
= POPA();
2398 _Jv_MonitorExit (value
);
2404 jobject val
= POPA();
2414 jobject val
= POPA();
2422 insn_multianewarray
:
2425 int kind_index
= GET2U ();
2429 = (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2431 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2433 for (int i
= dim
- 1; i
>= 0; i
--)
2438 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2444 #ifndef DIRECT_THREADED
2447 jint the_mod_op
= get1u (pc
++);
2448 jint wide
= get2u (pc
); pc
+= 2;
2493 pc
= (unsigned char*) PEEKA (wide
);
2498 jint amount
= get2s (pc
); pc
+= 2;
2499 jint value
= PEEKI (wide
);
2500 POKEI (wide
, value
+amount
);
2505 throw_internal_error ("illegal bytecode modified by wide");
2509 #endif /* DIRECT_THREADED */
2513 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint
));
2515 // Send JVMTI notification
2516 using namespace ::java::lang
;
2517 jmethodID method
= meth
->self
;
2518 jlocation location
= meth
->insn_index (pc
- 1);
2519 Thread
*thread
= Thread::currentThread ();
2520 JNIEnv
*jni_env
= _Jv_GetCurrentJNIEnv ();
2522 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT
, thread
, jni_env
,
2525 // Continue execution
2526 using namespace gnu::gcj::jvmti
;
2528 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong
> (method
),
2530 JvAssert (bp
!= NULL
);
2532 pc_t opc
= reinterpret_cast<pc_t
> (bp
->getInsn ());
2534 #ifdef DIRECT_THREADED
2537 goto *(insn_target
[*opc
]);
2541 catch (java::lang::Throwable
*ex
)
2543 #ifdef DIRECT_THREADED
2544 void *logical_pc
= (void *) ((insn_slot
*) pc
- 1);
2546 int logical_pc
= pc
- 1 - meth
->bytecode ();
2548 _Jv_InterpException
*exc
= meth
->exceptions ();
2549 jclass exc_class
= ex
->getClass ();
2551 for (int i
= 0; i
< meth
->exc_count
; i
++)
2553 if (PCVAL (exc
[i
].start_pc
) <= logical_pc
2554 && logical_pc
< PCVAL (exc
[i
].end_pc
))
2556 #ifdef DIRECT_THREADED
2557 jclass handler
= (jclass
) exc
[i
].handler_type
.p
;
2559 jclass handler
= NULL
;
2560 if (exc
[i
].handler_type
.i
!= 0)
2561 handler
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2562 exc
[i
].handler_type
.i
)).clazz
;
2563 #endif /* DIRECT_THREADED */
2565 if (handler
== NULL
|| handler
->isAssignableFrom (exc_class
))
2568 #ifdef DIRECT_THREADED
2569 pc
= (insn_slot
*) exc
[i
].handler_pc
.p
;
2571 pc
= meth
->bytecode () + exc
[i
].handler_pc
.i
;
2572 #endif /* DIRECT_THREADED */
2574 sp
++->o
= ex
; // Push exception.
2580 // No handler, so re-throw.