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)
49 // Set the "this" pointer for this frame
50 _Jv_word
*this_ptr
= reinterpret_cast<_Jv_word
*> (args
);
51 frame_desc
.obj_ptr
= this_ptr
[0].o
;
52 frame_desc
.locals_type
[0] = 'o';
56 // Now parse the method signature to set the types of the other arguments.
57 int sig_len
= method
->signature
->len ();
58 char *signature
= method
->signature
->chars ();
59 for (int i
= 1; signature
[i
] != ')' && i
<= sig_len
; i
++)
61 if (signature
[i
] == 'Z' || signature
[i
] == 'B' || signature
[i
] == 'C'
62 || signature
[i
] == 'S' || signature
[i
] == 'I')
64 frame_desc
.locals_type
[type_ctr
] = 'i';
68 else if (signature
[i
] == 'F')
70 frame_desc
.locals_type
[type_ctr
] = 'f';
74 else if (signature
[i
] == 'J')
76 frame_desc
.locals_type
[type_ctr
] = 'l';
77 frame_desc
.locals_type
[type_ctr
+1] = 'x';
81 else if (signature
[i
] == 'D')
83 frame_desc
.locals_type
[type_ctr
] = 'd';
84 frame_desc
.locals_type
[type_ctr
+1] = 'x';
88 else if (signature
[i
] == 'L')
90 frame_desc
.locals_type
[type_ctr
] = 'o';
92 while (signature
[i
] != ';')
96 else if (signature
[i
] == '[')
98 frame_desc
.locals_type
[type_ctr
] = 'o';
101 // Ignore multi-dimensional arrays.
102 while (signature
[i
] == '[')
105 // Check for an object array
106 if (signature
[i
] == 'L')
108 while (signature
[i
] != ';')
116 #define INSN_LABEL(op) &&insn_##op
118 static const void *const insn_target
[] =
121 INSN_LABEL(aconst_null
),
122 INSN_LABEL(iconst_m1
),
123 INSN_LABEL(iconst_0
),
124 INSN_LABEL(iconst_1
),
125 INSN_LABEL(iconst_2
),
126 INSN_LABEL(iconst_3
),
127 INSN_LABEL(iconst_4
),
128 INSN_LABEL(iconst_5
),
129 INSN_LABEL(lconst_0
),
130 INSN_LABEL(lconst_1
),
131 INSN_LABEL(fconst_0
),
132 INSN_LABEL(fconst_1
),
133 INSN_LABEL(fconst_2
),
134 INSN_LABEL(dconst_0
),
135 INSN_LABEL(dconst_1
),
179 INSN_LABEL(istore_0
),
180 INSN_LABEL(istore_1
),
181 INSN_LABEL(istore_2
),
182 INSN_LABEL(istore_3
),
183 INSN_LABEL(lstore_0
),
184 INSN_LABEL(lstore_1
),
185 INSN_LABEL(lstore_2
),
186 INSN_LABEL(lstore_3
),
187 INSN_LABEL(fstore_0
),
188 INSN_LABEL(fstore_1
),
189 INSN_LABEL(fstore_2
),
190 INSN_LABEL(fstore_3
),
191 INSN_LABEL(dstore_0
),
192 INSN_LABEL(dstore_1
),
193 INSN_LABEL(dstore_2
),
194 INSN_LABEL(dstore_3
),
195 INSN_LABEL(astore_0
),
196 INSN_LABEL(astore_1
),
197 INSN_LABEL(astore_2
),
198 INSN_LABEL(astore_3
),
279 INSN_LABEL(if_icmpeq
),
280 INSN_LABEL(if_icmpne
),
281 INSN_LABEL(if_icmplt
),
282 INSN_LABEL(if_icmpge
),
283 INSN_LABEL(if_icmpgt
),
284 INSN_LABEL(if_icmple
),
285 INSN_LABEL(if_acmpeq
),
286 INSN_LABEL(if_acmpne
),
290 INSN_LABEL(tableswitch
),
291 INSN_LABEL(lookupswitch
),
298 INSN_LABEL(getstatic
),
299 INSN_LABEL(putstatic
),
300 INSN_LABEL(getfield
),
301 INSN_LABEL(putfield
),
302 INSN_LABEL(invokevirtual
),
303 INSN_LABEL(invokespecial
),
304 INSN_LABEL(invokestatic
),
305 INSN_LABEL(invokeinterface
),
306 INSN_LABEL(breakpoint
),
308 INSN_LABEL(newarray
),
309 INSN_LABEL(anewarray
),
310 INSN_LABEL(arraylength
),
312 INSN_LABEL(checkcast
),
313 INSN_LABEL(instanceof
),
314 INSN_LABEL(monitorenter
),
315 INSN_LABEL(monitorexit
),
316 #ifdef DIRECT_THREADED
321 INSN_LABEL(multianewarray
),
323 INSN_LABEL(ifnonnull
),
326 #ifdef DIRECT_THREADED
327 INSN_LABEL (ldc_class
)
335 #ifdef DIRECT_THREADED
342 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
344 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
345 jmethodID method = meth->self; \
346 jlocation loc = meth->insn_index (pc); \
347 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
350 goto *((pc++)->insn); \
355 #define NEXT_INSN goto *((pc++)->insn)
358 #define INTVAL() ((pc++)->int_val)
359 #define AVAL() ((pc++)->datum)
361 #define GET1S() INTVAL ()
362 #define GET2S() INTVAL ()
363 #define GET1U() INTVAL ()
364 #define GET2U() INTVAL ()
365 #define AVAL1U() AVAL ()
366 #define AVAL2U() AVAL ()
367 #define AVAL2UP() AVAL ()
368 #define SKIP_GOTO ++pc
369 #define GOTO_VAL() (insn_slot *) pc->datum
370 #define PCVAL(unionval) unionval.p
371 #define AMPAMP(label) &&label
373 // Compile if we must. NOTE: Double-check locking.
374 if (meth
->prepared
== NULL
)
376 _Jv_MutexLock (&compile_mutex
);
377 if (meth
->prepared
== NULL
)
378 meth
->compile (insn_target
);
379 _Jv_MutexUnlock (&compile_mutex
);
382 // If we're only compiling, stop here
386 pc
= (insn_slot
*) meth
->prepared
;
394 if (JVMTI_REQUESTED_EVENT (SingleStep)) \
396 JNIEnv *env = _Jv_GetCurrentJNIEnv (); \
397 jmethodID method = meth->self; \
398 jlocation loc = meth->insn_index (pc); \
399 _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \
402 goto *(insn_target[*pc++])
404 #define NEXT_INSN goto *(insn_target[*pc++])
407 #define GET1S() get1s (pc++)
408 #define GET2S() (pc += 2, get2s (pc- 2))
409 #define GET1U() get1u (pc++)
410 #define GET2U() (pc += 2, get2u (pc - 2))
411 // Note that these could be more efficient when not handling 'ldc
414 ({ int index = get1u (pc++); \
415 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
417 ({ int index = get2u (pc); pc += 2; \
418 _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; })
419 // Note that we don't need to resolve the pool entry here as class
420 // constants are never wide.
421 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
422 #define SKIP_GOTO pc += 2
423 #define GOTO_VAL() pc - 1 + get2s (pc)
424 #define PCVAL(unionval) unionval.i
425 #define AMPAMP(label) NULL
427 pc
= meth
->bytecode ();
429 #endif /* DIRECT_THREADED */
431 #define TAKE_GOTO pc = GOTO_VAL ()
433 /* Go straight at it! the ffi raw format matches the internal
434 stack representation exactly. At least, that's the idea.
436 memcpy ((void*) locals
, (void*) args
, meth
->args_raw_size
);
438 _Jv_word
*pool_data
= meth
->defining_class
->constants
.data
;
440 /* These three are temporaries for common code used by several
443 _Jv_ResolvedMethod
* rmeth
;
448 // We keep nop around. It is used if we're interpreting the
449 // bytecodes and not doing direct threading.
453 /* The first few instructions here are ordered according to their
454 frequency, in the hope that this will improve code locality a
457 insn_aload_0
: // 0x2a
465 insn_iload_1
: // 0x1b
469 insn_invokevirtual
: // 0xb6
472 int index
= GET2U ();
474 /* _Jv_Linker::resolve_pool_entry returns immediately if the
475 * value already is resolved. If we want to clutter up the
476 * code here to gain a little performance, then we can check
477 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
478 * directly. For now, I don't think it is worth it. */
480 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
483 sp
-= rmeth
->stack_item_count
;
485 if (rmeth
->method
->accflags
& Modifier::FINAL
)
487 // We can't rely on NULLCHECK working if the method is final.
489 throw_null_pointer_exception ();
491 // Final methods might not appear in the vtable.
492 fun
= (void (*)()) rmeth
->method
->ncode
;
497 jobject rcv
= sp
[0].o
;
498 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
499 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
502 #ifdef DIRECT_THREADED
503 // Rewrite instruction so that we use a faster pre-resolved
505 pc
[-2].insn
= &&invokevirtual_resolved
;
506 pc
[-1].datum
= rmeth
;
507 #endif /* DIRECT_THREADED */
511 #ifdef DIRECT_THREADED
512 invokevirtual_resolved
:
515 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
516 sp
-= rmeth
->stack_item_count
;
518 if (rmeth
->method
->accflags
& Modifier::FINAL
)
520 // We can't rely on NULLCHECK working if the method is final.
522 throw_null_pointer_exception ();
524 // Final methods might not appear in the vtable.
525 fun
= (void (*)()) rmeth
->method
->ncode
;
529 jobject rcv
= sp
[0].o
;
530 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
531 fun
= (void (*)()) table
->get_method (rmeth
->method
->index
);
535 #endif /* DIRECT_THREADED */
539 /* here goes the magic again... */
540 ffi_cif
*cif
= &rmeth
->cif
;
541 ffi_raw
*raw
= (ffi_raw
*) sp
;
545 #if FFI_NATIVE_RAW_API
546 /* We assume that this is only implemented if it's correct */
547 /* to use it here. On a 64 bit machine, it never is. */
548 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
550 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
553 int rtype
= cif
->rtype
->type
;
555 /* the likelyhood of object, int, or void return is very high,
556 * so those are checked before the switch */
557 if (rtype
== FFI_TYPE_POINTER
)
559 PUSHA (rvalue
.object_value
);
561 else if (rtype
== FFI_TYPE_SINT32
)
563 PUSHI (rvalue
.int_value
);
565 else if (rtype
== FFI_TYPE_VOID
)
574 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
577 case FFI_TYPE_SINT16
:
578 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
581 case FFI_TYPE_UINT16
:
582 PUSHI (rvalue
.int_value
& 0xffff);
586 PUSHF (rvalue
.float_value
);
589 case FFI_TYPE_DOUBLE
:
590 PUSHD (rvalue
.double_value
);
593 case FFI_TYPE_SINT64
:
594 PUSHL (rvalue
.long_value
);
598 throw_internal_error ("unknown return type in invokeXXX");
665 // For direct threaded, bipush and sipush are the same.
666 #ifndef DIRECT_THREADED
669 #endif /* DIRECT_THREADED */
675 // For direct threaded, ldc and ldc_w are the same.
676 #ifndef DIRECT_THREADED
677 PUSHA ((jobject
) AVAL1U ());
679 #endif /* DIRECT_THREADED */
681 PUSHA ((jobject
) AVAL2U ());
684 #ifdef DIRECT_THREADED
685 // For direct threaded we have a separate 'ldc class' operation.
689 // We could rewrite the instruction at this point.
690 int index
= INTVAL ();
691 jobject k
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
696 #endif /* DIRECT_THREADED */
700 void *where
= AVAL2UP ();
701 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
797 jintArray arr
= (jintArray
) POPA();
798 NULLARRAYCHECK (arr
);
799 ARRAYBOUNDSCHECK (arr
, index
);
800 PUSHI( elements(arr
)[index
] );
807 jlongArray arr
= (jlongArray
) POPA();
808 NULLARRAYCHECK (arr
);
809 ARRAYBOUNDSCHECK (arr
, index
);
810 PUSHL( elements(arr
)[index
] );
817 jfloatArray arr
= (jfloatArray
) POPA();
818 NULLARRAYCHECK (arr
);
819 ARRAYBOUNDSCHECK (arr
, index
);
820 PUSHF( elements(arr
)[index
] );
827 jdoubleArray arr
= (jdoubleArray
) POPA();
828 NULLARRAYCHECK (arr
);
829 ARRAYBOUNDSCHECK (arr
, index
);
830 PUSHD( elements(arr
)[index
] );
837 jobjectArray arr
= (jobjectArray
) POPA();
838 NULLARRAYCHECK (arr
);
839 ARRAYBOUNDSCHECK (arr
, index
);
840 PUSHA( elements(arr
)[index
] );
847 jbyteArray arr
= (jbyteArray
) POPA();
848 NULLARRAYCHECK (arr
);
849 ARRAYBOUNDSCHECK (arr
, index
);
850 PUSHI( elements(arr
)[index
] );
857 jcharArray arr
= (jcharArray
) POPA();
858 NULLARRAYCHECK (arr
);
859 ARRAYBOUNDSCHECK (arr
, index
);
860 PUSHI( elements(arr
)[index
] );
867 jshortArray arr
= (jshortArray
) POPA();
868 NULLARRAYCHECK (arr
);
869 ARRAYBOUNDSCHECK (arr
, index
);
870 PUSHI( elements(arr
)[index
] );
978 jintArray arr
= (jintArray
) POPA();
979 NULLARRAYCHECK (arr
);
980 ARRAYBOUNDSCHECK (arr
, index
);
981 elements(arr
)[index
] = value
;
987 jlong value
= POPL();
989 jlongArray arr
= (jlongArray
) POPA();
990 NULLARRAYCHECK (arr
);
991 ARRAYBOUNDSCHECK (arr
, index
);
992 elements(arr
)[index
] = value
;
998 jfloat value
= POPF();
1000 jfloatArray arr
= (jfloatArray
) POPA();
1001 NULLARRAYCHECK (arr
);
1002 ARRAYBOUNDSCHECK (arr
, index
);
1003 elements(arr
)[index
] = value
;
1009 jdouble value
= POPD();
1010 jint index
= POPI();
1011 jdoubleArray arr
= (jdoubleArray
) POPA();
1012 NULLARRAYCHECK (arr
);
1013 ARRAYBOUNDSCHECK (arr
, index
);
1014 elements(arr
)[index
] = value
;
1020 jobject value
= POPA();
1021 jint index
= POPI();
1022 jobjectArray arr
= (jobjectArray
) POPA();
1023 NULLARRAYCHECK (arr
);
1024 ARRAYBOUNDSCHECK (arr
, index
);
1025 _Jv_CheckArrayStore (arr
, value
);
1026 elements(arr
)[index
] = value
;
1032 jbyte value
= (jbyte
) POPI();
1033 jint index
= POPI();
1034 jbyteArray arr
= (jbyteArray
) POPA();
1035 NULLARRAYCHECK (arr
);
1036 ARRAYBOUNDSCHECK (arr
, index
);
1037 elements(arr
)[index
] = value
;
1043 jchar value
= (jchar
) POPI();
1044 jint index
= POPI();
1045 jcharArray arr
= (jcharArray
) POPA();
1046 NULLARRAYCHECK (arr
);
1047 ARRAYBOUNDSCHECK (arr
, index
);
1048 elements(arr
)[index
] = value
;
1054 jshort value
= (jshort
) POPI();
1055 jint index
= POPI();
1056 jshortArray arr
= (jshortArray
) POPA();
1057 NULLARRAYCHECK (arr
);
1058 ARRAYBOUNDSCHECK (arr
, index
);
1059 elements(arr
)[index
] = value
;
1077 dupx (sp
, 1, 1); sp
+=1;
1081 dupx (sp
, 1, 2); sp
+=1;
1091 dupx (sp
, 2, 1); sp
+=2;
1095 dupx (sp
, 2, 2); sp
+=2;
1100 jobject tmp1
= POPA();
1101 jobject tmp2
= POPA();
1158 jint value2
= POPI();
1159 jint value1
= POPI();
1160 jint res
= _Jv_divI (value1
, value2
);
1168 jlong value2
= POPL();
1169 jlong value1
= POPL();
1170 jlong res
= _Jv_divJ (value1
, value2
);
1177 jfloat value2
= POPF();
1178 jfloat value1
= POPF();
1179 jfloat res
= value1
/ value2
;
1186 jdouble value2
= POPD();
1187 jdouble value1
= POPD();
1188 jdouble res
= value1
/ value2
;
1196 jint value2
= POPI();
1197 jint value1
= POPI();
1198 jint res
= _Jv_remI (value1
, value2
);
1206 jlong value2
= POPL();
1207 jlong value1
= POPL();
1208 jlong res
= _Jv_remJ (value1
, value2
);
1215 jfloat value2
= POPF();
1216 jfloat value1
= POPF();
1217 jfloat res
= __ieee754_fmod (value1
, value2
);
1224 jdouble value2
= POPD();
1225 jdouble value1
= POPD();
1226 jdouble res
= __ieee754_fmod (value1
, value2
);
1233 jint value
= POPI();
1240 jlong value
= POPL();
1247 jfloat value
= POPF();
1254 jdouble value
= POPD();
1261 jint shift
= (POPI() & 0x1f);
1262 jint value
= POPI();
1263 PUSHI (value
<< shift
);
1269 jint shift
= (POPI() & 0x3f);
1270 jlong value
= POPL();
1271 PUSHL (value
<< shift
);
1277 jint shift
= (POPI() & 0x1f);
1278 jint value
= POPI();
1279 PUSHI (value
>> shift
);
1285 jint shift
= (POPI() & 0x3f);
1286 jlong value
= POPL();
1287 PUSHL (value
>> shift
);
1293 jint shift
= (POPI() & 0x1f);
1294 _Jv_uint value
= (_Jv_uint
) POPI();
1295 PUSHI ((jint
) (value
>> shift
));
1301 jint shift
= (POPI() & 0x3f);
1302 _Jv_ulong value
= (_Jv_ulong
) POPL();
1303 PUSHL ((jlong
) (value
>> shift
));
1333 jint index
= GET1U ();
1334 jint amount
= GET1S ();
1335 locals
[index
].i
+= amount
;
1340 {jlong value
= POPI(); PUSHL (value
);}
1344 {jfloat value
= POPI(); PUSHF (value
);}
1348 {jdouble value
= POPI(); PUSHD (value
);}
1352 {jint value
= POPL(); PUSHI (value
);}
1356 {jfloat value
= POPL(); PUSHF (value
);}
1360 {jdouble value
= POPL(); PUSHD (value
);}
1365 using namespace java::lang
;
1366 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1373 using namespace java::lang
;
1374 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1380 { jdouble value
= POPF (); PUSHD(value
); }
1385 using namespace java::lang
;
1386 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
1393 using namespace java::lang
;
1394 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
1400 { jfloat value
= POPD (); PUSHF(value
); }
1404 { jbyte value
= POPI (); PUSHI(value
); }
1408 { jchar value
= POPI (); PUSHI(value
); }
1412 { jshort value
= POPI (); PUSHI(value
); }
1417 jlong value2
= POPL ();
1418 jlong value1
= POPL ();
1419 if (value1
> value2
)
1421 else if (value1
== value2
)
1437 jfloat value2
= POPF ();
1438 jfloat value1
= POPF ();
1439 if (value1
> value2
)
1441 else if (value1
== value2
)
1443 else if (value1
< value2
)
1459 jdouble value2
= POPD ();
1460 jdouble value1
= POPD ();
1461 if (value1
> value2
)
1463 else if (value1
== value2
)
1465 else if (value1
< value2
)
1528 jint value2
= POPI();
1529 jint value1
= POPI();
1530 if (value1
== value2
)
1539 jint value2
= POPI();
1540 jint value1
= POPI();
1541 if (value1
!= value2
)
1550 jint value2
= POPI();
1551 jint value1
= POPI();
1552 if (value1
< value2
)
1561 jint value2
= POPI();
1562 jint value1
= POPI();
1563 if (value1
>= value2
)
1572 jint value2
= POPI();
1573 jint value1
= POPI();
1574 if (value1
> value2
)
1583 jint value2
= POPI();
1584 jint value1
= POPI();
1585 if (value1
<= value2
)
1594 jobject value2
= POPA();
1595 jobject value1
= POPA();
1596 if (value1
== value2
)
1605 jobject value2
= POPA();
1606 jobject value1
= POPA();
1607 if (value1
!= value2
)
1615 #ifndef DIRECT_THREADED
1616 // For direct threaded, goto and goto_w are the same.
1617 pc
= pc
- 1 + get4 (pc
);
1619 #endif /* DIRECT_THREADED */
1625 #ifndef DIRECT_THREADED
1626 // For direct threaded, jsr and jsr_w are the same.
1628 pc_t next
= pc
- 1 + get4 (pc
);
1630 PUSHA ((jobject
) pc
);
1634 #endif /* DIRECT_THREADED */
1637 pc_t next
= GOTO_VAL();
1639 PUSHA ((jobject
) pc
);
1646 jint index
= GET1U ();
1647 pc
= (pc_t
) PEEKA (index
);
1653 #ifdef DIRECT_THREADED
1654 void *def
= (pc
++)->datum
;
1658 jint low
= INTVAL ();
1659 jint high
= INTVAL ();
1661 if (index
< low
|| index
> high
)
1662 pc
= (insn_slot
*) def
;
1664 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
1666 pc_t base_pc
= pc
- 1;
1667 int index
= POPI ();
1669 pc_t base
= (pc_t
) meth
->bytecode ();
1670 while ((pc
- base
) % 4 != 0)
1673 jint def
= get4 (pc
);
1674 jint low
= get4 (pc
+ 4);
1675 jint high
= get4 (pc
+ 8);
1676 if (index
< low
|| index
> high
)
1679 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
1680 #endif /* DIRECT_THREADED */
1686 #ifdef DIRECT_THREADED
1687 void *def
= (pc
++)->insn
;
1691 jint npairs
= INTVAL ();
1693 int max
= npairs
- 1;
1696 // Simple binary search...
1699 int half
= (min
+ max
) / 2;
1700 int match
= pc
[2 * half
].int_val
;
1705 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
1708 else if (index
< match
)
1709 // We can use HALF - 1 here because we check again on
1713 // We can use HALF + 1 here because we check again on
1717 if (index
== pc
[2 * min
].int_val
)
1718 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
1720 pc
= (insn_slot
*) def
;
1722 unsigned char *base_pc
= pc
-1;
1725 unsigned char* base
= meth
->bytecode ();
1726 while ((pc
-base
) % 4 != 0)
1729 jint def
= get4 (pc
);
1730 jint npairs
= get4 (pc
+4);
1735 // Simple binary search...
1738 int half
= (min
+max
)/2;
1739 int match
= get4 (pc
+ 4*(2 + 2*half
));
1743 else if (index
< match
)
1744 // We can use HALF - 1 here because we check again on
1748 // We can use HALF + 1 here because we check again on
1753 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
1754 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
1757 #endif /* DIRECT_THREADED */
1762 *(jobject
*) retp
= POPA ();
1766 *(jlong
*) retp
= POPL ();
1770 *(jfloat
*) retp
= POPF ();
1774 *(jdouble
*) retp
= POPD ();
1778 *(jint
*) retp
= POPI ();
1786 jint fieldref_index
= GET2U ();
1787 SAVE_PC(); // Constant pool resolution could throw.
1788 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1789 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1791 if ((field
->flags
& Modifier::STATIC
) == 0)
1792 throw_incompatible_class_change_error
1793 (JvNewStringLatin1 ("field no longer static"));
1795 jclass type
= field
->type
;
1797 // We rewrite the instruction once we discover what it refers
1799 void *newinsn
= NULL
;
1800 if (type
->isPrimitive ())
1802 switch (type
->size_in_bytes
)
1805 PUSHI (*field
->u
.byte_addr
);
1806 newinsn
= AMPAMP (getstatic_resolved_1
);
1810 if (type
== JvPrimClass (char))
1812 PUSHI (*field
->u
.char_addr
);
1813 newinsn
= AMPAMP (getstatic_resolved_char
);
1817 PUSHI (*field
->u
.short_addr
);
1818 newinsn
= AMPAMP (getstatic_resolved_short
);
1823 PUSHI(*field
->u
.int_addr
);
1824 newinsn
= AMPAMP (getstatic_resolved_4
);
1828 PUSHL(*field
->u
.long_addr
);
1829 newinsn
= AMPAMP (getstatic_resolved_8
);
1835 PUSHA(*field
->u
.object_addr
);
1836 newinsn
= AMPAMP (getstatic_resolved_obj
);
1839 #ifdef DIRECT_THREADED
1840 pc
[-2].insn
= newinsn
;
1841 pc
[-1].datum
= field
->u
.addr
;
1842 #endif /* DIRECT_THREADED */
1846 #ifdef DIRECT_THREADED
1847 getstatic_resolved_1
:
1848 PUSHI (*(jbyte
*) AVAL ());
1851 getstatic_resolved_char
:
1852 PUSHI (*(jchar
*) AVAL ());
1855 getstatic_resolved_short
:
1856 PUSHI (*(jshort
*) AVAL ());
1859 getstatic_resolved_4
:
1860 PUSHI (*(jint
*) AVAL ());
1863 getstatic_resolved_8
:
1864 PUSHL (*(jlong
*) AVAL ());
1867 getstatic_resolved_obj
:
1868 PUSHA (*(jobject
*) AVAL ());
1870 #endif /* DIRECT_THREADED */
1875 jint fieldref_index
= GET2U ();
1876 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1877 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1879 if ((field
->flags
& Modifier::STATIC
) != 0)
1880 throw_incompatible_class_change_error
1881 (JvNewStringLatin1 ("field is static"));
1883 jclass type
= field
->type
;
1884 jint field_offset
= field
->u
.boffset
;
1886 jobject obj
= POPA();
1889 void *newinsn
= NULL
;
1890 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
1891 if (type
->isPrimitive ())
1893 switch (type
->size_in_bytes
)
1896 PUSHI (val
->byte_value
);
1897 newinsn
= AMPAMP (getfield_resolved_1
);
1901 if (type
== JvPrimClass (char))
1903 PUSHI (val
->char_value
);
1904 newinsn
= AMPAMP (getfield_resolved_char
);
1908 PUSHI (val
->short_value
);
1909 newinsn
= AMPAMP (getfield_resolved_short
);
1914 PUSHI (val
->int_value
);
1915 newinsn
= AMPAMP (getfield_resolved_4
);
1919 PUSHL (val
->long_value
);
1920 newinsn
= AMPAMP (getfield_resolved_8
);
1926 PUSHA (val
->object_value
);
1927 newinsn
= AMPAMP (getfield_resolved_obj
);
1930 #ifdef DIRECT_THREADED
1931 pc
[-2].insn
= newinsn
;
1932 pc
[-1].int_val
= field_offset
;
1933 #endif /* DIRECT_THREADED */
1937 #ifdef DIRECT_THREADED
1938 getfield_resolved_1
:
1940 char *obj
= (char *) POPA ();
1942 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
1946 getfield_resolved_char
:
1948 char *obj
= (char *) POPA ();
1950 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
1954 getfield_resolved_short
:
1956 char *obj
= (char *) POPA ();
1958 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
1962 getfield_resolved_4
:
1964 char *obj
= (char *) POPA ();
1966 PUSHI (*(jint
*) (obj
+ INTVAL ()));
1970 getfield_resolved_8
:
1972 char *obj
= (char *) POPA ();
1974 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
1978 getfield_resolved_obj
:
1980 char *obj
= (char *) POPA ();
1982 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
1985 #endif /* DIRECT_THREADED */
1990 jint fieldref_index
= GET2U ();
1991 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
1992 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
1994 jclass type
= field
->type
;
1996 // ResolvePoolEntry cannot check this
1997 if ((field
->flags
& Modifier::STATIC
) == 0)
1998 throw_incompatible_class_change_error
1999 (JvNewStringLatin1 ("field no longer static"));
2001 void *newinsn
= NULL
;
2002 if (type
->isPrimitive ())
2004 switch (type
->size_in_bytes
)
2008 jint value
= POPI();
2009 *field
->u
.byte_addr
= value
;
2010 newinsn
= AMPAMP (putstatic_resolved_1
);
2016 jint value
= POPI();
2017 *field
->u
.char_addr
= value
;
2018 newinsn
= AMPAMP (putstatic_resolved_2
);
2024 jint value
= POPI();
2025 *field
->u
.int_addr
= value
;
2026 newinsn
= AMPAMP (putstatic_resolved_4
);
2032 jlong value
= POPL();
2033 *field
->u
.long_addr
= value
;
2034 newinsn
= AMPAMP (putstatic_resolved_8
);
2041 jobject value
= POPA();
2042 *field
->u
.object_addr
= value
;
2043 newinsn
= AMPAMP (putstatic_resolved_obj
);
2046 #ifdef DIRECT_THREADED
2047 pc
[-2].insn
= newinsn
;
2048 pc
[-1].datum
= field
->u
.addr
;
2049 #endif /* DIRECT_THREADED */
2053 #ifdef DIRECT_THREADED
2054 putstatic_resolved_1
:
2055 *(jbyte
*) AVAL () = POPI ();
2058 putstatic_resolved_2
:
2059 *(jchar
*) AVAL () = POPI ();
2062 putstatic_resolved_4
:
2063 *(jint
*) AVAL () = POPI ();
2066 putstatic_resolved_8
:
2067 *(jlong
*) AVAL () = POPL ();
2070 putstatic_resolved_obj
:
2071 *(jobject
*) AVAL () = POPA ();
2073 #endif /* DIRECT_THREADED */
2078 jint fieldref_index
= GET2U ();
2079 _Jv_Linker::resolve_pool_entry (meth
->defining_class
, fieldref_index
);
2080 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2082 jclass type
= field
->type
;
2084 if ((field
->flags
& Modifier::STATIC
) != 0)
2085 throw_incompatible_class_change_error
2086 (JvNewStringLatin1 ("field is static"));
2088 jint field_offset
= field
->u
.boffset
;
2090 void *newinsn
= NULL
;
2091 if (type
->isPrimitive ())
2093 switch (type
->size_in_bytes
)
2097 jint value
= POPI();
2098 jobject obj
= POPA();
2100 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2101 newinsn
= AMPAMP (putfield_resolved_1
);
2107 jint value
= POPI();
2108 jobject obj
= POPA();
2110 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2111 newinsn
= AMPAMP (putfield_resolved_2
);
2117 jint value
= POPI();
2118 jobject obj
= POPA();
2120 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2121 newinsn
= AMPAMP (putfield_resolved_4
);
2127 jlong value
= POPL();
2128 jobject obj
= POPA();
2130 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2131 newinsn
= AMPAMP (putfield_resolved_8
);
2138 jobject value
= POPA();
2139 jobject obj
= POPA();
2141 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2142 newinsn
= AMPAMP (putfield_resolved_obj
);
2145 #ifdef DIRECT_THREADED
2146 pc
[-2].insn
= newinsn
;
2147 pc
[-1].int_val
= field_offset
;
2148 #endif /* DIRECT_THREADED */
2152 #ifdef DIRECT_THREADED
2153 putfield_resolved_1
:
2156 char *obj
= (char *) POPA ();
2158 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2162 putfield_resolved_2
:
2165 char *obj
= (char *) POPA ();
2167 *(jchar
*) (obj
+ INTVAL ()) = val
;
2171 putfield_resolved_4
:
2174 char *obj
= (char *) POPA ();
2176 *(jint
*) (obj
+ INTVAL ()) = val
;
2180 putfield_resolved_8
:
2182 jlong val
= POPL ();
2183 char *obj
= (char *) POPA ();
2185 *(jlong
*) (obj
+ INTVAL ()) = val
;
2189 putfield_resolved_obj
:
2191 jobject val
= POPA ();
2192 char *obj
= (char *) POPA ();
2194 *(jobject
*) (obj
+ INTVAL ()) = val
;
2197 #endif /* DIRECT_THREADED */
2202 int index
= GET2U ();
2204 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2207 sp
-= rmeth
->stack_item_count
;
2209 // We don't use NULLCHECK here because we can't rely on that
2210 // working for <init>. So instead we do an explicit test.
2214 throw_null_pointer_exception ();
2217 fun
= (void (*)()) rmeth
->method
->ncode
;
2219 #ifdef DIRECT_THREADED
2220 // Rewrite instruction so that we use a faster pre-resolved
2222 pc
[-2].insn
= &&invokespecial_resolved
;
2223 pc
[-1].datum
= rmeth
;
2224 #endif /* DIRECT_THREADED */
2226 goto perform_invoke
;
2228 #ifdef DIRECT_THREADED
2229 invokespecial_resolved
:
2232 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2233 sp
-= rmeth
->stack_item_count
;
2234 // We don't use NULLCHECK here because we can't rely on that
2235 // working for <init>. So instead we do an explicit test.
2238 throw_null_pointer_exception ();
2240 fun
= (void (*)()) rmeth
->method
->ncode
;
2242 goto perform_invoke
;
2243 #endif /* DIRECT_THREADED */
2248 int index
= GET2U ();
2250 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2253 sp
-= rmeth
->stack_item_count
;
2255 fun
= (void (*)()) rmeth
->method
->ncode
;
2257 #ifdef DIRECT_THREADED
2258 // Rewrite instruction so that we use a faster pre-resolved
2260 pc
[-2].insn
= &&invokestatic_resolved
;
2261 pc
[-1].datum
= rmeth
;
2262 #endif /* DIRECT_THREADED */
2264 goto perform_invoke
;
2266 #ifdef DIRECT_THREADED
2267 invokestatic_resolved
:
2270 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2271 sp
-= rmeth
->stack_item_count
;
2272 fun
= (void (*)()) rmeth
->method
->ncode
;
2274 goto perform_invoke
;
2275 #endif /* DIRECT_THREADED */
2277 insn_invokeinterface
:
2280 int index
= GET2U ();
2282 rmeth
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2285 sp
-= rmeth
->stack_item_count
;
2287 jobject rcv
= sp
[0].o
;
2292 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2293 rmeth
->method
->name
,
2294 rmeth
->method
->signature
);
2296 #ifdef DIRECT_THREADED
2297 // Rewrite instruction so that we use a faster pre-resolved
2299 pc
[-2].insn
= &&invokeinterface_resolved
;
2300 pc
[-1].datum
= rmeth
;
2302 // Skip dummy bytes.
2304 #endif /* DIRECT_THREADED */
2306 goto perform_invoke
;
2308 #ifdef DIRECT_THREADED
2309 invokeinterface_resolved
:
2312 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2313 sp
-= rmeth
->stack_item_count
;
2314 jobject rcv
= sp
[0].o
;
2317 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2318 rmeth
->method
->name
,
2319 rmeth
->method
->signature
);
2321 goto perform_invoke
;
2322 #endif /* DIRECT_THREADED */
2327 int index
= GET2U ();
2328 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2330 /* VM spec, section 3.11.5 */
2331 if ((klass
->getModifiers() & Modifier::ABSTRACT
)
2332 || klass
->isInterface())
2333 throw new java::lang::InstantiationException
;
2334 jobject res
= _Jv_AllocObject (klass
);
2337 #ifdef DIRECT_THREADED
2338 pc
[-2].insn
= &&new_resolved
;
2339 pc
[-1].datum
= klass
;
2340 #endif /* DIRECT_THREADED */
2344 #ifdef DIRECT_THREADED
2347 jclass klass
= (jclass
) AVAL ();
2348 jobject res
= _Jv_AllocObject (klass
);
2352 #endif /* DIRECT_THREADED */
2356 int atype
= GET1U ();
2358 jobject result
= _Jv_NewArray (atype
, size
);
2366 int index
= GET2U ();
2367 jclass klass
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2370 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2373 #ifdef DIRECT_THREADED
2374 pc
[-2].insn
= &&anewarray_resolved
;
2375 pc
[-1].datum
= klass
;
2376 #endif /* DIRECT_THREADED */
2380 #ifdef DIRECT_THREADED
2383 jclass klass
= (jclass
) AVAL ();
2385 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2389 #endif /* DIRECT_THREADED */
2393 __JArray
*arr
= (__JArray
*)POPA();
2394 NULLARRAYCHECK (arr
);
2395 PUSHI (arr
->length
);
2401 jobject value
= POPA();
2402 throw static_cast<jthrowable
>(value
);
2409 jobject value
= POPA();
2410 jint index
= GET2U ();
2411 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2414 value
= (jobject
) _Jv_CheckCast (to
, value
);
2418 #ifdef DIRECT_THREADED
2419 pc
[-2].insn
= &&checkcast_resolved
;
2421 #endif /* DIRECT_THREADED */
2425 #ifdef DIRECT_THREADED
2429 jobject value
= POPA ();
2430 jclass to
= (jclass
) AVAL ();
2431 value
= (jobject
) _Jv_CheckCast (to
, value
);
2435 #endif /* DIRECT_THREADED */
2440 jobject value
= POPA();
2441 jint index
= GET2U ();
2442 jclass to
= (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2444 PUSHI (to
->isInstance (value
));
2446 #ifdef DIRECT_THREADED
2447 pc
[-2].insn
= &&instanceof_resolved
;
2449 #endif /* DIRECT_THREADED */
2453 #ifdef DIRECT_THREADED
2454 instanceof_resolved
:
2456 jobject value
= POPA ();
2457 jclass to
= (jclass
) AVAL ();
2458 PUSHI (to
->isInstance (value
));
2461 #endif /* DIRECT_THREADED */
2465 jobject value
= POPA();
2467 _Jv_MonitorEnter (value
);
2473 jobject value
= POPA();
2475 _Jv_MonitorExit (value
);
2481 jobject val
= POPA();
2491 jobject val
= POPA();
2499 insn_multianewarray
:
2502 int kind_index
= GET2U ();
2506 = (_Jv_Linker::resolve_pool_entry (meth
->defining_class
,
2508 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
2510 for (int i
= dim
- 1; i
>= 0; i
--)
2515 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
2521 #ifndef DIRECT_THREADED
2524 jint the_mod_op
= get1u (pc
++);
2525 jint wide
= get2u (pc
); pc
+= 2;
2570 pc
= (unsigned char*) PEEKA (wide
);
2575 jint amount
= get2s (pc
); pc
+= 2;
2576 jint value
= PEEKI (wide
);
2577 POKEI (wide
, value
+amount
);
2582 throw_internal_error ("illegal bytecode modified by wide");
2586 #endif /* DIRECT_THREADED */
2590 JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint
));
2592 // Send JVMTI notification
2593 using namespace ::java::lang
;
2594 jmethodID method
= meth
->self
;
2595 jlocation location
= meth
->insn_index (pc
- 1);
2596 Thread
*thread
= Thread::currentThread ();
2597 JNIEnv
*jni_env
= _Jv_GetCurrentJNIEnv ();
2599 _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT
, thread
, jni_env
,
2602 // Continue execution
2603 using namespace gnu::gcj::jvmti
;
2605 = BreakpointManager::getBreakpoint (reinterpret_cast<jlong
> (method
),
2607 JvAssert (bp
!= NULL
);
2609 pc_t opc
= reinterpret_cast<pc_t
> (bp
->getInsn ());
2611 #ifdef DIRECT_THREADED
2614 goto *(insn_target
[*opc
]);
2618 catch (java::lang::Throwable
*ex
)
2621 // This needs to be done before the pc is changed.
2622 jlong throw_loc
= meth
->insn_index (pc
);
2624 // Check if the exception is handled and, if so, set the pc to the start
2625 // of the appropriate catch block.
2626 if (meth
->check_handler (&pc
, meth
, ex
))
2629 sp
++->o
= ex
; // Push exception.
2631 if (JVMTI_REQUESTED_EVENT (Exception
))
2633 using namespace gnu::gcj::jvmti
;
2634 jlong throw_meth
= reinterpret_cast<jlong
> (meth
->get_method ());
2635 jlong catch_loc
= meth
->insn_index (pc
);
2636 ExceptionEvent::postExceptionEvent (thread
, throw_meth
,
2637 throw_loc
, ex
, throw_meth
,
2644 if (JVMTI_REQUESTED_EVENT (Exception
))
2646 using namespace gnu::gcj::jvmti
;
2647 jlong throw_meth
= reinterpret_cast<jlong
> (meth
->get_method ());
2648 ExceptionEvent::postExceptionEvent (thread
, throw_meth
, throw_loc
,
2652 // No handler, so re-throw.