Skip to content

Commit

Permalink
Showing 3 changed files with 57 additions and 3 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/hash_tags.txt

This file was deleted.

55 changes: 55 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/array/ArrayNodes.java
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.runtime.Helpers;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.builtins.CoreClass;
@@ -88,8 +89,10 @@
import org.jruby.truffle.language.objects.TaintNodeGen;
import org.jruby.truffle.language.yield.YieldNode;
import org.jruby.util.Memo;

import java.util.Arrays;
import java.util.Comparator;

import static org.jruby.truffle.core.array.ArrayHelpers.createArray;
import static org.jruby.truffle.core.array.ArrayHelpers.getSize;
import static org.jruby.truffle.core.array.ArrayHelpers.getStore;
@@ -911,6 +914,58 @@ protected Object fillFallback(VirtualFrame frame, DynamicObject array, Object[]

}

@CoreMethod(names = "hash_internal")
public abstract static class HashNode extends ArrayCoreMethodNode {

@Child private ToIntNode toIntNode;

@Specialization(guards = "isNullArray(array)")
public long hashNull(DynamicObject array) {
final int arraySize = 0;
long h = Helpers.hashStart(getContext().getJRubyRuntime(), arraySize);
h = Helpers.murmurCombine(h, System.identityHashCode(ArrayNodes.class));
h = Helpers.hashEnd(h);
return h;
}

@Specialization(guards = "strategy.matches(array)", limit = "ARRAY_STRATEGIES")
public long hash(VirtualFrame frame, DynamicObject array,
@Cached("of(array)") ArrayStrategy strategy,
@Cached("createMethodCall()") CallDispatchHeadNode toHashNode) {

final int arraySize = getSize(array);
// TODO BJF Jul 4, 2016 Seed could be chosen in advance to avoid branching
long h = Helpers.hashStart(getContext().getJRubyRuntime(), arraySize);
h = Helpers.murmurCombine(h, System.identityHashCode(ArrayNodes.class));
final ArrayMirror store = strategy.newMirror(array);

int n = 0;

for (; n < arraySize; n++) {
final Object value = store.get(n);
final long valueHash = toLong(frame, toHashNode.call(frame, value, "hash", null));
h = Helpers.murmurCombine(h, valueHash);
}

h = Helpers.hashEnd(h);
return h;
}

private long toLong(VirtualFrame frame, Object indexObject) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
toIntNode = insert(ToIntNode.create());
}
final Object result = toIntNode.executeIntOrLong(frame, indexObject);
if (result instanceof Integer) {
return Long.valueOf((int) result);
} else {
return (long) result;
}
}

}

@CoreMethod(names = "include?", required = 1)
public abstract static class IncludeNode extends ArrayCoreMethodNode {

4 changes: 2 additions & 2 deletions truffle/src/main/ruby/core/array.rb
Original file line number Diff line number Diff line change
@@ -460,7 +460,7 @@ def hash
begin
objects[id] = true

each { |x| hash_val = ((hash_val & mask) << 1) ^ x.hash }
hash_val = self.hash_internal
ensure
objects.delete id
end
@@ -472,7 +472,7 @@ def hash
objects[:__detect_outermost_recursion__] = true
objects[id] = true

each { |x| hash_val = ((hash_val & mask) << 1) ^ x.hash }
hash_val = self.hash_internal

# An inner version will raise to return back here, indicating that
# the whole structure is recursive. In which case, abondon most of

0 comments on commit 74a21e5

Please sign in to comment.