don't try to release monitor if we get OOME when trying to acquire it

We can't blindly try release the monitors for all synchronized methods
when unwinding the stack since we may not have finished acquiring the
most recent one when the exception was thrown.
This commit is contained in:
Joel Dice 2011-03-25 18:37:02 -06:00
parent 3e93d5d337
commit b9f8188544
3 changed files with 51 additions and 23 deletions

View File

@ -235,7 +235,8 @@ class MyThread: public Thread {
: makeArchitecture(m->system, useNativeFeatures)), : makeArchitecture(m->system, useNativeFeatures)),
transition(0), transition(0),
traceContext(0), traceContext(0),
stackLimit(0) stackLimit(0),
methodLockIsClean(true)
{ {
arch->acquire(); arch->acquire();
} }
@ -256,6 +257,7 @@ class MyThread: public Thread {
Context* transition; Context* transition;
TraceContext* traceContext; TraceContext* traceContext;
uintptr_t stackLimit; uintptr_t stackLimit;
bool methodLockIsClean;
}; };
void void
@ -1982,16 +1984,23 @@ void
releaseLock(MyThread* t, object method, void* stack) releaseLock(MyThread* t, object method, void* stack)
{ {
if (methodFlags(t, method) & ACC_SYNCHRONIZED) { if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
object lock; if (t->methodLockIsClean) {
if (methodFlags(t, method) & ACC_STATIC) { object lock;
lock = methodClass(t, method); if (methodFlags(t, method) & ACC_STATIC) {
} else { lock = methodClass(t, method);
lock = *localObject } else {
(t, stackForFrame(t, stack, method), method, lock = *localObject
savedTargetIndex(t, method)); (t, stackForFrame(t, stack, method), method,
} savedTargetIndex(t, method));
}
release(t, lock); release(t, lock);
} else {
// got an exception while trying to acquire the lock for a
// synchronized method -- don't try to release it, since we
// never succeeded in acquiring it.
t->methodLockIsClean = true;
}
} }
} }
@ -2764,6 +2773,18 @@ acquireMonitorForObject(MyThread* t, object o)
} }
} }
void
acquireMonitorForObjectOnEntrance(MyThread* t, object o)
{
if (LIKELY(o)) {
t->methodLockIsClean = false;
acquire(t, o);
t->methodLockIsClean = true;
} else {
throwNew(t, Machine::NullPointerExceptionType);
}
}
void void
releaseMonitorForObject(MyThread* t, object o) releaseMonitorForObject(MyThread* t, object o)
{ {
@ -3456,7 +3477,7 @@ handleEntrance(MyThread* t, Frame* frame)
} }
handleMonitorEvent handleMonitorEvent
(t, frame, getThunk(t, acquireMonitorForObjectThunk)); (t, frame, getThunk(t, acquireMonitorForObjectOnEntranceThunk));
} }
void void

View File

@ -322,15 +322,29 @@ setLocalLong(Thread* t, unsigned index, uint64_t value)
void void
pushFrame(Thread* t, object method) pushFrame(Thread* t, object method)
{ {
if (t->frame >= 0) { PROTECT(t, method);
pokeInt(t, t->frame + FrameIpOffset, t->ip);
}
t->ip = 0;
unsigned parameterFootprint = methodParameterFootprint(t, method); unsigned parameterFootprint = methodParameterFootprint(t, method);
unsigned base = t->sp - parameterFootprint; unsigned base = t->sp - parameterFootprint;
unsigned locals = parameterFootprint; unsigned locals = parameterFootprint;
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
// Try to acquire the monitor before doing anything else.
// Otherwise, if we were to push the frame first, we risk trying
// to release a monitor we never successfully acquired when we try
// to pop the frame back off.
if (methodFlags(t, method) & ACC_STATIC) {
acquire(t, methodClass(t, method));
} else {
acquire(t, peekObject(t, base));
}
}
if (t->frame >= 0) {
pokeInt(t, t->frame + FrameIpOffset, t->ip);
}
t->ip = 0;
if ((methodFlags(t, method) & ACC_NATIVE) == 0) { if ((methodFlags(t, method) & ACC_NATIVE) == 0) {
t->code = methodCode(t, method); t->code = methodCode(t, method);
@ -349,14 +363,6 @@ pushFrame(Thread* t, object method)
pokeInt(t, frame + FrameBaseOffset, base); pokeInt(t, frame + FrameBaseOffset, base);
pokeObject(t, frame + FrameMethodOffset, method); pokeObject(t, frame + FrameMethodOffset, method);
pokeInt(t, t->frame + FrameIpOffset, 0); pokeInt(t, t->frame + FrameIpOffset, 0);
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
if (methodFlags(t, method) & ACC_STATIC) {
acquire(t, methodClass(t, method));
} else {
acquire(t, peekObject(t, base));
}
}
} }
void void

View File

@ -45,6 +45,7 @@ THUNK(makeBlankArray)
THUNK(lookUpAddress) THUNK(lookUpAddress)
THUNK(setMaybeNull) THUNK(setMaybeNull)
THUNK(acquireMonitorForObject) THUNK(acquireMonitorForObject)
THUNK(acquireMonitorForObjectOnEntrance)
THUNK(releaseMonitorForObject) THUNK(releaseMonitorForObject)
THUNK(makeMultidimensionalArray) THUNK(makeMultidimensionalArray)
THUNK(makeMultidimensionalArrayFromReference) THUNK(makeMultidimensionalArrayFromReference)