|
36 | 36 | import org.truffleruby.core.regexp.MatchDataNodesFactory.ValuesNodeFactory;
|
37 | 37 | import org.truffleruby.core.rope.Rope;
|
38 | 38 | import org.truffleruby.core.rope.RopeNodes;
|
39 |
| -import org.truffleruby.core.rope.RopeOperations; |
40 | 39 | import org.truffleruby.core.string.RubyString;
|
41 | 40 | import org.truffleruby.core.string.StringSupport;
|
42 | 41 | import org.truffleruby.core.string.StringUtils;
|
@@ -309,26 +308,35 @@ protected Object getIndexSymbolKnownRegexp(RubyMatchData matchData, RubySymbol s
|
309 | 308 | @Cached("getRegexp(matchData)") RubyRegexp cachedRegexp,
|
310 | 309 | @Cached("findNameEntry(cachedRegexp, cachedSymbol)") NameEntry nameEntry,
|
311 | 310 | @Cached("numBackRefs(nameEntry)") int backRefs,
|
312 |
| - @Cached("backRefIndex(nameEntry)") int backRefIndex) { |
| 311 | + @Cached("backRefIndex(nameEntry)") int backRefIndex, |
| 312 | + @Cached ConditionProfile lazyProfile, |
| 313 | + @CachedLibrary(limit = "getInteropCacheLimit()") InteropLibrary libInterop) { |
313 | 314 | if (backRefs == 1) {
|
314 | 315 | return executeGetIndex(matchData, backRefIndex, NotProvided.INSTANCE);
|
315 | 316 | } else {
|
316 |
| - final int i = getBackRef(matchData, cachedRegexp, nameEntry); |
| 317 | + final int i = getBackRef(matchData, cachedRegexp, nameEntry, lazyProfile, libInterop); |
317 | 318 | return executeGetIndex(matchData, i, NotProvided.INSTANCE);
|
318 | 319 | }
|
319 | 320 | }
|
320 | 321 |
|
321 | 322 | @Specialization
|
322 |
| - protected Object getIndexSymbol(RubyMatchData matchData, RubySymbol index, NotProvided length) { |
323 |
| - return executeGetIndex(matchData, getBackRefFromSymbol(matchData, index), NotProvided.INSTANCE); |
| 323 | + protected Object getIndexSymbol(RubyMatchData matchData, RubySymbol index, NotProvided length, |
| 324 | + @Cached ConditionProfile lazyProfile, |
| 325 | + @CachedLibrary(limit = "getInteropCacheLimit()") InteropLibrary libInterop) { |
| 326 | + return executeGetIndex( |
| 327 | + matchData, |
| 328 | + getBackRefFromSymbol(matchData, index, lazyProfile, libInterop), |
| 329 | + NotProvided.INSTANCE); |
324 | 330 | }
|
325 | 331 |
|
326 | 332 | @Specialization(guards = "libIndex.isRubyString(index)")
|
327 | 333 | protected Object getIndexString(RubyMatchData matchData, Object index, NotProvided length,
|
328 |
| - @CachedLibrary(limit = "2") RubyStringLibrary libIndex) { |
| 334 | + @CachedLibrary(limit = "2") RubyStringLibrary libIndex, |
| 335 | + @Cached ConditionProfile lazyProfile, |
| 336 | + @CachedLibrary(limit = "getInteropCacheLimit()") InteropLibrary libInterop) { |
329 | 337 | return executeGetIndex(
|
330 | 338 | matchData,
|
331 |
| - getBackRefFromRope(matchData, libIndex.getRope(index)), |
| 339 | + getBackRefFromRope(matchData, libIndex.getRope(index), lazyProfile, libInterop), |
332 | 340 | NotProvided.INSTANCE);
|
333 | 341 | }
|
334 | 342 |
|
@@ -388,34 +396,50 @@ protected RubyRegexp getRegexp(RubyMatchData matchData) {
|
388 | 396 | return regexpNode.executeGetRegexp(matchData);
|
389 | 397 | }
|
390 | 398 |
|
391 |
| - @TruffleBoundary |
392 |
| - private int getBackRefFromSymbol(RubyMatchData matchData, RubySymbol index) { |
393 |
| - return getBackRefFromRope(matchData, index.getRope()); |
| 399 | + private int getBackRefFromSymbol(RubyMatchData matchData, RubySymbol index, ConditionProfile lazyProfile, |
| 400 | + InteropLibrary libInterop) { |
| 401 | + return getBackRefFromRope(matchData, index.getRope(), lazyProfile, libInterop); |
| 402 | + } |
| 403 | + |
| 404 | + private int getBackRefFromRope(RubyMatchData matchData, Rope value, ConditionProfile lazyProfile, |
| 405 | + InteropLibrary libInterop) { |
| 406 | + if (lazyProfile.profile(matchData.tRegexResult != null)) { |
| 407 | + // force the calculation of lazy capture group results before invoking |
| 408 | + // nameToBackrefNumber |
| 409 | + forceLazyMatchData(matchData, libInterop); |
| 410 | + } |
| 411 | + return nameToBackrefNumber(matchData, getRegexp(matchData), value.getBytes(), 0, value.byteLength()); |
| 412 | + } |
| 413 | + |
| 414 | + private int getBackRef(RubyMatchData matchData, RubyRegexp regexp, NameEntry name, ConditionProfile lazyProfile, |
| 415 | + InteropLibrary libInterop) { |
| 416 | + if (lazyProfile.profile(matchData.tRegexResult != null)) { |
| 417 | + // force the calculation of lazy capture group results before invoking |
| 418 | + // nameToBackrefNumber |
| 419 | + forceLazyMatchData(matchData, libInterop); |
| 420 | + } |
| 421 | + return nameToBackrefNumber(matchData, regexp, name.name, name.nameP, name.nameEnd); |
394 | 422 | }
|
395 | 423 |
|
396 | 424 | @TruffleBoundary
|
397 |
| - private int getBackRefFromRope(RubyMatchData matchData, Rope value) { |
| 425 | + private int nameToBackrefNumber(RubyMatchData matchData, RubyRegexp regexp, byte[] name, int nameP, |
| 426 | + int nameEnd) { |
398 | 427 | try {
|
399 |
| - return getRegexp(matchData).regex.nameToBackrefNumber( |
400 |
| - value.getBytes(), |
401 |
| - 0, |
402 |
| - value.byteLength(), |
| 428 | + return regexp.regex.nameToBackrefNumber( |
| 429 | + name, |
| 430 | + nameP, |
| 431 | + nameEnd, |
403 | 432 | matchData.region);
|
404 | 433 | } catch (ValueException e) {
|
405 | 434 | throw new RaiseException(
|
406 | 435 | getContext(),
|
407 | 436 | coreExceptions().indexError(
|
408 | 437 | StringUtils
|
409 |
| - .format("undefined group name reference: %s", RopeOperations.decodeRope(value)), |
| 438 | + .format("undefined group name reference: %s", new String(name, nameP, nameEnd)), |
410 | 439 | this));
|
411 | 440 | }
|
412 | 441 | }
|
413 | 442 |
|
414 |
| - @TruffleBoundary |
415 |
| - private int getBackRef(RubyMatchData matchData, RubyRegexp regexp, NameEntry name) { |
416 |
| - return regexp.regex.nameToBackrefNumber(name.name, name.nameP, name.nameEnd, matchData.region); |
417 |
| - } |
418 |
| - |
419 | 443 | @TruffleBoundary
|
420 | 444 | protected static int numBackRefs(NameEntry nameEntry) {
|
421 | 445 | return nameEntry == null ? 0 : nameEntry.getBackRefs().length;
|
|
0 commit comments