Skip to content

Commit 8c74bc3

Browse files
committed
[Truffle] Split Array#at and Array#[].
* Array#at is close to a "array get at index" primitive (except the to_int conversion which we don't support yet).
1 parent ab5fd74 commit 8c74bc3

File tree

2 files changed

+67
-35
lines changed

2 files changed

+67
-35
lines changed

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

+67-34
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,21 @@
3232
import org.jruby.truffle.nodes.methods.locals.ReadLevelVariableNodeFactory;
3333
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
3434
import org.jruby.truffle.runtime.*;
35+
import org.jruby.truffle.nodes.core.ArrayNodesFactory.AtNodeFactory;
36+
import org.jruby.truffle.runtime.RubyArguments;
37+
import org.jruby.truffle.runtime.RubyContext;
38+
import org.jruby.truffle.runtime.UndefinedPlaceholder;
3539
import org.jruby.truffle.runtime.control.BreakException;
3640
import org.jruby.truffle.runtime.control.NextException;
3741
import org.jruby.truffle.runtime.control.RaiseException;
3842
import org.jruby.truffle.runtime.control.RedoException;
39-
import org.jruby.truffle.runtime.core.*;
43+
import org.jruby.truffle.runtime.core.RubyArray;
44+
import org.jruby.truffle.runtime.core.RubyModule;
45+
import org.jruby.truffle.runtime.core.RubyNilClass;
46+
import org.jruby.truffle.runtime.core.RubyProc;
47+
import org.jruby.truffle.runtime.core.RubyRange;
48+
import org.jruby.truffle.runtime.core.RubyString;
49+
import org.jruby.truffle.runtime.core.RubySymbol;
4050
import org.jruby.truffle.runtime.methods.MethodLike;
4151
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
4252
import org.jruby.truffle.runtime.util.ArrayUtils;
@@ -529,24 +539,26 @@ public boolean equal(VirtualFrame frame, RubyArray a, Object b) {
529539

530540
}
531541

