Skip to content

Commit

Permalink
Merge branch 'jruby-9.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Apr 12, 2018
2 parents 0cd6a92 + d6f95e1 commit 9510c6a
Show file tree
Hide file tree
Showing 2 changed files with 1,498 additions and 17 deletions.
36 changes: 19 additions & 17 deletions core/src/main/java/org/jruby/RubyClass.java
Expand Up @@ -92,6 +92,7 @@
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.CodegenUtils;
import org.jruby.util.JavaNameMangler;
import org.jruby.util.collections.ConcurrentWeakHashMap;
import org.jruby.util.collections.WeakHashSet;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
Expand Down Expand Up @@ -1100,7 +1101,7 @@ public final Collection<RubyClass> subclasses() {
}

public Collection<RubyClass> subclasses(boolean includeDescendants) {
Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses != null) {
Collection<RubyClass> mine = new ArrayList<>();
subclassesInner(mine, includeDescendants);
Expand All @@ -1111,11 +1112,12 @@ public Collection<RubyClass> subclasses(boolean includeDescendants) {
}

private void subclassesInner(Collection<RubyClass> mine, boolean includeDescendants) {
Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses != null) {
mine.addAll(subclasses);
Set<RubyClass> keys = subclasses.keySet();
mine.addAll(keys);
if (includeDescendants) {
for (RubyClass klass: subclasses) {
for (RubyClass klass: keys) {
klass.subclassesInner(mine, includeDescendants);
}
}
Expand All @@ -1132,18 +1134,18 @@ private void subclassesInner(Collection<RubyClass> mine, boolean includeDescenda
* @param subclass The subclass to add
*/
public void addSubclass(RubyClass subclass) {
Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses == null) {
// check again
synchronized (this) {
subclasses = this.subclasses;
if (subclasses == null) {
this.subclasses = subclasses = Collections.synchronizedSet(new WeakHashSet<RubyClass>(4));
this.subclasses = subclasses = new ConcurrentWeakHashMap<>(4, 0.75f, 1);
}
}
}

subclasses.add(subclass);
subclasses.put(subclass, NEVER);
}

/**
Expand All @@ -1152,7 +1154,7 @@ public void addSubclass(RubyClass subclass) {
* @param subclass The subclass to remove
*/
public void removeSubclass(RubyClass subclass) {
Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses == null) return;

subclasses.remove(subclass);
Expand All @@ -1165,20 +1167,20 @@ public void removeSubclass(RubyClass subclass) {
* @param newSubclass The subclass to replace it with
*/
public void replaceSubclass(RubyClass subclass, RubyClass newSubclass) {
Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses == null) return;

subclasses.remove(subclass);
subclasses.add(newSubclass);
subclasses.put(newSubclass, NEVER);
}

@Override
public void becomeSynchronized() {
// make this class and all subclasses sync
super.becomeSynchronized();
Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses != null) {
for (RubyClass subclass : subclasses) subclass.becomeSynchronized();
for (RubyClass subclass : subclasses.keySet()) subclass.becomeSynchronized();
}
}

Expand All @@ -1198,9 +1200,9 @@ public void becomeSynchronized() {
public void invalidateCacheDescendants() {
super.invalidateCacheDescendants();

Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
if (subclasses != null) {
for (RubyClass subclass : subclasses) subclass.invalidateCacheDescendants();
for (RubyClass subclass : subclasses.keySet()) subclass.invalidateCacheDescendants();
}
}

Expand All @@ -1211,12 +1213,12 @@ public void addInvalidatorsAndFlush(List<Invalidator> invalidators) {
// if we're not at boot time, don't bother fully clearing caches
if (!runtime.isBootingCore()) cachedMethods.clear();

Set<RubyClass> subclasses = this.subclasses;
Map<RubyClass, Object> subclasses = this.subclasses;
// no subclasses, don't bother with lock and iteration
if (subclasses == null || subclasses.isEmpty()) return;

// cascade into subclasses
for (RubyClass subclass : subclasses) subclass.addInvalidatorsAndFlush(invalidators);
for (RubyClass subclass : subclasses.keySet()) subclass.addInvalidatorsAndFlush(invalidators);
}

public final Ruby getClassRuntime() {
Expand Down Expand Up @@ -2329,7 +2331,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject self, String name,
protected final Ruby runtime;
private ObjectAllocator allocator; // the default allocator
protected ObjectMarshal marshal;
private volatile Set<RubyClass> subclasses;
private volatile Map<RubyClass, Object> subclasses;
public static final int CS_IDX_INITIALIZE = 0;
public enum CS_NAMES {
INITIALIZE("initialize");
Expand Down

0 comments on commit 9510c6a

Please sign in to comment.