Skip to content

Commit 2e4b00a

Browse files
committed
Address truffle-interpreted-performance warnings
1 parent 3f27f63 commit 2e4b00a

23 files changed

+321
-334
lines changed

src/main/java/org/truffleruby/cext/CExtNodes.java

Lines changed: 76 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@
8080
import org.truffleruby.interop.ToJavaStringNode;
8181
import org.truffleruby.interop.TranslateInteropExceptionNode;
8282
import org.truffleruby.core.string.ImmutableRubyString;
83-
import org.truffleruby.language.LazyWarnNode;
83+
import org.truffleruby.language.LazyWarningNode;
8484
import org.truffleruby.language.LexicalScope;
8585
import org.truffleruby.language.Nil;
8686
import org.truffleruby.language.RubyBaseNode;
8787
import org.truffleruby.language.RubyDynamicObject;
8888
import org.truffleruby.language.RubyGuards;
8989
import org.truffleruby.language.RubyRootNode;
90-
import org.truffleruby.language.WarnNode;
90+
import org.truffleruby.language.WarningNode;
9191
import org.truffleruby.language.arguments.ArgumentsDescriptor;
9292
import org.truffleruby.language.arguments.EmptyArgumentsDescriptor;
9393
import org.truffleruby.language.arguments.KeywordArgumentsDescriptor;
@@ -1046,55 +1046,47 @@ Object rbConstSet(RubyModule module, Object name, Object value,
10461046
@Primitive(name = "rb_gv_get")
10471047
@ReportPolymorphism
10481048
public abstract static class RbGvGetNode extends PrimitiveArrayArgumentsNode {
1049-
1050-
@Specialization(guards = "name == cachedName", limit = "getCacheLimit()")
1051-
static Object rbGvGetCached(VirtualFrame frame, String name,
1052-
@Cached("name") String cachedName,
1053-
@Cached("create(cachedName)") ReadGlobalVariableNode readGlobalVariableNode,
1049+
@Specialization
1050+
Object rbGvGet(VirtualFrame frame, String name,
10541051
@Cached InlinedBranchProfile notExistsProfile,
1055-
@Cached @Shared LazyWarnNode lazyWarnNode,
1056-
@Bind("this") Node node) {
1057-
boolean exists = getContext(node).getCoreLibrary().globalVariables.contains(cachedName);
1052+
@Cached LazyWarningNode lazyWarningNode,
1053+
@Cached RbGvGetInnerNode rbGvGetInnerNode) {
1054+
boolean exists = getContext().getCoreLibrary().globalVariables.contains(name);
10581055

1056+
// Check if it exists and return if not, before creating the GlobalVariableStorage
10591057
if (!exists) {
1060-
notExistsProfile.enter(node);
1061-
warn(node, lazyWarnNode.get(node),
1062-
StringUtils.format("global variable `%s' not initialized", cachedName));
1063-
1058+
notExistsProfile.enter(this);
1059+
WarningNode warningNode = lazyWarningNode.get(this);
1060+
if (warningNode.shouldWarn()) {
1061+
warningNode.warningMessage(getContext(this).getCallStack().getTopMostUserSourceSection(),
1062+
StringUtils.format("global variable `%s' not initialized", name));
1063+
}
10641064
return nil;
10651065
}
10661066

1067-
return readGlobalVariableNode.execute(frame);
1067+
return rbGvGetInnerNode.execute(frame, this, name);
10681068
}
1069+
}
10691070

1070-
@TruffleBoundary
1071-
@Specialization
1072-
Object rbGvGetUncached(String name,
1073-
@Cached DispatchNode dispatchNode,
1074-
@Cached @Shared LazyWarnNode lazyWarnNode) {
1075-
boolean exists = getContext().getCoreLibrary().globalVariables.contains(name);
1076-
1077-
if (!exists) {
1078-
warn(this, lazyWarnNode.get(this), StringUtils.format("global variable `%s' not initialized", name));
10791071

1080-
return nil;
1081-
}
1072+
@GenerateInline
1073+
@GenerateCached(false)
1074+
public abstract static class RbGvGetInnerNode extends RubyBaseNode {
10821075

1083-
return dispatchNode.call(coreLibrary().topLevelBinding, "eval", name);
1084-
}
1076+
public abstract Object execute(VirtualFrame frame, Node node, String name);
10851077

1086-
private static void warn(Node node, WarnNode warnNode, String message) {
1087-
if (warnNode.shouldWarn()) {
1088-
warnNode.warningMessage(
1089-
getContext(node).getCallStack().getTopMostUserSourceSection(),
1090-
message);
1091-
}
1078+
@Specialization(guards = "name == cachedName", limit = "getDefaultCacheLimit()")
1079+
static Object rbGvGetCached(VirtualFrame frame, Node node, String name,
1080+
@Cached("name") String cachedName,
1081+
@Cached(value = "create(cachedName)", inline = false) ReadGlobalVariableNode readGlobalVariableNode) {
1082+
return readGlobalVariableNode.execute(frame);
10921083
}
10931084

1094-
protected int getCacheLimit() {
1095-
return getLanguage().options.DEFAULT_CACHE;
1085+
@Specialization
1086+
static Object rbGvGetUncached(Node node, String name,
1087+
@Cached(inline = false) DispatchNode dispatchNode) {
1088+
return dispatchNode.call(coreLibrary(node).topLevelBinding, "eval", name);
10961089
}
1097-
10981090
}
10991091

11001092
@CoreMethod(names = "cext_module_function", onSingleton = true, required = 2)
@@ -1988,60 +1980,28 @@ protected RubyArray compileArgTypes(AbstractTruffleString format, RubyEncoding e
19881980
@ReportPolymorphism
19891981
public abstract static class RBSprintfNode extends CoreMethodArrayArgumentsNode {
19901982

1991-
@Specialization(
1992-
guards = {
1993-
"libFormat.isRubyString(format)",
1994-
"equalNode.execute(node, libFormat, format, cachedFormat, cachedEncoding)" },
1995-
limit = "2")
1996-
static RubyString formatCached(Object format, Object stringReader, RubyArray argArray,
1997-
@Cached @Shared ArrayToObjectArrayNode arrayToObjectArrayNode,
1998-
@Cached @Shared RubyStringLibrary libFormat,
1999-
@Cached @Shared InlinedBranchProfile exceptionProfile,
2000-
@Cached @Shared InlinedConditionProfile resizeProfile,
2001-
@Cached @Shared TruffleString.FromByteArrayNode fromByteArrayNode,
2002-
@Cached("asTruffleStringUncached(format)") TruffleString cachedFormat,
2003-
@Cached("libFormat.getEncoding(format)") RubyEncoding cachedEncoding,
2004-
@Cached("cachedFormat.byteLength(cachedEncoding.tencoding)") int cachedFormatLength,
2005-
@Cached("create(compileFormat(cachedFormat, cachedEncoding, stringReader))") DirectCallNode formatNode,
2006-
@Cached StringHelperNodes.EqualSameEncodingNode equalNode,
1983+
@Specialization(guards = "libFormat.isRubyString(format)", limit = "1")
1984+
static RubyString format(Object format, Object stringReader, RubyArray argArray,
1985+
@Cached ArrayToObjectArrayNode arrayToObjectArrayNode,
1986+
@Cached RubyStringLibrary libFormat,
1987+
@Cached TruffleString.FromByteArrayNode fromByteArrayNode,
1988+
@Cached RBSprintfInnerNode rbSprintfInnerNode,
1989+
@Cached InlinedBranchProfile exceptionProfile,
1990+
@Cached InlinedConditionProfile resizeProfile,
20071991
@Bind("this") Node node) {
2008-
final BytesResult result;
2009-
final Object[] arguments = arrayToObjectArrayNode.executeToObjectArray(argArray);
2010-
try {
2011-
result = (BytesResult) formatNode.call(new Object[]{ arguments, arguments.length, null });
2012-
} catch (FormatException e) {
2013-
exceptionProfile.enter(node);
2014-
throw FormatExceptionTranslator.translate(getContext(node), node, e);
2015-
}
2016-
2017-
return finishFormat(node, cachedFormatLength, result, resizeProfile, fromByteArrayNode);
2018-
}
2019-
2020-
@Specialization(guards = "libFormat.isRubyString(format)", replaces = "formatCached")
2021-
RubyString formatUncached(Object format, Object stringReader, RubyArray argArray,
2022-
@Cached IndirectCallNode formatNode,
2023-
@Cached @Shared InlinedBranchProfile exceptionProfile,
2024-
@Cached @Shared InlinedConditionProfile resizeProfile,
2025-
@Cached @Shared TruffleString.FromByteArrayNode fromByteArrayNode,
2026-
@Cached @Shared ArrayToObjectArrayNode arrayToObjectArrayNode,
2027-
@Cached @Shared RubyStringLibrary libFormat) {
20281992
var tstring = libFormat.getTString(format);
20291993
var encoding = libFormat.getEncoding(format);
20301994
final Object[] arguments = arrayToObjectArrayNode.executeToObjectArray(argArray);
1995+
20311996
final BytesResult result;
20321997
try {
2033-
result = (BytesResult) formatNode.call(compileFormat(tstring, encoding, stringReader),
2034-
new Object[]{ arguments, arguments.length, null });
1998+
result = rbSprintfInnerNode.execute(node, tstring, encoding, stringReader, arguments);
20351999
} catch (FormatException e) {
2036-
exceptionProfile.enter(this);
2037-
throw FormatExceptionTranslator.translate(getContext(), this, e);
2000+
exceptionProfile.enter(node);
2001+
throw FormatExceptionTranslator.translate(getContext(node), node, e);
20382002
}
20392003

2040-
return finishFormat(this, tstring.byteLength(encoding.tencoding), result, resizeProfile, fromByteArrayNode);
2041-
}
2042-
2043-
private static RubyString finishFormat(Node node, int formatLength, BytesResult result,
2044-
InlinedConditionProfile resizeProfile, TruffleString.FromByteArrayNode fromByteArrayNode) {
2004+
int formatLength = tstring.byteLength(encoding.tencoding);
20452005
byte[] bytes = result.getOutput();
20462006

20472007
if (resizeProfile.profile(node, bytes.length != result.getOutputLength())) {
@@ -2052,14 +2012,43 @@ private static RubyString finishFormat(Node node, int formatLength, BytesResult
20522012
result.getEncoding().getEncodingForLength(formatLength));
20532013
}
20542014

2015+
}
2016+
2017+
@GenerateInline
2018+
@GenerateCached(false)
2019+
public abstract static class RBSprintfInnerNode extends RubyBaseNode {
2020+
2021+
public abstract BytesResult execute(Node node, AbstractTruffleString format, RubyEncoding encoding,
2022+
Object stringReader, Object[] arguments);
2023+
2024+
@Specialization(
2025+
guards = "equalNode.execute(node, format, encoding, cachedFormat, cachedEncoding)",
2026+
limit = "2")
2027+
static BytesResult formatCached(
2028+
Node node, AbstractTruffleString format, RubyEncoding encoding, Object stringReader, Object[] arguments,
2029+
@Cached("format.asTruffleStringUncached(encoding.tencoding)") TruffleString cachedFormat,
2030+
@Cached("encoding") RubyEncoding cachedEncoding,
2031+
@Cached(value = "create(compileFormat(cachedFormat, cachedEncoding, stringReader, node))",
2032+
inline = false) DirectCallNode formatNode,
2033+
@Cached StringHelperNodes.EqualSameEncodingNode equalNode) {
2034+
return (BytesResult) formatNode.call(new Object[]{ arguments, arguments.length, null });
2035+
}
2036+
2037+
@Specialization(replaces = "formatCached")
2038+
static BytesResult formatUncached(
2039+
Node node, AbstractTruffleString format, RubyEncoding encoding, Object stringReader, Object[] arguments,
2040+
@Cached(inline = false) IndirectCallNode formatNode) {
2041+
return (BytesResult) formatNode.call(compileFormat(format, encoding, stringReader, node),
2042+
new Object[]{ arguments, arguments.length, null });
2043+
}
2044+
20552045
@TruffleBoundary
2056-
protected RootCallTarget compileFormat(AbstractTruffleString format, RubyEncoding encoding,
2057-
Object stringReader) {
2046+
protected static RootCallTarget compileFormat(AbstractTruffleString format, RubyEncoding encoding,
2047+
Object stringReader, Node node) {
20582048
try {
2059-
return new RBSprintfCompiler(getLanguage(), this)
2060-
.compile(format, encoding, stringReader);
2049+
return new RBSprintfCompiler(getLanguage(node), node).compile(format, encoding, stringReader);
20612050
} catch (InvalidFormatException e) {
2062-
throw new RaiseException(getContext(), coreExceptions().argumentError(e.getMessage(), this));
2051+
throw new RaiseException(getContext(node), coreExceptions(node).argumentError(e.getMessage(), node));
20632052
}
20642053
}
20652054
}

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

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -474,10 +474,9 @@ public abstract static class ClearNode extends ArrayCoreMethodNode {
474474

475475
@Specialization
476476
RubyArray clear(RubyArray array,
477-
@Cached IsSharedNode isSharedNode,
478-
@Cached ConditionProfile sharedProfile) {
477+
@Cached IsSharedNode isSharedNode) {
479478
setStoreAndSize(array,
480-
ArrayStoreLibrary.initialStorage(sharedProfile.profile(isSharedNode.executeIsShared(this, array))),
479+
ArrayStoreLibrary.initialStorage(isSharedNode.execute(this, array)),
481480
0);
482481
return array;
483482
}
@@ -1031,13 +1030,15 @@ public abstract static class HashNode extends PrimitiveArrayArgumentsNode {
10311030

10321031
private static final int CLASS_SALT = 42753062; // random number, stops hashes for similar values but different classes being the same, static because we want deterministic hashes
10331032

1033+
// Inlined profiles/nodes are @Exclusive to fix truffle-interpreted-performance warning
1034+
10341035
@Specialization(limit = "storageStrategyLimit()")
1035-
static long hash(VirtualFrame frame, RubyArray array,
1036+
static long hash(RubyArray array,
10361037
@Bind("array.getStore()") Object store,
10371038
@CachedLibrary("store") ArrayStoreLibrary stores,
10381039
@Cached HashingNodes.ToHashByHashCode toHashByHashCode,
1039-
@Cached @Shared InlinedIntValueProfile arraySizeProfile,
1040-
@Cached @Shared InlinedLoopConditionProfile loopProfile,
1040+
@Cached @Exclusive InlinedIntValueProfile arraySizeProfile,
1041+
@Cached @Exclusive InlinedLoopConditionProfile loopProfile,
10411042
@Bind("this") Node node) {
10421043
final int size = arraySizeProfile.profile(node, array.size);
10431044
long h = getContext(node).getHashing(node).start(size);
@@ -1107,28 +1108,28 @@ public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode
11071108
protected abstract RubyArray executeInitialize(RubyArray array, Object size, Object fillingValue,
11081109
Object block);
11091110

1111+
// Inlined profiles/nodes are @Exclusive to fix truffle-interpreted-performance warning
1112+
11101113
@Specialization
11111114
RubyArray initializeNoArgs(RubyArray array, NotProvided size, NotProvided fillingValue, Nil block,
1112-
@Cached @Shared IsSharedNode isSharedNode,
1113-
@Cached @Shared ConditionProfile sharedProfile) {
1115+
@Cached @Shared IsSharedNode isSharedNode) {
11141116
setStoreAndSize(array,
1115-
ArrayStoreLibrary.initialStorage(sharedProfile.profile(isSharedNode.executeIsShared(this, array))),
1117+
ArrayStoreLibrary.initialStorage(isSharedNode.execute(this, array)),
11161118
0);
11171119
return array;
11181120
}
11191121

11201122
@Specialization
11211123
RubyArray initializeOnlyBlock(RubyArray array, NotProvided size, NotProvided fillingValue, RubyProc block,
11221124
@Cached @Shared IsSharedNode isSharedNode,
1123-
@Cached @Shared ConditionProfile sharedProfile,
11241125
@Cached("new()") WarningNode warningNode) {
11251126
if (warningNode.shouldWarn()) {
11261127
final SourceSection sourceSection = getContext().getCallStack().getTopMostUserSourceSection();
11271128
warningNode.warningMessage(sourceSection, "given block not used");
11281129
}
11291130

11301131
setStoreAndSize(array,
1131-
ArrayStoreLibrary.initialStorage(sharedProfile.profile(isSharedNode.executeIsShared(this, array))),
1132+
ArrayStoreLibrary.initialStorage(isSharedNode.execute(this, array)),
11321133
0);
11331134
return array;
11341135
}
@@ -1157,10 +1158,9 @@ RubyArray initializeSizeTooBig(RubyArray array, long size, NotProvided fillingVa
11571158
@Specialization(guards = "size >= 0")
11581159
RubyArray initializeWithSizeNoValue(RubyArray array, int size, NotProvided fillingValue, Nil block,
11591160
@Cached @Shared IsSharedNode isSharedNode,
1160-
@Cached @Shared ConditionProfile sharedProfile,
11611161
@CachedLibrary(limit = "2") @Exclusive ArrayStoreLibrary stores) {
11621162
final Object store;
1163-
if (sharedProfile.profile(isSharedNode.executeIsShared(this, array))) {
1163+
if (isSharedNode.execute(this, array)) {
11641164
store = new SharedArrayStorage(new Object[size]);
11651165
} else {
11661166
store = new Object[size];
@@ -1209,8 +1209,8 @@ RubyArray initializeSizeOther(RubyArray array, Object size, Object fillingValue,
12091209
static Object initializeBlock(RubyArray array, int size, Object unusedFillingValue, RubyProc block,
12101210
@Cached ArrayBuilderNode arrayBuilder,
12111211
@CachedLibrary(limit = "2") @Exclusive ArrayStoreLibrary stores,
1212-
@Cached @Shared IsSharedNode isSharedNode,
1213-
@Cached @Shared ConditionProfile sharedProfile,
1212+
// @Exclusive to fix truffle-interpreted-performance warning
1213+
@Cached @Exclusive IsSharedNode isSharedNode,
12141214
@Cached @Exclusive LoopConditionProfile loopProfile,
12151215
@Cached CallBlockNode yieldNode,
12161216
@Bind("this") Node node) {
@@ -1225,7 +1225,7 @@ static Object initializeBlock(RubyArray array, int size, Object unusedFillingVal
12251225
} finally {
12261226
profileAndReportLoopCount(node, loopProfile, n);
12271227
Object store = arrayBuilder.finish(state, n);
1228-
if (sharedProfile.profile(isSharedNode.executeIsShared(node, array))) {
1228+
if (isSharedNode.execute(node, array)) {
12291229
store = stores.makeShared(store, n);
12301230
}
12311231
setStoreAndSize(array, store, n);
@@ -1796,12 +1796,11 @@ RubyArray replace(RubyArray array, Object otherObject,
17961796
@Cached ToAryNode toAryNode,
17971797
@Cached ArrayCopyOnWriteNode cowNode,
17981798
@Cached IsSharedNode isSharedNode,
1799-
@Cached ConditionProfile sharedProfile,
18001799
@CachedLibrary(limit = "2") ArrayStoreLibrary stores) {
18011800
final var other = toAryNode.execute(this, otherObject);
18021801
final int size = other.size;
18031802
Object store = cowNode.execute(other, 0, size);
1804-
if (sharedProfile.profile(isSharedNode.executeIsShared(this, array))) {
1803+
if (isSharedNode.execute(this, array)) {
18051804
store = stores.makeShared(store, size);
18061805
}
18071806
setStoreAndSize(array, store, size);

0 commit comments

Comments
 (0)