Skip to content

Commit

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

This file was deleted.

59 changes: 59 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,11 @@
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyFixnum;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.builtins.CoreClass;
@@ -90,6 +95,9 @@
import org.jruby.util.Memo;
import java.util.Arrays;
import java.util.Comparator;

import static org.jruby.runtime.Helpers.hashEnd;
import static org.jruby.runtime.Helpers.murmurCombine;
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 +919,57 @@ protected Object fillFallback(VirtualFrame frame, DynamicObject array, Object[]

}

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

@Child private ToIntNode toIntNode;
@Child private ArrayReadSliceNormalizedNode readSliceNode;

@Specialization(guards = "isNullArray(array)")
public long hashNull(VirtualFrame frame, DynamicObject array) {
final int arraySize = 0;
long h = Helpers.hashStart(getContext().getJRubyRuntime(), arraySize);
h = Helpers.murmurCombine(h, System.identityHashCode(ArrayNodes.class));
h = 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("new()") SnippetNode snippetNode) {

final int arraySize = getSize(array);
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, snippetNode.execute(frame, "value.hash", "value", value));
h = murmurCombine(h, valueHash);
}

h = hashEnd(h);
return h;
}

private long toLong(VirtualFrame frame, Object indexObject) {
if (toIntNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
toIntNode = insert(ToIntNode.create());
}
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 75ca057

Please sign in to comment.