third attempt to properly fix race condition in compile function

This commit is contained in:
Joel Dice 2008-07-11 22:01:42 -06:00
parent 5a97caa4ca
commit fcd4f0c8f5
3 changed files with 78 additions and 59 deletions

View File

@ -3610,21 +3610,6 @@ compareTraceElementPointers(const void* va, const void* vb)
}
}
intptr_t
compareMethodBounds(Thread* t, object a, object b)
{
if (DebugMethodTree) {
fprintf(stderr, "compare %p to %p\n",
&singletonValue(t, methodCompiled(t, a), 0),
&singletonValue(t, methodCompiled(t, b), 0));
}
return reinterpret_cast<intptr_t>
(&singletonValue(t, methodCompiled(t, a), 0))
- reinterpret_cast<intptr_t>
(&singletonValue(t, methodCompiled(t, b), 0));
}
unsigned
frameObjectMapSize(MyThread* t, object method, object map)
{
@ -5074,40 +5059,78 @@ compile(MyThread* t, object method)
{
MyProcessor* p = processor(t);
PROTECT(t, method);
ACQUIRE(t, t->m->classLock);
if (methodCompiled(t, method) == p->defaultThunk) {
initClass(t, methodClass(t, method));
if (UNLIKELY(t->exception)) return;
PROTECT(t, method);
ACQUIRE(t, t->m->classLock);
if (methodCompiled(t, method) == p->defaultThunk) {
object compiled;
if (methodFlags(t, method) & ACC_NATIVE) {
compiled = p->nativeThunk;
} else {
Context context(t, method);
compiled = compile(t, &context);
if (UNLIKELY(t->exception)) return;
}
initClass(t, methodClass(t, method));
if (UNLIKELY(t->exception)) return;
set(t, method, MethodCompiled, compiled);
if ((methodFlags(t, method) & ACC_NATIVE) == 0) {
if (DebugMethodTree) {
fprintf(stderr, "insert method at %p\n",
&singletonValue(t, methodCompiled(t, method), 0));
}
if (methodCompiled(t, method) == p->defaultThunk) {
object node;
object compiled;
if (methodFlags(t, method) & ACC_NATIVE) {
node = 0;
compiled = p->nativeThunk;
} else {
Context context(t, method);
compiled = compile(t, &context);
if (UNLIKELY(t->exception)) return;
methodTree(t) = treeInsert
(t, methodTree(t), method, methodTreeSentinal(t),
compareMethodBounds);
}
PROTECT(t, compiled);
if (methodVirtual(t, method)) {
classVtable(t, methodClass(t, method), methodOffset(t, method))
= &singletonValue(t, methodCompiled(t, method), 0);
if (DebugMethodTree) {
fprintf(stderr, "insert method at %p\n",
&singletonValue(t, compiled, 0));
}
// We can't set the MethodCompiled field on the original
// method before it is placed into the method tree, since
// another thread might call the method, from which stack
// unwinding would fail (since there is not yet an entry in
// the method tree). However, we can't insert the original
// method into the tree before setting the MethodCompiled
// field on it since we rely on that field to determine its
// position in the tree. Therefore, we insert a clone in
// its place. Later, we'll replace the clone with the
// original to save memory.
object clone = makeMethod
(t, methodVmFlags(t, method),
methodReturnCode(t, method),
methodParameterCount(t, method),
methodParameterFootprint(t, method),
methodFlags(t, method),
methodOffset(t, method),
methodName(t, method),
methodSpec(t, method),
methodClass(t, method),
methodCode(t, method),
compiled);
node = makeTreeNode
(t, clone, methodTreeSentinal(t), methodTreeSentinal(t));
PROTECT(t, node);
methodTree(t) = treeInsertNode
(t, methodTree(t), reinterpret_cast<intptr_t>
(&singletonValue(t, compiled, 0)), node, methodTreeSentinal(t),
compareIpToMethodBounds);
}
set(t, method, MethodCompiled, compiled);
if (methodVirtual(t, method)) {
classVtable(t, methodClass(t, method), methodOffset(t, method))
= &singletonValue(t, compiled, 0);
}
if (node) {
set(t, node, TreeNodeValue, method);
}
}
}
}

View File

@ -59,8 +59,8 @@ cloneTreeNode(Thread* t, object n)
}
object
treeFind(Thread* t, object old, object node, object sentinal,
intptr_t (*compare)(Thread* t, object a, object b))
treeFind(Thread* t, object old, intptr_t key, object node, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b))
{
PROTECT(t, old);
PROTECT(t, node);
@ -78,8 +78,7 @@ treeFind(Thread* t, object old, object node, object sentinal,
while (old != sentinal) {
ancestors = makePair(t, new_, ancestors);
intptr_t difference = compare
(t, getTreeNodeValue(t, node), getTreeNodeValue(t, old));
intptr_t difference = compare(t, key, getTreeNodeValue(t, old));
if (difference < 0) {
old = treeNodeLeft(t, old);
@ -536,20 +535,16 @@ treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
}
object
treeInsert(Thread* t, object tree, object value, object sentinal,
intptr_t (*compare)(Thread* t, object a, object b))
treeInsertNode(Thread* t, object tree, intptr_t key, object node,
object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b))
{
PROTECT(t, tree);
PROTECT(t, sentinal);
object node = makeTreeNode(t, value, sentinal, sentinal);
object path = treeFind(t, tree, node, sentinal, compare);
if (treePathFresh(t, path)) {
return treeAdd(t, path);
} else {
return tree;
}
object path = treeFind(t, tree, key, node, sentinal, compare);
expect(t, treePathFresh(t, path));
return treeAdd(t, path);
}
} // namespace vm

View File

@ -88,8 +88,9 @@ treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b));
object
treeInsert(Thread* t, object tree, object value, object sentinal,
intptr_t (*compare)(Thread* t, object a, object b));
treeInsertNode(Thread* t, object tree, intptr_t key, object node,
object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b));
} // vm