_Jv_InterpFrame frame_desc (meth, thread);
#endif
+#ifdef DIRECT_THREADED
+ ThreadCountAdjuster adj (meth, &frame_desc);
+#endif // DIRECT_THREADED
+
_Jv_word stack[meth->max_stack];
_Jv_word *sp = stack;
} \
while (0)
+// We fail to rewrite a breakpoint if there is another thread
+// currently executing this method. This is a bug, but there's
+// nothing else we can do that doesn't cause a data race.
#undef REWRITE_INSN
#define REWRITE_INSN(INSN,SLOT,VALUE) \
- do { \
- if (pc[-2].insn == breakpoint_insn->insn) \
- { \
- using namespace ::gnu::gcj::jvmti; \
- jlocation location = meth->insn_index (pc - 2); \
- _Jv_RewriteBreakpointInsn (meth->self, location, (pc_t) INSN); \
- } \
- else \
- pc[-2].insn = INSN; \
+ do \
+ { \
+ _Jv_MutexLock (&rewrite_insn_mutex); \
+ if (meth->thread_count <= 1) \
+ { \
+ if (pc[-2].insn == breakpoint_insn->insn) \
+ { \
+ using namespace ::gnu::gcj::jvmti; \
+ jlocation location = meth->insn_index (pc - 2); \
+ _Jv_RewriteBreakpointInsn (meth->self, location, (pc_t) INSN); \
+ } \
+ else \
+ pc[-2].insn = INSN; \
\
- pc[-1].SLOT = VALUE; \
- } \
+ pc[-1].SLOT = VALUE; \
+ } \
+ _Jv_MutexUnlock (&rewrite_insn_mutex); \
+ } \
while (0)
#undef INTERP_REPORT_EXCEPTION
#else // !DEBUG
#undef NEXT_INSN
#define NEXT_INSN goto *((pc++)->insn)
+
+// Rewriting a multi-word instruction in the presence of multiple
+// threads is a data race if a thread reads part of an instruction
+// while some other thread is rewriting that instruction. We detect
+// more than one thread executing a method and don't rewrite the
+// instruction. A thread entering a method blocks on
+// rewrite_insn_mutex until the write is complete.
#define REWRITE_INSN(INSN,SLOT,VALUE) \
do { \
- pc[-2].insn = INSN; \
- pc[-1].SLOT = VALUE; \
+ _Jv_MutexLock (&rewrite_insn_mutex); \
+ if (meth->thread_count <= 1) \
+ { \
+ pc[-2].insn = INSN; \
+ pc[-1].SLOT = VALUE; \
+ } \
+ _Jv_MutexUnlock (&rewrite_insn_mutex); \
} \
while (0)
{
/* here goes the magic again... */
ffi_cif *cif = &rmeth->cif;
- ffi_raw *raw = (ffi_raw*) sp;
+ INTERP_FFI_RAW_TYPE *raw = (INTERP_FFI_RAW_TYPE *) sp;
_Jv_value rvalue;