Skip to content

Commit

Permalink
[Truffle] Disentangle hashing from JRuby classic.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Nov 3, 2016
1 parent 8418945 commit 6b0df4c
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 23 deletions.
82 changes: 82 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/core/Hashing.java
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.core;

import org.jruby.util.cli.Options;

import java.util.Random;

public class Hashing {

private static final boolean SIPHASH_ENABLED = Options.SIPHASH_ENABLED.load();
private static final boolean CONSISTENT_HASHING_ENABLED = Options.CONSISTENT_HASHING.load();

private static final int MURMUR2_MAGIC = 0x5bd1e995;

public static final long SEED_K0;
public static final long SEED_K1;

static {
if (CONSISTENT_HASHING_ENABLED) {
SEED_K0 = -561135208506705104l;
SEED_K1 = 7114160726623585955l;
} else {
final Random random = new Random();
SEED_K0 = random.nextLong();
SEED_K1 = random.nextLong();
}
}

public static long hash(long seed, long value) {
return end(update(start(seed), value));
}

public static long start(long value) {
long hash = value;

if (SIPHASH_ENABLED) {
hash += SEED_K0;
} else {
hash += SEED_K1;
}
return hash;
}

public static long update(long hash, long value) {
long v = 0;
hash += value;
v = murmur1(v + hash);
v = murmur1(v + (hash >>> 4*8));
return v;
}

public static long end(long hash) {
hash = murmur_step(hash, 10);
hash = murmur_step(hash, 17);
return hash;
}

private static long murmur1(long h) {
return murmur_step(h, 16);
}

public static long murmur_step(long h, long k) {
return murmur((h), (k), 16);
}

public static long murmur(long h, long k, int r) {
long m = MURMUR2_MAGIC;
h += k;
h *= m;
h ^= h >> r;
return h;
}

}
Expand Up @@ -36,6 +36,7 @@
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.CoreMethodNode;
import org.jruby.truffle.builtins.YieldingCoreMethodNode;
import org.jruby.truffle.core.Hashing;
import org.jruby.truffle.core.array.ArrayNodesFactory.RejectInPlaceNodeFactory;
import org.jruby.truffle.core.array.ArrayNodesFactory.ReplaceNodeFactory;
import org.jruby.truffle.core.cast.ToAryNodeGen;
Expand Down Expand Up @@ -924,9 +925,9 @@ public abstract static class HashNode extends ArrayCoreMethodNode {
@Specialization(guards = "isNullArray(array)")
public long hashNull(DynamicObject array) {
final int size = 0;
long h = Helpers.hashStart(getContext().getJRubyRuntime(), size);
h = Helpers.murmurCombine(h, MURMUR_ARRAY_SEED);
return Helpers.hashEnd(h);
long h = Hashing.start(size);
h = Hashing.update(h, MURMUR_ARRAY_SEED);
return Hashing.end(h);
}

@Specialization(guards = "strategy.matches(array)", limit = "ARRAY_STRATEGIES")
Expand All @@ -935,17 +936,17 @@ public long hash(VirtualFrame frame, DynamicObject array,
@Cached("createMethodCall()") CallDispatchHeadNode toHashNode) {
final int size = getSize(array);
// TODO BJF Jul 4, 2016 Seed could be chosen in advance to avoid branching
long h = Helpers.hashStart(getContext().getJRubyRuntime(), size);
h = Helpers.murmurCombine(h, MURMUR_ARRAY_SEED);
long h = Hashing.start(size);
h = Hashing.update(h, MURMUR_ARRAY_SEED);
final ArrayMirror store = strategy.newMirror(array);

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

return Helpers.hashEnd(h);
return Hashing.end(h);
}

private long toLong(VirtualFrame frame, Object indexObject) {
Expand Down
Expand Up @@ -52,6 +52,7 @@
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.builtins.UnaryCoreMethodNode;
import org.jruby.truffle.core.Hashing;
import org.jruby.truffle.core.ObjectNodes;
import org.jruby.truffle.core.ObjectNodesFactory;
import org.jruby.truffle.core.array.ArrayUtils;
Expand Down Expand Up @@ -896,16 +897,12 @@ public abstract static class HashNode extends CoreMethodArrayArgumentsNode {

@Specialization
public long hash(int value) {
long h = Helpers.hashStart(getContext().getJRubyRuntime(), MURMUR_SEED);
h = Helpers.murmurCombine(h, value);
return Helpers.hashEnd(h);
return Hashing.hash(MURMUR_SEED, value);
}

@Specialization
public long hash(long value) {
long h = Helpers.hashStart(getContext().getJRubyRuntime(), MURMUR_SEED);
h = Helpers.murmurCombine(h, value);
return Helpers.hashEnd(h);
return Hashing.hash(MURMUR_SEED, value);
}

@Specialization
Expand Down
Expand Up @@ -29,6 +29,7 @@
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.UnaryCoreMethodNode;
import org.jruby.truffle.core.Hashing;
import org.jruby.truffle.core.basicobject.BasicObjectNodes.ReferenceEqualNode;
import org.jruby.truffle.core.cast.ProcOrNullNode;
import org.jruby.truffle.core.cast.ProcOrNullNodeGen;
Expand Down Expand Up @@ -112,10 +113,10 @@ public abstract static class HashNode extends CoreMethodArrayArgumentsNode {
@Specialization
public long hash(DynamicObject rubyMethod) {
final InternalMethod method = Layouts.METHOD.getMethod(rubyMethod);
long h = Helpers.hashStart(getContext().getJRubyRuntime(), method.getDeclaringModule().hashCode());
h = Helpers.murmurCombine(h, Layouts.METHOD.getReceiver(rubyMethod).hashCode());
h = Helpers.murmurCombine(h, method.getSharedMethodInfo().hashCode());
return Helpers.hashEnd(h);
long h = Hashing.start(method.getDeclaringModule().hashCode());
h = Hashing.update(h, Layouts.METHOD.getReceiver(rubyMethod).hashCode());
h = Hashing.update(h, method.getSharedMethodInfo().hashCode());
return Hashing.end(h);
}

}
Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.jruby.truffle.builtins.CoreMethod;
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.UnaryCoreMethodNode;
import org.jruby.truffle.core.Hashing;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.arguments.ArgumentDescriptorUtils;
Expand Down Expand Up @@ -108,10 +109,10 @@ public abstract static class HashNode extends CoreMethodArrayArgumentsNode {
@Specialization
public long hash(DynamicObject rubyMethod) {
final InternalMethod method = Layouts.UNBOUND_METHOD.getMethod(rubyMethod);
long h = Helpers.hashStart(getContext().getJRubyRuntime(), method.getDeclaringModule().hashCode());
h = Helpers.murmurCombine(h, Layouts.UNBOUND_METHOD.getOrigin(rubyMethod).hashCode());
h = Helpers.murmurCombine(h, method.getSharedMethodInfo().hashCode());
return Helpers.hashEnd(h);
long h = Hashing.start(method.getDeclaringModule().hashCode());
h = Hashing.update(h, Layouts.UNBOUND_METHOD.getOrigin(rubyMethod).hashCode());
h = Hashing.update(h, method.getSharedMethodInfo().hashCode());
return Hashing.end(h);
}

}
Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.core.CoreLibrary;
import org.jruby.truffle.core.Hashing;
import org.jruby.truffle.core.InlinableBuiltin;
import org.jruby.truffle.core.numeric.FixnumNodesFactory.DivNodeFactory;
import org.jruby.truffle.core.rope.LazyIntRope;
Expand Down Expand Up @@ -1194,8 +1195,7 @@ public long memhashLongLong(long a, long b) {
final ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES * 2);
buffer.putLong(a);
buffer.putLong(b);
return SipHashInline.hash24(getContext().getJRubyRuntime().getHashSeedK0(),
getContext().getJRubyRuntime().getHashSeedK1(), buffer.array());
return SipHashInline.hash24(Hashing.SEED_K0, Hashing.SEED_K1, buffer.array());
}


Expand Down

0 comments on commit 6b0df4c

Please sign in to comment.