aboutsummaryrefslogtreecommitdiff
path: root/libjava/interpret-run.cc
diff options
context:
space:
mode:
authorAndrew Haley <aph@redhat.com>2008-09-23 13:51:58 +0000
committerAndrew Haley <aph@redhat.com>2008-09-23 13:51:58 +0000
commit051008685ad9572eef4e38b46583ffe5695f5d6a (patch)
tree5aa7ac0da62ededbaab14350de950b012a5759a3 /libjava/interpret-run.cc
parentbe85a99f4e682552ffe3794a3893d233a2e20deb (diff)
2008-09-17 Andrew Haley <aph@redhat.com>
PR libgcj/8995: * defineclass.cc (_Jv_ClassReader::handleCodeAttribute): Initialize thread_count. * include/java-interp.h (_Jv_InterpMethod::thread_count): New field. (_Jv_InterpMethod::rewrite_insn_mutex): New mutex. (_Jv_InterpFrame:: _Jv_InterpFrame): Pass frame_type. * interpret.cc (ThreadCountAdjuster): New class. (_Jv_InterpMethod::thread_count): New field. (_Jv_InitInterpreter): Initialize rewrite_insn_mutex. Increment and decrement thread_count field in methods. * interpret-run.cc (REWRITE_INSN): Check thread_count <= 1. (REWRITE_INSN): Likewise. Declare a ThreadCountAdjuster. * java/lang/reflect/natVMProxy.cc (run_proxy): Initialize frame type as frame_proxy. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@140593 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/interpret-run.cc')
-rw-r--r--libjava/interpret-run.cc67
1 files changed, 40 insertions, 27 deletions
diff --git a/libjava/interpret-run.cc b/libjava/interpret-run.cc
index 2934b9b8956..059195360ed 100644
--- a/libjava/interpret-run.cc
+++ b/libjava/interpret-run.cc
@@ -29,6 +29,10 @@ details. */
_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;
@@ -361,20 +365,29 @@ details. */
} \
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
@@ -383,23 +396,23 @@ details. */
#undef NEXT_INSN
#define NEXT_INSN goto *((pc++)->insn)
-// REWRITE_INSN does nothing.
-//
// Rewriting a multi-word instruction in the presence of multiple
-// threads leads to a data race if a thread reads part of an
-// instruction while some other thread is rewriting that instruction.
-// For example, an invokespecial instruction may be rewritten to
-// invokespecial_resolved and its operand changed from an index to a
-// pointer while another thread is executing invokespecial. This
-// other thread then reads the pointer that is now the operand of
-// invokespecial_resolved and tries to use it as an index.
-//
-// Fixing this requires either spinlocks, a more elaborate data
-// structure, or even per-thread allocated pages. It's clear from the
-// locking in meth->compile below that the presence of multiple
-// threads was contemplated when this code was written, but the full
-// consequences were not fully appreciated.
-#define REWRITE_INSN(INSN,SLOT,VALUE)
+// 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 { \
+ _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)
#undef INTERP_REPORT_EXCEPTION
#define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */