Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Truffle] New implementation of non-small hashes #2328

Merged
merged 12 commits into from
Dec 17, 2014
Merged
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ private final void alloc(int buckets) {
* ============================
*/

private static final int MRI_PRIMES[] = {
public static final int MRI_PRIMES[] = {
8 + 3, 16 + 3, 32 + 5, 64 + 3, 128 + 3, 256 + 27, 512 + 9, 1024 + 9, 2048 + 5, 4096 + 3,
8192 + 27, 16384 + 43, 32768 + 3, 65536 + 45, 131072 + 29, 262144 + 3, 524288 + 21, 1048576 + 7,
2097152 + 17, 4194304 + 15, 8388608 + 9, 16777216 + 43, 33554432 + 35, 67108864 + 15,
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.jruby.truffle.runtime.core.RubyHash;
import org.jruby.truffle.runtime.core.RubyRange;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.hash.BucketSearchResult;
import org.jruby.truffle.runtime.rubinius.RubiniusByteArray;
import org.jruby.truffle.runtime.rubinius.RubiniusChannel;

Expand Down Expand Up @@ -191,6 +192,10 @@ public RubyEncodingConverter executeRubyEncodingConverter(VirtualFrame frame) th
return RubyTypesGen.RUBYTYPES.expectRubyEncodingConverter(execute(frame));
}

public BucketSearchResult executeBucketSearchResult(VirtualFrame frame) throws UnexpectedResultException {
return RubyTypesGen.RUBYTYPES.expectBucketSearchResult(execute(frame));
}

public Dispatch.DispatchAction executeDispatchAction(VirtualFrame frame) {
throw new UnsupportedOperationException();
}
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/RubyTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.jruby.truffle.runtime.core.RubyHash;
import org.jruby.truffle.runtime.core.RubyRange;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.hash.BucketSearchResult;
import org.jruby.truffle.runtime.rubinius.RubiniusByteArray;
import org.jruby.truffle.runtime.rubinius.RubiniusChannel;
import org.jruby.truffle.runtime.LexicalScope;
Expand Down Expand Up @@ -61,6 +62,7 @@
RubiniusByteArray.class, //
RubyEncodingConverter.class, //
RubyBasicObject.class, //
BucketSearchResult.class, //
Object[].class})

public class RubyTypes {
Expand Down
38 changes: 37 additions & 1 deletion core/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,6 @@ public ClearNode(ClearNode prev) {
@Specialization
public RubyArray clear(RubyArray array) {
notDesignedForCompilation();

array.setSize(0);
return array;
}
Expand Down Expand Up @@ -3551,6 +3550,43 @@ public RubyArray toA(RubyArray array) {

}

@CoreMethod(names = "uniq")
public abstract static class UniqNode extends CoreMethodNode {

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

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

@Specialization
public RubyArray uniq(RubyArray array) {
notDesignedForCompilation();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MRI uses a temporary Hash to avoid O(n2) here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So maybe we could have an overload of notDesignedForCompilation() mapping to CompilerAsserts.neverPartOfCompilation(String message) so to keep track of what is not compilation ready when not obvious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea - we can go through and add a reason for all the notDesigneds when we do a spring clean after 0.6 is released.


final RubyArray uniq = new RubyArray(getContext().getCoreLibrary().getArrayClass(), null, 0);

for (Object value : array.slowToArray()) {
boolean duplicate = false;

for (Object compare : uniq.slowToArray()) {
if ((boolean) DebugOperations.send(getContext(), value, "==", null, compare)) {
duplicate = true;
break;
}
}

if (!duplicate) {
uniq.slowPush(value);
}
}

return uniq;
}

}

@CoreMethod(names = "unshift", argumentsAsArray = true)
public abstract static class UnshiftNode extends CoreMethodNode {

Expand Down
22 changes: 5 additions & 17 deletions core/src/main/java/org/jruby/truffle/nodes/core/HashGuards.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
package org.jruby.truffle.nodes.core;

import org.jruby.truffle.runtime.core.RubyHash;

import java.util.LinkedHashMap;
import org.jruby.truffle.runtime.hash.Bucket;

public class HashGuards {

Expand All @@ -20,23 +19,12 @@ public static boolean isNull(RubyHash hash) {
}

public static boolean isObjectArray(RubyHash hash) {
return hash.getStore() instanceof Object[];
}

public static boolean isObjectLinkedHashMap(RubyHash hash) {
return hash.getStore() instanceof LinkedHashMap<?, ?>;
}

public static boolean isOtherNull(RubyHash hash, RubyHash other) {
return other.getStore() == null;
}

public static boolean isOtherObjectArray(RubyHash hash, RubyHash other) {
return other.getStore() instanceof Object[];
// Arrays are covariant in Java!
return hash.getStore() instanceof Object[] && !(hash.getStore() instanceof Bucket[]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this means there is no good way to check that the ObjectArray strategy is actually only using just a Object[] with instanceof?
But getClass() should do it then, so the assertions in RubyHash constructor should be adapted?
Wondering if 2 instanceof is also better than 1 getClass().

}

public static boolean isOtherObjectLinkedHashMap(RubyHash hash, RubyHash other) {
return other.getStore() instanceof LinkedHashMap<?, ?>;
public static boolean isBucketArray(RubyHash hash) {
return hash.getStore() instanceof Bucket[];
}

}
Loading