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: 23568373b59c
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7d22b206f6d7
Choose a head ref
  • 19 commits
  • 17 files changed
  • 1 contributor

Commits on Sep 23, 2016

  1. Remove premade field-based DynamicScope and generate instead.

    Instead of having hand-written DynamicScope subtypes that use
    fields instead of an array, this logic generates those subclasses
    as needed.
    
    Currently it only overrides the base getValue and setValue methods
    and DynamicScope now implements the other previously-abstract
    methods by calling those two. This is not optimal for generic
    access via those indexed methods, but the expectation is that JIT
    can just go after the fields directly. The additional overrides
    would likely be useful for the interpreter, though.
    
    See #4167.
    headius committed Sep 23, 2016
    Copy the full SHA
    c9370c2 View commit details
  2. Copy the full SHA
    2403780 View commit details
  3. Copy the full SHA
    6049fe1 View commit details

Commits on Sep 27, 2016

  1. Copy the full SHA
    838fd07 View commit details
  2. Copy the full SHA
    eb890dc View commit details

Commits on Sep 28, 2016

  1. Expand specialization of generated DynamicScope.

    * Get and set of depth zero, offset = 0..9
    * Flip override of sets to void versions
    * Add test for the key methods
    headius committed Sep 28, 2016
    Copy the full SHA
    8a7f32a View commit details
  2. Copy the full SHA
    2dffd52 View commit details
  3. Copy the full SHA
    496c133 View commit details
  4. Tweaks to DynScope generation.

    * Limit specialized subclasses to 50 wide.
    * Move to a generator class.
    * Cache construction logic to StaticScope.
    * Cache constructor in StaticScope.
    * Reduce duplication in code gen.
    * Move offset error to a shared method in generated classes.
    * Use a single OneShotClassLoader since we never dereference.
    * Misc perf, style tweaks.
    headius committed Sep 28, 2016
    Copy the full SHA
    ccf3743 View commit details
  5. Copy the full SHA
    f261580 View commit details
  6. Copy the full SHA
    60241ad View commit details

Commits on Sep 29, 2016

  1. Copy the full SHA
    8ce1238 View commit details
  2. Clean up set code a bit.

    headius committed Sep 29, 2016
    Copy the full SHA
    380e42a View commit details
  3. Copy the full SHA
    b561339 View commit details
  4. Copy the full SHA
    1b657df View commit details
  5. Copy the full SHA
    06a0d8b View commit details
  6. Update for jitescript 4.1.

    headius committed Sep 29, 2016
    Copy the full SHA
    1a7d10a View commit details
  7. Copy the full SHA
    3156979 View commit details

Commits on Sep 30, 2016

  1. Use jitescript 0.4.1.

    headius committed Sep 30, 2016
    Copy the full SHA
    7d22b20 View commit details
5 changes: 4 additions & 1 deletion core/pom.rb
Original file line number Diff line number Diff line change
@@ -79,6 +79,8 @@
jar 'org.slf4j:slf4j-api:1.7.12', :scope => 'provided', :optional => true
jar 'org.slf4j:slf4j-simple:1.7.12', :scope => 'test'

jar 'me.qmx.jitescript:jitescript:0.4.1', :exclusions => ['org.ow2.asm:asm-all']

plugin_management do
plugin( 'org.eclipse.m2e:lifecycle-mapping:1.0.0',
'lifecycleMappingMetadata' => {
@@ -231,7 +233,8 @@
'argLine' => '-Xmx${jruby.test.memory} -XX:MaxPermSize=${jruby.test.memory.permgen} -Dfile.encoding=UTF-8 -Djava.awt.headless=true',
'includes' => [ 'org/jruby/test/MainTestSuite.java',
'org/jruby/embed/**/*Test*.java',
'org/jruby/util/**/*Test*.java' ],
'org/jruby/util/**/*Test*.java',
'org/jruby/runtime/**/*Test*.java' ],
'additionalClasspathElements' => [ '${basedir}/src/test/ruby' ] )

