mirror of
https://github.com/corda/corda.git
synced 2025-03-12 15:34:58 +00:00
avoid creating unecessary garbage in treeInsertNode and friends
This commit is contained in:
parent
fccf906349
commit
4392b04fd0
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
196
src/util.cpp
196
src/util.cpp
@ -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
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user