Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 17b4ed275aa1
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 306e7b59f5b6
Choose a head ref
  • 3 commits
  • 8 files changed
  • 1 contributor

Commits on Aug 22, 2015

  1. Copy the full SHA
    8020abe View commit details
  2. Copy the full SHA
    76a422f View commit details
  3. [Truffle] FindBugs.

    chrisseaton committed Aug 22, 2015
    Copy the full SHA
    306e7b5 View commit details
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ private Object lookupRestKeywordArgumentHash(VirtualFrame frame) {
final DynamicObject hash = RubyArguments.getUserKeywordsHash(frame.getArguments(), minimum);

if (hash == null) {
return HashNodes.createEmptyHash(getContext().getCoreLibrary().getHashClass());
return Layouts.HASH.createHash(getContext().getCoreLibrary().getHashFactory(), null, null, null, 0, null, null, false);
}

final List<Map.Entry<Object, Object>> entries = new ArrayList<>();
@@ -78,7 +78,7 @@ private Object lookupRestKeywordArgumentHash(VirtualFrame frame) {
entries.add(keyValue);
}

return BucketsStrategy.create(getContext().getCoreLibrary().getHashClass(), entries, Layouts.HASH.getCompareByIdentity(hash));
return BucketsStrategy.create(getContext(), entries, Layouts.HASH.getCompareByIdentity(hash));
}

}
Original file line number Diff line number Diff line change
@@ -292,7 +292,7 @@ public DynamicObject coverageResult() {
converted.put(createString(source.getKey().getPath()), array);
}

return BucketsStrategy.create(getContext().getCoreLibrary().getHashClass(), converted.entrySet(), false);
return BucketsStrategy.create(getContext(), converted.entrySet(), false);
}

private Object[] lineCountsStore(Long[] array) {
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ public Object execute(VirtualFrame frame) {
}
}

return BucketsStrategy.create(getContext().getCoreLibrary().getHashClass(), keyValues, false);
return BucketsStrategy.create(getContext(), keyValues, false);
}

}
Original file line number Diff line number Diff line change
@@ -23,7 +23,9 @@
import org.jruby.truffle.nodes.objects.IsFrozenNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.hash.BucketsStrategy;
import org.jruby.truffle.runtime.hash.Entry;
import org.jruby.truffle.runtime.hash.PackedArrayStrategy;
import org.jruby.truffle.runtime.layouts.Layouts;

public abstract class HashLiteralNode extends RubyNode {

@@ -77,7 +79,7 @@ public EmptyHashLiteralNode(RubyContext context, SourceSection sourceSection) {
@ExplodeLoop
@Override
public Object execute(VirtualFrame frame) {
return HashNodes.createEmptyHash(getContext().getCoreLibrary().getHashClass());
return Layouts.HASH.createHash(getContext().getCoreLibrary().getHashFactory(), null, null, null, 0, null, null, false);
}

}
@@ -135,7 +137,7 @@ public Object execute(VirtualFrame frame) {
size++;
}

return HashNodes.createHash(getContext().getCoreLibrary().getHashClass(), store, size);
return Layouts.HASH.createHash(getContext().getCoreLibrary().getHashFactory(), null, null, store, size, null, null, false);
}

}
@@ -155,7 +157,10 @@ public Object execute(VirtualFrame frame) {
setNode = insert(SetNodeGen.create(getContext(), getEncapsulatingSourceSection(), null, null, null, null));
}

final DynamicObject hash = BucketsStrategy.create(getContext().getCoreLibrary().getHashClass(), keyValues.length / 2);
final int bucketsCount = BucketsStrategy.capacityGreaterThan(keyValues.length / 2) * BucketsStrategy.OVERALLOCATE_FACTOR;
final Entry[] newEntries = new Entry[bucketsCount];

final DynamicObject hash = Layouts.HASH.createHash(getContext().getCoreLibrary().getHashFactory(), null, null, newEntries, 0, null, null, false);