build do
12 changes: 12 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -276,6 +276,17 @@ DO NOT MODIFIY - GENERATED CODE
<version>1.7.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>me.qmx.jitescript</groupId>
<artifactId>jitescript</artifactId>
<version>0.4.1</version>
<exclusions>
<exclusion>
<artifactId>asm-all</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<defaultGoal>package</defaultGoal>
@@ -595,6 +606,7 @@ DO NOT MODIFIY - GENERATED CODE
<include>org/jruby/test/MainTestSuite.java</include>
<include>org/jruby/embed/**/*Test*.java</include>
<include>org/jruby/util/**/*Test*.java</include>
<include>org/jruby/runtime/**/*Test*.java</include>
</includes>
<additionalClasspathElements>
<additionalClasspathElement>${basedir}/src/test/ruby</additionalClasspathElement>
Original file line number Diff line number Diff line change
@@ -567,7 +567,7 @@ protected static void setResult(Object[] temp, DynamicScope currDynScope, Variab
temp[((TemporaryLocalVariable)resultVar).offset] = result;
} else {
LocalVariable lv = (LocalVariable)resultVar;
currDynScope.setValue((IRubyObject) result, lv.getLocation(), lv.getScopeDepth());
currDynScope.setValueVoid((IRubyObject) result, lv.getLocation(), lv.getScopeDepth());
}
}

