Skip to content

Commit 8306ad5

Browse files
committed
[GR-32916] Force computation of lazy capture groups before resolving group names.
PullRequest: truffleruby/2838
2 parents aa0a082 + 43a8258 commit 8306ad5

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

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

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -300,34 +300,43 @@ protected RubyArray getIndex(RubyMatchData matchData, int index, int length,
300300

301301
@Specialization(
302302
guards = {
303-
"name != null",
304-
"getRegexp(matchData) == regexp",
305-
"cachedIndex == index" })
306-
protected Object getIndexSymbolSingleMatch(RubyMatchData matchData, RubySymbol index, NotProvided length,
307-
@Cached("index") RubySymbol cachedIndex,
308-
@Cached("getRegexp(matchData)") RubyRegexp regexp,
309-
@Cached("findNameEntry(regexp, index)") NameEntry name,
310-
@Cached("numBackRefs(name)") int backRefs,
311-
@Cached("backRefIndex(name)") int backRefIndex) {
303+
"nameEntry != null",
304+
"getRegexp(matchData) == cachedRegexp",
305+
"symbol == cachedSymbol" })
306+
protected Object getIndexSymbolKnownRegexp(RubyMatchData matchData, RubySymbol symbol, NotProvided length,
307+
@Cached("symbol") RubySymbol cachedSymbol,
308+
@Cached("getRegexp(matchData)") RubyRegexp cachedRegexp,
309+
@Cached("findNameEntry(cachedRegexp, cachedSymbol)") NameEntry nameEntry,
310+
@Cached("numBackRefs(nameEntry)") int backRefs,
311+
@Cached("backRefIndex(nameEntry)") int backRefIndex,
312+
@Cached ConditionProfile lazyProfile,
313+
@CachedLibrary(limit = "getInteropCacheLimit()") InteropLibrary libInterop) {
312314
if (backRefs == 1) {
313315
return executeGetIndex(matchData, backRefIndex, NotProvided.INSTANCE);
314316
} else {
315-
final int i = getBackRef(matchData, regexp, name);
317+
final int i = getBackRef(matchData, cachedRegexp, cachedSymbol.getRope(), lazyProfile, libInterop);
316318
return executeGetIndex(matchData, i, NotProvided.INSTANCE);
317319
}
318320
}
319321

320322
@Specialization
321-
protected Object getIndexSymbol(RubyMatchData matchData, RubySymbol index, NotProvided length) {
322-
return executeGetIndex(matchData, getBackRefFromSymbol(matchData, index), NotProvided.INSTANCE);
323+
protected Object getIndexSymbol(RubyMatchData matchData, RubySymbol symbol, NotProvided length,
324+
@Cached ConditionProfile lazyProfile,
325+
@CachedLibrary(limit = "getInteropCacheLimit()") InteropLibrary libInterop) {
326+
return executeGetIndex(
327+
matchData,
328+
getBackRef(matchData, getRegexp(matchData), symbol.getRope(), lazyProfile, libInterop),
329+
NotProvided.INSTANCE);
323330
}
324331

325332
@Specialization(guards = "libIndex.isRubyString(index)")
326333
protected Object getIndexString(RubyMatchData matchData, Object index, NotProvided length,
327-
@CachedLibrary(limit = "2") RubyStringLibrary libIndex) {
334+
@CachedLibrary(limit = "2") RubyStringLibrary libIndex,
335+
@Cached ConditionProfile lazyProfile,
336+
@CachedLibrary(limit = "getInteropCacheLimit()") InteropLibrary libInterop) {
328337
return executeGetIndex(
329338
matchData,
330-
getBackRefFromRope(matchData, libIndex.getRope(index)),
339+
getBackRef(matchData, getRegexp(matchData), libIndex.getRope(index), lazyProfile, libInterop),
331340
NotProvided.INSTANCE);
332341
}
333342

@@ -387,42 +396,41 @@ protected RubyRegexp getRegexp(RubyMatchData matchData) {
387396
return regexpNode.executeGetRegexp(matchData);
388397
}
389398

390-
@TruffleBoundary
391-
private int getBackRefFromSymbol(RubyMatchData matchData, RubySymbol index) {
392-
return getBackRefFromRope(matchData, index.getRope());
399+
private int getBackRef(RubyMatchData matchData, RubyRegexp regexp, Rope name,
400+
ConditionProfile lazyProfile, InteropLibrary libInterop) {
401+
if (lazyProfile.profile(matchData.tRegexResult != null)) {
402+
// force the calculation of lazy capture group results before invoking nameToBackrefNumber()
403+
forceLazyMatchData(matchData, libInterop);
404+
}
405+
return nameToBackrefNumber(matchData, regexp, name);
393406
}
394407

395408
@TruffleBoundary
396-
private int getBackRefFromRope(RubyMatchData matchData, Rope value) {
409+
private int nameToBackrefNumber(RubyMatchData matchData, RubyRegexp regexp, Rope name) {
397410
try {
398-
return getRegexp(matchData).regex.nameToBackrefNumber(
399-
value.getBytes(),
411+
return regexp.regex.nameToBackrefNumber(
412+
name.getBytes(),
400413
0,
401-
value.byteLength(),
414+
name.byteLength(),
402415
matchData.region);
403416
} catch (ValueException e) {
404417
throw new RaiseException(
405418
getContext(),
406419
coreExceptions().indexError(
407420
StringUtils
408-
.format("undefined group name reference: %s", RopeOperations.decodeRope(value)),
421+
.format("undefined group name reference: %s", RopeOperations.decodeRope(name)),
409422
this));
410423
}
411424
}
412425

413426
@TruffleBoundary
414-
private int getBackRef(RubyMatchData matchData, RubyRegexp regexp, NameEntry name) {
415-
return regexp.regex.nameToBackrefNumber(name.name, name.nameP, name.nameEnd, matchData.region);
416-
}
417-
418-
@TruffleBoundary
419-
protected static int numBackRefs(NameEntry name) {
420-
return name == null ? 0 : name.getBackRefs().length;
427+
protected static int numBackRefs(NameEntry nameEntry) {
428+
return nameEntry == null ? 0 : nameEntry.getBackRefs().length;
421429
}
422430

423431
@TruffleBoundary
424-
protected static int backRefIndex(NameEntry name) {
425-
return name == null ? 0 : name.getBackRefs()[0];
432+
protected static int backRefIndex(NameEntry nameEntry) {
433+
return nameEntry == null ? 0 : nameEntry.getBackRefs()[0];
426434
}
427435

428436
@TruffleBoundary

0 commit comments

Comments
 (0)