Skip to content

Commit

Permalink
[Truffle] Restore a highly optimised version of one particular path i…
Browse files Browse the repository at this point in the history
…n Hash#[]
  • Loading branch information
chrisseaton committed Mar 9, 2015
1 parent 777284b commit 9d31d67
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
80 changes: 80 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java
Expand Up @@ -117,6 +117,86 @@ public boolean equalNonHash(RubyHash a, Object b) {

}

@CoreMethod(names = "[]", onSingleton = true, argumentsAsArray = true, reallyDoesNeedSelf = true)
public abstract static class ConstructNode extends HashCoreMethodNode {

public ConstructNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public ConstructNode(ConstructNode prev) {
super(prev);
}

@ExplodeLoop
@Specialization(guards = "isSmallArrayOfPairs")
public Object construct(VirtualFrame frame, RubyClass hashClass, Object[] args) {
final RubyArray array = (RubyArray) args[0];

final Object[] store = (Object[]) array.getStore();

final int size = array.getSize();
final Object[] newStore = new Object[HashOperations.SMALL_HASH_SIZE * 2];

for (int n = 0; n < HashOperations.SMALL_HASH_SIZE; n++) {
if (n < size) {
final Object pair = store[n];

if (!(pair instanceof RubyArray)) {
CompilerDirectives.transferToInterpreter();
return constructFallback(frame, hashClass, args);
}

final RubyArray pairArray = (RubyArray) pair;

if (!(pairArray.getStore() instanceof Object[])) {
CompilerDirectives.transferToInterpreter();
return constructFallback(frame, hashClass, args);
}

final Object[] pairStore = (Object[]) pairArray.getStore();

newStore[n * 2] = pairStore[0];
newStore[n * 2 + 1] = pairStore[1];
}
}

return new RubyHash(hashClass, null, null, newStore, size, null);
}

@Specialization
public Object constructFallback(VirtualFrame frame, RubyClass hashClass, Object[] args) {
return ruby(frame, "_constructor_fallback(*args)", "args", RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(), args));
}

public static boolean isSmallArrayOfPairs(RubyClass hashClass, Object[] args) {
if (args.length != 1) {
return false;
}

final Object arg = args[0];

if (!(arg instanceof RubyArray)) {
return false;
}

final RubyArray array = (RubyArray) arg;

if (!(array.getStore() instanceof Object[])) {
return false;
}

final Object[] store = (Object[]) array.getStore();

if (store.length > HashOperations.SMALL_HASH_SIZE) {
return false;
}

return true;
}

}

@CoreMethod(names = "[]", required = 1)
public abstract static class GetIndexNode extends HashCoreMethodNode {

Expand Down
4 changes: 3 additions & 1 deletion truffle/src/main/ruby/core/rubinius/common/hash.rb
Expand Up @@ -368,7 +368,9 @@ def ==(other)
true
end

def self.[](*args)
# Renamed version of the Rubinius Hash#[] method
#def self.[](*args)
def self._constructor_fallback(*args)
if args.size == 1
obj = args.first
if hash = Rubinius::Type.check_convert_type(obj, Hash, :to_hash)
Expand Down

0 comments on commit 9d31d67

Please sign in to comment.