implement persistent red-black tree in util.cpp based on PersistentSet.java

This commit is contained in:
Joel Dice 2007-11-26 18:40:47 -07:00
parent 0bbe9489a7
commit 466c958d2b
6 changed files with 284 additions and 26 deletions

View File

@ -105,13 +105,13 @@ ifeq ($(platform),windows)
endif
ifeq ($(mode),debug)
cflags += -O0 -g3
cflags += -O0 -g3 -DNDEBUG
endif
ifeq ($(mode),stress)
cflags += -O0 -g3 -DVM_STRESS
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS
endif
ifeq ($(mode),stress-major)
cflags += -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS -DVM_STRESS_MAJOR
endif
ifeq ($(mode),fast)
cflags += -O3 -g3 -DNDEBUG

View File

@ -108,7 +108,7 @@ Java_java_lang_Object_clone(Thread* t, jclass, jobject o)
// clear any object header flags:
setObjectClass(t, *o, objectClass(t, *o));
} else {
clone = make(t, objectClass(t, *o));
clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(*o) + 1,
size - BytesPerWord);

View File

@ -2749,8 +2749,8 @@ finish(MyThread* t, Compiler* c, object method, Buffer* objectPool,
traceLog->get(i + BytesPerWord + 2 + 1 + 4, map, mapSize);
object node = makeTraceNode
(t, reinterpret_cast<intptr_t>(start + offset->value()), 0, 0, method,
target, virtualCall, mapSize / BytesPerWord, false);
(t, reinterpret_cast<intptr_t>(start + offset->value()), 0, 0, 0,
method, target, virtualCall, mapSize / BytesPerWord, false);
if (mapSize) {
memcpy(&traceNodeMap(t, node, 0), map, mapSize);
@ -3328,6 +3328,7 @@ class MyProcessor: public Processor {
defaultCompiled(0),
nativeCompiled(0),
addressTree(0),
addressTreeSentinal(0),
indirectCaller(0)
{ }
@ -3587,13 +3588,41 @@ class MyProcessor: public Processor {
object defaultCompiled;
object nativeCompiled;
object addressTree;
object addressTreeSentinal;
void* indirectCaller;
};
MyProcessor*
processor(MyThread* t)
{
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
if (p->addressTree == 0) {
ACQUIRE(t, t->m->classLock);
if (p->addressTree == 0) {
p->addressTreeSentinal = makeTraceNode(t, 0, 0, 0, 0, 0, 0, 0, 0, false);
set(t, p->addressTreeSentinal, TreeNodeLeft, p->addressTreeSentinal);
set(t, p->addressTreeSentinal, TreeNodeRight, p->addressTreeSentinal);
p->addressTree = p->addressTreeSentinal;
Compiler* c = makeCompiler(t->m->system, 0);
c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t)));
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t)));
c->jmp(c->indirectTarget());
p->indirectCaller = t->m->system->allocate(c->size());
c->writeTo(p->indirectCaller);
}
}
return p;
}
void
compile(MyThread* t, object method)
{
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
MyProcessor* p = processor(t);
object stub = p->getDefaultCompiled(t);
@ -3603,18 +3632,6 @@ compile(MyThread* t, object method)
ACQUIRE(t, t->m->classLock);
if (methodCompiled(t, method) == stub) {
if (p->indirectCaller == 0) {
Compiler* c = makeCompiler(t->m->system, 0);
c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t)));
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t)));
c->jmp(c->indirectTarget());
p->indirectCaller = t->m->system->allocate(c->size());
c->writeTo(p->indirectCaller);
}
PROTECT(t, method);
Compiler* c = makeCompiler(t->m->system, p->indirectCaller);
@ -3630,15 +3647,17 @@ compile(MyThread* t, object method)
object
findTraceNode(MyThread* t, void* address)
{
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
return treeQuery(t, p->addressTree, reinterpret_cast<intptr_t>(address));
MyProcessor* p = processor(t);
return treeQuery(t, p->addressTree, reinterpret_cast<intptr_t>(address),
p->addressTreeSentinal);
}
void
insertTraceNode(MyThread* t, object node)
{
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
p->addressTree = treeInsert(t, p->addressTree, node);
MyProcessor* p = processor(t);
p->addressTree = treeInsert
(t, p->addressTree, node, p->addressTreeSentinal);
}
} // namespace

View File

