Skip to content

Commit 2e8c6c4

Browse files
committed
Avoid streams
1 parent 21ad763 commit 2e8c6c4

14 files changed

+120
-148
lines changed

src/main/.checkstyle_checks.xml

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@
277277
<property name="format" value="@Exclusive @Cached"/>
278278
<property name="message" value="Wrong order of annotations. The correct order is @Cached @Exclusive."/>
279279
</module>
280+
<module name="RegexpSinglelineJava">
281+
<property name="format" value="Stream\.of\(|Arrays\.stream\(|\.stream\(\)|import java\.util\.stream\."/>
282+
<property name="message" value="Avoid using Java Streams, they cause lots of allocations and are slow for startup and in interpreter."/>
283+
</module>
280284
<module name="IllegalType">
281285
<!-- Use PrintStream instead of PrintWriter, PrintWriter does not consistently flush, even when writing \n.-->
282286
<property name="illegalClassNames" value="PrintWriter"/>
@@ -287,62 +291,11 @@
287291
<property name="tokens" value="ANNOTATION_FIELD_DEF,INTERFACE_DEF,METHOD_CALL,METHOD_DEF,METHOD_REF,PARAMETER_DEF,VARIABLE_DEF,PATTERN_VARIABLE_DEF,RECORD_DEF,RECORD_COMPONENT_DEF"/>
288292
</module>
289293

290-
<module name="SuppressionCommentFilter">
291-
<property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
292-
<property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
293-
<property name="checkFormat" value="ConstantNameCheck"/>
294-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
295-
</module>
296-
<module name="SuppressionCommentFilter">
297-
<property name="offCommentFormat" value="Checkstyle: stop method name check"/>
298-
<property name="onCommentFormat" value="Checkstyle: resume method name check"/>
299-
<property name="checkFormat" value="MethodName"/>
300-
<property name="checkC" value="false"/>
301-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
302-
</module>
303-
<module name="SuppressionCommentFilter">
304-
<property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
305-
<property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
306-
<property name="checkFormat" value="ParameterAssignment"/>
307-
<property name="checkC" value="false"/>
308-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
309-
</module>
310-
<module name="SuppressionCommentFilter">
311-
<property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
312-
<property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
313-
<property name="checkFormat" value="FinalLocalVariable"/>
314-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
315-
</module>
316294
<module name="SuppressionCommentFilter">
317295
<property name="offCommentFormat" value="Checkstyle: stop"/>
318296
<property name="onCommentFormat" value="Checkstyle: resume"/>
319297
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
320298
</module>
321-
<module name="SuppressionCommentFilter">
322-
<property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
323-
<property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
324-
<property name="checkFormat" value="InnerAssignment"/>
325-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
326-
</module>
327-
<module name="SuppressionCommentFilter">
328-
<property name="offCommentFormat" value="Checkstyle: stop field name check"/>
329-
<property name="onCommentFormat" value="Checkstyle: resume field name check"/>
330-
<property name="checkFormat" value="MemberName"/>
331-
<property name="checkC" value="false"/>
332-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
333-
</module>
334-
<module name="SuppressionCommentFilter">
335-
<property name="offCommentFormat" value="CheckStyle: stop system..print check"/>
336-
<property name="onCommentFormat" value="CheckStyle: resume system..print check"/>
337-
<property name="checkFormat" value="RegexpSingleline"/>
338-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
339-
</module>
340-
<module name="SuppressionCommentFilter">
341-
<property name="offCommentFormat" value="CheckStyle: stop header check"/>
342-
<property name="onCommentFormat" value="CheckStyle: resume header check"/>
343-
<property name="checkFormat" value=".*Header"/>
344-
<metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
345-
</module>
346299
<module name="SuppressionCommentFilter">
347300
<property name="offCommentFormat" value="CheckStyle: start generated"/>
348301
<property name="onCommentFormat" value="CheckStyle: stop generated"/>

src/main/java/org/truffleruby/aot/ParserCache.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
import java.io.IOException;
1313
import java.util.HashMap;
1414
import java.util.Map;
15-
import java.util.stream.Collectors;
1615

