Skip to content

Commit 1087e5e

Browse files
committed
[GR-18163] Fix the --regexp-instrument-creation option
PullRequest: truffleruby/2841
2 parents 6bbbabb + ac66dc8 commit 1087e5e

File tree

6 files changed

+50
-37
lines changed

6 files changed

+50
-37
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
slow:The --regexp-instrument-creation option works
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. This
2+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
3+
# redistribute it and/or modify it under the terms of the:
4+
#
5+
# Eclipse Public License version 2.0, or
6+
# GNU General Public License version 2, or
7+
# GNU Lesser General Public License version 2.1.
8+
9+
require_relative '../../ruby/spec_helper'
10+
11+
describe "The --regexp-instrument-creation option" do
12+
it "works" do
13+
out = ruby_exe("/abc/i", options: "--experimental-options --regexp-instrument-creation")
14+
out.should.include? "Regular expression statistics"
15+
out.should.include? "1 /abc/i"
16+
end
17+
end

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,10 @@ private static Regex getRegexpFromCache(RubyContext context, RopeBuilder bytes,
127127
}
128128

129129
final Rope rope = RopeOperations.ropeFromRopeBuilder(bytes);
130-
final int joniOptions = options.toJoniOptions();
131130
final RegexpCacheKey cacheKey = new RegexpCacheKey(
132131
rope,
133132
encoding,
134-
joniOptions,
133+
options,
135134
context.getHashing(context.getRegexpCache()));
136135

137136
final Regex regex = context.getRegexpCache().get(cacheKey);

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

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@
1313
import org.truffleruby.core.encoding.RubyEncoding;
1414
import org.truffleruby.core.rope.NativeRope;
1515
import org.truffleruby.core.rope.Rope;
16-
import org.truffleruby.parser.ReOptions;
16+
import org.truffleruby.core.rope.RopeOperations;
1717