for (int n = 0; n < keyValues.length; n += 2) {
final Object key = keyValues[n].execute(frame);
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@
import org.jruby.truffle.nodes.core.array.ArrayBuilderNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.objects.AllocateObjectNode;
import org.jruby.truffle.nodes.objects.AllocateObjectNodeGen;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyArguments;
@@ -171,18 +173,6 @@ public static void setStore(DynamicObject hash, Object store, int size, Entry fi

}

public static DynamicObject createEmptyHash(DynamicObject hashClass) {
return createHash(hashClass, null, null, null, 0, null, null);
}

public static DynamicObject createHash(DynamicObject hashClass, Object[] store, int size) {
return createHash(hashClass, null, null, store, size, null, null);
}

public static DynamicObject createHash(DynamicObject hashClass, DynamicObject defaultBlock, Object defaultValue, Object store, int size, Entry firstInSequence, Entry lastInSequence) {
return Layouts.HASH.createHash(Layouts.CLASS.getInstanceFactory(hashClass), defaultBlock, defaultValue, store, size, firstInSequence, lastInSequence, false);
}

@TruffleBoundary
public static Iterator<Map.Entry<Object, Object>> iterateKeyValues(DynamicObject hash) {
assert RubyGuards.isRubyHash(hash);
@@ -215,13 +205,16 @@ public Iterator<Map.Entry<Object, Object>> iterator() {
@CoreMethod(names = "allocate", constructor = true)
public abstract static class AllocateNode extends CoreMethodArrayArgumentsNode {

@Child private AllocateObjectNode allocateObjectNode;

public AllocateNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
}

@Specialization
public DynamicObject allocate(DynamicObject rubyClass) {
return HashNodes.createEmptyHash(rubyClass);
return allocateObjectNode.allocate(rubyClass, null, null, null, 0, null, null, false);
}

}
@@ -231,10 +224,12 @@ public DynamicObject allocate(DynamicObject rubyClass) {
public abstract static class ConstructNode extends CoreMethodArrayArgumentsNode {

@Child private HashNode hashNode;
@Child private AllocateObjectNode allocateObjectNode;

public ConstructNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = new HashNode(context, sourceSection);
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
}

@ExplodeLoop
@@ -276,7 +271,7 @@ public Object construct(VirtualFrame frame, DynamicObject hashClass, Object[] ar
}
}

return createHash(hashClass, newStore, size);
return allocateObjectNode.allocate(hashClass, null, null, newStore, size, null, null, false);
}

@Specialization
@@ -914,6 +909,7 @@ public abstract static class MergeNode extends YieldingCoreMethodNode {
@Child private CallDispatchHeadNode fallbackCallNode;
@Child private LookupEntryNode lookupEntryNode;
@Child private SetNode setNode;
@Child private AllocateObjectNode allocateObjectNode;

private final BranchProfile nothingFromFirstProfile = BranchProfile.create();
private final BranchProfile considerResultIsSmallProfile = BranchProfile.create();
@@ -924,6 +920,7 @@ public MergeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
eqlNode = DispatchHeadNodeFactory.createMethodCall(context);
setNode = SetNodeGen.create(context, sourceSection, null, null, null, null);
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, null, null);
}

// Merge with an empty hash, without a block
@@ -934,7 +931,7 @@ public MergeNode(RubyContext context, SourceSection sourceSection) {
"isNullHash(other)"
})
public DynamicObject mergeEmptyEmpty(DynamicObject hash, DynamicObject other, NotProvided block) {
return createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), null, 0, null, null);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), null, 0, null, null, false);
}

@Specialization(guards = {
@@ -945,7 +942,7 @@ public DynamicObject mergeEmptyEmpty(DynamicObject hash, DynamicObject other, No
public DynamicObject mergeEmptyPacked(DynamicObject hash, DynamicObject other, NotProvided block) {
final Object[] store = (Object[]) Layouts.HASH.getStore(other);
final Object[] copy = PackedArrayStrategy.copyStore(store);
return createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), copy, Layouts.HASH.getSize(other), null, null);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), copy, Layouts.HASH.getSize(other), null, null, false);
}

@Specialization(guards = {
@@ -956,7 +953,7 @@ public DynamicObject mergeEmptyPacked(DynamicObject hash, DynamicObject other, N
public DynamicObject mergePackedEmpty(DynamicObject hash, DynamicObject other, NotProvided block) {
final Object[] store = (Object[]) Layouts.HASH.getStore(hash);
final Object[] copy = PackedArrayStrategy.copyStore(store);
return createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), copy, Layouts.HASH.getSize(hash), null, null);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), copy, Layouts.HASH.getSize(hash), null, null, false);
}

