diff --git a/src/arch.h b/src/arch.h index 1dc335de6c..622e99a2fc 100644 --- a/src/arch.h +++ b/src/arch.h @@ -17,6 +17,20 @@ extern "C" void NO_RETURN vmJump(void* address, void* base, void* stack, void* thread, uintptr_t returnLow, uintptr_t returnHigh); +namespace vm { + +inline void +compileTimeMemoryBarrier() +{ +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else + __asm__ __volatile__("": : :"memory"); +#endif +} + +} // namespace vm + #if (defined ARCH_x86_32) || (defined ARCH_x86_64) # include "x86.h" #elif defined ARCH_powerpc diff --git a/src/compile-powerpc.S b/src/compile-powerpc.S index c90f16c625..8936899b53 100644 --- a/src/compile-powerpc.S +++ b/src/compile-powerpc.S @@ -24,11 +24,11 @@ # define GLOBAL(x) x #endif -#define THREAD_CONTINUATION 100 -#define THREAD_EXCEPTION 36 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 104 -#define THREAD_EXCEPTION_OFFSET 108 -#define THREAD_EXCEPTION_HANDLER 112 +#define THREAD_CONTINUATION 112 +#define THREAD_EXCEPTION 44 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 116 +#define THREAD_EXCEPTION_OFFSET 120 +#define THREAD_EXCEPTION_HANDLER 124 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/compile.cpp b/src/compile.cpp index 00fa33aa15..a695bd2367 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -588,8 +588,8 @@ print(SubroutinePath* path) if (path) { fprintf(stderr, " ("); while (true) { - fprintf(stderr, "%p", reinterpret_cast - (path->call->returnAddress->value())); + fprintf(stderr, "%p", path->call->returnAddress->resolved() ? + reinterpret_cast(path->call->returnAddress->value()) : 0); path = path->stackNext; if (path) { fprintf(stderr, ", "); @@ -603,13 +603,18 @@ print(SubroutinePath* path) class SubroutineTrace { public: - SubroutineTrace(SubroutinePath* path, SubroutineTrace* next): + SubroutineTrace(SubroutinePath* path, SubroutineTrace* next, + unsigned mapSize): path(path), - next(next) - { } + next(next), + watch(false) + { + memset(map, 0, mapSize * BytesPerWord); + } SubroutinePath* path; SubroutineTrace* next; + bool watch; uintptr_t map[0]; }; @@ -619,17 +624,21 @@ class TraceElement: public TraceHandler { static const unsigned TailCall = 1 << 1; static const unsigned LongCall = 1 << 2; - TraceElement(Context* context, object target, unsigned flags, - TraceElement* next): + TraceElement(Context* context, unsigned ip, object target, unsigned flags, + TraceElement* next, unsigned mapSize): context(context), address(0), next(next), subroutineTrace(0), - subroutineTraceCount(0), target(target), + ip(ip), + subroutineTraceCount(0), argumentIndex(0), - flags(flags) - { } + flags(flags), + watch(false) + { + memset(map, 0, mapSize * BytesPerWord); + } virtual void handleTrace(Promise* address, unsigned argumentIndex) { if (this->address == 0) { @@ -642,10 +651,12 @@ class TraceElement: public TraceHandler { Promise* address; TraceElement* next; SubroutineTrace* subroutineTrace; - unsigned subroutineTraceCount; object target; + unsigned ip; + unsigned subroutineTraceCount; unsigned argumentIndex; unsigned flags; + bool watch; uintptr_t map[0]; }; @@ -1587,7 +1598,7 @@ class Frame { TraceElement* e = context->traceLog = new (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) - TraceElement(context, target, flags, context->traceLog); + TraceElement(context, ip, target, flags, context->traceLog, mapSize); ++ context->traceLogCount; @@ -4923,6 +4934,63 @@ printSet(uintptr_t m, unsigned limit) } } +void +calculateTryCatchRoots(Context* context, SubroutinePath* subroutinePath, + uintptr_t* roots, unsigned mapSize, unsigned start, + unsigned end) +{ + memset(roots, 0xFF, mapSize * BytesPerWord); + + if (DebugFrameMaps) { + fprintf(stderr, "calculate try/catch roots from %d to %d", start, end); + if (subroutinePath) { + fprintf(stderr, " "); + print(subroutinePath); + } + fprintf(stderr, "\n"); + } + + for (TraceElement* te = context->traceLog; te; te = te->next) { + if (te->ip >= start and te->ip < end) { + uintptr_t* traceRoots = 0; + if (subroutinePath == 0) { + traceRoots = te->map; + te->watch = true; + } else { + for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) { + if (t->path == subroutinePath) { + traceRoots = t->map; + t->watch = true; + break; + } + } + } + + if (traceRoots) { + if (DebugFrameMaps) { + fprintf(stderr, " use roots at ip %3d: ", te->ip); + printSet(*traceRoots, mapSize); + fprintf(stderr, "\n"); + } + + for (unsigned wi = 0; wi < mapSize; ++wi) { + roots[wi] &= traceRoots[wi]; + } + } else { + if (DebugFrameMaps) { + fprintf(stderr, " skip roots at ip %3d\n", te->ip); + } + } + } + } + + if (DebugFrameMaps) { + fprintf(stderr, "result roots : "); + printSet(*roots, mapSize); + fprintf(stderr, "\n"); + } +} + unsigned calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, unsigned eventIndex, SubroutinePath* subroutinePath = 0) @@ -4969,7 +5037,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, eventIndex += 2; if (DebugFrameMaps) { - fprintf(stderr, " roots at ip %3d: ", ip); + fprintf(stderr, " roots at ip %3d: ", ip); printSet(*RUNTIME_ARRAY_BODY(roots), mapSize); fprintf(stderr, "\n"); } @@ -4998,7 +5066,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, } if (DebugFrameMaps) { - fprintf(stderr, "table roots at ip %3d: ", ip); + fprintf(stderr, " table roots at ip %3d: ", ip); printSet(*tableRoots, mapSize); fprintf(stderr, "\n"); } @@ -5022,27 +5090,27 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, } break; case PushExceptionHandlerEvent: { - unsigned reference = context->eventLog.get2(eventIndex); + unsigned start = context->eventLog.get2(eventIndex); + eventIndex += 2; + unsigned end = context->eventLog.get2(eventIndex); eventIndex += 2; - if (context->subroutineTable and context->subroutineTable[reference]) { - Subroutine* s = context->subroutineTable[reference]; + if (context->subroutineTable and context->subroutineTable[start]) { + Subroutine* s = context->subroutineTable[start]; unsigned originalEventIndex = eventIndex; for (SubroutineCall* c = s->calls; c; c = c->next) { for (SubroutinePath* p = c->paths; p; p = p->listNext) { - memcpy(RUNTIME_ARRAY_BODY(roots), - p->rootTable + (reference * mapSize), - mapSize * BytesPerWord); + calculateTryCatchRoots + (context, p, RUNTIME_ARRAY_BODY(roots), mapSize, start, end); eventIndex = calculateFrameMaps (t, context, RUNTIME_ARRAY_BODY(roots), originalEventIndex, p); } } } else { - memcpy(RUNTIME_ARRAY_BODY(roots), - context->rootTable + (reference * mapSize), - mapSize * BytesPerWord); + calculateTryCatchRoots + (context, 0, RUNTIME_ARRAY_BODY(roots), mapSize, start, end); eventIndex = calculateFrameMaps (t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, 0); @@ -5052,7 +5120,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, case TraceEvent: { TraceElement* te; context->eventLog.get(eventIndex, &te, BytesPerWord); if (DebugFrameMaps) { - fprintf(stderr, "trace roots at ip %3d: ", ip); + fprintf(stderr, " trace roots at ip %3d: ", ip); printSet(*RUNTIME_ARRAY_BODY(roots), mapSize); if (subroutinePath) { fprintf(stderr, " "); @@ -5060,14 +5128,18 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, } fprintf(stderr, "\n"); } - + + uintptr_t* map; + bool watch; if (subroutinePath == 0) { - memcpy(te->map, RUNTIME_ARRAY_BODY(roots), mapSize * BytesPerWord); + map = te->map; + watch = te->watch; } else { SubroutineTrace* trace = 0; for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) { if (t->path == subroutinePath) { trace = t; + break; } } @@ -5075,12 +5147,27 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, te->subroutineTrace = trace = new (context->zone.allocate (sizeof(SubroutineTrace) + (mapSize * BytesPerWord))) - SubroutineTrace(subroutinePath, te->subroutineTrace); + SubroutineTrace(subroutinePath, te->subroutineTrace, mapSize); ++ te->subroutineTraceCount; } - memcpy(trace->map, RUNTIME_ARRAY_BODY(roots), mapSize * BytesPerWord); + map = trace->map; + watch = trace->watch; + } + + for (unsigned wi = 0; wi < mapSize; ++wi) { + uintptr_t v = RUNTIME_ARRAY_BODY(roots)[wi]; + + if (watch and map[wi] != v) { + if (DebugFrameMaps) { + fprintf(stderr, "dirty roots due to trace watch!\n"); + } + + context->dirtyRoots = true; + } + + map[wi] = v; } eventIndex += BytesPerWord; @@ -5184,14 +5271,12 @@ copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits, SubroutinePath* subroutinePath) { if (DebugFrameMaps) { - fprintf(stderr, " orig roots at ip %p: ", reinterpret_cast - (p->address->value())); + fprintf(stderr, " orig roots at ip %3d: ", p->ip); printSet(src[0], ceiling(mapSizeInBits, BitsPerWord)); print(subroutinePath); fprintf(stderr, "\n"); - fprintf(stderr, "final roots at ip %p: ", reinterpret_cast - (p->address->value())); + fprintf(stderr, " final roots at ip %3d: ", p->ip); } for (unsigned j = 0; j < p->argumentIndex; ++j) { @@ -5698,8 +5783,16 @@ compile(MyThread* t, Allocator* allocator, Context* context) codeMaxStack(t, methodCode(t, context->method))); Frame frame2(&frame, RUNTIME_ARRAY_BODY(stackMap)); + unsigned end = exceptionHandlerEnd(eh); + if (exceptionHandlerIp(eh) >= start + and exceptionHandlerIp(eh) < end) + { + end = exceptionHandlerIp(eh); + } + context->eventLog.append(PushExceptionHandlerEvent); context->eventLog.append2(start); + context->eventLog.append2(end); for (unsigned i = 1; i < codeMaxStack(t, methodCode(t, context->method)); @@ -7211,9 +7304,9 @@ class MyProcessor: public Processor { compile(static_cast(t), local::codeAllocator(static_cast(t)), 0, resolveMethod(t, t->m->loader, - "java/beans/PropertyChangeSupport", - "firePropertyChange", - "(Ljava/beans/PropertyChangeEvent;)V")); + "com/ecovate/nat/logic/Cache", + "findInCache", + "(Ljava/lang/String;Ljava/lang/String;JZ)Lcom/ecovate/shared/xmlrpc/Resource;")); trap(); } diff --git a/src/continuations-x86.S b/src/continuations-x86.S index 2151659ddf..aeee640388 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,11 +10,11 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 176 -#define THREAD_EXCEPTION 64 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 184 -#define THREAD_EXCEPTION_OFFSET 192 -#define THREAD_EXCEPTION_HANDLER 200 +#define THREAD_CONTINUATION 192 +#define THREAD_EXCEPTION 80 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 200 +#define THREAD_EXCEPTION_OFFSET 208 +#define THREAD_EXCEPTION_HANDLER 216 #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 @@ -89,11 +89,11 @@ LOCAL(vmInvoke_exit): #elif defined __i386__ -#define THREAD_CONTINUATION 100 -#define THREAD_EXCEPTION 36 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 104 -#define THREAD_EXCEPTION_OFFSET 108 -#define THREAD_EXCEPTION_HANDLER 112 +#define THREAD_CONTINUATION 108 +#define THREAD_EXCEPTION 44 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 112 +#define THREAD_EXCEPTION_OFFSET 116 +#define THREAD_EXCEPTION_HANDLER 120 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/machine.cpp b/src/machine.cpp index 8507e9c256..44247f52cb 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1808,17 +1808,13 @@ removeMonitor(Thread* t, object o) hash = objectHash(t, o); } - object p = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual); + object m = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual); - expect(t, p); + expect(t, m); if (DebugMonitors) { - fprintf(stderr, "dispose monitor %p for object %x\n", - static_cast(pointerValue(t, p)), - hash); + fprintf(stderr, "dispose monitor %p for object %x\n", m, hash); } - - static_cast(pointerValue(t, p))->dispose(); } void @@ -2185,9 +2181,11 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): parent(parent), peer((parent ? parent->child : 0)), child(0), + waitNext(0), state(NoState), criticalLevel(0), systemThread(0), + lock(0), javaThread(javaThread), exception(0), heapIndex(0), @@ -2201,6 +2199,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): backupHeap(0), backupHeapIndex(0), backupHeapSizeInWords(0), + waiting(false), tracing(false) #ifdef VM_STRESS , stress(false) @@ -2255,6 +2254,8 @@ Thread::init() parent->child = this; } + expect(this, m->system->success(m->system->make(&lock))); + if (javaThread == 0) { this->javaThread = makeJavaThread(this, parent); } @@ -2282,6 +2283,8 @@ Thread::exit() void Thread::dispose() { + lock->dispose(); + if (systemThread) { systemThread->dispose(); } @@ -3419,52 +3422,48 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)) t->m->finalizers = f; } -System::Monitor* +object objectMonitor(Thread* t, object o, bool createNew) { assert(t, t->state == Thread::ActiveState); - object p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual); + object m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual); - if (p) { + if (m) { if (DebugMonitors) { - fprintf(stderr, "found monitor %p for object %x\n", - static_cast(pointerValue(t, p)), - objectHash(t, o)); + fprintf(stderr, "found monitor %p for object %x\n", m, objectHash(t, o)); } - return static_cast(pointerValue(t, p)); + return m; } else if (createNew) { PROTECT(t, o); + PROTECT(t, m); - ENTER(t, Thread::ExclusiveState); + { ENTER(t, Thread::ExclusiveState); + + m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual); + if (m) { + if (DebugMonitors) { + fprintf(stderr, "found monitor %p for object %x\n", + m, objectHash(t, o)); + } + + return m; + } + + object head = makeMonitorNode(t, 0, 0); + m = makeMonitor(t, 0, 0, 0, head, head, 0); - p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual); - if (p) { if (DebugMonitors) { - fprintf(stderr, "found monitor %p for object %x\n", - static_cast(pointerValue(t, p)), + fprintf(stderr, "made monitor %p for object %x\n", m, objectHash(t, o)); } - return static_cast(pointerValue(t, p)); + hashMapInsert(t, t->m->monitorMap, o, m, objectHash); + + addFinalizer(t, o, removeMonitor); } - System::Monitor* m; - System::Status s = t->m->system->make(&m); - expect(t, t->m->system->success(s)); - - if (DebugMonitors) { - fprintf(stderr, "made monitor %p for object %x\n", - m, - objectHash(t, o)); - } - - p = makePointer(t, m); - hashMapInsert(t, t->m->monitorMap, o, p, objectHash); - - addFinalizer(t, o, removeMonitor); - return m; } else { return 0; diff --git a/src/machine.h b/src/machine.h index fa8d99936d..2ea8b94bd5 100644 --- a/src/machine.h +++ b/src/machine.h @@ -17,6 +17,7 @@ #include "finder.h" #include "processor.h" #include "constants.h" +#include "arch.h" #ifdef PLATFORM_WINDOWS # define JNICALL __stdcall @@ -1345,9 +1346,11 @@ class Thread { Thread* parent; Thread* peer; Thread* child; + Thread* waitNext; State state; unsigned criticalLevel; System::Thread* systemThread; + System::Monitor* lock; object javaThread; object exception; unsigned heapIndex; @@ -1360,6 +1363,7 @@ class Thread { uintptr_t* backupHeap; unsigned backupHeapIndex; unsigned backupHeapSizeInWords; + bool waiting; bool tracing; #ifdef VM_STRESS bool stress; @@ -2296,7 +2300,316 @@ parameterFootprint(Thread* t, const char* s, bool static_); void addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); -System::Monitor* +inline bool +atomicCompareAndSwapObject(Thread* t, object target, unsigned offset, + object old, object new_) +{ + if (atomicCompareAndSwap(&cast(target, offset), + reinterpret_cast(old), + reinterpret_cast(new_))) + { + mark(t, target, offset); + return true; + } else { + return false; + } +} + +// The following two methods (monitorAtomicAppendAcquire and +// monitorAtomicPollAcquire) use the Michael and Scott Non-Blocking +// Queue Algorithm: http://www.cs.rochester.edu/u/michael/PODC96.html + +inline void +monitorAtomicAppendAcquire(Thread* t, object monitor) +{ + PROTECT(t, monitor); + + object node = makeMonitorNode(t, t, 0); + + while (true) { + object tail = monitorAcquireTail(t, monitor); + + loadMemoryBarrier(); + + object next = monitorNodeNext(t, tail); + + loadMemoryBarrier(); + + if (tail == monitorAcquireTail(t, monitor)) { + if (next) { + atomicCompareAndSwapObject + (t, monitor, MonitorAcquireTail, tail, next); + } else if (atomicCompareAndSwapObject + (t, tail, MonitorNodeNext, 0, node)) + { + atomicCompareAndSwapObject + (t, monitor, MonitorAcquireTail, tail, node); + return; + } + } + } +} + +inline Thread* +monitorAtomicPollAcquire(Thread* t, object monitor, bool remove) +{ + while (true) { + object head = monitorAcquireHead(t, monitor); + + loadMemoryBarrier(); + + object tail = monitorAcquireTail(t, monitor); + + loadMemoryBarrier(); + + object next = monitorNodeNext(t, head); + + loadMemoryBarrier(); + + if (head == monitorAcquireHead(t, monitor)) { + if (head == tail) { + if (next) { + atomicCompareAndSwapObject + (t, monitor, MonitorAcquireTail, tail, next); + } else { + return 0; + } + } else { + Thread* value = static_cast(monitorNodeValue(t, next)); + if ((not remove) + or atomicCompareAndSwapObject + (t, monitor, MonitorAcquireHead, head, next)) + { + return value; + } + } + } + } +} + +inline bool +monitorTryAcquire(Thread* t, object monitor) +{ + if (monitorOwner(t, monitor) == t + or (monitorAtomicPollAcquire(t, monitor, false) == 0 + and atomicCompareAndSwap + (reinterpret_cast(&monitorOwner(t, monitor)), 0, + reinterpret_cast(t)))) + { + ++ monitorDepth(t, monitor); + return true; + } else { + return false; + } +} + +inline void +monitorAcquire(Thread* t, object monitor) +{ + if (not monitorTryAcquire(t, monitor)) { + PROTECT(t, monitor); + + ACQUIRE(t, t->lock); + + monitorAtomicAppendAcquire(t, monitor); + + // note that we don't try to acquire the lock until we're first in + // line, both because it's fair and because we don't support + // removing elements from arbitrary positions in the queue + + while (not (t == monitorAtomicPollAcquire(t, monitor, false) + and atomicCompareAndSwap + (reinterpret_cast(&monitorOwner(t, monitor)), 0, + reinterpret_cast(t)))) + { + ENTER(t, Thread::IdleState); + + t->lock->wait(t->systemThread, 0); + } + + expect(t, t == monitorAtomicPollAcquire(t, monitor, true)); + + ++ monitorDepth(t, monitor); + } + + assert(t, monitorOwner(t, monitor) == t); +} + +inline void +monitorRelease(Thread* t, object monitor) +{ + expect(t, monitorOwner(t, monitor) == t); + + if (-- monitorDepth(t, monitor) == 0) { + monitorOwner(t, monitor) = 0; + + storeLoadMemoryBarrier(); + + Thread* next = monitorAtomicPollAcquire(t, monitor, false); + + if (next) { + ACQUIRE(t, next->lock); + + next->lock->notify(t->systemThread); + } + } +} + +inline void +monitorAppendWait(Thread* t, object monitor) +{ + assert(t, monitorOwner(t, monitor) == t); + + expect(t, not t->waiting); + expect(t, t->waitNext == 0); + + t->waiting = true; + + if (monitorWaitTail(t, monitor)) { + static_cast(monitorWaitTail(t, monitor))->waitNext = t; + } else { + monitorWaitHead(t, monitor) = t; + } + + monitorWaitTail(t, monitor) = t; +} + +inline void +monitorRemoveWait(Thread* t, object monitor) +{ + assert(t, monitorOwner(t, monitor) == t); + + Thread* previous = 0; + for (Thread* current = static_cast(monitorWaitHead(t, monitor)); + current; current = current->waitNext) + { + if (t == current) { + if (t == monitorWaitHead(t, monitor)) { + monitorWaitHead(t, monitor) = t->waitNext; + } else { + previous->waitNext = t->waitNext; + } + + if (t == monitorWaitTail(t, monitor)) { + assert(t, t->waitNext == 0); + monitorWaitTail(t, monitor) = previous; + } + + t->waitNext = 0; + t->waiting = false; + + return; + } else { + previous = current; + } + } + + abort(t); +} + +inline bool +monitorFindWait(Thread* t, object monitor) +{ + assert(t, monitorOwner(t, monitor) == t); + + for (Thread* current = static_cast(monitorWaitHead(t, monitor)); + current; current = current->waitNext) + { + if (t == current) { + return true; + } + } + + return false; +} + +inline bool +monitorWait(Thread* t, object monitor, int64_t time) +{ + expect(t, monitorOwner(t, monitor) == t); + + bool interrupted; + unsigned depth; + + PROTECT(t, monitor); + + { ACQUIRE(t, t->lock); + + monitorAppendWait(t, monitor); + + depth = monitorDepth(t, monitor); + monitorDepth(t, monitor) = 1; + + monitorRelease(t, monitor); + + ENTER(t, Thread::IdleState); + + interrupted = t->lock->wait(t->systemThread, time); + } + + monitorAcquire(t, monitor); + + monitorDepth(t, monitor) = depth; + + if (t->waiting) { + monitorRemoveWait(t, monitor); + } else { + expect(t, not monitorFindWait(t, monitor)); + } + + assert(t, monitorOwner(t, monitor) == t); + + return interrupted; +} + +inline Thread* +monitorPollWait(Thread* t, object monitor) +{ + assert(t, monitorOwner(t, monitor) == t); + + Thread* next = static_cast(monitorWaitHead(t, monitor)); + + if (next) { + monitorWaitHead(t, monitor) = next->waitNext; + next->waiting = false; + next->waitNext = 0; + if (next == monitorWaitTail(t, monitor)) { + monitorWaitTail(t, monitor) = 0; + } + } else { + assert(t, monitorWaitTail(t, monitor) == 0); + } + + return next; +} + +inline bool +monitorNotify(Thread* t, object monitor) +{ + expect(t, monitorOwner(t, monitor) == t); + + Thread* next = monitorPollWait(t, monitor); + + if (next) { + ACQUIRE(t, next->lock); + + next->lock->notify(t->systemThread); + + return true; + } else { + return false; + } +} + +inline void +monitorNotifyAll(Thread* t, object monitor) +{ + PROTECT(t, monitor); + + while (monitorNotify(t, monitor)) { } +} + +object objectMonitor(Thread* t, object o, bool createNew); inline void @@ -2307,14 +2620,14 @@ acquire(Thread* t, object o) hash = objectHash(t, o); } - System::Monitor* m = objectMonitor(t, o, true); + object m = objectMonitor(t, o, true); if (DebugMonitors) { fprintf(stderr, "thread %p acquires %p for %x\n", t, m, hash); } - acquire(t, m); + monitorAcquire(t, m); } inline void @@ -2325,14 +2638,14 @@ release(Thread* t, object o) hash = objectHash(t, o); } - System::Monitor* m = objectMonitor(t, o, false); + object m = objectMonitor(t, o, false); if (DebugMonitors) { fprintf(stderr, "thread %p releases %p for %x\n", t, m, hash); } - release(t, m); + monitorRelease(t, m); } inline void @@ -2343,18 +2656,17 @@ wait(Thread* t, object o, int64_t milliseconds) hash = objectHash(t, o); } - System::Monitor* m = objectMonitor(t, o, false); + object m = objectMonitor(t, o, false); if (DebugMonitors) { fprintf(stderr, "thread %p waits %d millis on %p for %x\n", t, static_cast(milliseconds), m, hash); } - if (m and m->owner() == t->systemThread) { - bool interrupted; - { ENTER(t, Thread::IdleState); - interrupted = m->wait(t->systemThread, milliseconds); - } + if (m and monitorOwner(t, m) == t) { + PROTECT(t, m); + + bool interrupted = monitorWait(t, m, milliseconds); if (interrupted) { t->exception = makeInterruptedException(t); @@ -2379,15 +2691,15 @@ notify(Thread* t, object o) hash = objectHash(t, o); } - System::Monitor* m = objectMonitor(t, o, false); + object m = objectMonitor(t, o, false); if (DebugMonitors) { fprintf(stderr, "thread %p notifies on %p for %x\n", t, m, hash); } - if (m and m->owner() == t->systemThread) { - m->notify(t->systemThread); + if (m and monitorOwner(t, m) == t) { + monitorNotify(t, m); } else { t->exception = makeIllegalMonitorStateException(t); } @@ -2396,15 +2708,15 @@ notify(Thread* t, object o) inline void notifyAll(Thread* t, object o) { - System::Monitor* m = objectMonitor(t, o, false); + object m = objectMonitor(t, o, false); if (DebugMonitors) { fprintf(stderr, "thread %p notifies all on %p for %x\n", t, m, objectHash(t, o)); } - if (m and m->owner() == t->systemThread) { - m->notifyAll(t->systemThread); + if (m and monitorOwner(t, m) == t) { + monitorNotifyAll(t, m); } else { t->exception = makeIllegalMonitorStateException(t); } diff --git a/src/types.def b/src/types.def index 9a704c3b91..184df800a0 100644 --- a/src/types.def +++ b/src/types.def @@ -111,6 +111,18 @@ (object first) (object second)) +(type monitor + (void* owner) + (void* waitHead) + (void* waitTail) + (object acquireHead) + (object acquireTail) + (unsigned depth)) + +(type monitorNode + (void* value) + (object next)) + (type continuationContext (object next) (object before) diff --git a/src/windows.cpp b/src/windows.cpp index 4ac44e4d05..b0146334b6 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -23,7 +23,7 @@ #undef max #undef min -#include "x86.h" +#include "arch.h" #include "system.h" #define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_) (s, x) diff --git a/src/x86.h b/src/x86.h index f5861de2d1..a3450377a7 100644 --- a/src/x86.h +++ b/src/x86.h @@ -161,11 +161,7 @@ trap() inline void programOrderMemoryBarrier() { -#ifdef _MSC_VER - _ReadWriteBarrier(); -#else - __asm__ __volatile__("": : :"memory"); -#endif + compileTimeMemoryBarrier(); } inline void diff --git a/test/GC.java b/test/GC.java index eb657ef786..d04c577fc8 100644 --- a/test/GC.java +++ b/test/GC.java @@ -104,6 +104,46 @@ public class GC { System.gc(); } + private static void stackMap7(boolean predicate) { + try { + if (predicate) { + Object a = null; + } else { + Object a = null; + } + + try { + int a = 42; + throw new DummyException(); + } finally { + System.gc(); + } + } catch (DummyException e) { + e.toString(); + } + } + + private static void stackMap8(boolean predicate) { + try { + Object x = new Object(); + if (predicate) { + Object a = null; + } else { + Object a = null; + } + + try { + int a = 42; + throw new DummyException(); + } finally { + System.gc(); + x.toString(); + } + } catch (DummyException e) { + e.toString(); + } + } + public static void main(String[] args) { Object[] array = new Object[1024 * 1024]; array[0] = new Object(); @@ -139,6 +179,13 @@ public class GC { stackMap6(true); stackMap6(false); + + stackMap7(true); + stackMap7(false); + + stackMap8(true); + stackMap8(false); } + private static class DummyException extends RuntimeException { } }