Skip to content

Commit

Permalink
[Truffle] Fix a couple of hash bugs.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Dec 16, 2014
1 parent 3c5c26d commit 18593e6
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 35 deletions.
55 changes: 31 additions & 24 deletions core/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java
Expand Up @@ -234,7 +234,7 @@ public Object getNull(VirtualFrame frame, RubyHash hash, Object key) {
@Specialization(guards = "isObjectArray")
public Object getObjectArray(VirtualFrame frame, RubyHash hash, Object key) {
final Object[] store = (Object[]) hash.getStore();
final int size = hash.getStoreSize();
final int size = hash.getSize();

for (int n = 0; n < HashOperations.SMALL_HASH_SIZE; n++) {
if (n < size && eqlNode.call(frame, store[n * 2], "eql?", null, key)) {
Expand Down Expand Up @@ -317,7 +317,7 @@ public Object setObjectArray(VirtualFrame frame, RubyHash hash, Object key, Obje
hash.checkFrozen(this);

final Object[] store = (Object[]) hash.getStore();
final int size = hash.getStoreSize();
final int size = hash.getSize();

for (int n = 0; n < HashOperations.SMALL_HASH_SIZE; n++) {
if (n < size && eqlNode.call(frame, store[n * 2], "eql?", null, key)) {
Expand All @@ -334,7 +334,7 @@ public Object setObjectArray(VirtualFrame frame, RubyHash hash, Object key, Obje
extendProfile.enter();
store[size * 2] = key;
store[size * 2 + 1] = value;
hash.setStoreSize(newSize);
hash.setSize(newSize);
return value;
}

Expand All @@ -360,7 +360,7 @@ public Object setBucketArray(RubyHash hash, Object key, Object value) {
notDesignedForCompilation();

if (HashOperations.verySlowSetInBuckets(hash, key, value)) {
hash.setStoreSize(hash.getStoreSize() + 1);
hash.setSize(hash.getSize() + 1);
}

return value;
Expand Down Expand Up @@ -421,7 +421,7 @@ public Object deleteObjectArray(VirtualFrame frame, RubyHash hash, Object key) {
hash.checkFrozen(this);

final Object[] store = (Object[]) hash.getStore();
final int size = hash.getStoreSize();
final int size = hash.getSize();

for (int n = 0; n < HashOperations.SMALL_HASH_SIZE * 2; n += 2) {
if (n < size && eqlNode.call(frame, store[n], "eql?", null, key)) {
Expand All @@ -430,7 +430,7 @@ public Object deleteObjectArray(VirtualFrame frame, RubyHash hash, Object key) {
// Move the later values down
System.arraycopy(store, n + 2, store, n, HashOperations.SMALL_HASH_SIZE * 2 - n - 2);

hash.setStoreSize(size - 1);
hash.setSize(size - 1);

return value;
}
Expand Down Expand Up @@ -477,7 +477,7 @@ public Object delete(VirtualFrame frame, RubyHash hash, Object key) {
bucket.getNextInLookup().setPreviousInLookup(bucket.getPreviousInLookup());
}

hash.setStoreSize(hash.getStoreSize() - 1);
hash.setSize(hash.getSize() - 1);

return bucket.getValue();
}
Expand Down Expand Up @@ -509,7 +509,7 @@ public RubyHash eachObjectArray(VirtualFrame frame, RubyHash hash, RubyProc bloc
notDesignedForCompilation();

final Object[] store = (Object[]) hash.getStore();
final int size = hash.getStoreSize();
final int size = hash.getSize();

int count = 0;

Expand Down Expand Up @@ -563,7 +563,7 @@ public boolean emptyNull(RubyHash hash) {

@Specialization(guards = "!isNull")
public boolean emptyObjectArray(RubyHash hash) {
return hash.getStoreSize() == 0;
return hash.getSize() == 0;
}

}
Expand Down Expand Up @@ -734,7 +734,7 @@ public boolean keyNull(RubyHash hash, Object key) {
public boolean keyObjectArray(VirtualFrame frame, RubyHash hash, Object key) {
notDesignedForCompilation();

final int size = hash.getStoreSize();
final int size = hash.getSize();
final Object[] store = (Object[]) hash.getStore();

for (int n = 0; n < store.length; n += 2) {
Expand Down Expand Up @@ -783,7 +783,7 @@ public RubyArray keysObjectArray(RubyHash hash) {

final Object[] store = (Object[]) hash.getStore();

final Object[] keys = new Object[hash.getStoreSize()];
final Object[] keys = new Object[hash.getSize()];

for (int n = 0; n < keys.length; n++) {
keys[n] = store[n * 2];
Expand All @@ -796,7 +796,7 @@ public RubyArray keysObjectArray(RubyHash hash) {
public RubyArray keysBucketArray(RubyHash hash) {
notDesignedForCompilation();

final Object[] keys = new Object[hash.getStoreSize()];
final Object[] keys = new Object[hash.getSize()];

Bucket bucket = hash.getFirstInSequence();
int n = 0;
Expand Down Expand Up @@ -828,7 +828,7 @@ public MapNode(MapNode prev) {
@Specialization(guards = "isObjectArray")
public RubyArray mapObjectArray(VirtualFrame frame, RubyHash hash, RubyProc block) {
final Object[] store = (Object[]) hash.getStore();
final int size = hash.getStoreSize();
final int size = hash.getSize();

final int resultSize = store.length / 2;
final Object[] result = new Object[resultSize];
Expand Down Expand Up @@ -899,7 +899,7 @@ public RubyHash mergeObjectArrayNull(RubyHash hash, RubyHash other) {
final Object[] store = (Object[]) hash.getStore();
final Object[] copy = Arrays.copyOf(store, HashOperations.SMALL_HASH_SIZE * 2);

return new RubyHash(getContext().getCoreLibrary().getHashClass(), hash.getDefaultBlock(), hash.getDefaultValue(), copy, hash.getStoreSize(), null);
return new RubyHash(getContext().getCoreLibrary().getHashClass(), hash.getDefaultBlock(), hash.getDefaultValue(), copy, hash.getSize(), null);
}

@ExplodeLoop
Expand All @@ -908,10 +908,10 @@ public RubyHash mergeObjectArrayObjectArray(VirtualFrame frame, RubyHash hash, R
// TODO(CS): what happens with the default block here? Which side does it get merged from?

final Object[] storeA = (Object[]) hash.getStore();
final int storeASize = hash.getStoreSize();
final int storeASize = hash.getSize();

final Object[] storeB = (Object[]) other.getStore();
final int storeBSize = hash.getStoreSize();
final int storeBSize = hash.getSize();

final boolean[] mergeFromA = new boolean[storeASize];
int mergeFromACount = 0;
Expand Down Expand Up @@ -983,17 +983,24 @@ public RubyHash mergeObjectArrayObjectArray(VirtualFrame frame, RubyHash hash, R


@Specialization
public RubyHash mergeBucketArrayBucketArray(VirtualFrame frame, RubyHash hash, RubyHash other) {
final RubyHash merged = new RubyHash(getContext().getCoreLibrary().getHashClass(), null, null, new Bucket[HashOperations.capacityGreaterThan(hash.getStoreSize() + hash.getStoreSize())], 0, null);
public RubyHash mergeBucketArrayBucketArray(RubyHash hash, RubyHash other) {
final RubyHash merged = new RubyHash(getContext().getCoreLibrary().getHashClass(), null, null, new Bucket[HashOperations.capacityGreaterThan(hash.getSize() + other.getSize())], 0, null);

int size = 0;

for (Entry entry : HashOperations.verySlowToEntries(hash)) {
HashOperations.verySlowSetInBuckets(merged, entry.getKey(), entry.getValue());
size++;
}

for (Entry entry : HashOperations.verySlowToEntries(other)) {
HashOperations.verySlowSetInBuckets(merged, entry.getKey(), entry.getValue());
if (HashOperations.verySlowSetInBuckets(merged, entry.getKey(), entry.getValue())) {
size++;
}
}

merged.setSize(size);

return merged;
}

Expand Down Expand Up @@ -1053,7 +1060,7 @@ public int sizeNull(RubyHash hash) {

@Specialization(guards = "!isNull")
public int sizeObjectArray(RubyHash hash) {
return hash.getStoreSize();
return hash.getSize();
}

}
Expand All @@ -1078,7 +1085,7 @@ public RubyArray valuesNull(RubyHash hash) {
public RubyArray valuesObjectArray(RubyHash hash) {
final Object[] store = (Object[]) hash.getStore();

final Object[] values = new Object[hash.getStoreSize()];
final Object[] values = new Object[hash.getSize()];

for (int n = 0; n < values.length; n++) {
values[n] = store[n * 2 + 1];
Expand All @@ -1091,7 +1098,7 @@ public RubyArray valuesObjectArray(RubyHash hash) {
public RubyArray valuesBucketArray(RubyHash hash) {
notDesignedForCompilation();

final Object[] values = new Object[hash.getStoreSize()];
final Object[] values = new Object[hash.getSize()];

Bucket bucket = hash.getFirstInSequence();
int n = 0;
Expand Down Expand Up @@ -1130,7 +1137,7 @@ public RubyArray toArrayObjectArray(RubyHash hash) {
notDesignedForCompilation();

final Object[] store = (Object[]) hash.getStore();
final int size = hash.getStoreSize();
final int size = hash.getSize();
final Object[] pairs = new Object[size];

for (int n = 0; n < size; n++) {
Expand All @@ -1144,7 +1151,7 @@ public RubyArray toArrayObjectArray(RubyHash hash) {
public RubyArray toArrayBucketArray(RubyHash hash) {
notDesignedForCompilation();

final int size = hash.getStoreSize();
final int size = hash.getSize();
final Object[] pairs = new Object[size];

int n = 0;
Expand Down
Expand Up @@ -90,7 +90,7 @@ public SmallHashLiteralNode(RubyContext context, SourceSection sourceSection, Ru
public RubyHash executeRubyHash(VirtualFrame frame) {
final Object[] storage = new Object[HashOperations.SMALL_HASH_SIZE * 2];

int position = 0;
int end = 0;

initializers: for (int n = 0; n < keyValues.length; n += 2) {
Object key = keyValues[n].execute(frame);
Expand All @@ -101,19 +101,19 @@ public RubyHash executeRubyHash(VirtualFrame frame) {

final Object value = keyValues[n + 1].execute(frame);

for (int i = 0; i < n; i += 2) {
for (int i = 0; i < end; i += 2) {
if (equalNode.call(frame, key, "eql?", null, storage[i])) {
storage[i + 1] = value;
continue initializers;
}
}

storage[position] = key;
storage[position + 1] = value;
position += 2;
storage[end] = key;
storage[end + 1] = value;
end += 2;
}

return new RubyHash(getContext().getCoreLibrary().getHashClass(), null, null, storage, position / 2, null);
return new RubyHash(getContext().getCoreLibrary().getHashClass(), null, null, storage, end / 2, null);
}

}
Expand Down
Expand Up @@ -74,11 +74,11 @@ public void setStore(Object store, int storeSize, Bucket firstInSequence, Bucket
this.lastInSequence = lastInSequence;
}

public int getStoreSize() {
public int getSize() {
return storeSize;
}

public void setStoreSize(int storeSize) {
public void setSize(int storeSize) {
this.storeSize = storeSize;
}

Expand Down
Expand Up @@ -49,7 +49,9 @@ public static RubyHash verySlowFromEntries(RubyContext context, List<Entry> entr
public static void dump(RubyHash hash) {
final StringBuilder builder = new StringBuilder();

builder.append("(");
builder.append("[");
builder.append(hash.getSize());
builder.append("](");

for (Bucket bucket : (Bucket[]) hash.getStore()) {
builder.append("(");
Expand Down Expand Up @@ -109,7 +111,7 @@ public static List<Entry> verySlowToEntries(RubyHash hash) {
bucket = bucket.getNextInSequence();
}
} else if (hash.getStore() instanceof Object[]) {
for (int n = 0; n < hash.getStoreSize(); n++) {
for (int n = 0; n < hash.getSize(); n++) {
entries.add(new Entry(((Object[]) hash.getStore())[n * 2], ((Object[]) hash.getStore())[n * 2 + 1]));
}
} else if (hash.getStore() != null) {
Expand Down Expand Up @@ -208,6 +210,6 @@ public static void verySlowSetEntries(RubyHash hash, List<Entry> entries) {
}
}

hash.setStoreSize(actualSize);
hash.setSize(actualSize);
}
}

0 comments on commit 18593e6

Please sign in to comment.