Skip to content

Commit 584ec92

Browse files
committed
Merge pull request #2571 from jruby/truffle-arrays
Truffle arrays
2 parents 7b206aa + ab9231e commit 584ec92

File tree

9 files changed

+276
-218
lines changed

9 files changed

+276
-218
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 1.0
7+
* GNU General Public License version 2
8+
* GNU Lesser General Public License version 2.1
9+
*/
10+
package org.jruby.truffle.nodes.array;
11+
12+
import com.oracle.truffle.api.CompilerDirectives;
13+
import com.oracle.truffle.api.dsl.NodeChild;
14+
import com.oracle.truffle.api.dsl.NodeChildren;
15+
import com.oracle.truffle.api.dsl.Specialization;
16+
import com.oracle.truffle.api.frame.VirtualFrame;
17+
import com.oracle.truffle.api.source.SourceSection;
18+
import org.jruby.truffle.nodes.RubyNode;
19+
import org.jruby.truffle.runtime.RubyContext;
20+
import org.jruby.truffle.runtime.core.RubyArray;
21+
22+
@NodeChildren({
23+
@NodeChild(value="array", type=RubyNode.class),
24+
@NodeChild(value="index", type=RubyNode.class)
25+
})
26+
public abstract class ArrayReadDenormalizedNode extends RubyNode {
27+
28+
@Child private ArrayReadNormalizedNode readNode;
29+
30+
public ArrayReadDenormalizedNode(RubyContext context, SourceSection sourceSection) {
31+
super(context, sourceSection);
32+
}
33+
34+
public ArrayReadDenormalizedNode(ArrayReadDenormalizedNode prev) {
35+
super(prev);
36+
readNode = prev.readNode;
37+
}
38+
39+
public abstract Object executeRead(VirtualFrame frame, RubyArray array, int index);
40+
41+
@Specialization
42+
public Object read(VirtualFrame frame, RubyArray array, int index) {
43+
if (readNode == null) {
44+
CompilerDirectives.transferToInterpreter();
45+
readNode = insert(ArrayReadNormalizedNodeFactory.create(getContext(), getSourceSection(), null, null));
46+
}
47+
48+
final int normalizedIndex = array.normaliseIndex(index);
49+
50+
return readNode.executeRead(frame, array, normalizedIndex);
51+
}
52+
53+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 1.0
7+
* GNU General Public License version 2
8+
* GNU Lesser General Public License version 2.1
9+
*/
10+
package org.jruby.truffle.nodes.array;
11+
12+
import com.oracle.truffle.api.dsl.ImportGuards;
13+
import com.oracle.truffle.api.dsl.NodeChild;
14+
import com.oracle.truffle.api.dsl.NodeChildren;
15+
import com.oracle.truffle.api.dsl.Specialization;
16+
import com.oracle.truffle.api.frame.VirtualFrame;
17+
import com.oracle.truffle.api.nodes.UnexpectedResultException;
18+
import com.oracle.truffle.api.source.SourceSection;
19+
import org.jruby.truffle.nodes.RubyNode;
20+
import org.jruby.truffle.nodes.core.ArrayGuards;
21+
import org.jruby.truffle.runtime.RubyContext;
22+
import org.jruby.truffle.runtime.core.RubyArray;
23+
import org.jruby.truffle.runtime.core.RubyNilClass;
24+
25+
@NodeChildren({
26+
@NodeChild(value="array", type=RubyNode.class),
27+
@NodeChild(value="index", type=RubyNode.class)
28+
})
29+
@ImportGuards(ArrayGuards.class)
30+
public abstract class ArrayReadNormalizedNode extends RubyNode {
31+
32+
public ArrayReadNormalizedNode(RubyContext context, SourceSection sourceSection) {
33+
super(context, sourceSection);
34+
}
35+
36+
public ArrayReadNormalizedNode(ArrayReadNormalizedNode prev) {
37+
super(prev);
38+
}
39+
40+
public abstract Object executeRead(VirtualFrame frame, RubyArray array, int index);
41+
42+
@Specialization(
43+
guards="isNullArray"
44+
)
45+
public RubyNilClass readNull(RubyArray array, int index) {
46+
return getContext().getCoreLibrary().getNilObject();
47+
}
48+
49+
@Specialization(
50+
guards={"isNormalisedInBounds", "isIntegerArray"}
51+
)
52+
public int readIntegerInBounds(RubyArray array, int index) {
53+
return ((int[]) array.getStore())[index];
54+
}
55+
56+
@Specialization(
57+
guards={"isNormalisedInBounds", "isLongArray"}
58+
)
59+
public long readLongInBounds(RubyArray array, int index) {
60+
return ((long[]) array.getStore())[index];
61+
}
62+
63+
@Specialization(
64+
guards={"isNormalisedInBounds", "isDoubleArray"}
65+
)
66+
public double readDoubleInBounds(RubyArray array, int index) {
67+
return ((double[]) array.getStore())[index];
68+
}
69+
70+
@Specialization(
71+
guards={"isNormalisedInBounds", "isObjectArray"}
72+
)
73+
public Object readObjectInBounds(RubyArray array, int index) {
74+
return ((Object[]) array.getStore())[index];
75+
}
76+
77+
@Specialization(
78+
guards="!isNormalisedInBounds"
79+
)
80+
public RubyNilClass readOutOfBounds(RubyArray array, int index) {
81+
return getContext().getCoreLibrary().getNilObject();
82+
}
83+
84+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 1.0
7+
* GNU General Public License version 2
8+
* GNU Lesser General Public License version 2.1
9+
*/
10+
package org.jruby.truffle.nodes.array;
11+
12+
import com.oracle.truffle.api.dsl.NodeChild;
13+
import com.oracle.truffle.api.dsl.Specialization;
14+
import com.oracle.truffle.api.source.SourceSection;
15+
import org.jruby.truffle.nodes.RubyNode;
16+
import org.jruby.truffle.runtime.RubyContext;
17+
import org.jruby.truffle.runtime.core.CoreLibrary;
18+
19+
/**
20+
* Passes through {@code int} values unmodified, but will convert a {@code long} value to an {@code int}, if it fits
21+
* within the range of an {@code int}. Leaves all other values unmodified. Used where a specialisation only accepts
22+
* {@code int}, such as Java array indexing, but we would like to also handle {@code long} if they also fit within an
23+
* {@code int}.
24+
*/
25+
@NodeChild(value="child", type=RubyNode.class)
26+
public abstract class NewFixnumLowerNode extends RubyNode {
27+
28+
public NewFixnumLowerNode(RubyContext context, SourceSection sourceSection) {
29+
super(context, sourceSection);
30+
}
31+
32+
public NewFixnumLowerNode(NewFixnumLowerNode prev) {
33+
super(prev);
34+
}
35+
36+
@Specialization
37+
public int lower(int value) {
38+
return value;
39+
}
40+
41+
@Specialization(guards="canLower")
42+
public int lower(long value) {
43+
return (int) value;
44+
}
45+
46+
@Specialization(guards="!canLower")
47+
public long lowerFails(long value) {
48+
return value;
49+
}
50+
51+
protected static boolean canLower(long value) {
52+
return CoreLibrary.fitsIntoInteger(value);
53+
}
54+
55+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 1.0
7+
* GNU General Public License version 2
8+
* GNU Lesser General Public License version 2.1
9+
*/
10+
package org.jruby.truffle.nodes.array;
11+
12+
import com.oracle.truffle.api.source.SourceSection;
13+
import org.jruby.truffle.nodes.RubyNode;
14+
import org.jruby.truffle.nodes.literal.FixnumLiteralNode;
15+
import org.jruby.truffle.runtime.RubyContext;
16+
17+
public abstract class PrimitiveArrayNodeFactory {
18+
19+
/**
20+
* Create a node to read from an array with a constant denormalised index.
21+
*/
22+
public static RubyNode read(RubyContext context, SourceSection sourceSection, RubyNode array, int index) {
23+
final RubyNode literalIndex = new FixnumLiteralNode.IntegerFixnumLiteralNode(context, sourceSection, index);
24+
25+
if (index > 0) {
26+
return ArrayReadNormalizedNodeFactory.create(context, sourceSection, array, literalIndex);
27+
} else {
28+
return ArrayReadDenormalizedNodeFactory.create(context, sourceSection, array, literalIndex);
29+
}
30+
}
31+
32+
}

truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayGuards.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,30 @@ public static boolean areBothObject(RubyArray a, RubyArray b) {
7373
return a.getStore() instanceof Object[] && b.getStore() instanceof Object[];
7474
}
7575

76+
// New names
77+
78+
public static boolean isNullArray(RubyArray array) {
79+
return array.getStore() == null;
80+
}
81+
82+
public static boolean isIntegerArray(RubyArray array) {
83+
return array.getStore() instanceof int[];
84+
}
85+
86+
public static boolean isLongArray(RubyArray array) {
87+
return array.getStore() instanceof long[];
88+
}
89+
90+
public static boolean isDoubleArray(RubyArray array) {
91+
return array.getStore() instanceof double[];
92+
}
93+
94+
public static boolean isObjectArray(RubyArray array) {
95+
return array.getStore() instanceof Object[];
96+
}
97+
98+
public static boolean isNormalisedInBounds(RubyArray array, int index) {
99+
return index >= 0 && index < array.getSize();
100+
}
101+
76102
}

truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayIndexNode.java

Lines changed: 0 additions & 125 deletions
This file was deleted.

0 commit comments

Comments
 (0)