1 // interpret-run.cc - Code to interpret bytecode
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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
251 #define NEXT_INSN goto *((pc++)->insn)
252 #define INTVAL() ((pc++)->int_val)
253 #define AVAL() ((pc++)->datum)
255 #define GET1S() INTVAL ()
256 #define GET2S() INTVAL ()
257 #define GET1U() INTVAL ()
258 #define GET2U() INTVAL ()
259 #define AVAL1U() AVAL ()
260 #define AVAL2U() AVAL ()
261 #define AVAL2UP() AVAL ()
262 #define SKIP_GOTO ++pc
263 #define GOTO_VAL() (insn_slot *) pc->datum
264 #define PCVAL(unionval) unionval.p
265 #define AMPAMP(label) &&label
267 // Compile if we must. NOTE: Double-check locking.
268 if (meth
->prepared
== NULL
)
270 _Jv_MutexLock (&compile_mutex
);
271 if (meth
->prepared
== NULL
)
272 meth
->compile (insn_target
);
273 _Jv_MutexUnlock (&compile_mutex
);
276 // If we're only compiling, stop here
280 pc
= (insn_slot
*) meth
->prepared
;
284 #define NEXT_INSN goto *(insn_target[*pc++])
286 #define GET1S() get1s (pc++)
287 #define GET2S() (pc += 2, get2s (pc- 2))
288 #define GET1U() get1u (pc++)
289 #define GET2U() (pc += 2, get2u (pc - 2))
290 // Note that these could be more efficient when not handling 'ldc
293 ({ int index = get1u (pc++); \
294 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
296 ({ int index = get2u (pc); pc += 2; \
297 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
298 // Note that we don't need to resolve the pool entry here as class
299 // constants are never wide.
300 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
301 #define SKIP_GOTO pc += 2
302 #define GOTO_VAL() pc - 1 + get2s (pc)
303 #define PCVAL(unionval) unionval.i
304 #define AMPAMP(label) NULL
306 pc
= meth
->bytecode ();
308 #endif /* DIRECT_THREADED */
310 #define TAKE_GOTO pc = GOTO_VAL ()
312 /* Go straight at it! the ffi raw format matches the internal
313 stack representation exactly. At least, that's the idea.
315 memcpy ((void*) locals
, (void*) args
, meth
->args_raw_size
);
317 _Jv_word
*pool_data
= meth
->defining_class
->constants
.data
;
319 /* These three are temporaries for common code used by several
322 _Jv_ResolvedMethod
* rmeth
;
327 // We keep nop around. It is used if we're interpreting the
328 // bytecodes and not doing direct threading.
332 /* The first few instructions here are ordered according to their
333 frequency, in the hope that this will improve code locality a
336 insn_aload_0
: // 0x2a
344 insn_iload_1
: // 0x1b
348 insn_invokevirtual
: // 0xb6
351 int index
= GET2U ();
353 /* _Jv_Linker::resolve_pool_entry returns immediately if the
354 * value already is resolved. If we want to clutter up the
355 * code here to gain a little performance, then we can check
356 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
357 * directly. For now, I don't think it is worth it. */
359 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
362 sp
-= rmeth
->stack_item_count
;
364 if (rmeth
->method
->accflags
& Modifier::FINAL
)
366 // We can't rely on NULLCHECK working if the method is final.
368 throw_null_pointer_exception ();
370 // Final methods might not appear in the vtable.
371 fun
= (void (*)()) rmeth
->method
->ncode
;
376 jobject rcv
= sp
[0].o
;
377 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
378 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
381 #ifdef DIRECT_THREADED
382 // Rewrite instruction so that we use a faster pre-resolved
384 pc
[-2].insn
= &&invokevirtual_resolved
;
385 pc
[-1].datum
= rmeth
;
386 #endif /* DIRECT_THREADED */
390 #ifdef DIRECT_THREADED
391 invokevirtual_resolved
:
394 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
395 sp
-= rmeth
->stack_item_count
;
397 if (rmeth
->method
->accflags
& Modifier::FINAL
)
399 // We can't rely on NULLCHECK working if the method is final.
401 throw_null_pointer_exception ();
403 // Final methods might not appear in the vtable.
404 fun
= (void (*)()) rmeth
->method
->ncode
;
408 jobject rcv
= sp
[0].o
;
409 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
410 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
414 #endif /* DIRECT_THREADED */
418 /* here goes the magic again... */
419 ffi_cif
*cif
= &rmeth
->cif
;
420 ffi_raw
*raw
= (ffi_raw
*) sp
;
424 #if FFI_NATIVE_RAW_API
425 /* We assume that this is only implemented if it's correct */
426 /* to use it here. On a 64 bit machine, it never is. */
427 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
429 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
432 int rtype
= cif
->rtype
->type
;
434 /* the likelyhood of object, int, or void return is very high,
435 * so those are checked before the switch */
436 if (rtype
== FFI_TYPE_POINTER
)
438 PUSHA (rvalue
.object_value
);
440 else if (rtype
== FFI_TYPE_SINT32
)
442 PUSHI (rvalue
.int_value
);
444 else if (rtype
== FFI_TYPE_VOID
)
453 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
456 case FFI_TYPE_SINT16
:
457 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
460 case FFI_TYPE_UINT16
:
461 PUSHI (rvalue
.int_value
& 0xffff);
465 PUSHF (rvalue
.float_value
);
468 case FFI_TYPE_DOUBLE
:
469 PUSHD (rvalue
.double_value
);
472 case FFI_TYPE_SINT64
:
473 PUSHL (rvalue
.long_value
);
477 throw_internal_error ("unknown return type in invokeXXX");
544 // For direct threaded, bipush and sipush are the same.
545 #ifndef DIRECT_THREADED
548 #endif /* DIRECT_THREADED */
554 // For direct threaded, ldc and ldc_w are the same.
555 #ifndef DIRECT_THREADED
556 PUSHA ((jobject
) AVAL1U ());
558 #endif /* DIRECT_THREADED */
560 PUSHA ((jobject
) AVAL2U ());
563 #ifdef DIRECT_THREADED
564 // For direct threaded we have a separate 'ldc class' operation.
568 // We could rewrite the instruction at this point.
569 int index
= INTVAL ();
570 jobject k
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
575 #endif /* DIRECT_THREADED */
579 void *where
= AVAL2UP ();
580 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
676 jintArray arr
= (jintArray
) POPA();
677 NULLARRAYCHECK (arr
);
678 ARRAYBOUNDSCHECK (arr
, index
);
679 PUSHI( elements(arr
)[index
] );
686 jlongArray arr
= (jlongArray
) POPA();
687 NULLARRAYCHECK (arr
);
688 ARRAYBOUNDSCHECK (arr
, index
);
689 PUSHL( elements(arr
)[index
] );
696 jfloatArray arr
= (jfloatArray
) POPA();
697 NULLARRAYCHECK (arr
);
698 ARRAYBOUNDSCHECK (arr
, index
);
699 PUSHF( elements(arr
)[index
] );
706 jdoubleArray arr
= (jdoubleArray
) POPA();
707 NULLARRAYCHECK (arr
);
708 ARRAYBOUNDSCHECK (arr
, index
);
709 PUSHD( elements(arr
)[index
] );
716 jobjectArray arr
= (jobjectArray
) POPA();
717 NULLARRAYCHECK (arr
);
718 ARRAYBOUNDSCHECK (arr
, index
);
719 PUSHA( elements(arr
)[index
] );
726 jbyteArray arr
= (jbyteArray
) POPA();
727 NULLARRAYCHECK (arr
);
728 ARRAYBOUNDSCHECK (arr
, index
);
729 PUSHI( elements(arr
)[index
] );
736 jcharArray arr
= (jcharArray
) POPA();
737 NULLARRAYCHECK (arr
);
738 ARRAYBOUNDSCHECK (arr
, index
);
739 PUSHI( elements(arr
)[index
] );
746 jshortArray arr
= (jshortArray
) POPA();
747 NULLARRAYCHECK (arr
);
748 ARRAYBOUNDSCHECK (arr
, index
);
749 PUSHI( elements(arr
)[index
] );
857 jintArray arr
= (jintArray
) POPA();
858 NULLARRAYCHECK (arr
);
859 ARRAYBOUNDSCHECK (arr
, index
);
860 elements(arr
)[index
] = value
;
866 jlong value
= POPL();
868 jlongArray arr
= (jlongArray
) POPA();
869 NULLARRAYCHECK (arr
);
870 ARRAYBOUNDSCHECK (arr
, index
);
871 elements(arr
)[index
] = value
;
877 jfloat value
= POPF();
879 jfloatArray arr
= (jfloatArray
) POPA();
880 NULLARRAYCHECK (arr
);
881 ARRAYBOUNDSCHECK (arr
, index
);
882 elements(arr
)[index
] = value
;
888 jdouble value
= POPD();
890 jdoubleArray arr
= (jdoubleArray
) POPA();
891 NULLARRAYCHECK (arr
);
892 ARRAYBOUNDSCHECK (arr
, index
);
893 elements(arr
)[index
] = value
;
899 jobject value
= POPA();
901 jobjectArray arr
= (jobjectArray
) POPA();
902 NULLARRAYCHECK (arr
);
903 ARRAYBOUNDSCHECK (arr
, index
);
904 _Jv_CheckArrayStore (arr
, value
);
905 elements(arr
)[index
] = value
;
911 jbyte value
= (jbyte
) POPI();
913 jbyteArray arr
= (jbyteArray
) POPA();
914 NULLARRAYCHECK (arr
);
915 ARRAYBOUNDSCHECK (arr
, index
);
916 elements(arr
)[index
] = value
;
922 jchar value
= (jchar
) POPI();
924 jcharArray arr
= (jcharArray
) POPA();
925 NULLARRAYCHECK (arr
);
926 ARRAYBOUNDSCHECK (arr
, index
);
927 elements(arr
)[index
] = value
;
933 jshort value
= (jshort
) POPI();
935 jshortArray arr
= (jshortArray
) POPA();
936 NULLARRAYCHECK (arr
);
937 ARRAYBOUNDSCHECK (arr
, index
);
938 elements(arr
)[index
] = value
;
956 dupx (sp
, 1, 1); sp
+=1;
960 dupx (sp
, 1, 2); sp
+=1;
970 dupx (sp
, 2, 1); sp
+=2;
974 dupx (sp
, 2, 2); sp
+=2;
979 jobject tmp1
= POPA();
980 jobject tmp2
= POPA();
1037 jint value2
= POPI();
1038 jint value1
= POPI();
1039 jint res
= _Jv_divI (value1
, value2
);
1047 jlong value2
= POPL();
1048 jlong value1
= POPL();
1049 jlong res
= _Jv_divJ (value1
, value2
);
1056 jfloat value2
= POPF();
1057 jfloat value1
= POPF();
1058 jfloat res
= value1
/ value2
;
1065 jdouble value2
= POPD();
1066 jdouble value1
= POPD();
1067 jdouble res
= value1
/ value2
;
1075 jint value2
= POPI();
1076 jint value1
= POPI();
1077 jint res
= _Jv_remI (value1
, value2
);
1085 jlong value2
= POPL();
1086 jlong value1
= POPL();
1087 jlong res
= _Jv_remJ (value1
, value2
);
1094 jfloat value2
= POPF();
1095 jfloat value1
= POPF();
1096 jfloat res
= __ieee754_fmod (value1
, value2
);
1103 jdouble value2
= POPD();
1104 jdouble value1
= POPD();
1105 jdouble res
= __ieee754_fmod (value1
, value2
);
1112 jint value
= POPI();
1119 jlong value
= POPL();
1126 jfloat value
= POPF();
1133 jdouble value
= POPD();
1140 jint shift
= (POPI() & 0x1f);
1141 jint value
= POPI();
1142 PUSHI (value
<< shift
);
1148 jint shift
= (POPI() & 0x3f);
1149 jlong value
= POPL();
1150 PUSHL (value
<< shift
);
1156 jint shift
= (POPI() & 0x1f);
1157 jint value
= POPI();
1158 PUSHI (value
>> shift
);
1164 jint shift
= (POPI() & 0x3f);
1165 jlong value
= POPL();
1166 PUSHL (value
>> shift
);
1172 jint shift
= (POPI() & 0x1f);
1173 _Jv_uint value
= (_Jv_uint
) POPI();
1174 PUSHI ((jint
) (value
>> shift
));
1180 jint shift
= (POPI() & 0x3f);
1181 _Jv_ulong value
= (_Jv_ulong
) POPL();
1182 PUSHL ((jlong
) (value
>> shift
));
1212 jint index
= GET1U ();
1213 jint amount
= GET1S ();
1214 locals
[index
].i
+= amount
;
1219 {jlong value
= POPI(); PUSHL (value
);}
1223 {jfloat value
= POPI(); PUSHF (value
);}
1227 {jdouble value
= POPI(); PUSHD (value
);}
1231 {jint value
= POPL(); PUSHI (value
);}
1235 {jfloat value
= POPL(); PUSHF (value
);}
1239 {jdouble value
= POPL(); PUSHD (value
);}
1244 using namespace java::lang
;
1245 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1252 using namespace java::lang
;
1253 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1259 { jdouble value
= POPF (); PUSHD(value
); }
1264 using namespace java::lang
;
1265 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1272 using namespace java::lang
;
1273 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1279 { jfloat value
= POPD (); PUSHF(value
); }
1283 { jbyte value
= POPI (); PUSHI(value
); }
1287 { jchar value
= POPI (); PUSHI(value
); }
1291 { jshort value
= POPI (); PUSHI(value
); }
1296 jlong value2
= POPL ();
1297 jlong value1
= POPL ();
1298 if (value1
> value2
)
1300 else if (value1
== value2
)
1316 jfloat value2
= POPF ();
1317 jfloat value1
= POPF ();
1318 if (value1
> value2
)
1320 else if (value1
== value2
)
1322 else if (value1
< value2
)
1338 jdouble value2
= POPD ();
1339 jdouble value1
= POPD ();
1340 if (value1
> value2
)
1342 else if (value1
== value2
)
1344 else if (value1
< value2
)
1407 jint value2
= POPI();
1408 jint value1
= POPI();
1409 if (value1
== value2
)
1418 jint value2
= POPI();
1419 jint value1
= POPI();
1420 if (value1
!= value2
)
1429 jint value2
= POPI();
1430 jint value1
= POPI();
1431 if (value1
< value2
)
1440 jint value2
= POPI();
1441 jint value1
= POPI();
1442 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 jobject value2
= POPA();
1474 jobject value1
= POPA();
1475 if (value1
== value2
)
1484 jobject value2
= POPA();
1485 jobject value1
= POPA();
1486 if (value1
!= value2
)
1494 #ifndef DIRECT_THREADED
1495 // For direct threaded, goto and goto_w are the same.
1496 pc
= pc
- 1 + get4 (pc
);
1498 #endif /* DIRECT_THREADED */
1504 #ifndef DIRECT_THREADED
1505 // For direct threaded, jsr and jsr_w are the same.
1507 pc_t next
= pc
- 1 + get4 (pc
);
1509 PUSHA ((jobject
) pc
);
1513 #endif /* DIRECT_THREADED */
1516 pc_t next
= GOTO_VAL();
1518 PUSHA ((jobject
) pc
);
1525 jint index
= GET1U ();
1526 pc
= (pc_t
) PEEKA (index
);
1532 #ifdef DIRECT_THREADED
1533 void *def
= (pc
++)->datum
;
1537 jint low
= INTVAL ();
1538 jint high
= INTVAL ();
1540 if (index
< low
|| index
> high
)
1541 pc
= (insn_slot
*) def
;
1543 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
1545 pc_t base_pc
= pc
- 1;
1546 int index
= POPI ();
1548 pc_t base
= (pc_t
) meth
->bytecode ();
1549 while ((pc
- base
) % 4 != 0)
1552 jint def
= get4 (pc
);
1553 jint low
= get4 (pc
+ 4);
1554 jint high
= get4 (pc
+ 8);
1555 if (index
< low
|| index
> high
)
1558 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
1559 #endif /* DIRECT_THREADED */
1565 #ifdef DIRECT_THREADED
1566 void *def
= (pc
++)->insn
;
1570 jint npairs
= INTVAL ();
1572 int max
= npairs
- 1;
1575 // Simple binary search...
1578 int half
= (min
+ max
) / 2;
1579 int match
= pc
[2 * half
].int_val
;
1584 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
1587 else if (index
< match
)
1588 // We can use HALF - 1 here because we check again on
1592 // We can use HALF + 1 here because we check again on
1596 if (index
== pc
[2 * min
].int_val
)
1597 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
1599 pc
= (insn_slot
*) def
;
1601 unsigned char *base_pc
= pc
-1;
1604 unsigned char* base
= meth
->bytecode ();
1605 while ((pc
-base
) % 4 != 0)
1608 jint def
= get4 (pc
);
1609 jint npairs
= get4 (pc
+4);
1614 // Simple binary search...
1617 int half
= (min
+max
)/2;
1618 int match
= get4 (pc
+ 4*(2 + 2*half
));
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
1632 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1633 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1636 #endif /* DIRECT_THREADED */
1641 *(jobject
*) retp
= POPA ();
1645 *(jlong
*) retp
= POPL ();
1649 *(jfloat
*) retp
= POPF ();
1653 *(jdouble
*) retp
= POPD ();
1657 *(jint
*) retp
= POPI ();
1665 jint fieldref_index
= GET2U ();
1666 SAVE_PC(); // Constant pool resolution could throw.
1667 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1668 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1670 if ((field
->flags
& Modifier::STATIC
) == 0)
1671 throw_incompatible_class_change_error
1672 (JvNewStringLatin1 ("field no longer static"));
1674 jclass type
= field
->type
;
1676 // We rewrite the instruction once we discover what it refers
1678 void *newinsn
= NULL
;
1679 if (type
->isPrimitive ())
1681 switch (type
->size_in_bytes
)
1684 PUSHI (*field
->u
.byte_addr
);
1685 newinsn
= AMPAMP (getstatic_resolved_1
);
1689 if (type
== JvPrimClass (char))
1691 PUSHI (*field
->u
.char_addr
);
1692 newinsn
= AMPAMP (getstatic_resolved_char
);
1696 PUSHI (*field
->u
.short_addr
);
1697 newinsn
= AMPAMP (getstatic_resolved_short
);
1702 PUSHI(*field
->u
.int_addr
);
1703 newinsn
= AMPAMP (getstatic_resolved_4
);
1707 PUSHL(*field
->u
.long_addr
);
1708 newinsn
= AMPAMP (getstatic_resolved_8
);
1714 PUSHA(*field
->u
.object_addr
);
1715 newinsn
= AMPAMP (getstatic_resolved_obj
);
1718 #ifdef DIRECT_THREADED
1719 pc
[-2].insn
= newinsn
;
1720 pc
[-1].datum
= field
->u
.addr
;
1721 #endif /* DIRECT_THREADED */
1725 #ifdef DIRECT_THREADED
1726 getstatic_resolved_1
:
1727 PUSHI (*(jbyte
*) AVAL ());
1730 getstatic_resolved_char
:
1731 PUSHI (*(jchar
*) AVAL ());
1734 getstatic_resolved_short
:
1735 PUSHI (*(jshort
*) AVAL ());
1738 getstatic_resolved_4
:
1739 PUSHI (*(jint
*) AVAL ());
1742 getstatic_resolved_8
:
1743 PUSHL (*(jlong
*) AVAL ());
1746 getstatic_resolved_obj
:
1747 PUSHA (*(jobject
*) AVAL ());
1749 #endif /* DIRECT_THREADED */
1754 jint fieldref_index
= GET2U ();
1755 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1756 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1758 if ((field
->flags
& Modifier::STATIC
) != 0)
1759 throw_incompatible_class_change_error
1760 (JvNewStringLatin1 ("field is static"));
1762 jclass type
= field
->type
;
1763 jint field_offset
= field
->u
.boffset
;
1765 jobject obj
= POPA();
1768 void *newinsn
= NULL
;
1769 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
1770 if (type
->isPrimitive ())
1772 switch (type
->size_in_bytes
)
1775 PUSHI (val
->byte_value
);
1776 newinsn
= AMPAMP (getfield_resolved_1
);
1780 if (type
== JvPrimClass (char))
1782 PUSHI (val
->char_value
);
1783 newinsn
= AMPAMP (getfield_resolved_char
);
1787 PUSHI (val
->short_value
);
1788 newinsn
= AMPAMP (getfield_resolved_short
);
1793 PUSHI (val
->int_value
);
1794 newinsn
= AMPAMP (getfield_resolved_4
);
1798 PUSHL (val
->long_value
);
1799 newinsn
= AMPAMP (getfield_resolved_8
);
1805 PUSHA (val
->object_value
);
1806 newinsn
= AMPAMP (getfield_resolved_obj
);
1809 #ifdef DIRECT_THREADED
1810 pc
[-2].insn
= newinsn
;
1811 pc
[-1].int_val
= field_offset
;
1812 #endif /* DIRECT_THREADED */
1816 #ifdef DIRECT_THREADED
1817 getfield_resolved_1
:
1819 char *obj
= (char *) POPA ();
1821 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
1825 getfield_resolved_char
:
1827 char *obj
= (char *) POPA ();
1829 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
1833 getfield_resolved_short
:
1835 char *obj
= (char *) POPA ();
1837 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
1841 getfield_resolved_4
:
1843 char *obj
= (char *) POPA ();
1845 PUSHI (*(jint
*) (obj
+ INTVAL ()));
1849 getfield_resolved_8
:
1851 char *obj
= (char *) POPA ();
1853 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
1857 getfield_resolved_obj
:
1859 char *obj
= (char *) POPA ();
1861 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
1864 #endif /* DIRECT_THREADED */
1869 jint fieldref_index
= GET2U ();
1870 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1871 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1873 jclass type
= field
->type
;
1875 // ResolvePoolEntry cannot check this
1876 if ((field
->flags
& Modifier::STATIC
) == 0)
1877 throw_incompatible_class_change_error
1878 (JvNewStringLatin1 ("field no longer static"));
1880 void *newinsn
= NULL
;
1881 if (type
->isPrimitive ())
1883 switch (type
->size_in_bytes
)
1887 jint value
= POPI();
1888 *field
->u
.byte_addr
= value
;
1889 newinsn
= AMPAMP (putstatic_resolved_1
);
1895 jint value
= POPI();
1896 *field
->u
.char_addr
= value
;
1897 newinsn
= AMPAMP (putstatic_resolved_2
);
1903 jint value
= POPI();
1904 *field
->u
.int_addr
= value
;
1905 newinsn
= AMPAMP (putstatic_resolved_4
);
1911 jlong value
= POPL();
1912 *field
->u
.long_addr
= value
;
1913 newinsn
= AMPAMP (putstatic_resolved_8
);
1920 jobject value
= POPA();
1921 *field
->u
.object_addr
= value
;
1922 newinsn
= AMPAMP (putstatic_resolved_obj
);
1925 #ifdef DIRECT_THREADED
1926 pc
[-2].insn
= newinsn
;
1927 pc
[-1].datum
= field
->u
.addr
;
1928 #endif /* DIRECT_THREADED */
1932 #ifdef DIRECT_THREADED
1933 putstatic_resolved_1
:
1934 *(jbyte
*) AVAL () = POPI ();
1937 putstatic_resolved_2
:
1938 *(jchar
*) AVAL () = POPI ();
1941 putstatic_resolved_4
:
1942 *(jint
*) AVAL () = POPI ();
1945 putstatic_resolved_8
:
1946 *(jlong
*) AVAL () = POPL ();
1949 putstatic_resolved_obj
:
1950 *(jobject
*) AVAL () = POPA ();
1952 #endif /* DIRECT_THREADED */
1957 jint fieldref_index
= GET2U ();
1958 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1959 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1961 jclass type
= field
->type
;
1963 if ((field
->flags
& Modifier::STATIC
) != 0)
1964 throw_incompatible_class_change_error
1965 (JvNewStringLatin1 ("field is static"));
1967 jint field_offset
= field
->u
.boffset
;
1969 void *newinsn
= NULL
;
1970 if (type
->isPrimitive ())
1972 switch (type
->size_in_bytes
)
1976 jint value
= POPI();
1977 jobject obj
= POPA();
1979 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
1980 newinsn
= AMPAMP (putfield_resolved_1
);
1986 jint value
= POPI();
1987 jobject obj
= POPA();
1989 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
1990 newinsn
= AMPAMP (putfield_resolved_2
);
1996 jint value
= POPI();
1997 jobject obj
= POPA();
1999 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2000 newinsn
= AMPAMP (putfield_resolved_4
);
2006 jlong value
= POPL();
2007 jobject obj
= POPA();
2009 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2010 newinsn
= AMPAMP (putfield_resolved_8
);
2017 jobject value
= POPA();
2018 jobject obj
= POPA();
2020 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2021 newinsn
= AMPAMP (putfield_resolved_obj
);
2024 #ifdef DIRECT_THREADED
2025 pc
[-2].insn
= newinsn
;
2026 pc
[-1].int_val
= field_offset
;
2027 #endif /* DIRECT_THREADED */
2031 #ifdef DIRECT_THREADED
2032 putfield_resolved_1
:
2035 char *obj
= (char *) POPA ();
2037 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2041 putfield_resolved_2
:
2044 char *obj
= (char *) POPA ();
2046 *(jchar
*) (obj
+ INTVAL ()) = val
;
2050 putfield_resolved_4
:
2053 char *obj
= (char *) POPA ();
2055 *(jint
*) (obj
+ INTVAL ()) = val
;
2059 putfield_resolved_8
:
2061 jlong val
= POPL ();
2062 char *obj
= (char *) POPA ();
2064 *(jlong
*) (obj
+ INTVAL ()) = val
;
2068 putfield_resolved_obj
:
2070 jobject val
= POPA ();
2071 char *obj
= (char *) POPA ();
2073 *(jobject
*) (obj
+ INTVAL ()) = val
;
2076 #endif /* DIRECT_THREADED */
2081 int index
= GET2U ();
2083 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2086 sp
-= rmeth
->stack_item_count
;
2088 // We don't use NULLCHECK here because we can't rely on that
2089 // working for <init>. So instead we do an explicit test.
2093 throw_null_pointer_exception ();
2096 fun
= (void (*)()) rmeth
->method
->ncode
;
2098 #ifdef DIRECT_THREADED
2099 // Rewrite instruction so that we use a faster pre-resolved
2101 pc
[-2].insn
= &&invokespecial_resolved
;
2102 pc
[-1].datum
= rmeth
;
2103 #endif /* DIRECT_THREADED */
2105 goto perform_invoke
;
2107 #ifdef DIRECT_THREADED
2108 invokespecial_resolved
:
2111 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2112 sp
-= rmeth
->stack_item_count
;
2113 // We don't use NULLCHECK here because we can't rely on that
2114 // working for <init>. So instead we do an explicit test.
2117 throw_null_pointer_exception ();
2119 fun
= (void (*)()) rmeth
->method
->ncode
;
2121 goto perform_invoke
;
2122 #endif /* DIRECT_THREADED */
2127 int index
= GET2U ();
2129 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2132 sp
-= rmeth
->stack_item_count
;
2134 fun
= (void (*)()) rmeth
->method
->ncode
;
2136 #ifdef DIRECT_THREADED
2137 // Rewrite instruction so that we use a faster pre-resolved
2139 pc
[-2].insn
= &&invokestatic_resolved
;
2140 pc
[-1].datum
= rmeth
;
2141 #endif /* DIRECT_THREADED */
2143 goto perform_invoke
;
2145 #ifdef DIRECT_THREADED
2146 invokestatic_resolved
:
2149 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2150 sp
-= rmeth
->stack_item_count
;
2151 fun
= (void (*)()) rmeth
->method
->ncode
;
2153 goto perform_invoke
;
2154 #endif /* DIRECT_THREADED */
2156 insn_invokeinterface
:
2159 int index
= GET2U ();
2161 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2164 sp
-= rmeth
->stack_item_count
;
2166 jobject rcv
= sp
[0].o
;
2171 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2172 rmeth
->method
->name
,
2173 rmeth
->method
->signature
);
2175 #ifdef DIRECT_THREADED
2176 // Rewrite instruction so that we use a faster pre-resolved
2178 pc
[-2].insn
= &&invokeinterface_resolved
;
2179 pc
[-1].datum
= rmeth
;
2181 // Skip dummy bytes.
2183 #endif /* DIRECT_THREADED */
2185 goto perform_invoke
;
2187 #ifdef DIRECT_THREADED
2188 invokeinterface_resolved
:
2191 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2192 sp
-= rmeth
->stack_item_count
;
2193 jobject rcv
= sp
[0].o
;
2196 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2197 rmeth
->method
->name
,
2198 rmeth
->method
->signature
);
2200 goto perform_invoke
;
2201 #endif /* DIRECT_THREADED */
2206 int index
= GET2U ();
2207 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2209 /* VM spec, section 3.11.5 */
2210 if ((klass
->getModifiers() & Modifier::ABSTRACT
)
2211 || klass
->isInterface())
2212 throw new java::lang::InstantiationException
;
2213 jobject res
= _Jv_AllocObject (klass
);
2216 #ifdef DIRECT_THREADED
2217 pc
[-2].insn
= &&new_resolved
;
2218 pc
[-1].datum
= klass
;
2219 #endif /* DIRECT_THREADED */
2223 #ifdef DIRECT_THREADED
2226 jclass klass
= (jclass
) AVAL ();
2227 jobject res
= _Jv_AllocObject (klass
);
2231 #endif /* DIRECT_THREADED */
2235 int atype
= GET1U ();
2237 jobject result
= _Jv_NewArray (atype
, size
);
2245 int index
= GET2U ();
2246 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2249 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2252 #ifdef DIRECT_THREADED
2253 pc
[-2].insn
= &&anewarray_resolved
;
2254 pc
[-1].datum
= klass
;
2255 #endif /* DIRECT_THREADED */
2259 #ifdef DIRECT_THREADED
2262 jclass klass
= (jclass
) AVAL ();
2264 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2268 #endif /* DIRECT_THREADED */
2272 __JArray
*arr
= (__JArray
*)POPA();
2273 NULLARRAYCHECK (arr
);
2274 PUSHI (arr
->length
);
2280 jobject value
= POPA();
2281 throw static_cast<jthrowable
>(value
);
2288 jobject value
= POPA();
2289 jint index
= GET2U ();
2290 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2293 value
= (jobject
) _Jv_CheckCast (to
, value
);
2297 #ifdef DIRECT_THREADED
2298 pc
[-2].insn
= &&checkcast_resolved
;
2300 #endif /* DIRECT_THREADED */
2304 #ifdef DIRECT_THREADED
2308 jobject value
= POPA ();
2309 jclass to
= (jclass
) AVAL ();
2310 value
= (jobject
) _Jv_CheckCast (to
, value
);
2314 #endif /* DIRECT_THREADED */
2319 jobject value
= POPA();
2320 jint index
= GET2U ();
2321 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2323 PUSHI (to
->isInstance (value
));
2325 #ifdef DIRECT_THREADED
2326 pc
[-2].insn
= &&instanceof_resolved
;
2328 #endif /* DIRECT_THREADED */
2332 #ifdef DIRECT_THREADED
2333 instanceof_resolved
:
2335 jobject value
= POPA ();
2336 jclass to
= (jclass
) AVAL ();
2337 PUSHI (to
->isInstance (value
));
2340 #endif /* DIRECT_THREADED */
2344 jobject value
= POPA();
2346 _Jv_MonitorEnter (value
);
2352 jobject value
= POPA();
2354 _Jv_MonitorExit (value
);
2360 jobject val
= POPA();
2370 jobject val
= POPA();
2378 insn_multianewarray
:
2381 int kind_index
= GET2U ();
2385 = (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2387 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2389 for (int i
= dim
- 1; i
>= 0; i
--)
2394 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2400 #ifndef DIRECT_THREADED
2403 jint the_mod_op
= get1u (pc
++);
2404 jint wide
= get2u (pc
); pc
+= 2;
2449 pc
= (unsigned char*) PEEKA (wide
);
2454 jint amount
= get2s (pc
); pc
+= 2;
2455 jint value
= PEEKI (wide
);
2456 POKEI (wide
, value
+amount
);
2461 throw_internal_error ("illegal bytecode modified by wide");
2465 #endif /* DIRECT_THREADED */
2472 catch (java::lang::Throwable
*ex
)
2474 #ifdef DIRECT_THREADED
2475 void *logical_pc
= (void *) ((insn_slot
*) pc
- 1);
2477 int logical_pc
= pc
- 1 - meth
->bytecode ();
2479 _Jv_InterpException
*exc
= meth
->exceptions ();
2480 jclass exc_class
= ex
->getClass ();
2482 for (int i
= 0; i
< meth
->exc_count
; i
++)
2484 if (PCVAL (exc
[i
].start_pc
) <= logical_pc
2485 && logical_pc
< PCVAL (exc
[i
].end_pc
))
2487 #ifdef DIRECT_THREADED
2488 jclass handler
= (jclass
) exc
[i
].handler_type
.p
;
2490 jclass handler
= NULL
;
2491 if (exc
[i
].handler_type
.i
!= 0)
2492 handler
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2493 exc
[i
].handler_type
.i
)).clazz
;
2494 #endif /* DIRECT_THREADED */
2496 if (handler
== NULL
|| handler
->isAssignableFrom (exc_class
))
2499 #ifdef DIRECT_THREADED
2500 pc
= (insn_slot
*) exc
[i
].handler_pc
.p
;
2502 pc
= meth
->bytecode () + exc
[i
].handler_pc
.i
;
2503 #endif /* DIRECT_THREADED */
2505 sp
++->o
= ex
; // Push exception.
2511 // No handler, so re-throw.