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
];
31 // This is the information needed to get and set local variables with
32 // proper type checking.
33 frame_desc
.locals
= locals
;
34 char locals_type
[meth
->max_locals
];
35 frame_desc
.locals_type
= locals_type
;
37 // Set all slots as invalid until they are written to.
38 memset (locals_type
, 'x', meth
->max_locals
);
40 // We need to set the local variable types for the method arguments since
41 // they are valid at invocation.
43 _Jv_Method
*method
= meth
->get_method ();
46 // If the method is non-static, we need to set the type for the "this" pointer.
47 if ((method
->accflags
& java::lang::reflect::Modifier::STATIC
) == 0)
51 // Set the "this" pointer for this frame.
52 _Jv_word
*this_ptr
= reinterpret_cast<_Jv_word
*> (args
);
53 frame_desc
.obj_ptr
= this_ptr
[0].o
;
56 frame_desc
.locals_type
[0] = 'o';
60 // Now parse the method signature to set the types of the other arguments.
61 int sig_len
= method
->signature
->len ();
62 char *signature
= method
->signature
->chars ();
63 for (int i
= 1; signature
[i
] != ')' && i
<= sig_len
; i
++)
65 if (signature
[i
] == 'Z' || signature
[i
] == 'B' || signature
[i
] == 'C'
66 || signature
[i
] == 'S' || signature
[i
] == 'I')
68 frame_desc
.locals_type
[type_ctr
] = 'i';
72 else if (signature
[i
] == 'F')
74 frame_desc
.locals_type
[type_ctr
] = 'f';
78 else if (signature
[i
] == 'J')
80 frame_desc
.locals_type
[type_ctr
] = 'l';
81 frame_desc
.locals_type
[type_ctr
+1] = 'x';
85 else if (signature
[i
] == 'D')
87 frame_desc
.locals_type
[type_ctr
] = 'd';
88 frame_desc
.locals_type
[type_ctr
+1] = 'x';
92 else if (signature
[i
] == 'L')
94 frame_desc
.locals_type
[type_ctr
] = 'o';
96 while (signature
[i
] != ';')
100 else if (signature
[i
] == '[')
102 frame_desc
.locals_type
[type_ctr
] = 'o';
105 // Ignore multi-dimensional arrays.
106 while (signature
[i
] == '[')
109 // Check for an object array
110 if (signature
[i
] == 'L')
112 while (signature
[i
] != ';')
120 #define INSN_LABEL(op) &&insn_##op
122 static const void *const insn_target
[] =
125 INSN_LABEL(aconst_null
),
126 INSN_LABEL(iconst_m1
),
127 INSN_LABEL(iconst_0
),
128 INSN_LABEL(iconst_1
),
129 INSN_LABEL(iconst_2
),
130 INSN_LABEL(iconst_3
),
131 INSN_LABEL(iconst_4
),
132 INSN_LABEL(iconst_5
),
133 INSN_LABEL(lconst_0
),
134 INSN_LABEL(lconst_1
),
135 INSN_LABEL(fconst_0
),
136 INSN_LABEL(fconst_1
),
137 INSN_LABEL(fconst_2
),
138 INSN_LABEL(dconst_0
),
139 INSN_LABEL(dconst_1
),
183 INSN_LABEL(istore_0
),
184 INSN_LABEL(istore_1
),
185 INSN_LABEL(istore_2
),
186 INSN_LABEL(istore_3
),
187 INSN_LABEL(lstore_0
),
188 INSN_LABEL(lstore_1
),
189 INSN_LABEL(lstore_2
),
190 INSN_LABEL(lstore_3
),
191 INSN_LABEL(fstore_0
),
192 INSN_LABEL(fstore_1
),
193 INSN_LABEL(fstore_2
),
194 INSN_LABEL(fstore_3
),
195 INSN_LABEL(dstore_0
),
196 INSN_LABEL(dstore_1
),
197 INSN_LABEL(dstore_2
),
198 INSN_LABEL(dstore_3
),
199 INSN_LABEL(astore_0
),
200 INSN_LABEL(astore_1
),
201 INSN_LABEL(astore_2
),
202 INSN_LABEL(astore_3
),
283 INSN_LABEL(if_icmpeq
),
284 INSN_LABEL(if_icmpne
),
285 INSN_LABEL(if_icmplt
),
286 INSN_LABEL(if_icmpge
),
287 INSN_LABEL(if_icmpgt
),
288 INSN_LABEL(if_icmple
),
289 INSN_LABEL(if_acmpeq
),
290 INSN_LABEL(if_acmpne
),
294 INSN_LABEL(tableswitch
),
295 INSN_LABEL(lookupswitch
),
302 INSN_LABEL(getstatic
),
303 INSN_LABEL(putstatic
),
304 INSN_LABEL(getfield
),
305 INSN_LABEL(putfield
),
306 INSN_LABEL(invokevirtual
),
307 INSN_LABEL(invokespecial
),
308 INSN_LABEL(invokestatic
),
309 INSN_LABEL(invokeinterface
),
310 INSN_LABEL(breakpoint
),
312 INSN_LABEL(newarray
),
313 INSN_LABEL(anewarray
),
314 INSN_LABEL(arraylength
),
316 INSN_LABEL(checkcast
),
317 INSN_LABEL(instanceof
),
318 INSN_LABEL(monitorenter
),
319 INSN_LABEL(monitorexit
),
320 #ifdef DIRECT_THREADED
325 INSN_LABEL(multianewarray
),
327 INSN_LABEL(ifnonnull
),
330 #ifdef DIRECT_THREADED
331 INSN_LABEL (ldc_class
)
339 #ifdef DIRECT_THREADED
346 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
348 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
349 jmethodID method = meth->self; \
350 jlocation loc = meth->insn_index (pc); \
351 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
354 goto *((pc++)->insn); \
359 #define NEXT_INSN goto *((pc++)->insn)
362 #define INTVAL() ((pc++)->int_val)
363 #define AVAL() ((pc++)->datum)
365 #define GET1S() INTVAL ()
366 #define GET2S() INTVAL ()
367 #define GET1U() INTVAL ()
368 #define GET2U() INTVAL ()
369 #define AVAL1U() AVAL ()
370 #define AVAL2U() AVAL ()
371 #define AVAL2UP() AVAL ()
372 #define SKIP_GOTO ++pc
373 #define GOTO_VAL() (insn_slot *) pc->datum
374 #define PCVAL(unionval) unionval.p
375 #define AMPAMP(label) &&label
377 // Compile if we must. NOTE: Double-check locking.
378 if (meth
->prepared
== NULL
)
380 _Jv_MutexLock (&compile_mutex
);
381 if (meth
->prepared
== NULL
)
382 meth
->compile (insn_target
);
383 _Jv_MutexUnlock (&compile_mutex
);
386 // If we're only compiling, stop here
390 pc
= (insn_slot
*) meth
->prepared
;
398 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
400 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
401 jmethodID method = meth->self; \
402 jlocation loc = meth->insn_index (pc); \
403 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
406 goto *(insn_target[*pc++])
408 #define NEXT_INSN goto *(insn_target[*pc++])
411 #define GET1S() get1s (pc++)
412 #define GET2S() (pc += 2, get2s (pc- 2))
413 #define GET1U() get1u (pc++)
414 #define GET2U() (pc += 2, get2u (pc - 2))
415 // Note that these could be more efficient when not handling 'ldc
418 ({ int index = get1u (pc++); \
419 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
421 ({ int index = get2u (pc); pc += 2; \
422 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
423 // Note that we don't need to resolve the pool entry here as class
424 // constants are never wide.
425 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
426 #define SKIP_GOTO pc += 2
427 #define GOTO_VAL() pc - 1 + get2s (pc)
428 #define PCVAL(unionval) unionval.i
429 #define AMPAMP(label) NULL
431 pc
= meth
->bytecode ();
433 #endif /* DIRECT_THREADED */
435 #define TAKE_GOTO pc = GOTO_VAL ()
437 /* Go straight at it! the ffi raw format matches the internal
438 stack representation exactly. At least, that's the idea.
440 memcpy ((void*) locals
, (void*) args
, meth
->args_raw_size
);
442 _Jv_word
*pool_data
= meth
->defining_class
->constants
.data
;
444 /* These three are temporaries for common code used by several
447 _Jv_ResolvedMethod
* rmeth
;
452 // We keep nop around. It is used if we're interpreting the
453 // bytecodes and not doing direct threading.
457 /* The first few instructions here are ordered according to their
458 frequency, in the hope that this will improve code locality a
461 insn_aload_0
: // 0x2a
469 insn_iload_1
: // 0x1b
473 insn_invokevirtual
: // 0xb6
476 int index
= GET2U ();
478 /* _Jv_Linker::resolve_pool_entry returns immediately if the
479 * value already is resolved. If we want to clutter up the
480 * code here to gain a little performance, then we can check
481 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
482 * directly. For now, I don't think it is worth it. */
484 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
487 sp
-= rmeth
->stack_item_count
;
489 if (rmeth
->method
->accflags
& Modifier::FINAL
)
491 // We can't rely on NULLCHECK working if the method is final.
493 throw_null_pointer_exception ();
495 // Final methods might not appear in the vtable.
496 fun
= (void (*)()) rmeth
->method
->ncode
;
501 jobject rcv
= sp
[0].o
;
502 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
503 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
506 #ifdef DIRECT_THREADED
507 // Rewrite instruction so that we use a faster pre-resolved
509 pc
[-2].insn
= &&invokevirtual_resolved
;
510 pc
[-1].datum
= rmeth
;
511 #endif /* DIRECT_THREADED */
515 #ifdef DIRECT_THREADED
516 invokevirtual_resolved
:
519 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
520 sp
-= rmeth
->stack_item_count
;
522 if (rmeth
->method
->accflags
& Modifier::FINAL
)
524 // We can't rely on NULLCHECK working if the method is final.
526 throw_null_pointer_exception ();
528 // Final methods might not appear in the vtable.
529 fun
= (void (*)()) rmeth
->method
->ncode
;
533 jobject rcv
= sp
[0].o
;
534 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
535 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
539 #endif /* DIRECT_THREADED */
543 /* here goes the magic again... */
544 ffi_cif
*cif
= &rmeth
->cif
;
545 ffi_raw
*raw
= (ffi_raw
*) sp
;
549 #if FFI_NATIVE_RAW_API
550 /* We assume that this is only implemented if it's correct */
551 /* to use it here. On a 64 bit machine, it never is. */
552 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
554 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
557 int rtype
= cif
->rtype
->type
;
559 /* the likelyhood of object, int, or void return is very high,
560 * so those are checked before the switch */
561 if (rtype
== FFI_TYPE_POINTER
)
563 PUSHA (rvalue
.object_value
);
565 else if (rtype
== FFI_TYPE_SINT32
)
567 PUSHI (rvalue
.int_value
);
569 else if (rtype
== FFI_TYPE_VOID
)
578 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
581 case FFI_TYPE_SINT16
:
582 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
585 case FFI_TYPE_UINT16
:
586 PUSHI (rvalue
.int_value
& 0xffff);
590 PUSHF (rvalue
.float_value
);
593 case FFI_TYPE_DOUBLE
:
594 PUSHD (rvalue
.double_value
);
597 case FFI_TYPE_SINT64
:
598 PUSHL (rvalue
.long_value
);
602 throw_internal_error ("unknown return type in invokeXXX");
669 // For direct threaded, bipush and sipush are the same.
670 #ifndef DIRECT_THREADED
673 #endif /* DIRECT_THREADED */
679 // For direct threaded, ldc and ldc_w are the same.
680 #ifndef DIRECT_THREADED
681 PUSHA ((jobject
) AVAL1U ());
683 #endif /* DIRECT_THREADED */
685 PUSHA ((jobject
) AVAL2U ());
688 #ifdef DIRECT_THREADED
689 // For direct threaded we have a separate 'ldc class' operation.
693 // We could rewrite the instruction at this point.
694 int index
= INTVAL ();
695 jobject k
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
700 #endif /* DIRECT_THREADED */
704 void *where
= AVAL2UP ();
705 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
801 jintArray arr
= (jintArray
) POPA();
802 NULLARRAYCHECK (arr
);
803 ARRAYBOUNDSCHECK (arr
, index
);
804 PUSHI( elements(arr
)[index
] );
811 jlongArray arr
= (jlongArray
) POPA();
812 NULLARRAYCHECK (arr
);
813 ARRAYBOUNDSCHECK (arr
, index
);
814 PUSHL( elements(arr
)[index
] );
821 jfloatArray arr
= (jfloatArray
) POPA();
822 NULLARRAYCHECK (arr
);
823 ARRAYBOUNDSCHECK (arr
, index
);
824 PUSHF( elements(arr
)[index
] );
831 jdoubleArray arr
= (jdoubleArray
) POPA();
832 NULLARRAYCHECK (arr
);
833 ARRAYBOUNDSCHECK (arr
, index
);
834 PUSHD( elements(arr
)[index
] );
841 jobjectArray arr
= (jobjectArray
) POPA();
842 NULLARRAYCHECK (arr
);
843 ARRAYBOUNDSCHECK (arr
, index
);
844 PUSHA( elements(arr
)[index
] );
851 jbyteArray arr
= (jbyteArray
) POPA();
852 NULLARRAYCHECK (arr
);
853 ARRAYBOUNDSCHECK (arr
, index
);
854 PUSHI( elements(arr
)[index
] );
861 jcharArray arr
= (jcharArray
) POPA();
862 NULLARRAYCHECK (arr
);
863 ARRAYBOUNDSCHECK (arr
, index
);
864 PUSHI( elements(arr
)[index
] );
871 jshortArray arr
= (jshortArray
) POPA();
872 NULLARRAYCHECK (arr
);
873 ARRAYBOUNDSCHECK (arr
, index
);
874 PUSHI( elements(arr
)[index
] );
982 jintArray arr
= (jintArray
) POPA();
983 NULLARRAYCHECK (arr
);
984 ARRAYBOUNDSCHECK (arr
, index
);
985 elements(arr
)[index
] = value
;
991 jlong value
= POPL();
993 jlongArray arr
= (jlongArray
) POPA();
994 NULLARRAYCHECK (arr
);
995 ARRAYBOUNDSCHECK (arr
, index
);
996 elements(arr
)[index
] = value
;
1002 jfloat value
= POPF();
1003 jint index
= POPI();
1004 jfloatArray arr
= (jfloatArray
) POPA();
1005 NULLARRAYCHECK (arr
);
1006 ARRAYBOUNDSCHECK (arr
, index
);
1007 elements(arr
)[index
] = value
;
1013 jdouble value
= POPD();
1014 jint index
= POPI();
1015 jdoubleArray arr
= (jdoubleArray
) POPA();
1016 NULLARRAYCHECK (arr
);
1017 ARRAYBOUNDSCHECK (arr
, index
);
1018 elements(arr
)[index
] = value
;
1024 jobject value
= POPA();
1025 jint index
= POPI();
1026 jobjectArray arr
= (jobjectArray
) POPA();
1027 NULLARRAYCHECK (arr
);
1028 ARRAYBOUNDSCHECK (arr
, index
);
1029 _Jv_CheckArrayStore (arr
, value
);
1030 elements(arr
)[index
] = value
;
1036 jbyte value
= (jbyte
) POPI();
1037 jint index
= POPI();
1038 jbyteArray arr
= (jbyteArray
) POPA();
1039 NULLARRAYCHECK (arr
);
1040 ARRAYBOUNDSCHECK (arr
, index
);
1041 elements(arr
)[index
] = value
;
1047 jchar value
= (jchar
) POPI();
1048 jint index
= POPI();
1049 jcharArray arr
= (jcharArray
) POPA();
1050 NULLARRAYCHECK (arr
);
1051 ARRAYBOUNDSCHECK (arr
, index
);
1052 elements(arr
)[index
] = value
;
1058 jshort value
= (jshort
) POPI();
1059 jint index
= POPI();
1060 jshortArray arr
= (jshortArray
) POPA();
1061 NULLARRAYCHECK (arr
);
1062 ARRAYBOUNDSCHECK (arr
, index
);
1063 elements(arr
)[index
] = value
;
1081 dupx (sp
, 1, 1); sp
+=1;
1085 dupx (sp
, 1, 2); sp
+=1;
1095 dupx (sp
, 2, 1); sp
+=2;
1099 dupx (sp
, 2, 2); sp
+=2;
1104 jobject tmp1
= POPA();
1105 jobject tmp2
= POPA();
1162 jint value2
= POPI();
1163 jint value1
= POPI();
1164 jint res
= _Jv_divI (value1
, value2
);
1172 jlong value2
= POPL();
1173 jlong value1
= POPL();
1174 jlong res
= _Jv_divJ (value1
, value2
);
1181 jfloat value2
= POPF();
1182 jfloat value1
= POPF();
1183 jfloat res
= value1
/ value2
;
1190 jdouble value2
= POPD();
1191 jdouble value1
= POPD();
1192 jdouble res
= value1
/ value2
;
1200 jint value2
= POPI();
1201 jint value1
= POPI();
1202 jint res
= _Jv_remI (value1
, value2
);
1210 jlong value2
= POPL();
1211 jlong value1
= POPL();
1212 jlong res
= _Jv_remJ (value1
, value2
);
1219 jfloat value2
= POPF();
1220 jfloat value1
= POPF();
1221 jfloat res
= __ieee754_fmod (value1
, value2
);
1228 jdouble value2
= POPD();
1229 jdouble value1
= POPD();
1230 jdouble res
= __ieee754_fmod (value1
, value2
);
1237 jint value
= POPI();
1244 jlong value
= POPL();
1251 jfloat value
= POPF();
1258 jdouble value
= POPD();
1265 jint shift
= (POPI() & 0x1f);
1266 jint value
= POPI();
1267 PUSHI (value
<< shift
);
1273 jint shift
= (POPI() & 0x3f);
1274 jlong value
= POPL();
1275 PUSHL (value
<< shift
);
1281 jint shift
= (POPI() & 0x1f);
1282 jint value
= POPI();
1283 PUSHI (value
>> shift
);
1289 jint shift
= (POPI() & 0x3f);
1290 jlong value
= POPL();
1291 PUSHL (value
>> shift
);
1297 jint shift
= (POPI() & 0x1f);
1298 _Jv_uint value
= (_Jv_uint
) POPI();
1299 PUSHI ((jint
) (value
>> shift
));
1305 jint shift
= (POPI() & 0x3f);
1306 _Jv_ulong value
= (_Jv_ulong
) POPL();
1307 PUSHL ((jlong
) (value
>> shift
));
1337 jint index
= GET1U ();
1338 jint amount
= GET1S ();
1339 locals
[index
].i
+= amount
;
1344 {jlong value
= POPI(); PUSHL (value
);}
1348 {jfloat value
= POPI(); PUSHF (value
);}
1352 {jdouble value
= POPI(); PUSHD (value
);}
1356 {jint value
= POPL(); PUSHI (value
);}
1360 {jfloat value
= POPL(); PUSHF (value
);}
1364 {jdouble value
= POPL(); PUSHD (value
);}
1369 using namespace java::lang
;
1370 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1377 using namespace java::lang
;
1378 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1384 { jdouble value
= POPF (); PUSHD(value
); }
1389 using namespace java::lang
;
1390 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1397 using namespace java::lang
;
1398 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1404 { jfloat value
= POPD (); PUSHF(value
); }
1408 { jbyte value
= POPI (); PUSHI(value
); }
1412 { jchar value
= POPI (); PUSHI(value
); }
1416 { jshort value
= POPI (); PUSHI(value
); }
1421 jlong value2
= POPL ();
1422 jlong value1
= POPL ();
1423 if (value1
> value2
)
1425 else if (value1
== value2
)
1441 jfloat value2
= POPF ();
1442 jfloat value1
= POPF ();
1443 if (value1
> value2
)
1445 else if (value1
== value2
)
1447 else if (value1
< value2
)
1463 jdouble value2
= POPD ();
1464 jdouble value1
= POPD ();
1465 if (value1
> value2
)
1467 else if (value1
== value2
)
1469 else if (value1
< value2
)
1532 jint value2
= POPI();
1533 jint value1
= POPI();
1534 if (value1
== value2
)
1543 jint value2
= POPI();
1544 jint value1
= POPI();
1545 if (value1
!= value2
)
1554 jint value2
= POPI();
1555 jint value1
= POPI();
1556 if (value1
< value2
)
1565 jint value2
= POPI();
1566 jint value1
= POPI();
1567 if (value1
>= value2
)
1576 jint value2
= POPI();
1577 jint value1
= POPI();
1578 if (value1
> value2
)
1587 jint value2
= POPI();
1588 jint value1
= POPI();
1589 if (value1
<= value2
)
1598 jobject value2
= POPA();
1599 jobject value1
= POPA();
1600 if (value1
== value2
)
1609 jobject value2
= POPA();
1610 jobject value1
= POPA();
1611 if (value1
!= value2
)
1619 #ifndef DIRECT_THREADED
1620 // For direct threaded, goto and goto_w are the same.
1621 pc
= pc
- 1 + get4 (pc
);
1623 #endif /* DIRECT_THREADED */
1629 #ifndef DIRECT_THREADED
1630 // For direct threaded, jsr and jsr_w are the same.
1632 pc_t next
= pc
- 1 + get4 (pc
);
1634 PUSHA ((jobject
) pc
);
1638 #endif /* DIRECT_THREADED */
1641 pc_t next
= GOTO_VAL();
1643 PUSHA ((jobject
) pc
);
1650 jint index
= GET1U ();
1651 pc
= (pc_t
) PEEKA (index
);
1657 #ifdef DIRECT_THREADED
1658 void *def
= (pc
++)->datum
;
1662 jint low
= INTVAL ();
1663 jint high
= INTVAL ();
1665 if (index
< low
|| index
> high
)
1666 pc
= (insn_slot
*) def
;
1668 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
1670 pc_t base_pc
= pc
- 1;
1671 int index
= POPI ();
1673 pc_t base
= (pc_t
) meth
->bytecode ();
1674 while ((pc
- base
) % 4 != 0)
1677 jint def
= get4 (pc
);
1678 jint low
= get4 (pc
+ 4);
1679 jint high
= get4 (pc
+ 8);
1680 if (index
< low
|| index
> high
)
1683 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
1684 #endif /* DIRECT_THREADED */
1690 #ifdef DIRECT_THREADED
1691 void *def
= (pc
++)->insn
;
1695 jint npairs
= INTVAL ();
1697 int max
= npairs
- 1;
1700 // Simple binary search...
1703 int half
= (min
+ max
) / 2;
1704 int match
= pc
[2 * half
].int_val
;
1709 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
1712 else if (index
< match
)
1713 // We can use HALF - 1 here because we check again on
1717 // We can use HALF + 1 here because we check again on
1721 if (index
== pc
[2 * min
].int_val
)
1722 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
1724 pc
= (insn_slot
*) def
;
1726 unsigned char *base_pc
= pc
-1;
1729 unsigned char* base
= meth
->bytecode ();
1730 while ((pc
-base
) % 4 != 0)
1733 jint def
= get4 (pc
);
1734 jint npairs
= get4 (pc
+4);
1739 // Simple binary search...
1742 int half
= (min
+max
)/2;
1743 int match
= get4 (pc
+ 4*(2 + 2*half
));
1747 else if (index
< match
)
1748 // We can use HALF - 1 here because we check again on
1752 // We can use HALF + 1 here because we check again on
1757 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1758 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1761 #endif /* DIRECT_THREADED */
1766 *(jobject
*) retp
= POPA ();
1770 *(jlong
*) retp
= POPL ();
1774 *(jfloat
*) retp
= POPF ();
1778 *(jdouble
*) retp
= POPD ();
1782 *(jint
*) retp
= POPI ();
1790 jint fieldref_index
= GET2U ();
1791 SAVE_PC(); // Constant pool resolution could throw.
1792 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1793 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1795 if ((field
->flags
& Modifier::STATIC
) == 0)
1796 throw_incompatible_class_change_error
1797 (JvNewStringLatin1 ("field no longer static"));
1799 jclass type
= field
->type
;
1801 // We rewrite the instruction once we discover what it refers
1803 void *newinsn
= NULL
;
1804 if (type
->isPrimitive ())
1806 switch (type
->size_in_bytes
)
1809 PUSHI (*field
->u
.byte_addr
);
1810 newinsn
= AMPAMP (getstatic_resolved_1
);
1814 if (type
== JvPrimClass (char))
1816 PUSHI (*field
->u
.char_addr
);
1817 newinsn
= AMPAMP (getstatic_resolved_char
);
1821 PUSHI (*field
->u
.short_addr
);
1822 newinsn
= AMPAMP (getstatic_resolved_short
);
1827 PUSHI(*field
->u
.int_addr
);
1828 newinsn
= AMPAMP (getstatic_resolved_4
);
1832 PUSHL(*field
->u
.long_addr
);
1833 newinsn
= AMPAMP (getstatic_resolved_8
);
1839 PUSHA(*field
->u
.object_addr
);
1840 newinsn
= AMPAMP (getstatic_resolved_obj
);
1843 #ifdef DIRECT_THREADED
1844 pc
[-2].insn
= newinsn
;
1845 pc
[-1].datum
= field
->u
.addr
;
1846 #endif /* DIRECT_THREADED */
1850 #ifdef DIRECT_THREADED
1851 getstatic_resolved_1
:
1852 PUSHI (*(jbyte
*) AVAL ());
1855 getstatic_resolved_char
:
1856 PUSHI (*(jchar
*) AVAL ());
1859 getstatic_resolved_short
:
1860 PUSHI (*(jshort
*) AVAL ());
1863 getstatic_resolved_4
:
1864 PUSHI (*(jint
*) AVAL ());
1867 getstatic_resolved_8
:
1868 PUSHL (*(jlong
*) AVAL ());
1871 getstatic_resolved_obj
:
1872 PUSHA (*(jobject
*) AVAL ());
1874 #endif /* DIRECT_THREADED */
1879 jint fieldref_index
= GET2U ();
1880 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1881 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1883 if ((field
->flags
& Modifier::STATIC
) != 0)
1884 throw_incompatible_class_change_error
1885 (JvNewStringLatin1 ("field is static"));
1887 jclass type
= field
->type
;
1888 jint field_offset
= field
->u
.boffset
;
1890 jobject obj
= POPA();
1893 void *newinsn
= NULL
;
1894 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
1895 if (type
->isPrimitive ())
1897 switch (type
->size_in_bytes
)
1900 PUSHI (val
->byte_value
);
1901 newinsn
= AMPAMP (getfield_resolved_1
);
1905 if (type
== JvPrimClass (char))
1907 PUSHI (val
->char_value
);
1908 newinsn
= AMPAMP (getfield_resolved_char
);
1912 PUSHI (val
->short_value
);
1913 newinsn
= AMPAMP (getfield_resolved_short
);
1918 PUSHI (val
->int_value
);
1919 newinsn
= AMPAMP (getfield_resolved_4
);
1923 PUSHL (val
->long_value
);
1924 newinsn
= AMPAMP (getfield_resolved_8
);
1930 PUSHA (val
->object_value
);
1931 newinsn
= AMPAMP (getfield_resolved_obj
);
1934 #ifdef DIRECT_THREADED
1935 pc
[-2].insn
= newinsn
;
1936 pc
[-1].int_val
= field_offset
;
1937 #endif /* DIRECT_THREADED */
1941 #ifdef DIRECT_THREADED
1942 getfield_resolved_1
:
1944 char *obj
= (char *) POPA ();
1946 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
1950 getfield_resolved_char
:
1952 char *obj
= (char *) POPA ();
1954 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
1958 getfield_resolved_short
:
1960 char *obj
= (char *) POPA ();
1962 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
1966 getfield_resolved_4
:
1968 char *obj
= (char *) POPA ();
1970 PUSHI (*(jint
*) (obj
+ INTVAL ()));
1974 getfield_resolved_8
:
1976 char *obj
= (char *) POPA ();
1978 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
1982 getfield_resolved_obj
:
1984 char *obj
= (char *) POPA ();
1986 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
1989 #endif /* DIRECT_THREADED */
1994 jint fieldref_index
= GET2U ();
1995 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1996 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1998 jclass type
= field
->type
;
2000 // ResolvePoolEntry cannot check this
2001 if ((field
->flags
& Modifier::STATIC
) == 0)
2002 throw_incompatible_class_change_error
2003 (JvNewStringLatin1 ("field no longer static"));
2005 void *newinsn
= NULL
;
2006 if (type
->isPrimitive ())
2008 switch (type
->size_in_bytes
)
2012 jint value
= POPI();
2013 *field
->u
.byte_addr
= value
;
2014 newinsn
= AMPAMP (putstatic_resolved_1
);
2020 jint value
= POPI();
2021 *field
->u
.char_addr
= value
;
2022 newinsn
= AMPAMP (putstatic_resolved_2
);
2028 jint value
= POPI();
2029 *field
->u
.int_addr
= value
;
2030 newinsn
= AMPAMP (putstatic_resolved_4
);
2036 jlong value
= POPL();
2037 *field
->u
.long_addr
= value
;
2038 newinsn
= AMPAMP (putstatic_resolved_8
);
2045 jobject value
= POPA();
2046 *field
->u
.object_addr
= value
;
2047 newinsn
= AMPAMP (putstatic_resolved_obj
);
2050 #ifdef DIRECT_THREADED
2051 pc
[-2].insn
= newinsn
;
2052 pc
[-1].datum
= field
->u
.addr
;
2053 #endif /* DIRECT_THREADED */
2057 #ifdef DIRECT_THREADED
2058 putstatic_resolved_1
:
2059 *(jbyte
*) AVAL () = POPI ();
2062 putstatic_resolved_2
:
2063 *(jchar
*) AVAL () = POPI ();
2066 putstatic_resolved_4
:
2067 *(jint
*) AVAL () = POPI ();
2070 putstatic_resolved_8
:
2071 *(jlong
*) AVAL () = POPL ();
2074 putstatic_resolved_obj
:
2075 *(jobject
*) AVAL () = POPA ();
2077 #endif /* DIRECT_THREADED */
2082 jint fieldref_index
= GET2U ();
2083 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
2084 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2086 jclass type
= field
->type
;
2088 if ((field
->flags
& Modifier::STATIC
) != 0)
2089 throw_incompatible_class_change_error
2090 (JvNewStringLatin1 ("field is static"));
2092 jint field_offset
= field
->u
.boffset
;
2094 void *newinsn
= NULL
;
2095 if (type
->isPrimitive ())
2097 switch (type
->size_in_bytes
)
2101 jint value
= POPI();
2102 jobject obj
= POPA();
2104 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2105 newinsn
= AMPAMP (putfield_resolved_1
);
2111 jint value
= POPI();
2112 jobject obj
= POPA();
2114 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2115 newinsn
= AMPAMP (putfield_resolved_2
);
2121 jint value
= POPI();
2122 jobject obj
= POPA();
2124 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2125 newinsn
= AMPAMP (putfield_resolved_4
);
2131 jlong value
= POPL();
2132 jobject obj
= POPA();
2134 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2135 newinsn
= AMPAMP (putfield_resolved_8
);
2142 jobject value
= POPA();
2143 jobject obj
= POPA();
2145 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2146 newinsn
= AMPAMP (putfield_resolved_obj
);
2149 #ifdef DIRECT_THREADED
2150 pc
[-2].insn
= newinsn
;
2151 pc
[-1].int_val
= field_offset
;
2152 #endif /* DIRECT_THREADED */
2156 #ifdef DIRECT_THREADED
2157 putfield_resolved_1
:
2160 char *obj
= (char *) POPA ();
2162 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2166 putfield_resolved_2
:
2169 char *obj
= (char *) POPA ();
2171 *(jchar
*) (obj
+ INTVAL ()) = val
;
2175 putfield_resolved_4
:
2178 char *obj
= (char *) POPA ();
2180 *(jint
*) (obj
+ INTVAL ()) = val
;
2184 putfield_resolved_8
:
2186 jlong val
= POPL ();
2187 char *obj
= (char *) POPA ();
2189 *(jlong
*) (obj
+ INTVAL ()) = val
;
2193 putfield_resolved_obj
:
2195 jobject val
= POPA ();
2196 char *obj
= (char *) POPA ();
2198 *(jobject
*) (obj
+ INTVAL ()) = val
;
2201 #endif /* DIRECT_THREADED */
2206 int index
= GET2U ();
2208 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2211 sp
-= rmeth
->stack_item_count
;
2213 // We don't use NULLCHECK here because we can't rely on that
2214 // working for <init>. So instead we do an explicit test.
2218 throw_null_pointer_exception ();
2221 fun
= (void (*)()) rmeth
->method
->ncode
;
2223 #ifdef DIRECT_THREADED
2224 // Rewrite instruction so that we use a faster pre-resolved
2226 pc
[-2].insn
= &&invokespecial_resolved
;
2227 pc
[-1].datum
= rmeth
;
2228 #endif /* DIRECT_THREADED */
2230 goto perform_invoke
;
2232 #ifdef DIRECT_THREADED
2233 invokespecial_resolved
:
2236 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2237 sp
-= rmeth
->stack_item_count
;
2238 // We don't use NULLCHECK here because we can't rely on that
2239 // working for <init>. So instead we do an explicit test.
2242 throw_null_pointer_exception ();
2244 fun
= (void (*)()) rmeth
->method
->ncode
;
2246 goto perform_invoke
;
2247 #endif /* DIRECT_THREADED */
2252 int index
= GET2U ();
2254 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2257 sp
-= rmeth
->stack_item_count
;
2259 fun
= (void (*)()) rmeth
->method
->ncode
;
2261 #ifdef DIRECT_THREADED
2262 // Rewrite instruction so that we use a faster pre-resolved
2264 pc
[-2].insn
= &&invokestatic_resolved
;
2265 pc
[-1].datum
= rmeth
;
2266 #endif /* DIRECT_THREADED */
2268 goto perform_invoke
;
2270 #ifdef DIRECT_THREADED
2271 invokestatic_resolved
:
2274 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2275 sp
-= rmeth
->stack_item_count
;
2276 fun
= (void (*)()) rmeth
->method
->ncode
;
2278 goto perform_invoke
;
2279 #endif /* DIRECT_THREADED */
2281 insn_invokeinterface
:
2284 int index
= GET2U ();
2286 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2289 sp
-= rmeth
->stack_item_count
;
2291 jobject rcv
= sp
[0].o
;
2296 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2297 rmeth
->method
->name
,
2298 rmeth
->method
->signature
);
2300 #ifdef DIRECT_THREADED
2301 // Rewrite instruction so that we use a faster pre-resolved
2303 pc
[-2].insn
= &&invokeinterface_resolved
;
2304 pc
[-1].datum
= rmeth
;
2306 // Skip dummy bytes.
2308 #endif /* DIRECT_THREADED */
2310 goto perform_invoke
;
2312 #ifdef DIRECT_THREADED
2313 invokeinterface_resolved
:
2316 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2317 sp
-= rmeth
->stack_item_count
;
2318 jobject rcv
= sp
[0].o
;
2321 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2322 rmeth
->method
->name
,
2323 rmeth
->method
->signature
);
2325 goto perform_invoke
;
2326 #endif /* DIRECT_THREADED */
2331 int index
= GET2U ();
2332 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2334 /* VM spec, section 3.11.5 */
2335 if ((klass
->getModifiers() & Modifier::ABSTRACT
)
2336 || klass
->isInterface())
2337 throw new java::lang::InstantiationException
;
2338 jobject res
= _Jv_AllocObject (klass
);
2341 #ifdef DIRECT_THREADED
2342 pc
[-2].insn
= &&new_resolved
;
2343 pc
[-1].datum
= klass
;
2344 #endif /* DIRECT_THREADED */
2348 #ifdef DIRECT_THREADED
2351 jclass klass
= (jclass
) AVAL ();
2352 jobject res
= _Jv_AllocObject (klass
);
2356 #endif /* DIRECT_THREADED */
2360 int atype
= GET1U ();
2362 jobject result
= _Jv_NewArray (atype
, size
);
2370 int index
= GET2U ();
2371 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2374 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2377 #ifdef DIRECT_THREADED
2378 pc
[-2].insn
= &&anewarray_resolved
;
2379 pc
[-1].datum
= klass
;
2380 #endif /* DIRECT_THREADED */
2384 #ifdef DIRECT_THREADED
2387 jclass klass
= (jclass
) AVAL ();
2389 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2393 #endif /* DIRECT_THREADED */
2397 __JArray
*arr
= (__JArray
*)POPA();
2398 NULLARRAYCHECK (arr
);
2399 PUSHI (arr
->length
);
2405 jobject value
= POPA();
2406 throw static_cast<jthrowable
>(value
);
2413 jobject value
= POPA();
2414 jint index
= GET2U ();
2415 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2418 value
= (jobject
) _Jv_CheckCast (to
, value
);
2422 #ifdef DIRECT_THREADED
2423 pc
[-2].insn
= &&checkcast_resolved
;
2425 #endif /* DIRECT_THREADED */
2429 #ifdef DIRECT_THREADED
2433 jobject value
= POPA ();
2434 jclass to
= (jclass
) AVAL ();
2435 value
= (jobject
) _Jv_CheckCast (to
, value
);
2439 #endif /* DIRECT_THREADED */
2444 jobject value
= POPA();
2445 jint index
= GET2U ();
2446 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2448 PUSHI (to
->isInstance (value
));
2450 #ifdef DIRECT_THREADED
2451 pc
[-2].insn
= &&instanceof_resolved
;
2453 #endif /* DIRECT_THREADED */
2457 #ifdef DIRECT_THREADED
2458 instanceof_resolved
:
2460 jobject value
= POPA ();
2461 jclass to
= (jclass
) AVAL ();
2462 PUSHI (to
->isInstance (value
));
2465 #endif /* DIRECT_THREADED */
2469 jobject value
= POPA();
2471 _Jv_MonitorEnter (value
);
2477 jobject value
= POPA();
2479 _Jv_MonitorExit (value
);
2485 jobject val
= POPA();
2495 jobject val
= POPA();
2503 insn_multianewarray
:
2506 int kind_index
= GET2U ();
2510 = (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2512 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2514 for (int i
= dim
- 1; i
>= 0; i
--)
2519 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2525 #ifndef DIRECT_THREADED
2528 jint the_mod_op
= get1u (pc
++);
2529 jint wide
= get2u (pc
); pc
+= 2;
2574 pc
= (unsigned char*) PEEKA (wide
);
2579 jint amount
= get2s (pc
); pc
+= 2;
2580 jint value
= PEEKI (wide
);
2581 POKEI (wide
, value
+amount
);
2586 throw_internal_error ("illegal bytecode modified by wide");
2590 #endif /* DIRECT_THREADED */
2594 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint
));
2596 // Send JVMTI notification
2597 using namespace ::java::lang
;
2598 jmethodID method
= meth
->self
;
2599 jlocation location
= meth
->insn_index (pc
- 1);
2600 Thread
*thread
= Thread::currentThread ();
2601 JNIEnv
*jni_env
= _Jv_GetCurrentJNIEnv ();
2603 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT
, thread
, jni_env
,
2606 // Continue execution
2607 using namespace gnu::gcj::jvmti
;
2609 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong
> (method
),
2611 JvAssert (bp
!= NULL
);
2613 pc_t opc
= reinterpret_cast<pc_t
> (bp
->getInsn ());
2615 #ifdef DIRECT_THREADED
2618 goto *(insn_target
[*opc
]);
2622 catch (java::lang::Throwable
*ex
)
2625 // This needs to be done before the pc is changed.
2626 jlong throw_loc
= meth
->insn_index (pc
);
2628 // Check if the exception is handled and, if so, set the pc to the start
2629 // of the appropriate catch block.
2630 if (meth
->check_handler (&pc
, meth
, ex
))
2633 sp
++->o
= ex
; // Push exception.
2635 if (JVMTI_REQUESTED_EVENT (Exception
))
2637 using namespace gnu::gcj::jvmti
;
2638 jlong throw_meth
= reinterpret_cast<jlong
> (meth
->get_method ());
2639 jlong catch_loc
= meth
->insn_index (pc
);
2640 ExceptionEvent::postExceptionEvent (thread
, throw_meth
,
2641 throw_loc
, ex
, throw_meth
,
2648 if (JVMTI_REQUESTED_EVENT (Exception
))
2650 using namespace gnu::gcj::jvmti
;
2651 jlong throw_meth
= reinterpret_cast<jlong
> (meth
->get_method ());
2652 ExceptionEvent::postExceptionEvent (thread
, throw_meth
, throw_loc
,
2656 // No handler, so re-throw.