Skip to content

Commit 9225568

Browse files
committed
ArrayEachIteratorNode supports DSL inlining
1 parent 9c5a6df commit 9225568

File tree

3 files changed

+87
-49
lines changed

3 files changed

+87
-49
lines changed

src/main/java/org/truffleruby/core/array/ArrayEachIteratorNode.java

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,72 +10,69 @@
1010
package org.truffleruby.core.array;
1111

1212
import com.oracle.truffle.api.TruffleSafepoint;
13-
import com.oracle.truffle.api.dsl.NeverDefault;
14-
import com.oracle.truffle.api.profiles.IntValueProfile;
13+
import com.oracle.truffle.api.dsl.GenerateInline;
14+
import com.oracle.truffle.api.nodes.Node;
15+
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
16+
import com.oracle.truffle.api.profiles.InlinedIntValueProfile;
17+
import com.oracle.truffle.api.profiles.InlinedLoopConditionProfile;
1518
import org.truffleruby.core.array.library.ArrayStoreLibrary;
19+
import org.truffleruby.core.cast.BooleanCastNode;
1620
import org.truffleruby.language.RubyBaseNode;
1721

18-
import com.oracle.truffle.api.CompilerDirectives;
1922
import com.oracle.truffle.api.dsl.Cached;
2023
import com.oracle.truffle.api.dsl.ImportStatic;
2124
import com.oracle.truffle.api.dsl.ReportPolymorphism;
2225
import com.oracle.truffle.api.dsl.Specialization;
2326
import com.oracle.truffle.api.library.CachedLibrary;
2427
import com.oracle.truffle.api.nodes.NodeInterface;
25-
import com.oracle.truffle.api.profiles.ConditionProfile;
26-
import com.oracle.truffle.api.profiles.LoopConditionProfile;
2728
import org.truffleruby.language.yield.CallBlockNode;
2829

2930
@ImportStatic(ArrayGuards.class)
3031
@ReportPolymorphism
32+
@GenerateInline(inlineByDefault = true)
3133
public abstract class ArrayEachIteratorNode extends RubyBaseNode {
3234

3335
public interface ArrayElementConsumerNode extends NodeInterface {
34-
void accept(CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index);
36+
void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index,
37+
BooleanCastNode booleanCastNode);
3538
}
3639