@Specialization(guards = {
@@ -965,7 +962,7 @@ public DynamicObject mergePackedEmpty(DynamicObject hash, DynamicObject other, N
"isBucketHash(other)"
})
public DynamicObject mergeEmptyBuckets(DynamicObject hash, DynamicObject other, NotProvided block) {
final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), null, 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), null, 0, null, null, false);
BucketsStrategy.copyInto(other, merged);
return merged;
}
@@ -976,7 +973,7 @@ public DynamicObject mergeEmptyBuckets(DynamicObject hash, DynamicObject other,
"isEmptyHash(other)"
})
public DynamicObject mergeBucketsEmpty(DynamicObject hash, DynamicObject other, NotProvided block) {
final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), null, 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), null, 0, null, null, false);
BucketsStrategy.copyInto(hash, merged);
return merged;
}
@@ -1034,7 +1031,7 @@ public DynamicObject mergePackedPacked(VirtualFrame frame, DynamicObject hash, D

if (mergeFromACount == 0) {
nothingFromFirstProfile.enter();
return createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), PackedArrayStrategy.copyStore(storeB), storeBSize, null, null);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), PackedArrayStrategy.copyStore(storeB), storeBSize, null, null, false);
}

// Cut off here
@@ -1070,14 +1067,14 @@ public DynamicObject mergePackedPacked(VirtualFrame frame, DynamicObject hash, D
index++;
}

return createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), merged, mergedSize, null, null);
return allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), Layouts.HASH.getDefaultBlock(hash), Layouts.HASH.getDefaultValue(hash), merged, mergedSize, null, null, false);
}

// Most complicated cases where things from both hashes, and it also needs to be promoted to buckets

promoteProfile.enter();

final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(mergedSize)], 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(mergedSize)], 0, null, null, false);

