#include <gnu/gcj/jvmti/Breakpoint.h>
#include <gnu/gcj/jvmti/BreakpointManager.h>
-#include <gnu/gcj/jvmti/ExceptionEvent.h>
-
-#ifdef INTERPRETER
// Execution engine for interpreted code.
_Jv_InterpreterEngine _Jv_soleInterpreterEngine;
// the Class monitor as user code in another thread could hold it.
static _Jv_Mutex_t compile_mutex;
+// See class ThreadCountAdjuster and REWRITE_INSN for how this is
+// used.
+_Jv_Mutex_t _Jv_InterpMethod::rewrite_insn_mutex;
+
void
_Jv_InitInterpreter()
{
_Jv_MutexInit (&compile_mutex);
+ _Jv_MutexInit (&_Jv_InterpMethod::rewrite_insn_mutex);
}
#else
void _Jv_InitInterpreter() {}
# define LOADD(I) LOADL(I)
#endif
-#define STOREA(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'o'); \
- locals[I].o = (--sp)->o; \
- } while (0)
-#define STOREI(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'i'); \
- locals[I].i = (--sp)->i; \
- } while (0)
-#define STOREF(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'f'); \
- locals[I].f = (--sp)->f; \
+#define STOREA(I) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'o'); \
+ locals[__idx].o = (--sp)->o; \
+ } \
+ while (0)
+#define STOREI(I) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'i'); \
+ locals[__idx].i = (--sp)->i; \
} while (0)
+#define STOREF(I) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'f'); \
+ locals[__idx].f = (--sp)->f; \
+ } \
+ while (0)
#if SIZEOF_VOID_P == 8
-# define STOREL(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'l'); \
- DEBUG_LOCALS_INSN (I + 1, 'x'); \
- (sp -= 2, locals[I].l = sp->l); \
- } while (0)
-# define STORED(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'd'); \
- DEBUG_LOCALS_INSN (I + 1, 'x'); \
- (sp -= 2, locals[I].d = sp->d); \
- } while (0)
+# define STOREL(I) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'l'); \
+ DEBUG_LOCALS_INSN (__idx + 1, 'x'); \
+ (sp -= 2, locals[__idx].l = sp->l); \
+ } \
+ while (0)
+# define STORED(I) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'd'); \
+ DEBUG_LOCALS_INSN (__idx + 1, 'x'); \
+ (sp -= 2, locals[__idx].d = sp->d); \
+ } \
+ while (0)
#else
-# define STOREL(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'l'); \
- DEBUG_LOCALS_INSN (I + 1, 'x'); \
- jint __idx = (I); \
- locals[__idx+1].ia[0] = (--sp)->ia[0]; \
- locals[__idx].ia[0] = (--sp)->ia[0]; \
- } while (0)
-# define STORED(I) \
- do { \
- DEBUG_LOCALS_INSN (I, 'd'); \
- DEBUG_LOCALS_INSN (I + 1, 'x'); \
- jint __idx = (I); \
- locals[__idx+1].ia[0] = (--sp)->ia[0]; \
- locals[__idx].ia[0] = (--sp)->ia[0]; \
+# define STOREL(I) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'l'); \
+ DEBUG_LOCALS_INSN (__idx + 1, 'x'); \
+ locals[__idx + 1].ia[0] = (--sp)->ia[0]; \
+ locals[__idx].ia[0] = (--sp)->ia[0]; \
+ } \
+ while (0)
+# define STORED(I) \
+ do { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'd'); \
+ DEBUG_LOCALS_INSN (__idx + 1, 'x'); \
+ locals[__idx + 1].ia[0] = (--sp)->ia[0]; \
+ locals[__idx].ia[0] = (--sp)->ia[0]; \
} while (0)
#endif
#define PEEKI(I) (locals+(I))->i
#define PEEKA(I) (locals+(I))->o
-#define POKEI(I,V) \
- DEBUG_LOCALS_INSN(I,'i'); \
- ((locals+(I))->i = (V))
+#define POKEI(I,V) \
+ do \
+ { \
+ jint __idx = (I); \
+ DEBUG_LOCALS_INSN (__idx, 'i'); \
+ ((locals + __idx)->i = (V)); \
+ } \
+ while (0)
#define BINOPI(OP) { \
void
_Jv_InterpMethod::run_normal (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_normal_debug (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_synch_object (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_synch_object_debug (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_class (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_class_debug (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_synch_class (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
void
_Jv_InterpMethod::run_synch_class_debug (ffi_cif *,
void *ret,
- ffi_raw *args,
+ INTERP_FFI_RAW_TYPE *args,
void *__this)
{
_Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
prepared = insns;
+ // Now remap the variable table for this method.
+ for (int i = 0; i < local_var_table_len; ++i)
+ {
+ int start_byte = local_var_table[i].bytecode_pc;
+ if (start_byte < 0 || start_byte >= code_length)
+ start_byte = 0;
+ jlocation start = pc_mapping[start_byte];
+
+ int end_byte = start_byte + local_var_table[i].length;
+ if (end_byte < 0)
+ end_byte = 0;
+ jlocation end = ((end_byte >= code_length)
+ ? number_insn_slots
+ : pc_mapping[end_byte]);
+
+ local_var_table[i].pc = &insns[start];
+ local_var_table[i].length = end - start + 1;
+ }
+
if (breakpoint_insn == NULL)
{
bp_insn_slot.insn = const_cast<void *> (insn_targets[op_breakpoint]);
/* Run the given method.
When args is NULL, don't run anything -- just compile it. */
void
-_Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+_Jv_InterpMethod::run (void *retp, INTERP_FFI_RAW_TYPE *args,
+ _Jv_InterpMethod *meth)
{
-#undef DEBUG
+#undef __GCJ_DEBUG
#undef DEBUG_LOCALS_INSN
#define DEBUG_LOCALS_INSN(s, t) do {} while (0)
}
void
-_Jv_InterpMethod::run_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+_Jv_InterpMethod::run_debug (void *retp, INTERP_FFI_RAW_TYPE *args,
+ _Jv_InterpMethod *meth)
{
-#define DEBUG
+#define __GCJ_DEBUG
#undef DEBUG_LOCALS_INSN
#define DEBUG_LOCALS_INSN(s, t) \
do \
return item_count;
}
-#if FFI_NATIVE_RAW_API
-# define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure_loc
-# define FFI_RAW_SIZE ffi_raw_size
-#else
-# define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure_loc
-# define FFI_RAW_SIZE ffi_java_raw_size
-#endif
-
/* we put this one here, and not in interpret.cc because it
* calls the utility routines _Jv_count_arguments
* which are static to this module. The following struct defines the
* layout we use for the stubs, it's only used in the ncode method. */
+#if FFI_NATIVE_RAW_API
+# define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure_loc
+# define FFI_RAW_SIZE ffi_raw_size
typedef struct {
ffi_raw_closure closure;
_Jv_ClosureList list;
ffi_cif cif;
ffi_type *arg_types[0];
} ncode_closure;
-
-typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
+typedef void (*ffi_closure_fun) (ffi_cif*,void*,INTERP_FFI_RAW_TYPE*,void*);
+#else
+# define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure_loc
+# define FFI_RAW_SIZE ffi_java_raw_size
+typedef struct {
+ ffi_java_raw_closure closure;
+ _Jv_ClosureList list;
+ ffi_cif cif;
+ ffi_type *arg_types[0];
+} ncode_closure;
+typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_java_raw*,void*);
+#endif
void *
_Jv_InterpMethod::ncode (jclass klass)
char **generic_sig, jlong *startloc,
jint *length, jint *slot,
int table_slot)
-{
+{
+#ifdef DIRECT_THREADED
+ _Jv_CompileMethod (this);
+#endif
+
if (local_var_table == NULL)
return -2;
if (table_slot >= local_var_table_len)
*sig = local_var_table[table_slot].descriptor;
*generic_sig = local_var_table[table_slot].descriptor;
- *startloc = static_cast<jlong>
- (local_var_table[table_slot].bytecode_start_pc);
+#ifdef DIRECT_THREADED
+ *startloc = insn_index (local_var_table[table_slot].pc);
+#else
+ *startloc = static_cast<jlong> (local_var_table[table_slot].bytecode_pc);
+#endif
*length = static_cast<jint> (local_var_table[table_slot].length);
*slot = static_cast<jint> (local_var_table[table_slot].slot);
}
- return local_var_table_len - table_slot -1;
+ return local_var_table_len - table_slot - 1;
}
pc_t
return &code[index];
}
+bool
+_Jv_InterpMethod::breakpoint_at (jlong index)
+{
+ pc_t insn = get_insn (index);
+ if (insn != NULL)
+ {
+#ifdef DIRECT_THREADED
+ return (insn->insn == breakpoint_insn->insn);
+#else
+ pc_t code = reinterpret_cast<pc_t> (bytecode ());
+ return (code[index] == breakpoint_insn);
+#endif
+ }
+
+ return false;
+}
+
void *
_Jv_JNIMethod::ncode (jclass klass)
{
CATCH_LOCATION with the method and location where the catch will
occur. If the exception is not caught, these are set to 0.
- This function should only be used with the DEBUG interpreter. */
+ This function should only be used with the __GCJ_DEBUG interpreter. */
static void
find_catch_location (::java::lang::Throwable *exc, jthread thread,
jmethodID *catch_method, jlong *catch_loc)
caught (if it is caught).
Like find_catch_location, this should only be called with the
- DEBUG interpreter. Since a few exceptions occur outside the
+ __GCJ_DEBUG interpreter. Since a few exceptions occur outside the
interpreter proper, it is important to not call this function
without checking JVMTI_REQUESTED_EVENT(Exception) first. */
void
}
}
#endif // DIRECT_THREADED
-
-#endif // INTERPRETER