Skip to content

Commit 74934f0

Browse files
committed
[Truffle] Pass loop counts up to the first call target for a method that is not a block.
1 parent 57cf0a2 commit 74934f0

26 files changed

+356
-185
lines changed

bench/truffle/compare.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
scores = {}
8484

8585
benchmarks.each do |benchmark|
86-
output = `../../bin/jruby -J-server -J-d64 -J-G:TruffleGraphMaxNodes=200000 -X+T -Xtruffle.printRuntime=true harness.rb -s #{time_budget_per_run} #{benchmark}.rb`
86+
output = `../../bin/jruby -J-server -J-d64 -J-Xmx1G -J-G:TruffleGraphMaxNodes=200000 -X+T -Xtruffle.printRuntime=true harness.rb -s #{time_budget_per_run} #{benchmark}.rb`
8787
score_match = /[a-z\-]+: (\d+\.\d+)/.match(output)
8888
if score_match.nil?
8989
score = 0

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@
1212
import com.oracle.truffle.api.*;
1313
import com.oracle.truffle.api.frame.*;
1414
import com.oracle.truffle.api.nodes.*;
15-
import org.jruby.truffle.runtime.RubyArguments;
16-
import org.jruby.truffle.runtime.methods.RubyMethod;
15+
import org.jruby.truffle.runtime.RubyCallStack;
1716
import org.jruby.truffle.runtime.methods.SharedMethodInfo;
1817

19-
import java.util.concurrent.ConcurrentHashMap;
20-
2118
/**
2219
* The root node in an AST for a method. Unlike {@link RubyNode}, this has a single entry point,
2320
* {@link #execute}, which Truffle knows about and can create a {@link CallTarget} from.
@@ -37,15 +34,15 @@ public RubyRootNode(SourceSection sourceSection, FrameDescriptor frameDescriptor
3734
uninitializedBody = NodeUtil.cloneNode(body);
3835
}
3936

37+
public RubyRootNode cloneRubyRootNode() {
38+
return new RubyRootNode(getSourceSection(), getFrameDescriptor(), sharedMethodInfo, NodeUtil.cloneNode(uninitializedBody));
39+
}
40+
4041
@Override
4142
public Object execute(VirtualFrame frame) {
4243
return body.execute(frame);
4344
}
4445

45-
public RubyRootNode cloneRubyRootNode() {
46-
return new RubyRootNode(getSourceSection(), getFrameDescriptor(), sharedMethodInfo, NodeUtil.cloneNode(uninitializedBody));
47-
}
48-
4946
@Override
5047
public RootNode split() {
5148
return cloneRubyRootNode();
@@ -56,6 +53,22 @@ public boolean isSplittable() {
5653
return true;
5754
}
5855

56+
public void reportLoopCountThroughBlocks(int count) {
57+
CompilerAsserts.neverPartOfCompilation();
58+
59+
for (FrameInstance frame : Truffle.getRuntime().getStackTrace()) {
60+
final RootNode rootNode = frame.getCallNode().getRootNode();
61+
62+
rootNode.reportLoopCount(count);
63+
64+
if (rootNode instanceof RubyRootNode && !((RubyRootNode) rootNode).getSharedMethodInfo().isBlock()) {
65+
break;
66+
}
67+
}
68+
69+
reportLoopCount(count);
70+
}
71+
5972
@Override
6073
public String toString() {
6174
final SourceSection sourceSection = getSourceSection();

core/src/main/java/org/jruby/truffle/nodes/control/DoWhileNode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.oracle.truffle.api.nodes.NodeInfo;
1616
import com.oracle.truffle.api.utilities.BranchProfile;
1717
import org.jruby.truffle.nodes.RubyNode;
18+
import org.jruby.truffle.nodes.RubyRootNode;
1819
import org.jruby.truffle.nodes.cast.BooleanCastNode;
1920
import org.jruby.truffle.runtime.NilPlaceholder;
2021
import org.jruby.truffle.runtime.RubyContext;
@@ -74,7 +75,7 @@ public Object execute(VirtualFrame frame) {
7475
}
7576
} finally {
7677
if (CompilerDirectives.inInterpreter()) {
77-
getRootNode().reportLoopCount(count);
78+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
7879
}
7980
}
8081

core/src/main/java/org/jruby/truffle/nodes/control/WhileNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public Object execute(VirtualFrame frame) {
6464
}
6565
} finally {
6666
if (CompilerDirectives.inInterpreter()) {
67-
getRootNode().reportLoopCount(count);
67+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
6868
}
6969
}
7070

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

Lines changed: 117 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
*/
1010
package org.jruby.truffle.nodes.core;
1111