129 changes: 39 additions & 90 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
import org.jruby.runtime.*;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.RefinedCachingCallSite;
import org.jruby.runtime.scope.DynamicScopeGenerator;
import org.jruby.util.ByteList;
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.JavaNameMangler;
@@ -392,41 +393,11 @@ private org.objectweb.asm.Label getJVMLabel(Label label) {

private void jvmStoreLocal(Variable variable) {
if (variable instanceof LocalVariable) {

LocalVariable localvariable = (LocalVariable) variable;

jvmLoadLocal(DYNAMIC_SCOPE);

jvmAdapter().swap();

if (localvariable.getScopeDepth() == 0) {

switch (localvariable.getOffset()) {
case 0:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueZeroDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
case 1:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueOneDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
case 2:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueTwoDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
case 3:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueThreeDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
default:
jvmAdapter().ldc(localvariable.getOffset());
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueDepthZeroVoid", sig(void.class, IRubyObject.class, int.class));
break;
}

} else {

jvmAdapter().ldc(localvariable.getOffset());
jvmAdapter().ldc(localvariable.getScopeDepth());
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueVoid", sig(void.class, IRubyObject.class, int.class, int.class));

}
genSetValue((LocalVariable) variable);
} else if (variable instanceof TemporaryLocalVariable) {
switch (((TemporaryLocalVariable)variable).getType()) {
case FLOAT: jvmAdapter().dstore(getJVMLocalVarIndex(variable)); break;
@@ -441,44 +412,11 @@ private void jvmStoreLocal(Variable variable) {

private void jvmStoreLocal(Runnable source, Variable variable) {
if (variable instanceof LocalVariable) {

LocalVariable localvariable = (LocalVariable) variable;

jvmLoadLocal(DYNAMIC_SCOPE);

if (localvariable.getScopeDepth() == 0) {

source.run();

switch (localvariable.getOffset()) {
case 0:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueZeroDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
case 1:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueOneDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
case 2:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueTwoDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
case 3:
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueThreeDepthZeroVoid", sig(void.class, IRubyObject.class));
break;
default:
jvmAdapter().ldc(localvariable.getOffset());
jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueDepthZeroVoid", sig(void.class, IRubyObject.class, int.class));
break;
}

} else {

source.run();

jvmAdapter().ldc(localvariable.getOffset());
jvmAdapter().ldc(localvariable.getScopeDepth());

jvmAdapter().invokevirtual(p(DynamicScope.class), "setValueVoid", sig(void.class, IRubyObject.class, int.class, int.class));
source.run();

}
genSetValue((LocalVariable) variable);
} else if (variable instanceof TemporaryLocalVariable) {
source.run();

@@ -495,6 +433,27 @@ private void jvmStoreLocal(Runnable source, Variable variable) {
}
}

private void genSetValue(LocalVariable localvariable) {
int depth = localvariable.getScopeDepth();
int location = localvariable.getLocation();

String baseName = p(DynamicScope.class);

if (depth == 0) {
if (location < DynamicScopeGenerator.SPECIALIZED_SETS.size()) {
jvmAdapter().invokevirtual(baseName, DynamicScopeGenerator.SPECIALIZED_SETS.get(location), sig(void.class, IRubyObject.class));
} else {
jvmAdapter().pushInt(location);
jvmAdapter().invokevirtual(baseName, "setValueDepthZeroVoid", sig(void.class, IRubyObject.class, int.class));
}
} else {
jvmAdapter().pushInt(location);
jvmAdapter().pushInt(depth);

jvmAdapter().invokevirtual(baseName, "setValueVoid", sig(void.class, IRubyObject.class, int.class, int.class));
}
}

private void jvmStoreLocal(String specialVar) {
jvmMethod().storeLocal(getJVMLocalVarIndex(specialVar));
}
@@ -2363,33 +2322,23 @@ public void Hash(Hash hash) {
@Override
public void LocalVariable(LocalVariable localvariable) {
IRBytecodeAdapter m = jvmMethod();
jvmLoadLocal(DYNAMIC_SCOPE);

int depth = localvariable.getScopeDepth();
int location = localvariable.getLocation();
OUTER: switch (depth) {
case 0:
switch (location) {
case 0:
m.adapter.invokevirtual(p(DynamicScope.class), "getValueZeroDepthZero", sig(IRubyObject.class));
break OUTER;
case 1:
m.adapter.invokevirtual(p(DynamicScope.class), "getValueOneDepthZero", sig(IRubyObject.class));
break OUTER;
case 2:
m.adapter.invokevirtual(p(DynamicScope.class), "getValueTwoDepthZero", sig(IRubyObject.class));
break OUTER;
case 3:
m.adapter.invokevirtual(p(DynamicScope.class), "getValueThreeDepthZero", sig(IRubyObject.class));
break OUTER;
default:
m.adapter.pushInt(location);
m.adapter.invokevirtual(p(DynamicScope.class), "getValueDepthZero", sig(IRubyObject.class, int.class));
break OUTER;
}
default:

jvmLoadLocal(DYNAMIC_SCOPE);

if (depth == 0) {
if (location < DynamicScopeGenerator.SPECIALIZED_GETS.size()) {
m.adapter.invokevirtual(p(DynamicScope.class), DynamicScopeGenerator.SPECIALIZED_GETS.get(location), sig(IRubyObject.class));
} else {
m.adapter.pushInt(location);
m.adapter.pushInt(depth);
m.adapter.invokevirtual(p(DynamicScope.class), "getValue", sig(IRubyObject.class, int.class, int.class));
m.adapter.invokevirtual(p(DynamicScope.class), "getValueDepthZero", sig(IRubyObject.class, int.class));
}
} else {
m.adapter.pushInt(location);
m.adapter.pushInt(depth);
m.adapter.invokevirtual(p(DynamicScope.class), "getValue", sig(IRubyObject.class, int.class, int.class));
}
}

45 changes: 42 additions & 3 deletions core/src/main/java/org/jruby/parser/StaticScope.java
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@
package org.jruby.parser;

import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;

import org.jruby.RubyModule;
@@ -45,10 +47,12 @@
import org.jruby.ir.IRScopeType;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.Signature;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.scope.DummyDynamicScope;
import org.jruby.runtime.scope.DynamicScopeGenerator;
import org.jruby.runtime.scope.ManyVarsDynamicScope;

/**
* StaticScope represents lexical scoping of variables and module/class constants.
@@ -62,7 +66,9 @@
*
*/
public class StaticScope implements Serializable {
private static final int MAX_SPECIALIZED_SIZE = 50;
private static final long serialVersionUID = 3423852552352498148L;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.publicLookup();

// Next immediate scope. Variable and constant scoping rules make use of this variable
// in different ways.
@@ -77,6 +83,8 @@ public class StaticScope implements Serializable {
// Our name holder (offsets are assigned as variables are added)
private String[] variableNames;

private int variableNamesLength;

// A list of booleans indicating which variables are named captures from regexp
private boolean[] namedCaptures;

@@ -106,6 +114,8 @@ public class StaticScope implements Serializable {

private RubyModule overlayModule;

private MethodHandle constructor;

public enum Type {
LOCAL, BLOCK, EVAL;

@@ -148,6 +158,7 @@ protected StaticScope(Type type, StaticScope enclosingScope, String[] names, int

this.enclosingScope = enclosingScope;
this.variableNames = names;
this.variableNamesLength = names.length;
this.type = type;
this.irScope = null;
this.isBlockOrEval = (type != Type.LOCAL);
@@ -164,6 +175,32 @@ public int getFirstKeywordIndex() {
return firstKeywordIndex;
}

public DynamicScope construct(DynamicScope parent) {
MethodHandle constructor = this.constructor;

if (constructor == null) constructor = acquireConstructor();

try {
return (DynamicScope) constructor.invokeExact(this, parent);
} catch (Throwable e) {
Helpers.throwException(e);
return null; // not reached
}
}

private MethodHandle acquireConstructor() {
MethodHandle constructor;
int numberOfVariables = getNumberOfVariables();

if (numberOfVariables > MAX_SPECIALIZED_SIZE) {
constructor = ManyVarsDynamicScope.CONSTRUCTOR;
} else {
constructor = DynamicScopeGenerator.generate(numberOfVariables);
}
this.constructor = constructor;
return constructor;
}

public IRScope getIRScope() {
return irScope;
}
@@ -260,14 +297,15 @@ public String[] getVariables() {
}

public int getNumberOfVariables() {
return variableNames.length;
return variableNamesLength;
}

public void setVariables(String[] names) {
assert names != null : "names is not null";
assert namesAreInterned(names);

variableNames = new String[names.length];
variableNamesLength = names.length;
System.arraycopy(names, 0, variableNames, 0, names.length);
}

@@ -563,7 +601,7 @@ public void setSignature(Signature signature) {
}

public DynamicScope getDummyScope() {
return dummyScope == null ? dummyScope = new DummyDynamicScope(this) : dummyScope;
return dummyScope == null ? dummyScope = DynamicScope.newDynamicScope(this) : dummyScope;
}

public void setCommandArgumentStack(long commandArgumentStack) {
@@ -579,6 +617,7 @@ private void growVariableNames(String name) {
String[] newVariableNames = new String[variableNames.length + 1];
System.arraycopy(variableNames, 0, newVariableNames, 0, variableNames.length);
variableNames = newVariableNames;
variableNamesLength = newVariableNames.length;
variableNames[variableNames.length - 1] = name;
}

8 changes: 1 addition & 7 deletions core/src/main/java/org/jruby/runtime/Binding.java
Original file line number Diff line number Diff line change
@@ -34,12 +34,10 @@

import org.jruby.Ruby;
import org.jruby.RubyBasicObject;
import org.jruby.parser.StaticScopeFactory;
import org.jruby.runtime.backtrace.BacktraceElement;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.scope.ManyVarsDynamicScope;
import org.jruby.runtime.scope.NoVarsDynamicScope;

/**
* Internal live representation of a block ({...} or do ... end).
@@ -51,11 +49,7 @@ public class Binding {
RubyBasicObject.NEVER,
// Can't use Frame.DUMMY because of circular static init seeing it before it's assigned
new Frame(),
Visibility.PUBLIC,
new NoVarsDynamicScope(StaticScopeFactory.newStaticScope(null, StaticScope.Type.BLOCK, null)),
"<dummy>",
"dummy",
-1);
Visibility.PUBLIC);

/**
* frame of method which defined this block
Loading