mirror of
https://github.com/corda/corda.git
synced 2025-01-09 14:33:30 +00:00
Merge branch 'master' of ssh://oss.readytalk.com/var/local/git/avian
This commit is contained in:
commit
103717a3f2
14
src/arch.h
14
src/arch.h
@ -17,6 +17,20 @@ extern "C" void NO_RETURN
|
|||||||
vmJump(void* address, void* base, void* stack, void* thread,
|
vmJump(void* address, void* base, void* stack, void* thread,
|
||||||
uintptr_t returnLow, uintptr_t returnHigh);
|
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)
|
#if (defined ARCH_x86_32) || (defined ARCH_x86_64)
|
||||||
# include "x86.h"
|
# include "x86.h"
|
||||||
#elif defined ARCH_powerpc
|
#elif defined ARCH_powerpc
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
# define GLOBAL(x) x
|
# define GLOBAL(x) x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define THREAD_CONTINUATION 100
|
#define THREAD_CONTINUATION 112
|
||||||
#define THREAD_EXCEPTION 36
|
#define THREAD_EXCEPTION 44
|
||||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 104
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 116
|
||||||
#define THREAD_EXCEPTION_OFFSET 108
|
#define THREAD_EXCEPTION_OFFSET 120
|
||||||
#define THREAD_EXCEPTION_HANDLER 112
|
#define THREAD_EXCEPTION_HANDLER 124
|
||||||
|
|
||||||
#define CONTINUATION_NEXT 4
|
#define CONTINUATION_NEXT 4
|
||||||
#define CONTINUATION_ADDRESS 16
|
#define CONTINUATION_ADDRESS 16
|
||||||
|
161
src/compile.cpp
161
src/compile.cpp
@ -588,8 +588,8 @@ print(SubroutinePath* path)
|
|||||||
if (path) {
|
if (path) {
|
||||||
fprintf(stderr, " (");
|
fprintf(stderr, " (");
|
||||||
while (true) {
|
while (true) {
|
||||||
fprintf(stderr, "%p", reinterpret_cast<void*>
|
fprintf(stderr, "%p", path->call->returnAddress->resolved() ?
|
||||||
(path->call->returnAddress->value()));
|
reinterpret_cast<void*>(path->call->returnAddress->value()) : 0);
|
||||||
path = path->stackNext;
|
path = path->stackNext;
|
||||||
if (path) {
|
if (path) {
|
||||||
fprintf(stderr, ", ");
|
fprintf(stderr, ", ");
|
||||||
@ -603,13 +603,18 @@ print(SubroutinePath* path)
|
|||||||
|
|
||||||
class SubroutineTrace {
|
class SubroutineTrace {
|
||||||
public:
|
public:
|
||||||
SubroutineTrace(SubroutinePath* path, SubroutineTrace* next):
|
SubroutineTrace(SubroutinePath* path, SubroutineTrace* next,
|
||||||
|
unsigned mapSize):
|
||||||
path(path),
|
path(path),
|
||||||
next(next)
|
next(next),
|
||||||
{ }
|
watch(false)
|
||||||
|
{
|
||||||
|
memset(map, 0, mapSize * BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
SubroutinePath* path;
|
SubroutinePath* path;
|
||||||
SubroutineTrace* next;
|
SubroutineTrace* next;
|
||||||
|
bool watch;
|
||||||
uintptr_t map[0];
|
uintptr_t map[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -619,17 +624,21 @@ class TraceElement: public TraceHandler {
|
|||||||
static const unsigned TailCall = 1 << 1;
|
static const unsigned TailCall = 1 << 1;
|
||||||
static const unsigned LongCall = 1 << 2;
|
static const unsigned LongCall = 1 << 2;
|
||||||
|
|
||||||
TraceElement(Context* context, object target, unsigned flags,
|
TraceElement(Context* context, unsigned ip, object target, unsigned flags,
|
||||||
TraceElement* next):
|
TraceElement* next, unsigned mapSize):
|
||||||
context(context),
|
context(context),
|
||||||
address(0),
|
address(0),
|
||||||
next(next),
|
next(next),
|
||||||
subroutineTrace(0),
|
subroutineTrace(0),
|
||||||
subroutineTraceCount(0),
|
|
||||||
target(target),
|
target(target),
|
||||||
|
ip(ip),
|
||||||
|
subroutineTraceCount(0),
|
||||||
argumentIndex(0),
|
argumentIndex(0),
|
||||||
flags(flags)
|
flags(flags),
|
||||||
{ }
|
watch(false)
|
||||||
|
{
|
||||||
|
memset(map, 0, mapSize * BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void handleTrace(Promise* address, unsigned argumentIndex) {
|
virtual void handleTrace(Promise* address, unsigned argumentIndex) {
|
||||||
if (this->address == 0) {
|
if (this->address == 0) {
|
||||||
@ -642,10 +651,12 @@ class TraceElement: public TraceHandler {
|
|||||||
Promise* address;
|
Promise* address;
|
||||||
TraceElement* next;
|
TraceElement* next;
|
||||||
SubroutineTrace* subroutineTrace;
|
SubroutineTrace* subroutineTrace;
|
||||||
unsigned subroutineTraceCount;
|
|
||||||
object target;
|
object target;
|
||||||
|
unsigned ip;
|
||||||
|
unsigned subroutineTraceCount;
|
||||||
unsigned argumentIndex;
|
unsigned argumentIndex;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
|
bool watch;
|
||||||
uintptr_t map[0];
|
uintptr_t map[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1587,7 +1598,7 @@ class Frame {
|
|||||||
|
|
||||||
TraceElement* e = context->traceLog = new
|
TraceElement* e = context->traceLog = new
|
||||||
(context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord)))
|
(context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord)))
|
||||||
TraceElement(context, target, flags, context->traceLog);
|
TraceElement(context, ip, target, flags, context->traceLog, mapSize);
|
||||||
|
|
||||||
++ context->traceLogCount;
|
++ 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
|
unsigned
|
||||||
calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
||||||
unsigned eventIndex, SubroutinePath* subroutinePath = 0)
|
unsigned eventIndex, SubroutinePath* subroutinePath = 0)
|
||||||
@ -4969,7 +5037,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
eventIndex += 2;
|
eventIndex += 2;
|
||||||
|
|
||||||
if (DebugFrameMaps) {
|
if (DebugFrameMaps) {
|
||||||
fprintf(stderr, " roots at ip %3d: ", ip);
|
fprintf(stderr, " roots at ip %3d: ", ip);
|
||||||
printSet(*RUNTIME_ARRAY_BODY(roots), mapSize);
|
printSet(*RUNTIME_ARRAY_BODY(roots), mapSize);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
@ -4998,7 +5066,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (DebugFrameMaps) {
|
if (DebugFrameMaps) {
|
||||||
fprintf(stderr, "table roots at ip %3d: ", ip);
|
fprintf(stderr, " table roots at ip %3d: ", ip);
|
||||||
printSet(*tableRoots, mapSize);
|
printSet(*tableRoots, mapSize);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
@ -5022,27 +5090,27 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PushExceptionHandlerEvent: {
|
case PushExceptionHandlerEvent: {
|
||||||
unsigned reference = context->eventLog.get2(eventIndex);
|
unsigned start = context->eventLog.get2(eventIndex);
|
||||||
|
eventIndex += 2;
|
||||||
|
unsigned end = context->eventLog.get2(eventIndex);
|
||||||
eventIndex += 2;
|
eventIndex += 2;
|
||||||
|
|
||||||
if (context->subroutineTable and context->subroutineTable[reference]) {
|
if (context->subroutineTable and context->subroutineTable[start]) {
|
||||||
Subroutine* s = context->subroutineTable[reference];
|
Subroutine* s = context->subroutineTable[start];
|
||||||
unsigned originalEventIndex = eventIndex;
|
unsigned originalEventIndex = eventIndex;
|
||||||
|
|
||||||
for (SubroutineCall* c = s->calls; c; c = c->next) {
|
for (SubroutineCall* c = s->calls; c; c = c->next) {
|
||||||
for (SubroutinePath* p = c->paths; p; p = p->listNext) {
|
for (SubroutinePath* p = c->paths; p; p = p->listNext) {
|
||||||
memcpy(RUNTIME_ARRAY_BODY(roots),
|
calculateTryCatchRoots
|
||||||
p->rootTable + (reference * mapSize),
|
(context, p, RUNTIME_ARRAY_BODY(roots), mapSize, start, end);
|
||||||
mapSize * BytesPerWord);
|
|
||||||
|
|
||||||
eventIndex = calculateFrameMaps
|
eventIndex = calculateFrameMaps
|
||||||
(t, context, RUNTIME_ARRAY_BODY(roots), originalEventIndex, p);
|
(t, context, RUNTIME_ARRAY_BODY(roots), originalEventIndex, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(RUNTIME_ARRAY_BODY(roots),
|
calculateTryCatchRoots
|
||||||
context->rootTable + (reference * mapSize),
|
(context, 0, RUNTIME_ARRAY_BODY(roots), mapSize, start, end);
|
||||||
mapSize * BytesPerWord);
|
|
||||||
|
|
||||||
eventIndex = calculateFrameMaps
|
eventIndex = calculateFrameMaps
|
||||||
(t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, 0);
|
(t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, 0);
|
||||||
@ -5052,7 +5120,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
case TraceEvent: {
|
case TraceEvent: {
|
||||||
TraceElement* te; context->eventLog.get(eventIndex, &te, BytesPerWord);
|
TraceElement* te; context->eventLog.get(eventIndex, &te, BytesPerWord);
|
||||||
if (DebugFrameMaps) {
|
if (DebugFrameMaps) {
|
||||||
fprintf(stderr, "trace roots at ip %3d: ", ip);
|
fprintf(stderr, " trace roots at ip %3d: ", ip);
|
||||||
printSet(*RUNTIME_ARRAY_BODY(roots), mapSize);
|
printSet(*RUNTIME_ARRAY_BODY(roots), mapSize);
|
||||||
if (subroutinePath) {
|
if (subroutinePath) {
|
||||||
fprintf(stderr, " ");
|
fprintf(stderr, " ");
|
||||||
@ -5061,13 +5129,17 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t* map;
|
||||||
|
bool watch;
|
||||||
if (subroutinePath == 0) {
|
if (subroutinePath == 0) {
|
||||||
memcpy(te->map, RUNTIME_ARRAY_BODY(roots), mapSize * BytesPerWord);
|
map = te->map;
|
||||||
|
watch = te->watch;
|
||||||
} else {
|
} else {
|
||||||
SubroutineTrace* trace = 0;
|
SubroutineTrace* trace = 0;
|
||||||
for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) {
|
for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) {
|
||||||
if (t->path == subroutinePath) {
|
if (t->path == subroutinePath) {
|
||||||
trace = t;
|
trace = t;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5075,12 +5147,27 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
te->subroutineTrace = trace = new
|
te->subroutineTrace = trace = new
|
||||||
(context->zone.allocate
|
(context->zone.allocate
|
||||||
(sizeof(SubroutineTrace) + (mapSize * BytesPerWord)))
|
(sizeof(SubroutineTrace) + (mapSize * BytesPerWord)))
|
||||||
SubroutineTrace(subroutinePath, te->subroutineTrace);
|
SubroutineTrace(subroutinePath, te->subroutineTrace, mapSize);
|
||||||
|
|
||||||
++ te->subroutineTraceCount;
|
++ 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;
|
eventIndex += BytesPerWord;
|
||||||
@ -5184,14 +5271,12 @@ copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits,
|
|||||||
SubroutinePath* subroutinePath)
|
SubroutinePath* subroutinePath)
|
||||||
{
|
{
|
||||||
if (DebugFrameMaps) {
|
if (DebugFrameMaps) {
|
||||||
fprintf(stderr, " orig roots at ip %p: ", reinterpret_cast<void*>
|
fprintf(stderr, " orig roots at ip %3d: ", p->ip);
|
||||||
(p->address->value()));
|
|
||||||
printSet(src[0], ceiling(mapSizeInBits, BitsPerWord));
|
printSet(src[0], ceiling(mapSizeInBits, BitsPerWord));
|
||||||
print(subroutinePath);
|
print(subroutinePath);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
fprintf(stderr, "final roots at ip %p: ", reinterpret_cast<void*>
|
fprintf(stderr, " final roots at ip %3d: ", p->ip);
|
||||||
(p->address->value()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned j = 0; j < p->argumentIndex; ++j) {
|
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)));
|
codeMaxStack(t, methodCode(t, context->method)));
|
||||||
Frame frame2(&frame, RUNTIME_ARRAY_BODY(stackMap));
|
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.append(PushExceptionHandlerEvent);
|
||||||
context->eventLog.append2(start);
|
context->eventLog.append2(start);
|
||||||
|
context->eventLog.append2(end);
|
||||||
|
|
||||||
for (unsigned i = 1;
|
for (unsigned i = 1;
|
||||||
i < codeMaxStack(t, methodCode(t, context->method));
|
i < codeMaxStack(t, methodCode(t, context->method));
|
||||||
@ -7211,9 +7304,9 @@ class MyProcessor: public Processor {
|
|||||||
compile(static_cast<MyThread*>(t),
|
compile(static_cast<MyThread*>(t),
|
||||||
local::codeAllocator(static_cast<MyThread*>(t)), 0,
|
local::codeAllocator(static_cast<MyThread*>(t)), 0,
|
||||||
resolveMethod(t, t->m->loader,
|
resolveMethod(t, t->m->loader,
|
||||||
"java/beans/PropertyChangeSupport",
|
"com/ecovate/nat/logic/Cache",
|
||||||
"firePropertyChange",
|
"findInCache",
|
||||||
"(Ljava/beans/PropertyChangeEvent;)V"));
|
"(Ljava/lang/String;Ljava/lang/String;JZ)Lcom/ecovate/shared/xmlrpc/Resource;"));
|
||||||
trap();
|
trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
#define THREAD_CONTINUATION 176
|
#define THREAD_CONTINUATION 192
|
||||||
#define THREAD_EXCEPTION 64
|
#define THREAD_EXCEPTION 80
|
||||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 184
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 200
|
||||||
#define THREAD_EXCEPTION_OFFSET 192
|
#define THREAD_EXCEPTION_OFFSET 208
|
||||||
#define THREAD_EXCEPTION_HANDLER 200
|
#define THREAD_EXCEPTION_HANDLER 216
|
||||||
|
|
||||||
#define CONTINUATION_NEXT 8
|
#define CONTINUATION_NEXT 8
|
||||||
#define CONTINUATION_ADDRESS 32
|
#define CONTINUATION_ADDRESS 32
|
||||||
@ -89,11 +89,11 @@ LOCAL(vmInvoke_exit):
|
|||||||
|
|
||||||
#elif defined __i386__
|
#elif defined __i386__
|
||||||
|
|
||||||
#define THREAD_CONTINUATION 100
|
#define THREAD_CONTINUATION 108
|
||||||
#define THREAD_EXCEPTION 36
|
#define THREAD_EXCEPTION 44
|
||||||
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 104
|
#define THREAD_EXCEPTION_STACK_ADJUSTMENT 112
|
||||||
#define THREAD_EXCEPTION_OFFSET 108
|
#define THREAD_EXCEPTION_OFFSET 116
|
||||||
#define THREAD_EXCEPTION_HANDLER 112
|
#define THREAD_EXCEPTION_HANDLER 120
|
||||||
|
|
||||||
#define CONTINUATION_NEXT 4
|
#define CONTINUATION_NEXT 4
|
||||||
#define CONTINUATION_ADDRESS 16
|
#define CONTINUATION_ADDRESS 16
|
||||||
|
@ -1808,17 +1808,13 @@ removeMonitor(Thread* t, object o)
|
|||||||
hash = objectHash(t, 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) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "dispose monitor %p for object %x\n",
|
fprintf(stderr, "dispose monitor %p for object %x\n", m, hash);
|
||||||
static_cast<System::Monitor*>(pointerValue(t, p)),
|
|
||||||
hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_cast<System::Monitor*>(pointerValue(t, p))->dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2185,9 +2181,11 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
|||||||
parent(parent),
|
parent(parent),
|
||||||
peer((parent ? parent->child : 0)),
|
peer((parent ? parent->child : 0)),
|
||||||
child(0),
|
child(0),
|
||||||
|
waitNext(0),
|
||||||
state(NoState),
|
state(NoState),
|
||||||
criticalLevel(0),
|
criticalLevel(0),
|
||||||
systemThread(0),
|
systemThread(0),
|
||||||
|
lock(0),
|
||||||
javaThread(javaThread),
|
javaThread(javaThread),
|
||||||
exception(0),
|
exception(0),
|
||||||
heapIndex(0),
|
heapIndex(0),
|
||||||
@ -2201,6 +2199,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
|||||||
backupHeap(0),
|
backupHeap(0),
|
||||||
backupHeapIndex(0),
|
backupHeapIndex(0),
|
||||||
backupHeapSizeInWords(0),
|
backupHeapSizeInWords(0),
|
||||||
|
waiting(false),
|
||||||
tracing(false)
|
tracing(false)
|
||||||
#ifdef VM_STRESS
|
#ifdef VM_STRESS
|
||||||
, stress(false)
|
, stress(false)
|
||||||
@ -2255,6 +2254,8 @@ Thread::init()
|
|||||||
parent->child = this;
|
parent->child = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect(this, m->system->success(m->system->make(&lock)));
|
||||||
|
|
||||||
if (javaThread == 0) {
|
if (javaThread == 0) {
|
||||||
this->javaThread = makeJavaThread(this, parent);
|
this->javaThread = makeJavaThread(this, parent);
|
||||||
}
|
}
|
||||||
@ -2282,6 +2283,8 @@ Thread::exit()
|
|||||||
void
|
void
|
||||||
Thread::dispose()
|
Thread::dispose()
|
||||||
{
|
{
|
||||||
|
lock->dispose();
|
||||||
|
|
||||||
if (systemThread) {
|
if (systemThread) {
|
||||||
systemThread->dispose();
|
systemThread->dispose();
|
||||||
}
|
}
|
||||||
@ -3419,52 +3422,48 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
|||||||
t->m->finalizers = f;
|
t->m->finalizers = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor*
|
object
|
||||||
objectMonitor(Thread* t, object o, bool createNew)
|
objectMonitor(Thread* t, object o, bool createNew)
|
||||||
{
|
{
|
||||||
assert(t, t->state == Thread::ActiveState);
|
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) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "found monitor %p for object %x\n",
|
fprintf(stderr, "found monitor %p for object %x\n", m, objectHash(t, o));
|
||||||
static_cast<System::Monitor*>(pointerValue(t, p)),
|
|
||||||
objectHash(t, o));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<System::Monitor*>(pointerValue(t, p));
|
return m;
|
||||||
} else if (createNew) {
|
} else if (createNew) {
|
||||||
PROTECT(t, o);
|
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) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "found monitor %p for object %x\n",
|
fprintf(stderr, "made monitor %p for object %x\n", m,
|
||||||
static_cast<System::Monitor*>(pointerValue(t, p)),
|
|
||||||
objectHash(t, o));
|
objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<System::Monitor*>(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;
|
return m;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
346
src/machine.h
346
src/machine.h
@ -17,6 +17,7 @@
|
|||||||
#include "finder.h"
|
#include "finder.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "arch.h"
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
# define JNICALL __stdcall
|
# define JNICALL __stdcall
|
||||||
@ -1345,9 +1346,11 @@ class Thread {
|
|||||||
Thread* parent;
|
Thread* parent;
|
||||||
Thread* peer;
|
Thread* peer;
|
||||||
Thread* child;
|
Thread* child;
|
||||||
|
Thread* waitNext;
|
||||||
State state;
|
State state;
|
||||||
unsigned criticalLevel;
|
unsigned criticalLevel;
|
||||||
System::Thread* systemThread;
|
System::Thread* systemThread;
|
||||||
|
System::Monitor* lock;
|
||||||
object javaThread;
|
object javaThread;
|
||||||
object exception;
|
object exception;
|
||||||
unsigned heapIndex;
|
unsigned heapIndex;
|
||||||
@ -1360,6 +1363,7 @@ class Thread {
|
|||||||
uintptr_t* backupHeap;
|
uintptr_t* backupHeap;
|
||||||
unsigned backupHeapIndex;
|
unsigned backupHeapIndex;
|
||||||
unsigned backupHeapSizeInWords;
|
unsigned backupHeapSizeInWords;
|
||||||
|
bool waiting;
|
||||||
bool tracing;
|
bool tracing;
|
||||||
#ifdef VM_STRESS
|
#ifdef VM_STRESS
|
||||||
bool stress;
|
bool stress;
|
||||||
@ -2296,7 +2300,316 @@ parameterFootprint(Thread* t, const char* s, bool static_);
|
|||||||
void
|
void
|
||||||
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
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<uintptr_t>(target, offset),
|
||||||
|
reinterpret_cast<uintptr_t>(old),
|
||||||
|
reinterpret_cast<uintptr_t>(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<Thread*>(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<uintptr_t*>(&monitorOwner(t, monitor)), 0,
|
||||||
|
reinterpret_cast<uintptr_t>(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<uintptr_t*>(&monitorOwner(t, monitor)), 0,
|
||||||
|
reinterpret_cast<uintptr_t>(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<Thread*>(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<Thread*>(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<Thread*>(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<Thread*>(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);
|
objectMonitor(Thread* t, object o, bool createNew);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -2307,14 +2620,14 @@ acquire(Thread* t, object o)
|
|||||||
hash = objectHash(t, o);
|
hash = objectHash(t, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor* m = objectMonitor(t, o, true);
|
object m = objectMonitor(t, o, true);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p acquires %p for %x\n",
|
fprintf(stderr, "thread %p acquires %p for %x\n",
|
||||||
t, m, hash);
|
t, m, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
acquire(t, m);
|
monitorAcquire(t, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -2325,14 +2638,14 @@ release(Thread* t, object o)
|
|||||||
hash = objectHash(t, o);
|
hash = objectHash(t, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor* m = objectMonitor(t, o, false);
|
object m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p releases %p for %x\n",
|
fprintf(stderr, "thread %p releases %p for %x\n",
|
||||||
t, m, hash);
|
t, m, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
release(t, m);
|
monitorRelease(t, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -2343,18 +2656,17 @@ wait(Thread* t, object o, int64_t milliseconds)
|
|||||||
hash = objectHash(t, o);
|
hash = objectHash(t, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor* m = objectMonitor(t, o, false);
|
object m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p waits %d millis on %p for %x\n",
|
fprintf(stderr, "thread %p waits %d millis on %p for %x\n",
|
||||||
t, static_cast<int>(milliseconds), m, hash);
|
t, static_cast<int>(milliseconds), m, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m and m->owner() == t->systemThread) {
|
if (m and monitorOwner(t, m) == t) {
|
||||||
bool interrupted;
|
PROTECT(t, m);
|
||||||
{ ENTER(t, Thread::IdleState);
|
|
||||||
interrupted = m->wait(t->systemThread, milliseconds);
|
bool interrupted = monitorWait(t, m, milliseconds);
|
||||||
}
|
|
||||||
|
|
||||||
if (interrupted) {
|
if (interrupted) {
|
||||||
t->exception = makeInterruptedException(t);
|
t->exception = makeInterruptedException(t);
|
||||||
@ -2379,15 +2691,15 @@ notify(Thread* t, object o)
|
|||||||
hash = objectHash(t, o);
|
hash = objectHash(t, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor* m = objectMonitor(t, o, false);
|
object m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p notifies on %p for %x\n",
|
fprintf(stderr, "thread %p notifies on %p for %x\n",
|
||||||
t, m, hash);
|
t, m, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m and m->owner() == t->systemThread) {
|
if (m and monitorOwner(t, m) == t) {
|
||||||
m->notify(t->systemThread);
|
monitorNotify(t, m);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeIllegalMonitorStateException(t);
|
t->exception = makeIllegalMonitorStateException(t);
|
||||||
}
|
}
|
||||||
@ -2396,15 +2708,15 @@ notify(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
notifyAll(Thread* t, object o)
|
notifyAll(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o, false);
|
object m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p notifies all on %p for %x\n",
|
fprintf(stderr, "thread %p notifies all on %p for %x\n",
|
||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m and m->owner() == t->systemThread) {
|
if (m and monitorOwner(t, m) == t) {
|
||||||
m->notifyAll(t->systemThread);
|
monitorNotifyAll(t, m);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeIllegalMonitorStateException(t);
|
t->exception = makeIllegalMonitorStateException(t);
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,18 @@
|
|||||||
(object first)
|
(object first)
|
||||||
(object second))
|
(object second))
|
||||||
|
|
||||||
|
(type monitor
|
||||||
|
(void* owner)
|
||||||
|
(void* waitHead)
|
||||||
|
(void* waitTail)
|
||||||
|
(object acquireHead)
|
||||||
|
(object acquireTail)
|
||||||
|
(unsigned depth))
|
||||||
|
|
||||||
|
(type monitorNode
|
||||||
|
(void* value)
|
||||||
|
(object next))
|
||||||
|
|
||||||
(type continuationContext
|
(type continuationContext
|
||||||
(object next)
|
(object next)
|
||||||
(object before)
|
(object before)
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#undef max
|
#undef max
|
||||||
#undef min
|
#undef min
|
||||||
|
|
||||||
#include "x86.h"
|
#include "arch.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_) (s, x)
|
#define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_) (s, x)
|
||||||
|
@ -161,11 +161,7 @@ trap()
|
|||||||
inline void
|
inline void
|
||||||
programOrderMemoryBarrier()
|
programOrderMemoryBarrier()
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
compileTimeMemoryBarrier();
|
||||||
_ReadWriteBarrier();
|
|
||||||
#else
|
|
||||||
__asm__ __volatile__("": : :"memory");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
47
test/GC.java
47
test/GC.java
@ -104,6 +104,46 @@ public class GC {
|
|||||||
System.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) {
|
public static void main(String[] args) {
|
||||||
Object[] array = new Object[1024 * 1024];
|
Object[] array = new Object[1024 * 1024];
|
||||||
array[0] = new Object();
|
array[0] = new Object();
|
||||||
@ -139,6 +179,13 @@ public class GC {
|
|||||||
|
|
||||||
stackMap6(true);
|
stackMap6(true);
|
||||||
stackMap6(false);
|
stackMap6(false);
|
||||||
|
|
||||||
|
stackMap7(true);
|
||||||
|
stackMap7(false);
|
||||||
|
|
||||||
|
stackMap8(true);
|
||||||
|
stackMap8(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DummyException extends RuntimeException { }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user