1716
import com.oracle.truffle.api.CompilerDirectives;
1817
import com.oracle.truffle.api.source.Source;
1918
import org.truffleruby.core.CoreLibrary;
19+
import org.truffleruby.core.array.ArrayUtils;
20+
import org.truffleruby.core.string.StringUtils;
2021
import org.truffleruby.language.loader.ResourceLoader;
2122
import org.truffleruby.parser.RubyDeferredWarnings;
23+
import org.truffleruby.parser.RubyDeferredWarnings.WarningMessage;
2224
import org.truffleruby.parser.RubySource;
2325
import org.truffleruby.parser.TranslatorDriver;
2426
import org.truffleruby.parser.ast.RootParseNode;
@@ -64,12 +66,11 @@ private static RootParseNode parse(RubySource source) {
6466
final StaticScope staticScope = new StaticScope(StaticScope.Type.LOCAL, null);
6567
final ParserConfiguration parserConfiguration = new ParserConfiguration(null, false, true, false);
6668
RubyDeferredWarnings rubyWarnings = new RubyDeferredWarnings();
67-
RootParseNode rootParseNode = TranslatorDriver
68-
.parseToJRubyAST(null, source, staticScope, parserConfiguration, rubyWarnings);
69+
var rootParseNode = TranslatorDriver.parseToJRubyAST(null, source, staticScope, parserConfiguration,
70+
rubyWarnings);
6971
if (!rubyWarnings.warnings.isEmpty()) {
70-
throw new RuntimeException("Core files should not emit warnings: " + String.join(
71-
"\n",
72-
rubyWarnings.warnings.stream().map(w -> w.getWarningMessage()).collect(Collectors.toList())));
72+
throw new RuntimeException("Core files should not emit warnings: " +
73+
StringUtils.join(ArrayUtils.map(rubyWarnings.warnings, WarningMessage::getWarningMessage), "\n"));
7374
}
7475
return rootParseNode;
7576
}

src/main/java/org/truffleruby/core/VMPrimitiveNodes.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@
3737
*/
3838
package org.truffleruby.core;
3939

40-
import java.util.Arrays;
4140
import java.util.Map.Entry;
42-
import java.util.stream.Stream;
4341

