Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5aecc45d35a3^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4ef1dc24a2cc
Choose a head ref
  • 4 commits
  • 12 files changed
  • 1 contributor

Commits on May 28, 2016

  1. Add a flag registry to ensure our bit flags are optimal.

    This implementation expects ancestors to register their flags
    first, ensuring they are packed tightly. The rest of the logic
    makes sure that no child overlaps any parent, and the flags are
    calculated based on the nearest flag-registering parent's last
    shift value.
    
    There's an additional piece of work here: rewrite the Constants
    class so that instead of calculating these flags at runtime, it
    just has the literal calculated flag values, so they can be
    folded into all places where they are called. See the hacky
    assertion in StringSupport for a reason why this would be better.
    
    Note that OpenJDK 7 and higher *will* fold runtime-calculated
    static final values when jitting, so performance wise this
    additional improvement would mostly just simplify javac-emitted
    bytecode and possibly improve the performance of interpreted
    bytecode *slightly*.
    headius committed May 28, 2016
    Copy the full SHA
    5aecc45 View commit details

Commits on Jun 6, 2016

  1. Work in progress.

    headius committed Jun 6, 2016
    Copy the full SHA
    fd120d5 View commit details

Commits on Jun 9, 2016

  1. Copy the full SHA
    67dfaf8 View commit details
  2. Wire up 1-obj arrays and unify some construction paths.

    This is not yet running properly.
    headius committed Jun 9, 2016
    Copy the full SHA
    4ef1dc2 View commit details
75 changes: 75 additions & 0 deletions core/src/main/java/org/jruby/FlagRegistry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.jruby;

import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;

/**
* This class serves as a registry of all bit flags we use on JRuby objects.
*
* In order to maximally use our bit flags and prevent overlap between ancestors and dependents,
* this class registers flags on a first-come, first-served basis using previous flags registered
* for ancestor classes as a base line for new flags in a descendant.
*
* Because of the first-come, first-served nature, the most general types will need to register
* their flags first. This guarantees all bit flags from the progenitor on down will be packed
* tightly while avoiding overlaps.
*/
public class FlagRegistry {
private final Map<Class, Integer> currentShift = new HashMap<>();
private final Map<Class, BitSet> registry = new HashMap<>();

/**
* Register a new flag for the given class.
*
* The bit index for the new flag will be calculated at runtime, by walking parent classes
* and looking for previously-registered flags. Ancestors should register all their flags
* before decendants (which means they should not be registered in a static initializer
* unless the parent is known to have fully run its own static initializers).
*
* @param klass the class for which to register a new flag
* @return an integer with the new flag bit set
*/
public synchronized int newFlag(Class klass) {
Class currentKlass = klass;
Integer shift = null;
while (currentKlass != null &&
(shift = currentShift.get(currentKlass)) == null) {
currentKlass = currentKlass.getSuperclass();
}
if (shift == null) shift = 0;

BitSet flags = registry.get(klass);
if (flags == null) {
flags = new BitSet();
registry.put(klass, flags);
}
flags.set(shift);

assert flagsAreValid(klass, shift);

currentShift.put(klass, shift + 1);

return 1 << shift++;
}

public synchronized void printFlags() {
System.out.println(registry);
}

private boolean flagsAreValid(Class klass, int bitIndex) {
BitSet gathered = new BitSet();
Class currentKlass = klass;
while (currentKlass != null) {
BitSet flags = registry.get(klass);
if (flags != null) {
if (flags.intersects(gathered)) {
throw new AssertionError(klass.getName() + " uses flag " + bitIndex + " that overlaps with " + currentKlass);
}
gathered.and(flags);
}
currentKlass = currentKlass.getSuperclass();
}
return true;
}
}
Loading