37-
@Child private ArrayEachIteratorNode recurseNode;
40+
public final RubyArray executeCached(RubyArray array, Object state, int startAt,
41+
ArrayElementConsumerNode consumerNode) {
42+
return execute(this, array, state, startAt, consumerNode);
3843

39-
@NeverDefault
40-
public static ArrayEachIteratorNode create() {
41-
return ArrayEachIteratorNodeGen.create();
4244
}
4345

44-
public abstract RubyArray execute(RubyArray array, Object state, int startAt,
46+
public abstract RubyArray execute(Node node, RubyArray array, Object state, int startAt,
4547
ArrayElementConsumerNode consumerNode);
4648

4749
@Specialization(limit = "storageStrategyLimit()")
48-
protected RubyArray iterateMany(RubyArray array, Object state, int startAt, ArrayElementConsumerNode consumerNode,
50+
protected static RubyArray iterateMany(
51+
Node node, RubyArray array, Object state, int startAt, ArrayElementConsumerNode consumerNode,
4952
// Checkstyle: stop -- Verified @Bind is not necessary here due to using `Library#accepts()`.
5053
@CachedLibrary("array.getStore()") ArrayStoreLibrary stores,
5154
// Checkstyle: resume
52-
@Cached LoopConditionProfile loopProfile,
53-
@Cached IntValueProfile arraySizeProfile,
54-
@Cached ConditionProfile strategyMatchProfile,
55+
@Cached InlinedLoopConditionProfile loopProfile,
56+
@Cached InlinedIntValueProfile arraySizeProfile,
57+
@Cached InlinedConditionProfile strategyMatchProfile,
58+
@Cached LazyArrayEachIteratorNode lazyArrayEachIteratorNode,
59+
@Cached BooleanCastNode booleanCastNode,
5560
@Cached CallBlockNode yieldNode) {
5661
int i = startAt;
5762
try {
58-
for (; loopProfile.inject(i < arraySizeProfile.profile(array.size)); i++) {
63+
for (; loopProfile.inject(node, i < arraySizeProfile.profile(node, array.size)); i++) {
5964
Object store = array.getStore();
60-
if (strategyMatchProfile.profile(stores.accepts(store))) {
61-
consumerNode.accept(yieldNode, array, state, stores.read(store, i), i);
65+
if (strategyMatchProfile.profile(node, stores.accepts(store))) {
66+
consumerNode.accept(node, yieldNode, array, state, stores.read(store, i), i, booleanCastNode);
6267
} else {
63-
return getRecurseNode().execute(array, state, i, consumerNode);
68+
return lazyArrayEachIteratorNode.get(node).executeCached(array, state, i, consumerNode);
6469
}
65-
TruffleSafepoint.poll(this);
70+
TruffleSafepoint.poll(node);
6671
}
6772
} finally {
68-
profileAndReportLoopCount(loopProfile, i - startAt);
73+
profileAndReportLoopCount(node, loopProfile, i - startAt);
6974
}
7075

7176
return array;
7277
}
73-
74-
private ArrayEachIteratorNode getRecurseNode() {
75-
if (recurseNode == null) {
76-
CompilerDirectives.transferToInterpreterAndInvalidate();
77-
recurseNode = insert(ArrayEachIteratorNode.create());
78-
}
79-
return recurseNode;
80-
}
8178
}

src/main/java/org/truffleruby/core/array/ArrayNodes.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -833,11 +833,12 @@ public abstract static class EachNode extends CoreMethodArrayArgumentsNode imple
833833
@Specialization
834834
protected Object each(RubyArray array, RubyProc block,
835835
@Cached ArrayEachIteratorNode iteratorNode) {
836-
return iteratorNode.execute(array, block, 0, this);
836+
return iteratorNode.execute(this, array, block, 0, this);
837837
}
838838

839839
@Override
840-
public void accept(CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index) {
840+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index,
841+
BooleanCastNode booleanCastNode) {
841842
RubyProc block = (RubyProc) state;
842843
yieldNode.yield(block, element);
843844
}
@@ -852,11 +853,12 @@ public abstract static class EachWithIndexNode extends PrimitiveArrayArgumentsNo
852853
@Specialization
853854
protected Object eachOther(RubyArray array, RubyProc block,
854855
@Cached ArrayEachIteratorNode iteratorNode) {
855-
return iteratorNode.execute(array, block, 0, this);
856+
return iteratorNode.execute(this, array, block, 0, this);
856857
}
857858

858859
@Override
859-
public void accept(CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index) {
860+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index,
861+
BooleanCastNode booleanCastNode) {
860862
RubyProc block = (RubyProc) state;
861863
yieldNode.yield(block, element, index);
862864
}
@@ -1389,13 +1391,14 @@ private Object injectBlockHelper(RubyArray array,
13891391
Object accumulator = initial;
13901392
State iterationState = new State(accumulator, block);
13911393

1392-
iteratorNode.execute(array, iterationState, start, this);
1394+
iteratorNode.execute(this, array, iterationState, start, this);
13931395

13941396
return iterationState.accumulator;
13951397
}
13961398

13971399
@Override
1398-
public void accept(CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element, int index) {
1400+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element,
1401+
int index, BooleanCastNode booleanCastNode) {
13991402
final State state = (State) stateObject;
14001403
state.accumulator = yieldNode.yield(state.block, state.accumulator, element);
14011404
}
@@ -1499,18 +1502,19 @@ private static class State {
14991502
@Specialization
15001503
protected Object map(RubyArray array, RubyProc block,
15011504
@Cached ArrayEachIteratorNode iteratorNode,
1502-
@Cached IntValueProfile arraySizeProfile) {
1503-
BuilderState builderState = arrayBuilder.start(arraySizeProfile.profile(array.size));
1505+
@Cached InlinedIntValueProfile arraySizeProfile) {
1506+
BuilderState builderState = arrayBuilder.start(arraySizeProfile.profile(this, array.size));
15041507
State iterationState = new State(builderState, block);
15051508

1506-
iteratorNode.execute(array, iterationState, 0, this);
1509+
iteratorNode.execute(this, array, iterationState, 0, this);
15071510

15081511
final int size = array.size;
15091512
return createArray(arrayBuilder.finish(iterationState.builderState, size), size);
15101513
}
15111514

15121515
@Override
1513-
public void accept(CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element, int index) {
1516+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element,
1517+
int index, BooleanCastNode booleanCastNode) {
15141518
final State state = (State) stateObject;
15151519

15161520
Object value = yieldNode.yield(state.block, element);
@@ -1529,11 +1533,12 @@ public abstract static class MapInPlaceNode extends CoreMethodArrayArgumentsNode
15291533
@Specialization
15301534
protected Object map(RubyArray array, RubyProc block,
15311535
@Cached ArrayEachIteratorNode iteratorNode) {
1532-
return iteratorNode.execute(array, block, 0, this);
1536+
return iteratorNode.execute(this, array, block, 0, this);
15331537
}
15341538

15351539
@Override
1536-
public void accept(CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index) {
1540+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object state, Object element, int index,
1541+
BooleanCastNode booleanCastNode) {
15371542
RubyProc block = (RubyProc) state;
15381543
writeNode.executeWrite(array, index, yieldNode.yield(block, element));
15391544
}
@@ -1796,18 +1801,19 @@ private static class State {
17961801
@Specialization
17971802
protected Object reject(RubyArray array, RubyProc block,
17981803
@Cached ArrayEachIteratorNode iteratorNode,
1799-
@Cached IntValueProfile arraySizeProfile) {
1800-
BuilderState builderState = arrayBuilder.start(arraySizeProfile.profile(array.size));
1804+
@Cached InlinedIntValueProfile arraySizeProfile) {
1805+
BuilderState builderState = arrayBuilder.start(arraySizeProfile.profile(this, array.size));
18011806
State iterationState = new State(builderState, 0, block);
18021807

1803-
iteratorNode.execute(array, iterationState, 0, this);
1808+
iteratorNode.execute(this, array, iterationState, 0, this);
18041809

18051810
int actualSize = iterationState.newArraySize;
18061811
return createArray(arrayBuilder.finish(builderState, actualSize), actualSize);
18071812
}
18081813

18091814
@Override
1810-
public void accept(CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element, int index) {
1815+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element,
1816+
int index, BooleanCastNode booleanCastNode) {
18111817
final State state = (State) stateObject;
18121818

18131819
if (!booleanCastNode.execute(yieldNode.yield(state.block, element))) {
@@ -2006,18 +2012,19 @@ private static class State {
20062012
@Specialization
20072013
protected Object select(RubyArray array, RubyProc block,
20082014
@Cached ArrayEachIteratorNode iteratorNode,
2009-
@Cached IntValueProfile arraySizeProfile) {
2010-
BuilderState builderState = arrayBuilder.start(arraySizeProfile.profile(array.size));
2015+
@Cached InlinedIntValueProfile arraySizeProfile) {
2016+
BuilderState builderState = arrayBuilder.start(arraySizeProfile.profile(this, array.size));
20112017
State iterationState = new State(builderState, 0, block);
20122018

2013-
iteratorNode.execute(array, iterationState, 0, this);
2019+
iteratorNode.execute(this, array, iterationState, 0, this);
20142020

20152021
int selectedSize = iterationState.selectedSize;
20162022
return createArray(arrayBuilder.finish(builderState, selectedSize), selectedSize);
20172023
}
20182024

20192025
@Override
2020-
public void accept(CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element, int index) {
2026+
public void accept(Node node, CallBlockNode yieldNode, RubyArray array, Object stateObject, Object element,
2027+
int index, BooleanCastNode booleanCastNode) {
20212028
final State state = (State) stateObject;
20222029

20232030
if (booleanCastNode.execute(yieldNode.yield(state.block, element))) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2023 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 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.core.array;
11+
12+
import com.oracle.truffle.api.dsl.Cached;
13+
import com.oracle.truffle.api.dsl.GenerateCached;
14+
import com.oracle.truffle.api.dsl.GenerateInline;
15+
import com.oracle.truffle.api.dsl.Specialization;
16+
import com.oracle.truffle.api.nodes.Node;
17+
import org.truffleruby.language.RubyBaseNode;
18+
19+
@GenerateInline
20+
@GenerateCached(false)
21+
public abstract class LazyArrayEachIteratorNode extends RubyBaseNode {
22+
23+
public final ArrayEachIteratorNode get(Node node) {
24+
return execute(node);
25+
}
26+
27+
protected abstract ArrayEachIteratorNode execute(Node node);
28+
29+
@Specialization
30+
protected static ArrayEachIteratorNode doLazy(
31+
@Cached(inline = false) ArrayEachIteratorNode arrayEachIteratorNode) {
32+
return arrayEachIteratorNode;
33+
}
34+
}

0 commit comments

Comments
 (0)