Skip to content

Commit 577e316

Browse files
committed
Some footprint/warmup improvements
PullRequest: truffleruby/535
2 parents 8fa71ce + 173cab6 commit 577e316

File tree

7 files changed

+62
-46
lines changed

7 files changed

+62
-46
lines changed

src/main/java/org/truffleruby/core/cast/NameToJavaStringNode.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package org.truffleruby.core.cast;
1111

12+
import com.oracle.truffle.api.CompilerDirectives;
1213
import com.oracle.truffle.api.dsl.Cached;
1314
import com.oracle.truffle.api.dsl.ImportStatic;
1415
import com.oracle.truffle.api.dsl.NodeChild;
@@ -33,21 +34,29 @@
3334
@NodeChild(value = "value", type = RubyNode.class)
3435
public abstract class NameToJavaStringNode extends RubyNode {
3536

37+
@Child private ToJavaStringNode toJavaStringNode;
38+
3639
public static NameToJavaStringNode create() {
3740
return NameToJavaStringNodeGen.create(null);
3841
}
3942

4043
public abstract String executeToJavaString(Object name);
4144

4245
@Specialization(guards = "isRubyString(value)")
43-
public String stringNameToJavaString(DynamicObject value,
44-
@Cached("create()") ToJavaStringNode toJavaStringNode) {
45-
return toJavaStringNode.executeToJavaString(value);
46+
public String stringNameToJavaString(DynamicObject value) {
47+
return executeToJavaString(value);
4648
}
4749

4850
@Specialization(guards = "isRubySymbol(value)")
49-
public String symbolNameToJavaString(DynamicObject value,
50-
@Cached("create()") ToJavaStringNode toJavaStringNode) {
51+
public String symbolNameToJavaString(DynamicObject value) {
52+
return executeToJavaString(value);
53+
}
54+
55+
private String executeToJavaString(DynamicObject value) {
56+
if (toJavaStringNode == null) {
57+
CompilerDirectives.transferToInterpreterAndInvalidate();
58+
toJavaStringNode = insert(ToJavaStringNode.create());
59+
}
5160
return toJavaStringNode.executeToJavaString(value);
5261
}
5362

src/main/java/org/truffleruby/core/cast/ToStringOrSymbolNode.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package org.truffleruby.core.cast;
1111

12+
import com.oracle.truffle.api.CompilerDirectives;
1213
import com.oracle.truffle.api.dsl.Cached;
1314
import com.oracle.truffle.api.dsl.NodeChild;
1415
import com.oracle.truffle.api.dsl.Specialization;
@@ -27,7 +28,7 @@
2728
@NodeChild(value = "child", type = RubyNode.class)
2829
public abstract class ToStringOrSymbolNode extends RubyNode {
2930

30-
@Child private CallDispatchHeadNode toStr = CallDispatchHeadNode.createPrivate();
31+
@Child private CallDispatchHeadNode toStr;
3132

3233
@Specialization(guards = "isRubySymbol(symbol)")
3334
public DynamicObject coerceRubySymbol(DynamicObject symbol) {
@@ -44,7 +45,7 @@ public DynamicObject coerceObject(VirtualFrame frame, Object object,
4445
@Cached("create()") BranchProfile errorProfile) {
4546
final Object coerced;
4647
try {
47-
coerced = toStr.call(object, "to_str");
48+
coerced = callToStr(object);
4849
} catch (RaiseException e) {
4950
errorProfile.enter();
5051
if (Layouts.BASIC_OBJECT.getLogicalClass(e.getException()) == coreLibrary().getNoMethodErrorClass()) {
@@ -61,4 +62,12 @@ public DynamicObject coerceObject(VirtualFrame frame, Object object,
6162
throw new RaiseException(getContext(), coreExceptions().typeErrorBadCoercion(object, "String", "to_str", coerced, this));
6263
}
6364
}
65+
66+
private Object callToStr(Object object) {
67+
if (toStr == null) {
68+
CompilerDirectives.transferToInterpreterAndInvalidate();
69+
toStr = insert(CallDispatchHeadNode.createPrivate());
70+
}
71+
return toStr.call(object, "to_str");
72+
}
6473
}

src/main/java/org/truffleruby/core/hash/HashNodes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public Object construct(DynamicObject hashClass, Object[] args) {
7979
final int size = Layouts.ARRAY.getSize(array);
8080
final Object[] newStore = PackedArrayStrategy.createStore(getContext());
8181

82+
// written very carefully to allow PE
8283
for (int n = 0; n < getContext().getOptions().HASH_PACKED_ARRAY_MAX; n++) {
8384
if (n < size) {
8485
final Object pair = store[n];

src/main/java/org/truffleruby/core/hash/SetNode.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import com.oracle.truffle.api.dsl.Specialization;
1616
import com.oracle.truffle.api.nodes.ExplodeLoop;
1717
import com.oracle.truffle.api.object.DynamicObject;
18-
import com.oracle.truffle.api.profiles.BranchProfile;
1918
import com.oracle.truffle.api.profiles.ConditionProfile;
2019
import org.truffleruby.Layouts;
2120
import org.truffleruby.language.RubyBaseNode;
@@ -27,6 +26,7 @@ public abstract class SetNode extends RubyBaseNode {
2726
@Child private LookupEntryNode lookupEntryNode;
2827
@Child private CompareHashKeysNode compareHashKeysNode = new CompareHashKeysNode();
2928
@Child private FreezeHashKeyIfNeededNode freezeHashKeyIfNeededNode = FreezeHashKeyIfNeededNodeGen.create();
29+
private final ConditionProfile byIdentityProfile = ConditionProfile.createBinaryProfile();
3030

3131
public static SetNode create() {
3232
return SetNodeGen.create();
@@ -35,8 +35,7 @@ public static SetNode create() {
3535
public abstract Object executeSet(DynamicObject hash, Object key, Object value, boolean byIdentity);
3636

3737
@Specialization(guards = "isNullHash(hash)")
38-
public Object setNull(DynamicObject hash, Object originalKey, Object value, boolean byIdentity,
39-
@Cached("createBinaryProfile()") ConditionProfile byIdentityProfile) {
38+
public Object setNull(DynamicObject hash, Object originalKey, Object value, boolean byIdentity) {
4039
assert HashOperations.verifyStore(getContext(), hash);
4140
boolean compareByIdentity = byIdentityProfile.profile(byIdentity);
4241
final Object key = freezeHashKeyIfNeededNode.executeFreezeIfNeeded(originalKey, compareByIdentity);
@@ -57,9 +56,7 @@ public Object setNull(DynamicObject hash, Object originalKey, Object value, bool
5756
@ExplodeLoop
5857
@Specialization(guards = "isPackedHash(hash)")
5958
public Object setPackedArray(DynamicObject hash, Object originalKey, Object value, boolean byIdentity,
60-
@Cached("createBinaryProfile()") ConditionProfile byIdentityProfile,
61-
@Cached("createBinaryProfile()") ConditionProfile strategyProfile,
62-
@Cached("create()") BranchProfile extendProfile) {
59+
@Cached("createBinaryProfile()") ConditionProfile strategyProfile) {
6360
assert HashOperations.verifyStore(getContext(), hash);
6461
final boolean compareByIdentity = byIdentityProfile.profile(byIdentity);
6562
final Object key = freezeHashKeyIfNeededNode.executeFreezeIfNeeded(originalKey, compareByIdentity);
@@ -69,6 +66,7 @@ public Object setPackedArray(DynamicObject hash, Object originalKey, Object valu
6966
final Object[] store = (Object[]) Layouts.HASH.getStore(hash);
7067
final int size = Layouts.HASH.getSize(hash);
7168

69+
// written very carefully to allow PE
7270
for (int n = 0; n < getContext().getOptions().HASH_PACKED_ARRAY_MAX; n++) {
7371
if (n < size) {
7472
final int otherHashed = PackedArrayStrategy.getHashed(store, n);
@@ -81,9 +79,7 @@ public Object setPackedArray(DynamicObject hash, Object originalKey, Object valu
8179
}
8280
}
8381

84-
extendProfile.enter();
85-
86-
if (strategyProfile.profile(size + 1 <= getContext().getOptions().HASH_PACKED_ARRAY_MAX)) {
82+
if (strategyProfile.profile(size < getContext().getOptions().HASH_PACKED_ARRAY_MAX)) {
8783
PackedArrayStrategy.setHashedKeyValue(store, size, hashed, key, value);
8884
Layouts.HASH.setSize(hash, size + 1);
8985
return value;
@@ -99,7 +95,6 @@ public Object setPackedArray(DynamicObject hash, Object originalKey, Object valu
9995

10096
@Specialization(guards = "isBucketHash(hash)")
10197
public Object setBuckets(DynamicObject hash, Object originalKey, Object value, boolean byIdentity,
102-
@Cached("createBinaryProfile()") ConditionProfile byIdentityProfile,
10398
@Cached("createBinaryProfile()") ConditionProfile foundProfile,
10499
@Cached("createBinaryProfile()") ConditionProfile bucketCollisionProfile,
105100
@Cached("createBinaryProfile()") ConditionProfile appendingProfile,

src/main/java/org/truffleruby/core/rope/RopeNodes.java

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -432,26 +432,12 @@ public Rope concat(ManagedRope left, ManagedRope right, Encoding encoding,
432432
throw new RaiseException(getContext(), getContext().getCoreExceptions().argumentError("Result of string concatenation exceeds the system maximum string length", this));
433433
}
434434

435-
if (shouldRebalanceProfile.profile(left.depth() >= getContext().getOptions().ROPE_DEPTH_THRESHOLD)) {
436-
if (flattenNode == null) {
437-
CompilerDirectives.transferToInterpreterAndInvalidate();
438-
flattenNode = insert(FlattenNode.create());
439-
}
440-
441-
if (left instanceof ConcatRope) {
442-
left = rebalance((ConcatRope) left, getContext().getOptions().ROPE_DEPTH_THRESHOLD, flattenNode);
443-
}
435+
if (shouldRebalanceProfile.profile(left.depth() >= getContext().getOptions().ROPE_DEPTH_THRESHOLD && left instanceof ConcatRope)) {
436+
left = rebalance((ConcatRope) left, getContext().getOptions().ROPE_DEPTH_THRESHOLD, getFlattenNode());
444437
}
445438

446-
if (shouldRebalanceProfile.profile(right.depth() >= getContext().getOptions().ROPE_DEPTH_THRESHOLD)) {
447-
if (flattenNode == null) {
448-
CompilerDirectives.transferToInterpreterAndInvalidate();
449-
flattenNode = insert(FlattenNode.create());
450-
}
451-
452-
if (right instanceof ConcatRope) {
453-
right = rebalance((ConcatRope) right, getContext().getOptions().ROPE_DEPTH_THRESHOLD, flattenNode);
454-
}
439+
if (shouldRebalanceProfile.profile(right.depth() >= getContext().getOptions().ROPE_DEPTH_THRESHOLD && right instanceof ConcatRope)) {
440+
right = rebalance((ConcatRope) right, getContext().getOptions().ROPE_DEPTH_THRESHOLD, getFlattenNode());
455441
}
456442

457443
int depth = depth(left, right);
@@ -465,6 +451,14 @@ public Rope concat(ManagedRope left, ManagedRope right, Encoding encoding,
465451
depth, isBalanced(left, right));
466452
}
467453

454+
private FlattenNode getFlattenNode() {
455+
if (flattenNode == null) {
456+
CompilerDirectives.transferToInterpreterAndInvalidate();
457+
flattenNode = insert(FlattenNode.create());
458+
}
459+
return flattenNode;
460+
}
461+
468462
private boolean isBalanced(Rope left, Rope right) {
469463
// Our definition of balanced is centered around the notion of rebalancing. We could have a simple structure
470464
// such as ConcatRope(ConcatRope(LeafRope, LeafRope), LeafRope) that is balanced on its own but may contribute

src/main/java/org/truffleruby/language/control/AndNode.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,19 @@ public AndNode(RubyNode left, RubyNode right) {
3434
public Object execute(VirtualFrame frame) {
3535
final Object leftValue = left.execute(frame);
3636

37-
if (leftCast == null) {
38-
CompilerDirectives.transferToInterpreterAndInvalidate();
39-
leftCast = insert(BooleanCastNodeGen.create(null));
40-
}
41-
42-
final boolean leftBoolean = leftCast.executeToBoolean(leftValue);
43-
44-
if (conditionProfile.profile(leftBoolean)) {
37+
if (conditionProfile.profile(castToBoolean(leftValue))) {
4538
return right.execute(frame);
4639
} else {
4740
return leftValue;
4841
}
4942
}
5043

44+
private boolean castToBoolean(final Object value) {
45+
if (leftCast == null) {
46+
CompilerDirectives.transferToInterpreterAndInvalidate();
47+
leftCast = insert(BooleanCastNodeGen.create(null));
48+
}
49+
return leftCast.executeToBoolean(value);
50+
}
51+
5152
}

src/main/java/org/truffleruby/language/control/OrNode.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package org.truffleruby.language.control;
1111

12+
import com.oracle.truffle.api.CompilerDirectives;
1213
import com.oracle.truffle.api.frame.VirtualFrame;
1314
import com.oracle.truffle.api.profiles.ConditionProfile;
1415
import org.truffleruby.core.cast.BooleanCastNode;
@@ -27,19 +28,25 @@ public class OrNode extends RubyNode {
2728
public OrNode(RubyNode left, RubyNode right) {
2829
this.left = left;
2930
this.right = right;
30-
leftCast = BooleanCastNodeGen.create(null);
3131
}
3232

3333
@Override
3434
public Object execute(VirtualFrame frame) {
3535
final Object leftValue = left.execute(frame);
36-
final boolean leftBoolean = leftCast.executeToBoolean(leftValue);
3736

38-
if (conditionProfile.profile(leftBoolean)) {
37+
if (conditionProfile.profile(castToBoolean(leftValue))) {
3938
return leftValue;
4039
} else {
4140
return right.execute(frame);
4241
}
4342
}
4443

44+
private boolean castToBoolean(final Object value) {
45+
if (leftCast == null) {
46+
CompilerDirectives.transferToInterpreterAndInvalidate();
47+
leftCast = insert(BooleanCastNodeGen.create(null));
48+
}
49+
return leftCast.executeToBoolean(value);
50+
}
51+
4552
}

0 commit comments

Comments
 (0)