1818
public final class RegexpCacheKey {
1919

2020
private final Rope rope;
2121
private final RubyEncoding encoding;
22-
private final int options;
22+
private final int joniOptions;
2323
private final Hashing hashing;
2424

25-
public RegexpCacheKey(Rope rope, RubyEncoding encoding, int options, Hashing hashing) {
25+
public RegexpCacheKey(Rope rope, RubyEncoding encoding, RegexpOptions options, Hashing hashing) {
2626
assert !(rope instanceof NativeRope);
2727
this.rope = rope;
2828
this.encoding = encoding;
29-
this.options = options;
29+
this.joniOptions = options.toJoniOptions();
3030
this.hashing = hashing;
3131
}
3232

@@ -39,25 +39,15 @@ public int hashCode() {
3939
public boolean equals(Object o) {
4040
if (o instanceof RegexpCacheKey) {
4141
final RegexpCacheKey other = (RegexpCacheKey) o;
42-
return rope.equals(other.rope) && encoding == other.encoding && options == other.options;
42+
return rope.equals(other.rope) && encoding == other.encoding && joniOptions == other.joniOptions;
4343
} else {
4444
return false;
4545
}
4646
}
4747

4848
@Override
4949
public String toString() {
50-
StringBuilder builder = new StringBuilder();
51-
builder.append('/').append(rope.toString()).append('/');
52-
if ((options & ReOptions.RE_OPTION_MULTILINE) != 0) {
53-
builder.append('m');
54-
}
55-
if ((options & ReOptions.RE_OPTION_IGNORECASE) != 0) {
56-
builder.append('i');
57-
}
58-
if ((options & ReOptions.RE_OPTION_EXTENDED) != 0) {
59-
builder.append('x');
60-
}
61-
return builder.toString();
50+
return '/' + RopeOperations.decodeOrEscapeBinaryRope(rope) + '/' +
51+
RegexpOptions.fromJoniOptions(joniOptions).toOptionsString();
6252
}
6353
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ protected void instrument(RubyRegexp regexp, Object string, boolean fromStart) {
654654
RubyEncoding enc = RubyStringLibrary.getUncached().getEncoding(string);
655655
RegexpOptions options = regexp.options;
656656
MatchInfo matchInfo = new MatchInfo(
657-
new RegexpCacheKey(source, enc, options.toJoniOptions(), Hashing.NO_SEED),
657+
new RegexpCacheKey(source, enc, options, Hashing.NO_SEED),
658658
fromStart);
659659
ConcurrentOperations.getOrCompute(MATCHED_REGEXPS, matchInfo, x -> new AtomicInteger()).incrementAndGet();
660660
}
@@ -730,7 +730,7 @@ public static Regex compile(RubyLanguage language, RubyDeferredWarnings rubyDefe
730730
final RegexpCacheKey key = new RegexpCacheKey(
731731
bytes.getRope(),
732732
enc,
733-
options.toJoniOptions(),
733+
options,
734734
Hashing.NO_SEED);
735735
ConcurrentOperations.getOrCompute(COMPILED_REGEXPS, key, x -> new AtomicInteger()).incrementAndGet();
736736
}

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -205,24 +205,24 @@ public static String decodeOrEscapeBinaryRope(Rope rope, byte[] bytes) {
205205
if (rope.isAsciiOnly() || rope.getEncoding() != ASCIIEncoding.INSTANCE) {
206206
return decodeRopeSegment(rope, bytes, 0, bytes.length);
207207
} else {
208-
// A Rope with BINARY encoding cannot be converted faithfully to a Java String.
209-
// (ISO_8859_1 would just show random characters for bytes above 128)
210-
// Therefore we convert non-US-ASCII characters to "\xNN".
211-
// MRI Symbol#inspect for binary symbols is similar: "\xff".b.to_sym => :"\xFF"
212-
213-
final StringBuilder builder = new StringBuilder(rope.byteLength());
208+
return escapeBinaryRope(bytes);
209+
}
210+
}
214211

215-
for (int i = 0; i < bytes.length; i++) {
216-
final byte c = bytes[i];
217-
if (c >= 0) { // US-ASCII character
218-
builder.append((char) (c & 0xFF));
219-
} else {
220-
builder.append("\\x").append(String.format("%02X", c & 0xFF));
221-
}
212+
private static String escapeBinaryRope(byte[] bytes) {
213+
// A Rope with BINARY encoding cannot be converted faithfully to a Java String.
214+
// (ISO_8859_1 would just show random characters for bytes above 128)
215+
// Therefore we convert non-US-ASCII characters to "\xNN".
216+
// MRI Symbol#inspect for binary symbols is similar: "\xff".b.to_sym => :"\xFF"
217+
final StringBuilder builder = new StringBuilder(bytes.length);
218+
for (final byte c : bytes) {
219+
if (c >= 0) { // US-ASCII character
220+
builder.append((char) (c & 0xFF));
221+
} else {
222+
builder.append("\\x").append(String.format("%02X", c & 0xFF));
222223
}
223-
224-
return builder.toString();
225224
}
225+
return builder.toString();
226226
}
227227

228228
public static String decodeRope(Rope value) {
@@ -242,9 +242,15 @@ private static String decodeRopeSegment(Rope value, byte[] bytes, int byteOffset
242242
}
243243
}
244244

245+
/** This method has no side effects, because it does not even have access to the Rope - for debugging only. */
245246
@TruffleBoundary
246247
public static String decode(Encoding encoding, byte[] bytes) {
247-
return decode(EncodingManager.charsetForEncoding(encoding), bytes, 0, bytes.length);
248+
if (encoding == ASCIIEncoding.INSTANCE) {
249+
return escapeBinaryRope(bytes);
250+
} else {
251+
final Charset charset = EncodingManager.charsetForEncoding(encoding);
252+
return decode(charset, bytes, 0, bytes.length);
253+
}
248254
}
249255

250256
private static String decode(Charset charset, byte[] bytes, int byteOffset, int byteLength) {

0 commit comments

Comments
 (0)