|
195 | 195 | import java.util.concurrent.TimeUnit;
|
196 | 196 | import java.util.concurrent.atomic.AtomicInteger;
|
197 | 197 | import java.util.concurrent.atomic.AtomicLong;
|
| 198 | +import java.util.function.BiFunction; |
| 199 | +import java.util.function.Function; |
198 | 200 | import java.util.regex.Pattern;
|
199 | 201 |
|
200 | 202 | import static java.lang.invoke.MethodHandles.explicitCastArguments;
|
@@ -4577,14 +4579,36 @@ public RubyString freezeAndDedupString(RubyString string) {
|
4577 | 4579 | RubyString deduped;
|
4578 | 4580 |
|
4579 | 4581 | if (dedupedRef == null || (deduped = dedupedRef.get()) == null) {
|
| 4582 | + // Never use incoming value as key |
4580 | 4583 | deduped = string.strDup(this);
|
4581 | 4584 | deduped.setFrozen(true);
|
4582 |
| - dedupMap.put(string, new WeakReference<RubyString>(deduped)); |
4583 |
| - } else if (deduped.getEncoding() != string.getEncoding()) { |
| 4585 | + |
| 4586 | + WeakReference<RubyString> weakref = new WeakReference<>(deduped); |
| 4587 | + WeakReference<RubyString> existing; |
| 4588 | + RubyString existingDeduped; |
| 4589 | + |
| 4590 | + // Check if someone else beat us to it. |
| 4591 | + // NOTE: This still races because Map.compute* API is Java 8+. |
| 4592 | + while ((existing = dedupMap.putIfAbsent(deduped, weakref)) != null ) { |
| 4593 | + |
| 4594 | + existingDeduped = existing.get(); |
| 4595 | + |
| 4596 | + if (existingDeduped != null) { |
| 4597 | + deduped = existingDeduped; |
| 4598 | + break; |
| 4599 | + } |
| 4600 | + |
| 4601 | + // keep trying to put it if existing has been evacuated |
| 4602 | + } |
| 4603 | + } |
| 4604 | + |
| 4605 | + if (deduped.getEncoding() != string.getEncoding()) { |
4584 | 4606 | // if encodings don't match, new string loses; can't dedup
|
| 4607 | + // FIXME: This may never happen, if we are properly considering encoding in RubyString.hashCode |
4585 | 4608 | deduped = string.strDup(this);
|
4586 | 4609 | deduped.setFrozen(true);
|
4587 | 4610 | }
|
| 4611 | + |
4588 | 4612 | return deduped;
|
4589 | 4613 | }
|
4590 | 4614 |
|
|
0 commit comments