4442
import com.oracle.truffle.api.TruffleStackTrace;
4543
import com.oracle.truffle.api.dsl.Bind;
@@ -621,15 +619,16 @@ RubyArray argumentsDescriptor(VirtualFrame frame) {
621619
private RubyArray descriptorToArray(ArgumentsDescriptor descriptor) {
622620
if (descriptor == EmptyArgumentsDescriptor.INSTANCE) {
623621
return createEmptyArray();
624-
} else if (descriptor instanceof KeywordArgumentsDescriptor) {
625-
final KeywordArgumentsDescriptor keywordArgumentsDescriptor = (KeywordArgumentsDescriptor) descriptor;
622+
} else if (descriptor instanceof KeywordArgumentsDescriptor keywordArgumentsDescriptor) {
623+
var keywords = keywordArgumentsDescriptor.getKeywords();
626624

627-
final Stream<RubySymbol> keywords = Stream.concat(
628-
Stream.of("keywords"),
629-
Arrays.stream(keywordArgumentsDescriptor.getKeywords()))
630-
.map(getLanguage()::getSymbol);
625+
Object[] array = new Object[1 + keywords.length];
626+
array[0] = getSymbol("keywords");
627+
for (int i = 0; i < keywords.length; i++) {
628+
array[i + 1] = getSymbol(keywords[i]);
629+
}
631630

632-
return createArray(keywords.toArray());
631+
return createArray(array);
633632
} else {
634633
throw CompilerDirectives.shouldNotReachHere();
635634
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
package org.truffleruby.core.array;
1111

1212
import java.lang.reflect.Array;
13+
import java.util.ArrayList;
1314
import java.util.Arrays;
15+
import java.util.Collection;
1416
import java.util.List;
17+
import java.util.function.Function;
1518

1619
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
1720
import com.oracle.truffle.api.TruffleSafepoint;
@@ -278,4 +281,35 @@ public static List<Object> asList(Object[] array) {
278281
return Arrays.asList(array);
279282
}
280283

284+
/** Compares by identity using Java {@code ==} */
285+
@TruffleBoundary
286+
public static Object[] subtract(Object[] a, Object[] b) {
287+
var result = new ArrayList<>();
288+
for (Object element : a) {
289+
if (!contains(b, element)) {
290+
result.add(element);
291+
}
292+
}
293+
return result.toArray();
294+
}
295+
296+
@TruffleBoundary
297+
public static <T, R> Object[] map(T[] array, Function<? super T, ? extends R> mapper) {
298+
var result = new Object[array.length];
299+
for (int i = 0; i < array.length; i++) {
300+
result[i] = mapper.apply(array[i]);
301+
}
302+
return result;
303+
}
304+
305+
@TruffleBoundary
306+
public static <T, R> Object[] map(Collection<T> list, Function<? super T, ? extends R> mapper) {
307+
var result = new Object[list.size()];
308+
var iterator = list.iterator();
309+
for (int i = 0; i < list.size(); i++) {
310+
result[i] = mapper.apply(iterator.next());
311+
}
312+
return result;
313+
}
314+
281315
}

src/main/java/org/truffleruby/core/regexp/TruffleRegexpNodes.java

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.concurrent.atomic.AtomicInteger;
2121
import java.util.concurrent.atomic.AtomicLong;
2222
import java.util.function.Function;
23-
import java.util.stream.Collectors;
2423

2524
import com.oracle.truffle.api.CompilerDirectives;
2625
import com.oracle.truffle.api.TruffleSafepoint;
@@ -458,32 +457,23 @@ protected <T> RubyArray fillinInstrumentData(Set<T> map, ArrayBuilderNode arrayB
458457
@TruffleBoundary
459458
protected static Set<RubyRegexp> allCompiledRegexps() {
460459
final Set<RubyRegexp> ret = new HashSet<>();
461-
462460
ret.addAll(DYNAMIC_REGEXPS);
463461
ret.addAll(LITERAL_REGEXPS);
464-
465462
return ret;
466463
}
467464

468465
@TruffleBoundary
469466
protected static Set<RubyRegexp> allMatchedRegexps() {
470467
final Set<RubyRegexp> ret = new HashSet<>();
471-
472-
ret.addAll(
473-
MATCHED_REGEXPS_JONI
474-
.keySet()
475-
.stream()
476-
.map(matchInfo -> matchInfo.regex)
477-
.collect(Collectors.toSet()));
478-
ret.addAll(
479-
MATCHED_REGEXPS_TREGEX
480-
.keySet()
481-
.stream()
482-
.map(matchInfo -> matchInfo.regex)
483-
.collect(Collectors.toSet()));
484-
468+
for (var matchInfo : MATCHED_REGEXPS_JONI.keySet()) {
469+
ret.add(matchInfo.regex);
470+
}
471+
for (var matchInfo : MATCHED_REGEXPS_TREGEX.keySet()) {
472+
ret.add(matchInfo.regex);
473+
}
485474
return ret;
486475
}
476+
487477
}
488478

489479
@CoreMethod(names = "regexp_compilation_stats_array", onSingleton = true, required = 1)

src/main/java/org/truffleruby/core/string/StringUtils.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,22 @@ public static String toUpperCase(String string) {
5656
return string.toUpperCase(Locale.ENGLISH);
5757
}
5858

59+
@TruffleBoundary
60+
public static String join(Object[] elements, String separator) {
61+
return join(elements, separator, "", "");
62+
}
63+
64+
@TruffleBoundary
65+
public static String join(Object[] elements, String separator, String prefix, String suffix) {
66+
var builder = new StringBuilder(prefix);
67+
for (int i = 0; i < elements.length; i++) {
68+
builder.append(elements[i]);
69+
if (i != elements.length - 1) {
70+
builder.append(separator);
71+
}
72+
}
73+
builder.append(suffix);
74+
return builder.toString();
75+
}
76+
5977
}

src/main/java/org/truffleruby/debug/TruffleASTPrinter.java

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
import java.util.Set;
1717
import java.util.TreeSet;
1818
import java.util.regex.Matcher;
19-
import java.util.stream.Collectors;
20-
import java.util.stream.Stream;
2119

2220
import com.oracle.truffle.api.profiles.Profile;
2321
import org.graalvm.collections.Pair;
2422
import org.truffleruby.core.proc.ProcCallTargets;
23+
import org.truffleruby.core.string.StringUtils;
2524
import org.truffleruby.core.support.DetailedInspectingSupport;
2625
import org.truffleruby.language.RubyRootNode;
2726
import org.truffleruby.language.methods.CachedLazyCallTargetSupplier;
@@ -121,23 +120,21 @@ private static List<Pair<String, Object>> getNodeAttributes(Node node) {
121120
}
122121

123122
var attributesMap = NodeUtil.collectNodeProperties(node);
124-
var attributes = new ArrayList<>(attributesMap.entrySet())
125-
.stream()
126-
.map(entry -> Pair.create(entry.getKey(), entry.getValue()))
127-
.map(pair -> {
128-
if (pair.getLeft().startsWith("field.")) {
129-
String name = pair.getLeft().substring("field.".length());
130-
return Pair.create(name, pair.getRight());
131-
} else {
132-
return pair;
133-
}
134-
})
135-
.filter(pair -> pair.getRight() != null) // hide numerous attributes that aren't initialized yet
136-
.filter(pair -> !attributesToIgnore.contains(pair.getLeft())) // ignore some noisy attributes
137-
.filter(pair -> !generatedFieldNames.contains(pair.getLeft())) // ignore attributes of generated -Gen classes
138-
.filter(pair -> !(pair.getRight() instanceof Profile)) // ignore ...Profile as far as they might be disabled/enabled that affects string representation
139-
.collect(Collectors.toList());
123+
var attributes = new ArrayList<Pair<String, Object>>();
124+
for (var entry : attributesMap.entrySet()) {
125+
String name = entry.getKey();
126+
Object value = entry.getValue();
127+
if (name.startsWith("field.")) {
128+
name = name.substring("field.".length());
129+
}
140130

131+
if (value != null && // hide numerous attributes that aren't initialized yet
132+
!attributesToIgnore.contains(name) && // ignore some noisy attributes
133+
!generatedFieldNames.contains(name) && // ignore attributes of generated -Gen classes
134+
!(value instanceof Profile)) { // ignore ...Profile as far as they might be disabled/enabled that affects string representation
135+
attributes.add(Pair.create(name, value));
136+
}
137+
}
141138
return attributes;
142139
}
143140