for (int n = 0; n < storeASize; n++) {
if (mergeFromA[n]) {
@@ -1106,7 +1103,7 @@ public DynamicObject mergePackedPacked(VirtualFrame frame, DynamicObject hash, D
public DynamicObject mergeBucketsBuckets(VirtualFrame frame, DynamicObject hash, DynamicObject other, NotProvided block) {
final boolean isCompareByIdentity = Layouts.HASH.getCompareByIdentity(hash);

final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null, false);

for (Map.Entry<Object, Object> keyValue : BucketsStrategy.iterableKeyValues(Layouts.HASH.getFirstInSequence(hash))) {
setNode.executeSet(frame, merged, keyValue.getKey(), keyValue.getValue(), isCompareByIdentity);
@@ -1133,7 +1130,7 @@ public DynamicObject mergeBucketsBuckets(VirtualFrame frame, DynamicObject hash,
public DynamicObject mergePackedBuckets(VirtualFrame frame, DynamicObject hash, DynamicObject other, NotProvided block) {
final boolean isCompareByIdentity = Layouts.HASH.getCompareByIdentity(hash);

final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null, false);

final Object[] hashStore = (Object[]) Layouts.HASH.getStore(hash);
final int hashSize = Layouts.HASH.getSize(hash);
@@ -1163,7 +1160,7 @@ public DynamicObject mergePackedBuckets(VirtualFrame frame, DynamicObject hash,
public DynamicObject mergeBucketsPacked(VirtualFrame frame, DynamicObject hash, DynamicObject other, NotProvided block) {
final boolean isCompareByIdentity = Layouts.HASH.getCompareByIdentity(hash);

final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null, false);

for (Map.Entry<Object, Object> keyValue : BucketsStrategy.iterableKeyValues(Layouts.HASH.getFirstInSequence(hash))) {
setNode.executeSet(frame, merged, keyValue.getKey(), keyValue.getValue(), isCompareByIdentity);
@@ -1189,7 +1186,7 @@ public DynamicObject mergeBucketsPacked(VirtualFrame frame, DynamicObject hash,
public DynamicObject merge(VirtualFrame frame, DynamicObject hash, DynamicObject other, DynamicObject block) {
CompilerDirectives.bailout("Hash#merge with a block cannot be compiled at the moment");

final DynamicObject merged = createHash(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null);
final DynamicObject merged = allocateObjectNode.allocate(Layouts.BASIC_OBJECT.getLogicalClass(hash), null, null, new Entry[BucketsStrategy.capacityGreaterThan(Layouts.HASH.getSize(hash) + Layouts.HASH.getSize(other))], 0, null, null, false);

int size = 0;

Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.array;

import java.util.Iterator;
import java.util.NoSuchElementException;

public abstract class BasicArrayMirror implements ArrayMirror {

@@ -46,7 +47,11 @@ public boolean hasNext() {
}

@Override
public Object next() {
public Object next() throws NoSuchElementException {
if (n >= length) {
throw new NoSuchElementException();
}

final Object object = get(n);
n++;
return object;
Original file line number Diff line number Diff line change
@@ -91,6 +91,7 @@ public class CoreLibrary {
private final DynamicObject floatClass;
private final DynamicObject floatDomainErrorClass;
private final DynamicObject hashClass;
private final DynamicObjectFactory hashFactory;
private final DynamicObject integerClass;
private final DynamicObject indexErrorClass;
private final DynamicObject ioErrorClass;
@@ -330,7 +331,8 @@ public CoreLibrary(RubyContext context) {
Layouts.CLASS.setInstanceFactoryUnsafe(fiberClass, Layouts.FIBER.createFiberShape(fiberClass, fiberClass));
defineModule("FileTest");
hashClass = defineClass("Hash");
Layouts.CLASS.setInstanceFactoryUnsafe(hashClass, Layouts.HASH.createHashShape(hashClass, hashClass));
hashFactory = Layouts.HASH.createHashShape(hashClass, hashClass);
Layouts.CLASS.setInstanceFactoryUnsafe(hashClass, hashFactory);
matchDataClass = defineClass("MatchData");
Layouts.CLASS.setInstanceFactoryUnsafe(matchDataClass, Layouts.MATCH_DATA.createMatchDataShape(matchDataClass, matchDataClass));
methodClass = defineClass("Method");
@@ -1550,4 +1552,8 @@ public DynamicObjectFactory getStringFactory() {
return stringFactory;
}

public DynamicObjectFactory getHashFactory() {
return hashFactory;
}

}
Original file line number Diff line number Diff line change
@@ -31,16 +31,8 @@ public abstract class BucketsStrategy {

private static final int[] CAPACITIES = Arrays.copyOf(org.jruby.RubyHash.MRI_PRIMES, org.jruby.RubyHash.MRI_PRIMES.length - 1);

public static DynamicObject create(DynamicObject hashClass, int capacity) {
final int bucketsCount = capacityGreaterThan(capacity) * OVERALLOCATE_FACTOR;
final Entry[] newEntries = new Entry[bucketsCount];

return HashNodes.createHash(hashClass, null, null, newEntries, 0, null, null);
}

public static DynamicObject create(DynamicObject hashClass, Collection<Map.Entry<Object, Object>> entries, boolean byIdentity) {
final RubyContext context = Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(hashClass)).getContext();

@TruffleBoundary
public static DynamicObject create(RubyContext context, Collection<Map.Entry<Object, Object>> entries, boolean byIdentity) {
int actualSize = entries.size();

final int bucketsCount = capacityGreaterThan(entries.size()) * OVERALLOCATE_FACTOR;
@@ -56,7 +48,7 @@ public static DynamicObject create(DynamicObject hashClass, Collection<Map.Entry
key = context.send(context.send(key, "dup", null), "freeze", null);
}

final int hashed = HashNodes.slowHashKey(Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(hashClass)).getContext(), key);
final int hashed = HashNodes.slowHashKey(context, key);
Entry newEntry = new Entry(hashed, key, entry.getValue());

final int index = BucketsStrategy.getBucketIndex(hashed, newEntries.length);
@@ -69,7 +61,7 @@ public static DynamicObject create(DynamicObject hashClass, Collection<Map.Entry

while (bucketEntry != null) {
if (hashed == bucketEntry.getHashed()
&& HashNodes.slowAreKeysEqual(Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(hashClass)).getContext(), bucketEntry.getKey(), key, byIdentity)) {
&& HashNodes.slowAreKeysEqual(context, bucketEntry.getKey(), key, byIdentity)) {
bucketEntry.setValue(entry.getValue());

actualSize--;
@@ -116,7 +108,7 @@ public static DynamicObject create(DynamicObject hashClass, Collection<Map.Entry
lastInSequence = newEntry;
}

return HashNodes.createHash(hashClass, null, null, newEntries, actualSize, firstInSequence, lastInSequence);
return Layouts.HASH.createHash(context.getCoreLibrary().getHashFactory(), null, null, newEntries, actualSize, firstInSequence, lastInSequence, false);
}

public static int capacityGreaterThan(int size) {