Skip to content

Instantly share code, notes, and snippets.

@headius
Created December 2, 2019 23:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save headius/340794413b33688f78325fc6f8398f40 to your computer and use it in GitHub Desktop.
Save headius/340794413b33688f78325fc6f8398f40 to your computer and use it in GitHub Desktop.
Patch to naively synchronize RubyHash to protect direct-addressing data store
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