@@ -163,12 +160,12 @@ private static List<Pair<String, Object>> getNodeChildren(Node node) {
163160
}
164161
}
165162

166-
var children = new ArrayList<>(childrenMap.entrySet())
167-
.stream()
168-
.map(entry -> Pair.create(entry.getKey(), entry.getValue()))
169-
.filter(pair -> pair.getRight() != null) // hide child nodes that aren't initialized yet
170-
.collect(Collectors.toList());
171-
163+
var children = new ArrayList<Pair<String, Object>>();
164+
for (var entry : childrenMap.entrySet()) {
165+
if (entry.getValue() != null) { // hide child nodes that aren't initialized yet
166+
children.add(Pair.create(entry.getKey(), entry.getValue()));
167+
}
168+
}
172169
return children;
173170
}
174171

@@ -316,7 +313,7 @@ private static String valueOrArrayToString(Object value) {
316313
strings[i] = valueToString(element);
317314
}
318315

319-
valueString = Stream.of(strings).collect(Collectors.joining(", ", "[", "]"));
316+
valueString = StringUtils.join(strings, ", ", "[", "]");
320317
} else {
321318
valueString = valueToString(value);
322319
}

src/main/java/org/truffleruby/debug/TruffleDebugNodes.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.truffleruby.core.RubyHandle;
4747
import org.truffleruby.core.array.ArrayGuards;
4848
import org.truffleruby.core.array.ArrayHelpers;
49+
import org.truffleruby.core.array.ArrayUtils;
4950
import org.truffleruby.core.array.RubyArray;
5051
import org.truffleruby.core.array.library.ArrayStoreLibrary;
5152
import org.truffleruby.core.binding.BindingNodes;
@@ -1403,10 +1404,9 @@ public abstract static class PrimitiveNamesNode extends CoreMethodArrayArguments
14031404
@TruffleBoundary
14041405
@Specialization
14051406
RubyArray primitiveNames() {
1406-
var primitiveNames = getLanguage().primitiveManager.getPrimitiveNames().stream()
1407-
.map(FromJavaStringNode::executeUncached);
1408-
1409-
return createArray(primitiveNames.toArray());
1407+
var primitives = getLanguage().primitiveManager.getPrimitiveNames();
1408+
var primitiveNames = ArrayUtils.map(primitives, FromJavaStringNode::executeUncached);
1409+
return createArray(primitiveNames);
14101410
}
14111411
}
14121412

src/main/java/org/truffleruby/language/TruffleBootNodes.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import java.io.IOException;
1414
import java.nio.charset.StandardCharsets;
1515
import java.util.List;
16-
import java.util.stream.Collectors;
1716

1817
import com.oracle.truffle.api.RootCallTarget;
1918
import com.oracle.truffle.api.nodes.NodeUtil;
@@ -29,6 +28,7 @@
2928
import org.truffleruby.core.array.RubyArray;
3029
import org.truffleruby.core.encoding.Encodings;
3130
import org.truffleruby.core.string.RubyString;
31+
import org.truffleruby.core.string.StringUtils;
3232
import org.truffleruby.core.symbol.RubySymbol;
3333
import org.truffleruby.language.control.RaiseException;
3434
import org.truffleruby.language.dispatch.DispatchNode;
@@ -409,10 +409,7 @@ Object toolchainPaths(RubySymbol pathName,
409409
final Toolchain toolchain = getToolchain(getContext(), this);
410410
final List<TruffleFile> paths = toolchain.getPaths(name);
411411
if (paths != null) {
412-
String path = paths
413-
.stream()
414-
.map(file -> file.getPath())
415-
.collect(Collectors.joining(File.pathSeparator));
412+
String path = StringUtils.join(paths.toArray(), File.pathSeparator);
416413
return createString(fromJavaStringNode, path, Encodings.UTF_8);
417414
} else {
418415
throw new RaiseException(

0 commit comments

Comments
 (0)