@ -93,14 +93,21 @@
(type treeNode
(intptr_t key)
(uintptr_t red)
(object left)
(object right))
(type treePath
(uintptr_t fresh)
(object node)
(object root)
(object ancestors))
(type traceNode
(extends treeNode)
(object method)
(object target)
(uint8_t virtualCall)
(uintptr_t virtualCall)
(array uintptr_t map))
(type array

View File

@ -1,5 +1,208 @@
#include "util.h"
using namespace vm;
namespace {
object
clone(Thread* t, object o)
{
object class_ = objectClass(t, o);
unsigned size = baseSize(t, o, class_) * BytesPerWord;
object clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(o) + 1,
size - BytesPerWord);
return clone;
}
object
treeFind(Thread* t, object oldRoot, object node, object sentinal)
{
object newRoot = clone(t, oldRoot);
object ancestors = 0;
object old = oldRoot;
object new_ = newRoot;
while (old != sentinal) {
ancestors = makePair(t, new_, ancestors);
intptr_t difference = treeNodeKey(t, node) - treeNodeKey(t, old);
if (difference < 0) {
old = treeNodeLeft(t, old);
object n = clone(t, old);
set(t, new_, TreeNodeLeft, n);
new_ = n;
} else if (difference > 0) {
old = treeNodeRight(t, old);
object n = clone(t, old);
set(t, new_, TreeNodeRight, n);
new_ = n;
} else {
return makeTreePath(t, false, new_, newRoot, pairSecond(t, ancestors));
}
}
object class_ = objectClass(t, node);
unsigned size = baseSize(t, node, class_) * BytesPerWord;
unsigned treeNodeSize = classFixedSize
(t, arrayBody(t, t->m->types, Machine::TreeNodeType)) * BytesPerWord;
unsigned diff = treeNodeSize - size;
if (diff) {
memcpy(reinterpret_cast<uint8_t*>(new_) + treeNodeSize,
reinterpret_cast<uint8_t*>(node) + treeNodeSize,
diff);
}
return makeTreePath(t, true, new_, newRoot, ancestors);
}
object
leftRotate(Thread* t, object n)
{
object child = clone(t, treeNodeRight(t, n));
set(t, n, TreeNodeRight, treeNodeLeft(t, child));
set(t, child, TreeNodeLeft, n);
return child;
}
object
rightRotate(Thread* t, object n)
{
object child = clone(t, treeNodeLeft(t, n));
set(t, n, TreeNodeLeft, treeNodeRight(t, child));
set(t, child, TreeNodeRight, n);
return child;
}
object
treeAdd(Thread* t, object path)
{
object new_ = treePathNode(t, path);
object newRoot = treePathRoot(t, path);
object ancestors = treePathAncestors(t, path);
// rebalance
treeNodeRed(t, new_) = true;
while (ancestors != 0 and treeNodeRed(t, pairFirst(t, ancestors))) {
if (pairFirst(t, ancestors)
== treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))))
{
if (treeNodeRed
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors)))))
{
treeNodeRed(t, pairFirst(t, ancestors)) = true;
object n = clone
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors))));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeRight, n);
treeNodeRed
(t, treeNodeRight
(t, pairFirst(t, pairSecond(t, ancestors)))) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = false;
new_ = pairFirst(t, pairSecond(t, ancestors));
ancestors = pairSecond(t, pairSecond(t, ancestors));
} else {
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) {
new_ = pairFirst(t, ancestors);
ancestors = pairSecond(t, ancestors);
object n = leftRotate(t, new_);
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) {
set(t, pairFirst(t, ancestors), TreeNodeRight, n);
} else {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n);
}
ancestors = makePair(t, n, ancestors);
}
treeNodeRed(t, pairFirst(t, ancestors)) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = true;
object n = rightRotate(t, pairFirst(t, pairSecond(t, ancestors)));
if (pairSecond(t, pairSecond(t, ancestors)) == 0) {
newRoot = n;
} else if (treeNodeRight
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))))
== pairFirst(t, pairSecond(t, ancestors)))
{
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeRight, n);
} else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeLeft, n);
}
// done
}
} else { // this is just the reverse of the code above (right and
// left swapped):
if (treeNodeRed
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))))
{
treeNodeRed(t, pairFirst(t, ancestors)) = true;
object n = clone
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeLeft, n);
treeNodeRed
(t, treeNodeLeft
(t, pairFirst(t, pairSecond(t, ancestors)))) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = false;
new_ = pairFirst(t, pairSecond(t, ancestors));
ancestors = pairSecond(t, pairSecond(t, ancestors));
} else {
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) {
new_ = pairFirst(t, ancestors);
ancestors = pairSecond(t, ancestors);
object n = rightRotate(t, new_);
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n);
} else {
set(t, pairFirst(t, ancestors), TreeNodeRight, n);
}
ancestors = makePair(t, n, ancestors);
}
treeNodeRed(t, pairFirst(t, ancestors)) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = true;
object n = leftRotate(t, pairFirst(t, pairSecond(t, ancestors)));
if (pairSecond(t, pairSecond(t, ancestors)) == 0) {
newRoot = n;
} else if (treeNodeLeft
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))))
== pairFirst(t, pairSecond(t, ancestors)))
{
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeLeft, n);
} else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeRight, n);
}
// done
}
}
}
treeNodeRed(t, newRoot) = false;
return newRoot;
}
} // namespace
namespace vm {
object
@ -249,4 +452,33 @@ vectorAppend(Thread* t, object vector, object value)
return vector;
}
object
treeQuery(Thread* t, object tree, intptr_t key, object sentinal)
{
object node = tree;
while (node != sentinal) {
intptr_t difference = key - treeNodeKey(t, node);
if (difference < 0) {
node = treeNodeLeft(t, node);
} else if (difference > 0) {
node = treeNodeRight(t, node);
} else {
return node;
}
}
return 0;
}
object
treeInsert(Thread* t, object tree, object node, object sentinal)
{
object path = treeFind(t, tree, node, sentinal);
if (treePathFresh(t, path)) {
return treeAdd(t, path);
} else {
return tree;
}
}
} // namespace vm

View File

@ -74,10 +74,10 @@ object
vectorAppend(Thread* t, object vector, object value);
object
treeQuery(Thread* t, object tree, intptr_t key);
treeQuery(Thread* t, object tree, intptr_t key, object sentinal);
object
treeInsert(Thread* t, object tree, object node);
treeInsert(Thread* t, object tree, object node, object sentinal);
} // vm