summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristophe Grand <christophe@cgrand.net>2009-08-10 18:43:27 +0200
committerRich Hickey <richhickey@gmail.com>2009-08-26 12:02:56 -0400
commite8fc494908acccdd0afd59b7678957b9d27afd68 (patch)
tree1e9ba23550309cfa7a972192b0b51d7ec2c712ca /src
parent307821cbb4c4ff2091f0a2cef0f5e631a900b5c2 (diff)
made ArrayNode to pack its children into a BitmapIndexedNode when count < 12
Signed-off-by: Rich Hickey <richhickey@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/PersistentHashMap2.java50
1 files changed, 41 insertions, 9 deletions
diff --git a/src/jvm/clojure/lang/PersistentHashMap2.java b/src/jvm/clojure/lang/PersistentHashMap2.java
index 6ef57c90..2d041a53 100644
--- a/src/jvm/clojure/lang/PersistentHashMap2.java
+++ b/src/jvm/clojure/lang/PersistentHashMap2.java
@@ -318,23 +318,25 @@ static interface INode{
}
final static class ArrayNode implements INode{
+ int count;
final INode[] array;
final AtomicReference<Thread> edit;
- ArrayNode(AtomicReference<Thread> edit, INode[] array){
+ ArrayNode(AtomicReference<Thread> edit, int count, INode[] array){
this.array = array;
this.edit = edit;
+ this.count = count;
}
public INode assoc(int shift, int hash, Object key, Object val, Box addedLeaf){
int idx = mask(hash, shift);
INode node = array[idx];
if(node == null)
- return new ArrayNode(null, cloneAndSet(array, idx, BitmapIndexedNode.EMPTY.assoc(shift + 5, hash, key, val, addedLeaf)));
+ return new ArrayNode(null, count + 1, cloneAndSet(array, idx, BitmapIndexedNode.EMPTY.assoc(shift + 5, hash, key, val, addedLeaf)));
INode n = node.assoc(shift + 5, hash, key, val, addedLeaf);
if(n == node)
return this;
- return new ArrayNode(null, cloneAndSet(array, idx, n));
+ return new ArrayNode(null, count, cloneAndSet(array, idx, n));
}
public INode without(int shift, int hash, Object key){
@@ -345,8 +347,12 @@ final static class ArrayNode implements INode{
INode n = node.without(shift + 5, hash, key);
if(n == node)
return this;
- // TODO: shrink if underflow
- return new ArrayNode(null, cloneAndSet(array, idx, n));
+ if (n == null) {
+ if (count <= 12) // shrink
+ return pack(null, idx);
+ return new ArrayNode(null, count - 1, cloneAndSet(array, idx, n));
+ } else
+ return new ArrayNode(null, count, cloneAndSet(array, idx, n));
}
public IMapEntry find(int shift, int hash, Object key){
@@ -372,7 +378,7 @@ final static class ArrayNode implements INode{
ArrayNode ensureEditable(AtomicReference<Thread> edit){
if(this.edit == edit)
return this;
- return new ArrayNode(edit, this.array.clone());
+ return new ArrayNode(edit, count, this.array.clone());
}
ArrayNode editAndSet(AtomicReference<Thread> edit, int i, INode n){
@@ -381,6 +387,26 @@ final static class ArrayNode implements INode{
return editable;
}
+
+ private INode pack(AtomicReference<Thread> edit, int idx) {
+ Object[] newArray = new Object[2*(count - 1)];
+ int j = 1;
+ int bitmap = 0;
+ for(int i = 0; i < idx; i++)
+ if (array[i] != null) {
+ newArray[j] = array[i];
+ bitmap |= 1 << i;
+ j += 2;
+ }
+ for(int i = idx + 1; i < array.length; i++)
+ if (array[i] != null) {
+ newArray[j] = array[i];
+ bitmap |= 1 << i;
+ j += 2;
+ }
+ return new BitmapIndexedNode(edit, bitmap, newArray);
+ }
+
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key, Object val, Box addedLeaf){
int idx = mask(hash, shift);
INode node = array[idx];
@@ -400,7 +426,13 @@ final static class ArrayNode implements INode{
INode n = node.without(edit, shift + 5, hash, key, removedLeaf);
if(n == node)
return this;
- // TODO: shrink if underflow
+ if(n == null) {
+ if (count <= 12) // shrink
+ return pack(edit, idx);
+ ArrayNode editable = editAndSet(edit, idx, n);
+ editable.count--;
+ return editable;
+ }
return editAndSet(edit, idx, n);
}
@@ -501,7 +533,7 @@ final static class BitmapIndexedNode implements INode{
nodes[i] = EMPTY.assoc(shift + 5, Util.hash(array[j]), array[j], array[j+1], addedLeaf);
j += 2;
}
- return new ArrayNode(null, nodes);
+ return new ArrayNode(null, n + 1, nodes);
} else {
Object[] newArray = new Object[2*(n+1)];
System.arraycopy(array, 0, newArray, 0, 2*idx);
@@ -645,7 +677,7 @@ final static class BitmapIndexedNode implements INode{
nodes[i] = EMPTY.assoc(edit, shift + 5, Util.hash(array[j]), array[j], array[j+1], addedLeaf);
j += 2;
}
- return new ArrayNode(edit, nodes);
+ return new ArrayNode(edit, n + 1, nodes);
} else {
Object[] newArray = new Object[2*(n+2)];
System.arraycopy(array, 0, newArray, 0, 2*idx);