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: 4707f66d0324
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 786eef56d432
Choose a head ref
  • 3 commits
  • 5 files changed
  • 1 contributor

Commits on Jun 13, 2017

  1. Copy the full SHA
    e82715c View commit details
  2. Copy the full SHA
    eb64b9a View commit details
  3. Copy the full SHA
    786eef5 View commit details
22 changes: 19 additions & 3 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -56,15 +56,13 @@
import org.jruby.ir.IRScope;
import org.jruby.ir.IRScriptBody;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.targets.Bootstrap;
import org.jruby.javasupport.JavaSupport;
import org.jruby.javasupport.JavaSupportImpl;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.invokedynamic.InvokeDynamicSupport;
import org.jruby.util.MRIRecursionGuard;
import org.jruby.util.invoke.MethodHandles;
import org.jruby.util.invoke.MethodType;
import org.objectweb.asm.util.TraceClassVisitor;

import jnr.constants.Constant;
@@ -4648,6 +4646,19 @@ public DynamicMethod getBaseNewMethod() {
return baseNewMethod;
}

/**
* Get the "nullToNil" method handle filter for this runtime.
*
* @return a method handle suitable for filtering a single IRubyObject value from null to nil
*/
public Object getNullToNilHandle() {
Object nullToNil = this.nullToNil;

if (nullToNil != null) return nullToNil;

return this.nullToNil = Bootstrap.createNullToNilHandle(this);
}

// Parser stats methods
private void addLoadParseToStats() {
if (parserStats != null) parserStats.addLoadParse();
@@ -5105,6 +5116,11 @@ public void addToObjectSpace(boolean useObjectSpace, IRubyObject object) {
*/
private DynamicMethod baseNewMethod;

/**
* The nullToNil filter for this runtime.
*/
private Object nullToNil;

public final org.jruby.util.collections.ClassValue<TypePopulator> POPULATORS = new MapBasedClassValue<TypePopulator>(new ClassValueCalculator<TypePopulator>() {
@Override
public TypePopulator computeValue(Class<?> type) {
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -300,6 +300,12 @@ public void addIncludingHierarchy(IncludedModule hierarchy) {
}
}

public Object getIdTest() {
Object idTest = this.idTest;
if (idTest != null) return idTest;
return this.idTest = Bootstrap.createIdTest(this);
}

/** separate path for MetaClass construction
*
*/
@@ -4495,7 +4501,7 @@ public IRubyObject initialize(Block block) {
* Pre-built test that takes ThreadContext, IRubyObject and checks that the object is a module with the
* same ID as this one.
*/
private MethodHandle idTest;
private Object idTest;

/**
* The class/module within whose namespace this class/module resides.
31 changes: 23 additions & 8 deletions core/src/main/java/org/jruby/ir/targets/Bootstrap.java
Original file line number Diff line number Diff line change
@@ -23,10 +23,7 @@
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.invokedynamic.GlobalSite;
import org.jruby.runtime.invokedynamic.InvocationLinker;
import org.jruby.runtime.invokedynamic.MathLinker;
import org.jruby.runtime.invokedynamic.VariableSite;
import org.jruby.runtime.invokedynamic.*;
import org.jruby.runtime.ivars.FieldVariableAccessor;
import org.jruby.runtime.ivars.VariableAccessor;
import org.jruby.runtime.opto.Invalidator;
@@ -664,10 +661,7 @@ public static IRubyObject ivarGet(VariableSite site, IRubyObject self) throws Th
VariableAccessor accessor = realClass.getVariableAccessorForRead(site.name());

// produce nil if the variable has not been initialize
IRubyObject nilObject = self.getRuntime().getNil();
MethodHandle nullToNil = lookup().findStatic(Helpers.class, "nullToNil", methodType(IRubyObject.class, IRubyObject.class, IRubyObject.class));
nullToNil = MethodHandles.insertArguments(nullToNil, 1, nilObject);
nullToNil = explicitCastArguments(nullToNil, methodType(IRubyObject.class, Object.class));
MethodHandle nullToNil = (MethodHandle) self.getRuntime().getNullToNilHandle();

// get variable value and filter with nullToNil
MethodHandle getValue;
@@ -1022,4 +1016,25 @@ public static Binding selfBinding(ThreadContext context, IRubyObject self, Dynam
public static Block constructBlock(Binding binding, CompiledIRBlockBody body) throws Throwable {
return new Block(body, binding);
}

/* Not the best place for this but better than tying Ruby to indy. */
public static Object createNullToNilHandle(Ruby runtime) {
IRubyObject nilObject = runtime.getNil();
MethodHandle nullToNil = Binder.from(IRubyObject.class, IRubyObject.class)
.append(nilObject)
.invokeStaticQuiet(lookup(), Helpers.class, "nullToNil");

return nullToNil;
}

/* Not the best place for this but better than tying RubyModule to indy. */
public static Object createIdTest(RubyModule module) {
return Binder.from(boolean.class, ThreadContext.class, IRubyObject.class)
.insert(2, module.id)
.invoke(testModuleMatch);
}

private static final MethodHandle testModuleMatch = Binder
.from(boolean.class, ThreadContext.class, IRubyObject.class, int.class)
.invokeStaticQuiet(LOOKUP, Bootstrap.class, "testModuleMatch");
}
10 changes: 1 addition & 9 deletions core/src/main/java/org/jruby/ir/targets/ConstantLookupSite.java
Original file line number Diff line number Diff line change
@@ -248,15 +248,7 @@ private void bind(Ruby runtime, RubyModule module, IRubyObject constant, MethodH
MethodHandle fallback = getFallback(module, cachingFallback);

// Test that module is same as before
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle testModuleMatch = null;
try {
testModuleMatch = lookup.findStatic(Bootstrap.class, "testModuleMatch", MethodType.methodType(boolean.class, ThreadContext.class, IRubyObject.class, int.class));
} catch (NoSuchMethodException | IllegalAccessException e) {
e.printStackTrace();
}
MethodHandle idTest = MethodHandles.insertArguments(testModuleMatch, 2, module.id);
target = guardWithTest(idTest, target, fallback);
target = guardWithTest((MethodHandle) module.getIdTest(), target, fallback);

// Global invalidation
SwitchPoint switchPoint = (SwitchPoint) runtime.getConstantInvalidator(name).getData();
14 changes: 0 additions & 14 deletions core/src/main/java/org/jruby/runtime/BlockBody.java
Original file line number Diff line number Diff line change
@@ -50,7 +50,6 @@
public abstract class BlockBody {

protected final Signature signature;
// protected volatile MethodHandle testBlockBody;

public BlockBody(Signature signature) {
this.signature = signature;
@@ -72,19 +71,6 @@ public boolean canCallDirect() {
return false;
}

// public MethodHandle getTestBlockBody() {
// final MethodHandle testBlockBody = this.testBlockBody;
// if (testBlockBody != null) return testBlockBody;
//
// return this.testBlockBody = Binder.from(boolean.class, ThreadContext.class, Block.class).drop(0).append(this).invoke(TEST_BLOCK_BODY);
// }
//
// private static final MethodHandle TEST_BLOCK_BODY = Binder.from(boolean.class, Block.class, BlockBody.class).invokeStaticQuiet(MethodHandles.lookup(), BlockBody.class, "testBlockBody");

public static boolean testBlockBody(Block block, BlockBody body) {
return block.getBody() == body;
}

protected IRubyObject callDirect(ThreadContext context, Block block, IRubyObject[] args, Block blockArg) {
throw new RuntimeException("callDirect not implemented in base class. We should never get here.");
}