Created
December 2, 2019 23:11
-
-
Save headius/340794413b33688f78325fc6f8398f40 to your computer and use it in GitHub Desktop.
Patch to naively synchronize RubyHash to protect direct-addressing data store
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/core/src/main/java/org/jruby/RubyHash.java b/core/src/main/java/org/jruby/RubyHash.java | |
index 231971b6be..a17a473e0a 100644 | |
--- a/core/src/main/java/org/jruby/RubyHash.java | |
+++ b/core/src/main/java/org/jruby/RubyHash.java | |
@@ -697,7 +697,7 @@ public class RubyHash extends RubyObject implements Map { | |
IRubyObject otherKey = entryKey(entries, index); | |
int otherHash = hashes[index]; | |
- if (internalKeyExist(key, hash, otherKey, otherHash)) return bin; | |
+ if (internalKeyExist(key, hash, otherKey, otherHash, isComparedByIdentity())) return bin; | |
} | |
bin = secondaryBucketIndex(bin, bins.length); | |
@@ -728,7 +728,7 @@ public class RubyHash extends RubyObject implements Map { | |
set(entries, index, null, null); | |
} | |
- private final int internalGetIndexLinearSearch(final int hash, final IRubyObject key) { | |
+ private synchronized final int internalGetIndexLinearSearch(final int hash, final IRubyObject key) { | |
long extents = this.extents; | |
int start = START(extents); | |
int end = END(extents); | |
@@ -741,7 +741,7 @@ public class RubyHash extends RubyObject implements Map { | |
int otherHash = hashes[i]; | |
- if (internalKeyExist(key, hash, otherKey, otherHash)) return i; | |
+ if (internalKeyExist(key, hash, otherKey, otherHash, isComparedByIdentity())) return i; | |
} | |
return EMPTY_BIN; | |
} | |
@@ -770,8 +770,8 @@ public class RubyHash extends RubyObject implements Map { | |
return internalGetEntry(key); | |
} | |
- private boolean internalKeyExist(IRubyObject key, int hash, IRubyObject otherKey, int otherHash) { | |
- return (hash == otherHash && (key == otherKey || (!isComparedByIdentity() && key.eql(otherKey)))); | |
+ private static boolean internalKeyExist(IRubyObject key, int hash, IRubyObject otherKey, int otherHash, boolean identity) { | |
+ return (hash == otherHash && (key == otherKey || (!identity && key.eql(otherKey)))); | |
} | |
// delete implementation | |
@@ -793,7 +793,7 @@ public class RubyHash extends RubyObject implements Map { | |
return internalDelete(hashValue(key), MATCH_ENTRY, key, value); | |
} | |
- private final IRubyObject internalDeleteOpenAddressing(final int hash, final EntryMatchType matchType, final IRubyObject key, final IRubyObject value) { | |
+ private synchronized final IRubyObject internalDeleteOpenAddressing(final int hash, final EntryMatchType matchType, final IRubyObject key, final IRubyObject value) { | |
int[] bins = this.bins; | |
int bin = bucketIndex(hash, bins.length); | |
@@ -824,7 +824,7 @@ public class RubyHash extends RubyObject implements Map { | |
return null; // no entry found | |
} | |
- private final IRubyObject internalDeleteLinearSearch(final EntryMatchType matchType, final IRubyObject key, final IRubyObject value) { | |
+ private synchronized final IRubyObject internalDeleteLinearSearch(final EntryMatchType matchType, final IRubyObject key, final IRubyObject value) { | |
long extents = this.extents; | |
int start = START(extents); | |
int end = END(extents); | |
@@ -946,7 +946,7 @@ public class RubyHash extends RubyObject implements Map { | |
visitLimited(context, visitor, -1, state); | |
} | |
- private <T> void visitLimited(ThreadContext context, VisitorWithState visitor, long size, T state) { | |
+ private synchronized <T> void visitLimited(ThreadContext context, VisitorWithState visitor, long size, T state) { | |
int startGeneration = generation; | |
long count = size; | |
int index = 0; | |
@@ -977,7 +977,7 @@ public class RubyHash extends RubyObject implements Map { | |
if (count > 0) throw concurrentModification(); | |
} | |
- public <T> boolean allSymbols() { | |
+ public synchronized <T> boolean allSymbols() { | |
int startGeneration = generation; | |
long extents = this.extents; | |
@@ -1243,7 +1243,7 @@ public class RubyHash extends RubyObject implements Map { | |
return this; | |
} | |
- private void rehashOpenAddressing() { | |
+ private synchronized void rehashOpenAddressing() { | |
IRubyObject[] entries = this.entries; | |
IRubyObject[] newEntries = new IRubyObject[entries.length]; | |
@@ -1274,7 +1274,7 @@ public class RubyHash extends RubyObject implements Map { | |
// cannot be non-EMPTY_BIN and not contain a valid newEntry. | |
IRubyObject otherKey = entryKey(newEntries, index); | |
int otherHash = newHashes[index]; | |
- if (internalKeyExist(key, hash, otherKey, otherHash)) { | |
+ if (internalKeyExist(key, hash, otherKey, otherHash, isComparedByIdentity())) { | |
// exists, we do not need to add this key | |
exists = true; | |
break; | |
@@ -1298,7 +1298,7 @@ public class RubyHash extends RubyObject implements Map { | |
this.setExtents(0, size = newIndex); | |
} | |
- private void rehashLinearSearch() { | |
+ private synchronized void rehashLinearSearch() { | |
IRubyObject[] entries = this.entries; | |
int[] hashes = this.hashes; | |
@@ -1319,7 +1319,7 @@ public class RubyHash extends RubyObject implements Map { | |
for(int j = 0; j < i; j++) { | |
int otherHash = hashes[j]; | |
IRubyObject otherKey = entryKey(newEntries, j); | |
- if (internalKeyExist(key, newHash, otherKey, otherHash)) { | |
+ if (internalKeyExist(key, newHash, otherKey, otherHash, isComparedByIdentity())) { | |
exists = true; | |
break; | |
} | |
@@ -2044,7 +2044,7 @@ public class RubyHash extends RubyObject implements Map { | |
* | |
*/ | |
@JRubyMethod(name = "shift") | |
- public IRubyObject shift(ThreadContext context) { | |
+ public synchronized IRubyObject shift(ThreadContext context) { | |
modify(); | |
long extents = this.extents; | |
@@ -2417,7 +2417,7 @@ public class RubyHash extends RubyObject implements Map { | |
} | |
@JRubyMethod(name = "compact!") | |
- public IRubyObject compact_bang(ThreadContext context) { | |
+ public synchronized IRubyObject compact_bang(ThreadContext context) { | |
boolean changed = false; | |
modify(); | |
iteratorEntry(); | |
@@ -2485,7 +2485,7 @@ public class RubyHash extends RubyObject implements Map { | |
return any_p_i(context, block); | |
} | |
- private IRubyObject any_p_i(ThreadContext context, Block block) { | |
+ private synchronized IRubyObject any_p_i(ThreadContext context, Block block) { | |
iteratorEntry(); | |
try { | |
long extents = this.extents; | |
@@ -2508,7 +2508,7 @@ public class RubyHash extends RubyObject implements Map { | |
} | |
} | |
- private IRubyObject any_p_i_fast(ThreadContext context, Block block) { | |
+ private synchronized IRubyObject any_p_i_fast(ThreadContext context, Block block) { | |
iteratorEntry(); | |
try { | |
long extents = this.extents; | |
@@ -2530,7 +2530,7 @@ public class RubyHash extends RubyObject implements Map { | |
} | |
} | |
- private IRubyObject any_p_p(ThreadContext context, IRubyObject pattern) { | |
+ private synchronized IRubyObject any_p_p(ThreadContext context, IRubyObject pattern) { | |
iteratorEntry(); | |
try { | |
long extents = this.extents; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment