Skip to content

Commit

Permalink
[Truffle] Pull out a node for calling hash and getting the result int…
Browse files Browse the repository at this point in the history
…o an int.
  • Loading branch information
chrisseaton committed May 1, 2015
1 parent 630660c commit 09c2a3f
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 22 deletions.
19 changes: 10 additions & 9 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.hash.FindEntryNode;
import org.jruby.truffle.nodes.hash.HashNode;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
Expand Down Expand Up @@ -118,7 +119,7 @@ public static boolean isSmallArrayOfPairs(RubyClass hashClass, Object[] args) {
@ImportStatic(HashGuards.class)
public abstract static class GetIndexNode extends CoreMethodArrayArgumentsNode {

@Child private CallDispatchHeadNode hashNode;
@Child private HashNode hashNode;
@Child private CallDispatchHeadNode eqlNode;
@Child private BasicObjectNodes.ReferenceEqualNode equalNode;
@Child private CallDispatchHeadNode callDefaultNode;
Expand All @@ -132,7 +133,7 @@ public abstract static class GetIndexNode extends CoreMethodArrayArgumentsNode {

public GetIndexNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = DispatchHeadNodeFactory.createMethodCall(context, true);
hashNode = new HashNode(context, sourceSection);
eqlNode = DispatchHeadNodeFactory.createMethodCall(context, false, false, null);
equalNode = BasicObjectNodesFactory.ReferenceEqualNodeFactory.create(context, sourceSection, null, null);
callDefaultNode = DispatchHeadNodeFactory.createMethodCall(context);
Expand All @@ -143,7 +144,7 @@ public GetIndexNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = "isNullStorage(hash)")
public Object getNull(VirtualFrame frame, RubyHash hash, Object key) {
hashNode.call(frame, key, "hash", null);
hashNode.hash(frame, key);

if (undefinedValue != null) {
return undefinedValue;
Expand All @@ -155,7 +156,7 @@ public Object getNull(VirtualFrame frame, RubyHash hash, Object key) {
@ExplodeLoop
@Specialization(guards = "isPackedArrayStorage(hash)")
public Object getPackedArray(VirtualFrame frame, RubyHash hash, Object key) {
hashNode.call(frame, key, "hash", null);
hashNode.hash(frame, key);

final Object[] store = (Object[]) hash.getStore();
final int size = hash.getSize();
Expand Down Expand Up @@ -233,7 +234,7 @@ public Object getOrUndefined(VirtualFrame frame, RubyHash hash, Object key) {
@ImportStatic(HashGuards.class)
public abstract static class SetIndexNode extends CoreMethodArrayArgumentsNode {

@Child private CallDispatchHeadNode hashNode;
@Child private HashNode hashNode;
@Child private CallDispatchHeadNode eqlNode;
@Child private BasicObjectNodes.ReferenceEqualNode equalNode;

Expand All @@ -243,15 +244,15 @@ public abstract static class SetIndexNode extends CoreMethodArrayArgumentsNode {

public SetIndexNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = DispatchHeadNodeFactory.createMethodCall(context, true);
hashNode = new HashNode(context, sourceSection);
eqlNode = DispatchHeadNodeFactory.createMethodCall(context, false, false, null);
equalNode = BasicObjectNodesFactory.ReferenceEqualNodeFactory.create(context, sourceSection, null, null);
}

@Specialization(guards = { "isNullStorage(hash)", "!isRubyString(key)" })
public Object setNull(VirtualFrame frame, RubyHash hash, Object key, Object value) {
final Object[] store = new Object[PackedArrayStrategy.TRUFFLE_HASH_PACKED_ARRAY_MAX * 2];
hashNode.call(frame, key, "hash", null);
hashNode.hash(frame, key);
store[0] = key;
store[1] = value;
hash.setStore(store, 1, null, null);
Expand All @@ -271,7 +272,7 @@ public Object setNull(VirtualFrame frame, RubyHash hash, RubyString key, Object
@ExplodeLoop
@Specialization(guards = {"isPackedArrayStorage(hash)", "!isRubyString(key)"})
public Object setPackedArray(VirtualFrame frame, RubyHash hash, Object key, Object value) {
hashNode.call(frame, key, "hash", null);
hashNode.hash(frame, key);

final Object[] store = (Object[]) hash.getStore();
final int size = hash.getSize();
Expand Down Expand Up @@ -1211,7 +1212,7 @@ public static boolean isNullStorage(RubyHash hash) {
}

public static boolean isPackedArrayStorage(RubyHash hash) {
// Can't do instanceof Object[] due to cavariance
// Can't do instanceof Object[] due to covariance
return !(isNullStorage(hash) || isBucketsStorage(hash));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,21 @@

public class FindEntryNode extends RubyNode {

@Child CallDispatchHeadNode hashNode;
@Child HashNode hashNode;
@Child CallDispatchHeadNode eqlNode;
@Child BasicObjectNodes.ReferenceEqualNode equalNode;

private final ConditionProfile byIdentityProfile = ConditionProfile.createBinaryProfile();

public FindEntryNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = DispatchHeadNodeFactory.createMethodCall(context, true);
hashNode = new HashNode(context, sourceSection);
eqlNode = DispatchHeadNodeFactory.createMethodCall(context, false, false, null);
equalNode = BasicObjectNodesFactory.ReferenceEqualNodeFactory.create(context, sourceSection, null, null);
}

public HashSearchResult search(VirtualFrame frame, RubyHash hash, Object key) {
final Object hashValue = hashNode.call(frame, key, "hash", null);

final int hashed;

if (hashValue instanceof Integer) {
hashed = (int) hashValue;
} else if (hashValue instanceof Long) {
hashed = (int) (long) hashValue;
} else {
throw new UnsupportedOperationException();
}
final int hashed = hashNode.hash(frame, key);

final Entry[] entries = (Entry[]) hash.getStore();
final int index = HashOperations.getIndex(hashed, entries.length);
Expand Down
49 changes: 49 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/hash/HashNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2015 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.nodes.hash;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;

public class HashNode extends RubyNode {

@Child private CallDispatchHeadNode hashNode;

private final ConditionProfile isIntegerProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile isLongProfile = ConditionProfile.createBinaryProfile();

public HashNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = DispatchHeadNodeFactory.createMethodCall(context, true);
}

public int hash(VirtualFrame frame, Object key) {
final Object hashedObject = hashNode.call(frame, key, "hash", null);

if (isIntegerProfile.profile(hashedObject instanceof Integer)) {
return (int) hashedObject;
} else if (isLongProfile.profile(hashedObject instanceof Long)) {
return (int) (long) hashedObject;
} else {
throw new UnsupportedOperationException();
}
}

@Override
public Object execute(VirtualFrame frame) {
throw new UnsupportedOperationException();
}

}

0 comments on commit 09c2a3f

Please sign in to comment.