avoid creating unecessary garbage in treeInsertNode and friends

This commit is contained in:
Joel Dice 2008-11-22 16:25:35 -07:00
parent fccf906349
commit 4392b04fd0
4 changed files with 122 additions and 85 deletions

View File

@ -5205,7 +5205,7 @@ compile(MyThread* t, object method)
PROTECT(t, node); PROTECT(t, node);
methodTree(t) = treeInsertNode methodTree(t) = treeInsertNode
(t, methodTree(t), reinterpret_cast<intptr_t> (t, &(context.zone), methodTree(t), reinterpret_cast<intptr_t>
(&singletonValue(t, compiled, 0)), node, methodTreeSentinal(t), (&singletonValue(t, compiled, 0)), node, methodTreeSentinal(t),
compareIpToMethodBounds); compareIpToMethodBounds);
} }

View File

@ -95,12 +95,6 @@
(object value) (object value)
(object left) (object left)
(object right)) (object right))
(type treePath
(uintptr_t fresh)
(object node)
(object root)
(object ancestors))
(type callNode (type callNode
(intptr_t address) (intptr_t address)

View File

@ -14,6 +14,54 @@ using namespace vm;
namespace { namespace {
class TreeContext {
public:
class Path {
public:
Path(object node, Path* next): node(node), next(next) { }
object node;
Path* next;
};
class MyProtector: public Thread::Protector {
public:
MyProtector(Thread* thread, TreeContext* context):
Protector(thread), context(context)
{ }
virtual void visit(Heap::Visitor* v) {
v->visit(&(context->root));
v->visit(&(context->node));
for (Path* p = context->ancestors; p; p = p->next) {
v->visit(&(p->node));
}
}
TreeContext* context;
};
TreeContext(Thread* thread, Zone* zone):
zone(zone), root(0), node(0), ancestors(0), protector(thread, this),
fresh(false)
{ }
Zone* zone;
object root;
object node;
Path* ancestors;
MyProtector protector;
bool fresh;
};
TreeContext::Path*
path(TreeContext* c, object node, TreeContext::Path* next)
{
return new (c->zone->allocate(sizeof(TreeContext::Path)))
TreeContext::Path(node, next);
}
inline object inline object
getTreeNodeValue(Thread*, object n) getTreeNodeValue(Thread*, object n)
{ {
@ -58,8 +106,9 @@ cloneTreeNode(Thread* t, object n)
return newNode; return newNode;
} }
object void
treeFind(Thread* t, object old, intptr_t key, object node, object sentinal, treeFind(Thread* t, TreeContext* c, object old, intptr_t key, object node,
object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b)) intptr_t (*compare)(Thread* t, intptr_t key, object b))
{ {
PROTECT(t, old); PROTECT(t, old);
@ -72,11 +121,8 @@ treeFind(Thread* t, object old, intptr_t key, object node, object sentinal,
object new_ = newRoot; object new_ = newRoot;
PROTECT(t, new_); PROTECT(t, new_);
object ancestors = 0;
PROTECT(t, ancestors);
while (old != sentinal) { while (old != sentinal) {
ancestors = makePair(t, new_, ancestors); c->ancestors = path(c, new_, c->ancestors);
intptr_t difference = compare(t, key, getTreeNodeValue(t, old)); intptr_t difference = compare(t, key, getTreeNodeValue(t, old));
@ -91,13 +137,20 @@ treeFind(Thread* t, object old, intptr_t key, object node, object sentinal,
set(t, new_, TreeNodeRight, n); set(t, new_, TreeNodeRight, n);
new_ = n; new_ = n;
} else { } else {
return makeTreePath(t, false, new_, newRoot, pairSecond(t, ancestors)); c->fresh = false;
c->root = newRoot;
c->node = new_;
c->ancestors = c->ancestors->next;
return;
} }
} }
setTreeNodeValue(t, new_, getTreeNodeValue(t, node)); setTreeNodeValue(t, new_, getTreeNodeValue(t, node));
return makeTreePath(t, true, new_, newRoot, ancestors); c->fresh = true;
c->root = newRoot;
c->node = new_;
c->ancestors = c->ancestors;
} }
object object
@ -123,122 +176,109 @@ rightRotate(Thread* t, object n)
} }
object object
treeAdd(Thread* t, object path) treeAdd(Thread* t, TreeContext* c)
{ {
object new_ = treePathNode(t, path); object new_ = c->node;
PROTECT(t, new_); PROTECT(t, new_);
object newRoot = treePathRoot(t, path); object newRoot = c->root;
PROTECT(t, newRoot); PROTECT(t, newRoot);
object ancestors = treePathAncestors(t, path);
PROTECT(t, ancestors);
// rebalance // rebalance
setTreeNodeRed(t, new_, true); setTreeNodeRed(t, new_, true);
while (ancestors != 0 and treeNodeRed(t, pairFirst(t, ancestors))) { while (c->ancestors != 0 and treeNodeRed(t, c->ancestors->node)) {
if (pairFirst(t, ancestors) if (c->ancestors->node
== treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))) == treeNodeLeft(t, c->ancestors->next->node))
{ {
if (treeNodeRed if (treeNodeRed
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors))))) (t, treeNodeRight(t, c->ancestors->next->node)))
{ {
setTreeNodeRed(t, pairFirst(t, ancestors), false); setTreeNodeRed(t, c->ancestors->node, false);
object n = cloneTreeNode object n = cloneTreeNode
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors)))); (t, treeNodeRight(t, c->ancestors->next->node));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeRight, n); set(t, c->ancestors->next->node, TreeNodeRight, n);
setTreeNodeRed setTreeNodeRed(t, treeNodeRight(t, c->ancestors->next->node), false);
(t, treeNodeRight
(t, pairFirst(t, pairSecond(t, ancestors))), false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); setTreeNodeRed(t, c->ancestors->next->node, true);
new_ = pairFirst(t, pairSecond(t, ancestors)); new_ = c->ancestors->next->node;
ancestors = pairSecond(t, pairSecond(t, ancestors)); c->ancestors = c->ancestors->next->next;
} else { } else {
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) { if (new_ == treeNodeRight(t, c->ancestors->node)) {
new_ = pairFirst(t, ancestors); new_ = c->ancestors->node;
ancestors = pairSecond(t, ancestors); c->ancestors = c->ancestors->next;
object n = leftRotate(t, new_); object n = leftRotate(t, new_);
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) { if (new_ == treeNodeRight(t, c->ancestors->node)) {
set(t, pairFirst(t, ancestors), TreeNodeRight, n); set(t, c->ancestors->node, TreeNodeRight, n);
} else { } else {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n); set(t, c->ancestors->node, TreeNodeLeft, n);
} }
ancestors = makePair(t, n, ancestors); c->ancestors = path(c, n, c->ancestors);
} }
setTreeNodeRed(t, pairFirst(t, ancestors), false); setTreeNodeRed(t, c->ancestors->node, false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); setTreeNodeRed(t, c->ancestors->next->node, true);
object n = rightRotate(t, pairFirst(t, pairSecond(t, ancestors))); object n = rightRotate(t, c->ancestors->next->node);
if (pairSecond(t, pairSecond(t, ancestors)) == 0) { if (c->ancestors->next->next == 0) {
newRoot = n; newRoot = n;
} else if (treeNodeRight } else if (treeNodeRight(t, c->ancestors->next->next->node)
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors)))) == c->ancestors->next->node)
== pairFirst(t, pairSecond(t, ancestors)))
{ {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), set(t, c->ancestors->next->next->node, TreeNodeRight, n);
TreeNodeRight, n);
} else { } else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), set(t, c->ancestors->next->next->node, TreeNodeLeft, n);
TreeNodeLeft, n);
} }
// done // done
} }
} else { // this is just the reverse of the code above (right and } else { // this is just the reverse of the code above (right and
// left swapped): // left swapped):
if (treeNodeRed if (treeNodeRed
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))))) (t, treeNodeLeft(t, c->ancestors->next->node)))
{ {
setTreeNodeRed(t, pairFirst(t, ancestors), false); setTreeNodeRed(t, c->ancestors->node, false);
object n = cloneTreeNode object n = cloneTreeNode
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))); (t, treeNodeLeft(t, c->ancestors->next->node));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeLeft, n); set(t, c->ancestors->next->node, TreeNodeLeft, n);
setTreeNodeRed setTreeNodeRed(t, treeNodeLeft(t, c->ancestors->next->node), false);
(t, treeNodeLeft
(t, pairFirst(t, pairSecond(t, ancestors))), false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); setTreeNodeRed(t, c->ancestors->next->node, true);
new_ = pairFirst(t, pairSecond(t, ancestors)); new_ = c->ancestors->next->node;
ancestors = pairSecond(t, pairSecond(t, ancestors)); c->ancestors = c->ancestors->next->next;
} else { } else {
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) { if (new_ == treeNodeLeft(t, c->ancestors->node)) {
new_ = pairFirst(t, ancestors); new_ = c->ancestors->node;
ancestors = pairSecond(t, ancestors); c->ancestors = c->ancestors->next;
object n = rightRotate(t, new_); object n = rightRotate(t, new_);
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) { if (new_ == treeNodeLeft(t, c->ancestors->node)) {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n); set(t, c->ancestors->node, TreeNodeLeft, n);
} else { } else {
set(t, pairFirst(t, ancestors), TreeNodeRight, n); set(t, c->ancestors->node, TreeNodeRight, n);
} }
ancestors = makePair(t, n, ancestors); c->ancestors = path(c, n, c->ancestors);
} }
setTreeNodeRed(t, pairFirst(t, ancestors), false); setTreeNodeRed(t, c->ancestors->node, false);
setTreeNodeRed(t, pairFirst(t, pairSecond(t, ancestors)), true); setTreeNodeRed(t, c->ancestors->next->node, true);
object n = leftRotate(t, pairFirst(t, pairSecond(t, ancestors))); object n = leftRotate(t, c->ancestors->next->node);
if (pairSecond(t, pairSecond(t, ancestors)) == 0) { if (c->ancestors->next->next == 0) {
newRoot = n; newRoot = n;
} else if (treeNodeLeft } else if (treeNodeLeft(t, c->ancestors->next->next->node)
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors)))) == c->ancestors->next->node)
== pairFirst(t, pairSecond(t, ancestors)))
{ {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), set(t, c->ancestors->next->next->node, TreeNodeLeft, n);
TreeNodeLeft, n);
} else { } else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))), set(t, c->ancestors->next->next->node, TreeNodeRight, n);
TreeNodeRight, n);
} }
// done // done
} }
@ -541,16 +581,18 @@ treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
} }
object object
treeInsertNode(Thread* t, object tree, intptr_t key, object node, treeInsertNode(Thread* t, Zone* zone, object tree, intptr_t key, object node,
object sentinal, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b)) intptr_t (*compare)(Thread* t, intptr_t key, object b))
{ {
PROTECT(t, tree); PROTECT(t, tree);
PROTECT(t, sentinal); PROTECT(t, sentinal);
object path = treeFind(t, tree, key, node, sentinal, compare); TreeContext c(t, zone);
expect(t, treePathFresh(t, path)); treeFind(t, &c, tree, key, node, sentinal, compare);
return treeAdd(t, path); expect(t, c.fresh);
return treeAdd(t, &c);
} }
} // namespace vm } // namespace vm

View File

@ -12,6 +12,7 @@
#define UTIL_H #define UTIL_H
#include "machine.h" #include "machine.h"
#include "zone.h"
namespace vm { namespace vm {
@ -88,7 +89,7 @@ treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b)); intptr_t (*compare)(Thread* t, intptr_t key, object b));
object object
treeInsertNode(Thread* t, object tree, intptr_t key, object node, treeInsertNode(Thread* t, Zone* zone, object tree, intptr_t key, object node,
object sentinal, object sentinal,
intptr_t (*compare)(Thread* t, intptr_t key, object b)); intptr_t (*compare)(Thread* t, intptr_t key, object b));