532-
@CoreMethod(names = {"[]", "at"}, required = 1, optional = 1, lowerFixnumParameters = {0, 1})
533-
public abstract static class IndexNode extends ArrayCoreMethodNode {
542+
@CoreMethod(names = "at", required = 1, lowerFixnumParameters = 0)
543+
public abstract static class AtNode extends ArrayCoreMethodNode {
534544

535-
public IndexNode(RubyContext context, SourceSection sourceSection) {
545+
public AtNode(RubyContext context, SourceSection sourceSection) {
536546
super(context, sourceSection);
537547
}
538548

539-
public IndexNode(IndexNode prev) {
549+
public AtNode(AtNode prev) {
540550
super(prev);
541551
}
542552

553+
public abstract Object executeAt(RubyArray array, int index);
554+
543555
@Specialization(guards = "isNull")
544-
public RubyNilClass getNull(RubyArray array, int index, UndefinedPlaceholder undefined) {
556+
public RubyNilClass getNull(RubyArray array, int index) {
545557
return getContext().getCoreLibrary().getNilObject();
546558
}
547559

548-
@Specialization(guards = "isIntegerFixnum", rewriteOn=UnexpectedResultException.class)
549-
public int getIntegerFixnumInBounds(RubyArray array, int index, UndefinedPlaceholder undefined) throws UnexpectedResultException {
560+
@Specialization(guards = "isIntegerFixnum", rewriteOn = UnexpectedResultException.class)
561+
public int getIntegerFixnumInBounds(RubyArray array, int index) throws UnexpectedResultException {
550562
int normalisedIndex = array.normaliseIndex(index);
551563

552564
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -557,7 +569,7 @@ public int getIntegerFixnumInBounds(RubyArray array, int index, UndefinedPlaceho
557569
}
558570

559571
@Specialization(contains = "getIntegerFixnumInBounds", guards = "isIntegerFixnum")
560-
public Object getIntegerFixnum(RubyArray array, int index, UndefinedPlaceholder undefined) {
572+
public Object getIntegerFixnum(RubyArray array, int index) {
561573
int normalisedIndex = array.normaliseIndex(index);
562574

563575
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -567,25 +579,8 @@ public Object getIntegerFixnum(RubyArray array, int index, UndefinedPlaceholder
567579
}
568580
}
569581

570-
@Specialization(guards = "isIntegerFixnum")
571-
public Object getIntegerFixnum(RubyArray array, int index, int length) {
572-
notDesignedForCompilation();
573-
574-
final int normalisedIndex = array.normaliseIndex(index);
575-
576-
if (normalisedIndex < 0 || normalisedIndex > array.getSize() || length < 0) {
577-
return getContext().getCoreLibrary().getNilObject();
578-
} else if (normalisedIndex == array.getSize()) {
579-
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), null, 0);
580-
} else {
581-
final int end = Math.min(array.getSize(), normalisedIndex + length);
582-
583-
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), Arrays.copyOfRange((int[]) array.getStore(), normalisedIndex, end), end - normalisedIndex);
584-
}
585-
}
586-
587-
@Specialization(guards = "isLongFixnum", rewriteOn=UnexpectedResultException.class)
588-
public long getLongFixnumInBounds(RubyArray array, int index, UndefinedPlaceholder undefined) throws UnexpectedResultException {
582+
@Specialization(guards = "isLongFixnum", rewriteOn = UnexpectedResultException.class)
583+
public long getLongFixnumInBounds(RubyArray array, int index) throws UnexpectedResultException {
589584
int normalisedIndex = array.normaliseIndex(index);
590585

591586
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -596,8 +591,7 @@ public long getLongFixnumInBounds(RubyArray array, int index, UndefinedPlacehold
596591
}
597592

598593
@Specialization(contains = "getLongFixnumInBounds", guards = "isLongFixnum")
599-
public Object getLongFixnum(RubyArray array, int index, UndefinedPlaceholder undefined) {
600-
594+
public Object getLongFixnum(RubyArray array, int index) {
601595
int normalisedIndex = array.normaliseIndex(index);
602596

603597
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -607,8 +601,8 @@ public Object getLongFixnum(RubyArray array, int index, UndefinedPlaceholder und
607601
}
608602
}
609603

610-
@Specialization(guards = "isFloat", rewriteOn=UnexpectedResultException.class)
611-
public double getFloatInBounds(RubyArray array, int index, UndefinedPlaceholder undefined) throws UnexpectedResultException {
604+
@Specialization(guards = "isFloat", rewriteOn = UnexpectedResultException.class)
605+
public double getFloatInBounds(RubyArray array, int index) throws UnexpectedResultException {
612606
int normalisedIndex = array.normaliseIndex(index);
613607

614608
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -619,7 +613,7 @@ public double getFloatInBounds(RubyArray array, int index, UndefinedPlaceholder
619613
}
620614

621615
@Specialization(contains = "getFloatInBounds", guards = "isFloat")
622-
public Object getFloat(RubyArray array, int index, UndefinedPlaceholder undefined) {
616+
public Object getFloat(RubyArray array, int index) {
623617
int normalisedIndex = array.normaliseIndex(index);
624618

625619
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -630,7 +624,7 @@ public Object getFloat(RubyArray array, int index, UndefinedPlaceholder undefine
630624
}
631625

632626
@Specialization(guards = "isObject")
633-
public Object getObject(RubyArray array, int index, UndefinedPlaceholder undefined) {
627+
public Object getObject(RubyArray array, int index) {
634628
int normalisedIndex = array.normaliseIndex(index);
635629

636630
if (normalisedIndex < 0 || normalisedIndex >= array.getSize()) {
@@ -640,6 +634,45 @@ public Object getObject(RubyArray array, int index, UndefinedPlaceholder undefin
640634
}
641635
}
642636

637+
}
638+
639+
@CoreMethod(names = "[]", required = 1, optional = 1, lowerFixnumParameters = { 0, 1 })
640+
public abstract static class IndexNode extends ArrayCoreMethodNode {
641+
642+
@Child protected AtNode atNode;
643+
644+
public IndexNode(RubyContext context, SourceSection sourceSection) {
645+
super(context, sourceSection);
646+
atNode = AtNodeFactory.create(context, sourceSection, new RubyNode[] { null, null });
647+
}
648+
649+
public IndexNode(IndexNode prev) {
650+
super(prev);
651+
atNode = prev.atNode;
652+
}
653+
654+
@Specialization
655+
public Object get(RubyArray array, int index, UndefinedPlaceholder undefined) {
656+
return atNode.executeAt(array, index);
657+
}
658+
659+
@Specialization(guards = "isIntegerFixnum")
660+
public Object getIntegerFixnum(RubyArray array, int index, int length) {
661+
notDesignedForCompilation();
662+
663+
final int normalisedIndex = array.normaliseIndex(index);
664+
665+
if (normalisedIndex < 0 || normalisedIndex > array.getSize() || length < 0) {
666+
return getContext().getCoreLibrary().getNilObject();
667+
} else if (normalisedIndex == array.getSize()) {
668+
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), null, 0);
669+
} else {
670+
final int end = Math.min(array.getSize(), normalisedIndex + length);
671+
672+
return new RubyArray(getContext().getCoreLibrary().getArrayClass(), Arrays.copyOfRange((int[]) array.getStore(), normalisedIndex, end), end - normalisedIndex);
673+
}
674+
}
675+
643676
@Specialization(guards = "isObject")
644677
public Object getObject(RubyArray array, int index, int length) {
645678
notDesignedForCompilation();
-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
fails:Array#at tries to convert the passed argument to an Integer using #to_int
2-
fails:Array#at raises an ArgumentError when 2 or more arguments is passed

0 commit comments

Comments
 (0)