12+
import com.oracle.truffle.api.CompilerDirectives;
1213
import com.oracle.truffle.api.CompilerDirectives.SlowPath;
1314
import com.oracle.truffle.api.SourceSection;
14-
import com.oracle.truffle.api.dsl.Generic;
1515
import com.oracle.truffle.api.dsl.Specialization;
1616
import com.oracle.truffle.api.frame.VirtualFrame;
17-
import com.oracle.truffle.api.nodes.ExplodeLoop;
1817
import com.oracle.truffle.api.nodes.UnexpectedResultException;
1918
import com.oracle.truffle.api.utilities.BranchProfile;
19+
import org.jruby.truffle.nodes.RubyRootNode;
2020
import org.jruby.truffle.nodes.call.DispatchHeadNode;
2121
import org.jruby.truffle.runtime.NilPlaceholder;
2222
import org.jruby.truffle.runtime.RubyContext;
@@ -543,21 +543,34 @@ public EachNode(EachNode prev) {
543543

544544
@Specialization
545545
public Object each(VirtualFrame frame, RubyArray array, RubyProc block) {
546-
outer: for (int n = 0; n < array.size(); n++) {
547-
while (true) {
548-
try {
549-
yield(frame, block, array.get(n));
550-
continue outer;
551-
} catch (BreakException e) {
552-
breakProfile.enter();
553-
return e.getResult();
554-
} catch (NextException e) {
555-
nextProfile.enter();
556-
continue outer;
557-
} catch (RedoException e) {
558-
redoProfile.enter();
546+
int count = 0;
547+
548+
try {
549+
outer:
550+
for (int n = 0; n < array.size(); n++) {
551+
while (true) {
552+
if (CompilerDirectives.inInterpreter()) {
553+
count++;
554+
}
555+
556+
try {
557+
yield(frame, block, array.get(n));
558+
continue outer;
559+
} catch (BreakException e) {
560+
breakProfile.enter();
561+
return e.getResult();
562+
} catch (NextException e) {
563+
nextProfile.enter();
564+
continue outer;
565+
} catch (RedoException e) {
566+
redoProfile.enter();
567+
}
559568
}
560569
}
570+
} finally {
571+
if (CompilerDirectives.inInterpreter()) {
572+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
573+
}
561574
}
562575

563576
return NilPlaceholder.INSTANCE;
@@ -578,11 +591,23 @@ public EachWithIndexNode(EachWithIndexNode prev) {
578591

579592
@Specialization
580593
public NilPlaceholder eachWithIndex(VirtualFrame frame, RubyArray array, RubyProc block) {
581-
for (int n = 0; n < array.size(); n++) {
582-
try {
583-
yield(frame, block, array.get(n), n);
584-
} catch (BreakException e) {
585-
break;
594+
int count = 0;
595+
596+
try {
597+
for (int n = 0; n < array.size(); n++) {
598+
if (CompilerDirectives.inInterpreter()) {
599+
count++;
600+
}
601+
602+
try {
603+
yield(frame, block, array.get(n), n);
604+
} catch (BreakException e) {
605+
break;
606+
}
607+
}
608+
} finally {
609+
if (CompilerDirectives.inInterpreter()) {
610+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
586611
}
587612
}
588613

@@ -740,8 +765,20 @@ public InjectNode(InjectNode prev) {
740765
public Object inject(VirtualFrame frame, RubyArray array, @SuppressWarnings("unused") UndefinedPlaceholder initial, RubyProc block) {
741766
Object accumulator = array.get(0);
742767

743-
for (int n = 1; n < array.size(); n++) {
744-
accumulator = yield(frame, block, accumulator, array.get(n));
768+
int count = 0;
769+
770+
try {
771+
for (int n = 1; n < array.size(); n++) {
772+
if (CompilerDirectives.inInterpreter()) {
773+
count++;
774+
}
775+
776+
accumulator = yield(frame, block, accumulator, array.get(n));
777+
}
778+
} finally {
779+
if (CompilerDirectives.inInterpreter()) {
780+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
781+
}
745782
}
746783

747784
return accumulator;
@@ -755,8 +792,20 @@ public Object inject(VirtualFrame frame, RubyArray array, Object initial, RubyPr
755792

756793
Object accumulator = initial;
757794

758-
for (int n = 0; n < array.size(); n++) {
759-
accumulator = yield(frame, block, accumulator, array.get(n));
795+
int count = 0;
796+
797+
try {
798+
for (int n = 0; n < array.size(); n++) {
799+
if (CompilerDirectives.inInterpreter()) {
800+
count++;
801+
}
802+
803+
accumulator = yield(frame, block, accumulator, array.get(n));
804+
}
805+
} finally {
806+
if (CompilerDirectives.inInterpreter()) {
807+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
808+
}
760809
}
761810

762811
return accumulator;
@@ -866,10 +915,22 @@ public MapNode(MapNode prev) {
866915

867916
@Specialization
868917
public RubyArray map(VirtualFrame frame, RubyArray array, RubyProc block) {
918+
int count = 0;
919+
869920
final RubyArray result = new RubyArray(array.getRubyClass().getContext().getCoreLibrary().getArrayClass());
870921

871-
for (int n = 0; n < array.size(); n++) {
872-
result.push(yield(frame, block, array.get(n)));
922+
try {
923+
for (int n = 0; n < array.size(); n++) {
924+
if (CompilerDirectives.inInterpreter()) {
925+
count++;
926+
}
927+
928+
result.push(yield(frame, block, array.get(n)));
929+
}
930+
} finally {
931+
if (CompilerDirectives.inInterpreter()) {
932+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
933+
}
873934
}
874935

875936
return result;
@@ -889,8 +950,20 @@ public MapInPlaceNode(MapInPlaceNode prev) {
889950

890951
@Specialization
891952
public RubyArray mapInPlace(VirtualFrame frame, RubyArray array, RubyProc block) {
892-
for (int n = 0; n < array.size(); n++) {
893-
array.set(n, yield(frame, block, array.get(n)));
953+
int count = 0;
954+
955+
try {
956+
for (int n = 0; n < array.size(); n++) {
957+
if (CompilerDirectives.inInterpreter()) {
958+
count++;
959+
}
960+
961+
array.set(n, yield(frame, block, array.get(n)));
962+
}
963+
} finally {
964+
if (CompilerDirectives.inInterpreter()) {
965+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
966+
}
894967
}
895968

896969
return array;
@@ -1137,11 +1210,23 @@ public SelectNode(SelectNode prev) {
11371210
public Object select(VirtualFrame frame, RubyArray array, RubyProc block) {
11381211
final RubyArray result = new RubyArray(getContext().getCoreLibrary().getArrayClass());
11391212

1140-
for (int n = 0; n < array.size(); n++) {
1141-
final Object value = array.get(n);
1213+
int count = 0;
11421214

1143-
if (yieldBoolean(frame, block, value)) {
1144-
result.push(value);
1215+
try {
1216+
for (int n = 0; n < array.size(); n++) {
1217+
if (CompilerDirectives.inInterpreter()) {
1218+
count++;
1219+
}
1220+
1221+
final Object value = array.get(n);
1222+
1223+
if (yieldBoolean(frame, block, value)) {
1224+
result.push(value);
1225+
}
1226+
}
1227+
} finally {
1228+
if (CompilerDirectives.inInterpreter()) {
1229+
((RubyRootNode) getRootNode()).reportLoopCountThroughBlocks(count);
11451230
}
11461231
}
11471232

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private static RubyRootNode makeGenericMethod(RubyContext context, MethodDetails
157157

158158
final SourceSection sourceSection = new CoreSourceSection(indicativeName);
159159

160-
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, methodDetails.getIndicativeName(), null);
160+
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, methodDetails.getIndicativeName(), false, null);
161161

162162
final Arity arity = new Arity(methodDetails.getMethodAnnotation().minArgs(), methodDetails.getMethodAnnotation().maxArgs());
163163

0 commit comments

Comments
 (0)