Skip to content

Commit 367c9de

Browse files
committed
Use Truffle utility methods, which intrinsify to vector instructions, when searching for single-byte characters in a String.
1 parent b8bccea commit 367c9de

File tree

3 files changed

+37
-18
lines changed

3 files changed

+37
-18
lines changed

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,32 @@ Bug fixes:
99
* Fixed `Addrinfo.new(String)` to reliably find the address family (#1702).
1010
* Fixed argument checks in `BasicSocket#setsockopt` (#1460).
1111
* Fixed `ObjectSpace.trace_object_allocations` (#1456).
12+
13+
Compatibility:
14+
15+
* Exceptions from `coerce` are no longer rescued, like MRI.
16+
* Implemented `Integer#{allbits?,anybits?,nobits?}`.
17+
* `Integer#{ceil,floor,truncate}` now accept a precision and `Integer#round` accepts a rounding mode.
18+
* Added missing `Enumerable#filter` and `Enumerator::Lazy#filter` aliases to the respective `select` method (#1610).
19+
* Implemented more `Ripper` methods as no-ops (#1694).
20+
* Implemented `rb_enc_sprintf` (#1702).
21+
* Implemented `ENV#{filter,filter!}` aliases for `select` and `select!`.
22+
* Non-blocking `StringIO` and `Socket` APIs now support `exception: false` like MRI (#1702).
23+
24+
Changes:
25+
26+
* Interactive sources (like the GraalVM polyglot shell) now all share the same binding (#1695).
27+
28+
Performance:
29+
30+
* `eval(code, binding)` for a fixed `code` containing blocks is now much faster. This improves the performance of rendering `ERB` templates containing loops.
31+
* Several `String` methods have been made faster by the usage of vector instructions
32+
when searching for a single-byte character in a String.
33+
34+
# 20.0.0 beta 1
35+
36+
Bug fixes:
37+
1238
* Fixed `BigDecimal#{clone,dup}` so it now just returns the receiver, per Ruby 2.5+ semantics (#1680).
1339
* Fixed creating `BigDecimal` instances from non-finite `Float` values (#1685).
1440
* Fixed `BigDecimal#inspect` output for non-finite values (e.g, NaN or -Infinity) (#1683).

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3627,26 +3627,24 @@ public Object stringIndexEmptyPattern(DynamicObject string, DynamicObject patter
36273627
})
36283628
public Object stringIndexSingleBytePattern(DynamicObject string, DynamicObject pattern, int byteOffset,
36293629
@Cached("create()") RopeNodes.BytesNode bytesNode,
3630-
@Cached("create()") BranchProfile matchFoundProfile,
3631-
@Cached("create()") BranchProfile noMatchProfile) {
3630+
@Cached("createBinaryProfile()") ConditionProfile offsetTooLargeProfile) {
36323631
assert byteOffset >= 0;
36333632

36343633
checkEncoding(string, pattern);
36353634

36363635
final Rope sourceRope = rope(string);
36373636
final int end = sourceRope.byteLength();
3637+
3638+
if (offsetTooLargeProfile.profile(byteOffset >= end)) {
3639+
return nil();
3640+
}
3641+
36383642
final byte[] sourceBytes = bytesNode.execute(sourceRope);
36393643
final byte searchByte = bytesNode.execute(rope(pattern))[0];
36403644

3641-
for (int i = byteOffset; i < end; i++) {
3642-
if (sourceBytes[i] == searchByte) {
3643-
matchFoundProfile.enter();
3644-
return i;
3645-
}
3646-
}
3645+
final int index = com.oracle.truffle.api.ArrayUtils.indexOf(sourceBytes, byteOffset, end, searchByte);
36473646

3648-
noMatchProfile.enter();
3649-
return nil();
3647+
return index == -1 ? nil() : index;
36503648
}
36513649

36523650
@Specialization(guards = {

src/main/java/org/truffleruby/core/support/ByteArrayNodes.java

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

12+
import com.oracle.truffle.api.ArrayUtils;
1213
import com.oracle.truffle.api.dsl.Cached;
1314
import com.oracle.truffle.api.dsl.Specialization;
1415
import com.oracle.truffle.api.object.DynamicObject;
@@ -195,15 +196,9 @@ public Object getByteSingleByte(DynamicObject bytes, DynamicObject pattern, int
195196
start = 0;
196197
}
197198

198-
for (int i = start; i < length; i++) {
199-
if (in.get(i) == searchByte) {
200-
matchFoundProfile.enter();
201-
return i + 1;
202-
}
203-
}
199+
final int index = ArrayUtils.indexOf(in.getUnsafeBytes(), start, length, searchByte);
204200

205-
noMatchProfile.enter();
206-
return nil();
201+
return index == -1 ? nil() : index + 1;
207202
}
208203

209204
@Specialization(guards = { "isRubyString(pattern)", "!isSingleBytePattern(pattern)" })

0 commit comments

Comments
 (0)