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

Commits on Mar 21, 2018

  1. Begin collapsing BlockBody logic.

    This commit does a few things:
    
    * IR blocks and their mechanisms for invoking are isolated from
    other BlockBody, since none of them implement those mechanisms.
    * Some BlockBody signatures have been condensed, favoring ones
      that always pass blockArg in.
    * All IR final dispatch targets feed into invoke or one of two
      direct invoke forms. The other paths will be reorganized and
      ideally turned into IR operations.
    headius committed Mar 21, 2018
    Copy the full SHA
    284ae60 View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    headius Charles Oliver Nutter
    Copy the full SHA
    3d53daf View commit details
  3. Copy the full SHA
    f1a357e View commit details
22 changes: 18 additions & 4 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -2005,9 +2005,7 @@ public IRubyObject defineMethodFromBlock(ThreadContext context, IRubyObject arg0
}
}

RubyProc proc = runtime.newProc(block.cloneForMethod());

newMethod = createProcMethod(name, visibility, proc);
newMethod = createProcMethod(name, visibility, block);

Helpers.addInstanceMethod(this, name, newMethod, visibility, context, runtime);

@@ -2062,14 +2060,30 @@ public IRubyObject define_method(ThreadContext context, IRubyObject[] args, Bloc
}

private DynamicMethod createProcMethod(String name, Visibility visibility, RubyProc proc) {
Block block = proc.getBlock().toLambda();
proc = proc.toLambda();
Block block = proc.getBlock();

prepBlockForMethod(block, name);

return new ProcMethod(this, proc, visibility, name);
}

private void prepBlockForMethod(Block block, String name) {
block.getBinding().getFrame().setKlazz(this);
block.getBinding().getFrame().setName(name);
block.getBinding().setMethod(name);

// various instructions can tell this scope is not an ordinary block but a block representing
// a method definition.
block.getBody().getStaticScope().makeArgumentScope();
}

private DynamicMethod createProcMethod(String name, Visibility visibility, Block block) {
block = block.cloneForMethod();

prepBlockForMethod(block, name);

RubyProc proc = RubyProc.newProc(getRuntime(), block);

return new ProcMethod(this, proc, visibility, name);
}
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/RubyProc.java
Original file line number Diff line number Diff line change
@@ -87,6 +87,11 @@ public static RubyProc newProc(Ruby runtime, Block block, String file, int line)
return proc;
}

public RubyProc toLambda() {
Ruby runtime = getRuntime();
return new RubyProc(runtime, runtime.getProc(), block.toLambda());
}

public static RubyClass createProcClass(Ruby runtime) {
RubyClass procClass = runtime.defineClass("Proc", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
runtime.setProc(procClass);
13 changes: 1 addition & 12 deletions core/src/main/java/org/jruby/RubySymbol.java
Original file line number Diff line number Diff line change
@@ -62,7 +62,6 @@
import org.jruby.util.ByteList;
import org.jruby.util.PerlHash;
import org.jruby.util.SipHashInline;
import org.jruby.util.StringSupport;

import java.lang.ref.WeakReference;
import java.util.concurrent.locks.ReentrantLock;
@@ -1074,20 +1073,10 @@ public IRubyObject yield(ThreadContext context, Block block, IRubyObject[] args,
}

@Override
public IRubyObject yield(ThreadContext context, Block block, IRubyObject value, Block blockArg) {
public IRubyObject yield(ThreadContext context, Block block, IRubyObject value, IRubyObject self, Block blockArg) {
return yieldInner(context, ArgsUtil.convertToRubyArray(context.runtime, value, false), blockArg);
}

@Override
protected IRubyObject doYield(ThreadContext context, Block block, IRubyObject value) {
return yieldInner(context, ArgsUtil.convertToRubyArray(context.runtime, value, false), Block.NULL_BLOCK);
}

@Override
protected IRubyObject doYield(ThreadContext context, Block block, IRubyObject[] args, IRubyObject self) {
return yieldInner(context, RubyArray.newArrayMayCopy(context.runtime, args), Block.NULL_BLOCK);
}

@Override
public IRubyObject yieldSpecific(ThreadContext context, Block block, IRubyObject arg0) {
return site.call(context, arg0, arg0);
19 changes: 7 additions & 12 deletions core/src/main/java/org/jruby/ext/set/RubySet.java
Original file line number Diff line number Diff line change
@@ -254,18 +254,12 @@ public IRubyObject yield(ThreadContext context, IRubyObject[] args) {
return yieldImpl(context, args[0]);
}

abstract IRubyObject yieldImpl(ThreadContext context, IRubyObject val) ;

@Override
protected final IRubyObject doYield(ThreadContext context, Block block, IRubyObject[] args, IRubyObject self) {
public IRubyObject yield(ThreadContext context, Block block, IRubyObject[] args, IRubyObject self, Block blockArg) {
return yieldImpl(context, args[0]);
}

@Override
protected final IRubyObject doYield(ThreadContext context, Block block, IRubyObject value) {
return yieldImpl(context, value); // avoid new IRubyObject[] { value }
}

abstract IRubyObject yieldImpl(ThreadContext context, IRubyObject val);
}

@JRubyMethod
@@ -994,13 +988,14 @@ private IRubyObject divideTSort(ThreadContext context, final Block block) {
new JavaInternalBlockBody(runtime, Signature.ONE_REQUIRED) {
@Override
public IRubyObject yield(ThreadContext context, IRubyObject[] args) {
return doYield(context, null, args[0]);
// set.add( self.class.new(css) ) :
set.addImpl(runtime, RubySet.this.newSet(context, Set, (RubyArray) args[0]));
return context.nil;
}

@Override
protected IRubyObject doYield(ThreadContext context, Block block, IRubyObject css) {
// set.add( self.class.new(css) ) :
set.addImpl(runtime, RubySet.this.newSet(context, Set, (RubyArray) css));
public IRubyObject yield(ThreadContext context, Block block, IRubyObject[] args, IRubyObject self, Block blockArg) {
set.addImpl(runtime, RubySet.this.newSet(context, Set, (RubyArray) args[0]));
return context.nil;
}
})
14 changes: 8 additions & 6 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -82,6 +82,8 @@
import org.jruby.util.log.LoggerFactory;
import org.objectweb.asm.Type;

import static org.jruby.runtime.Helpers.arrayOf;

public class IRRuntimeHelpers {
private static final Logger LOG = LoggerFactory.getLogger(IRRuntimeHelpers.class);

@@ -465,28 +467,28 @@ public static IRubyObject[] convertValueIntoArgArray(ThreadContext context, IRub

switch (signature.arityValue()) {
case -1 :
return argIsArray || (signature.opt() > 1 && value instanceof RubyArray) ? ((RubyArray)value).toJavaArray() : new IRubyObject[] { value };
case 0 : return new IRubyObject[] { value };
return argIsArray || (signature.opt() > 1 && value instanceof RubyArray) ? ((RubyArray)value).toJavaArray() : arrayOf(value);
case 0 : return arrayOf(value);
case 1 : {
if (argIsArray) {
RubyArray valArray = ((RubyArray)value);
if (valArray.size() == 0) {
value = RubyArray.newEmptyArray(context.runtime);
}
}
return new IRubyObject[] { value };
return arrayOf(value);
}
default :
if (argIsArray) {
RubyArray valArray = (RubyArray)value;
if (valArray.size() == 1) value = valArray.eltInternal(0);
value = Helpers.aryToAry(context, value);
return (value instanceof RubyArray) ? ((RubyArray)value).toJavaArray() : new IRubyObject[] { value };
return (value instanceof RubyArray) ? ((RubyArray)value).toJavaArray() : arrayOf(value);
} else {
IRubyObject val0 = Helpers.aryToAry(context, value);
// FIXME: This logic exists in RubyProc and IRRubyBlockBody. consolidate when we do block call protocol work
if (val0.isNil()) {
return new IRubyObject[] { value };
return arrayOf(value);
} else if (!(val0 instanceof RubyArray)) {
throw context.runtime.newTypeError(value.getType().getName() + "#to_ary should return Array");
} else {
@@ -1945,7 +1947,7 @@ public static IRubyObject[] singleBlockArgToArray(IRubyObject value) {
if (value instanceof RubyArray) {
args = value.convertToArray().toJavaArray();
} else {
args = new IRubyObject[] { value };
args = arrayOf(value);
}
return args;
}
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.UndefinedValue;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallType;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
@@ -167,10 +168,11 @@ public void loadSuperName() {
}

public void loadBlockType() {
if (signature.argOffset("type") == -1) {
if (signature.argOffset("selfBlock") == -1) {
adapter.aconst_null();
} else {
adapter.aload(signature.argOffset("type"));
adapter.aload(signature.argOffset("selfBlock"));
adapter.getfield(p(Block.class), "type", ci(Block.Type.class));
}
}

2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@ public class JVMVisitor extends IRVisitor {

public static final Signature CLOSURE_SIGNATURE = Signature
.returning(IRubyObject.class)
.appendArgs(new String[]{"context", SELF_BLOCK_NAME, "scope", "self", "args", BLOCK_ARG_NAME, "superName", "type"}, ThreadContext.class, Block.class, StaticScope.class, IRubyObject.class, IRubyObject[].class, Block.class, String.class, Block.Type.class);
.appendArgs(new String[]{"context", SELF_BLOCK_NAME, "scope", "self", "args", BLOCK_ARG_NAME, "superName"}, ThreadContext.class, Block.class, StaticScope.class, IRubyObject.class, IRubyObject[].class, Block.class, String.class);

public JVMVisitor(Ruby runtime) {
this.jvm = Options.COMPILE_INVOKEDYNAMIC.load() ? new JVM7() : new JVM6();
54 changes: 2 additions & 52 deletions core/src/main/java/org/jruby/ir/targets/YieldSite.java
Original file line number Diff line number Diff line change
@@ -60,61 +60,11 @@ public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, Metho
return site;
}

public IRubyObject yield(ThreadContext context, Block block, IRubyObject arg) throws Throwable {
// BlockBody body = block.getBody();
// MethodHandle target;
//
// if (block.getBody() instanceof CompiledIRBlockBody) {
// CompiledIRBlockBody compiledBody = (CompiledIRBlockBody) block.getBody();
//
// target = unwrap ? compiledBody.getNormalYieldUnwrapHandle() : compiledBody.getNormalYieldHandle();
// } else {
// target = Binder.from(type())
// .append(unwrap)
// .invokeStaticQuiet(MethodHandles.lookup(), IRRuntimeHelpers.class, "yield");
// }
//
// MethodHandle fallback = getTarget();
// MethodHandle test = body.getTestBlockBody();
//
// MethodHandle guard = MethodHandles.guardWithTest(test, target, fallback);
//
// setTarget(guard);
//
// return (IRubyObject)target.invokeExact(context, block, arg);

// Fully MH-based dispatch for these still seems slower than megamorphic path
public IRubyObject yield(ThreadContext context, Block block, IRubyObject arg) {
return IRRuntimeHelpers.yield(context, block, arg, unwrap);
}

public IRubyObject yieldSpecific(ThreadContext context, Block block) throws Throwable {
// BlockBody body = block.getBody();
// MethodHandle target;
//
// if (block.getBody() instanceof CompiledIRBlockBody) {
// CompiledIRBlockBody compiledBody = (CompiledIRBlockBody) block.getBody();
//
// target = compiledBody.getNormalYieldSpecificHandle();
// } else {
// target = Binder.from(type())
// .permute(0, 1)
// .invokeVirtualQuiet(MethodHandles.lookup(), "yieldSpecific");
// }
//
// MethodHandle fallback = getTarget();
// MethodHandle test = body.getTestBlockBody();
//
// MethodHandle guard = MethodHandles.guardWithTest(test, target, fallback);
//
// setTarget(guard);
//
// return (IRubyObject)target.invokeExact(context, block);

// Fully MH-based dispatch for these still seems slower than megamorphic path
public IRubyObject yieldSpecific(ThreadContext context, Block block) {
return IRRuntimeHelpers.yieldSpecific(context, block);
}

public IRubyObject yieldValues(ThreadContext context, Block block, IRubyObject[] args) {
return block.yieldValues(context, args);
}
}
11 changes: 0 additions & 11 deletions core/src/main/java/org/jruby/javasupport/ext/JavaLang.java
Original file line number Diff line number Diff line change
@@ -309,17 +309,6 @@ public IRubyObject yield(ThreadContext context, IRubyObject[] args) {
final IRubyObject yieldImpl(ThreadContext context) {
runnable.run(); return context.nil;
}

@Override
protected final IRubyObject doYield(ThreadContext context, Block block, IRubyObject[] args, IRubyObject self) {
return yieldImpl(context);
}

@Override
protected final IRubyObject doYield(ThreadContext context, Block block, IRubyObject value) {
return yieldImpl(context); // avoid new IRubyObject[] { value }
}

}

}
22 changes: 12 additions & 10 deletions core/src/main/java/org/jruby/runtime/Block.java
Original file line number Diff line number Diff line change
@@ -43,6 +43,8 @@
import org.jruby.runtime.block.ThreadBlock;
import org.jruby.runtime.builtin.IRubyObject;

import static org.jruby.runtime.Helpers.arrayOf;

/**
* Internal live representation of a block ({...} or do ... end).
*/
@@ -176,24 +178,24 @@ public void setEvalType(EvalType evalType) {
}

public IRubyObject call(ThreadContext context, IRubyObject[] args) {
return body.call(context, this, args);
return body.call(context, this, args, NULL_BLOCK);
}

public IRubyObject call(ThreadContext context, IRubyObject[] args, Block blockArg) {
return body.call(context, this, args, blockArg);
}

public IRubyObject call(ThreadContext context) {
return body.call(context, this);
return body.call(context, this, IRubyObject.NULL_ARRAY, NULL_BLOCK);
}
public IRubyObject call(ThreadContext context, Block blockArg) {
return body.call(context, this, blockArg);
return body.call(context, this, IRubyObject.NULL_ARRAY, blockArg);
}
public IRubyObject yieldSpecific(ThreadContext context) {
return body.yieldSpecific(context, this);
}
public IRubyObject call(ThreadContext context, IRubyObject arg0) {
return body.call(context, this, arg0);
return body.call(context, this, arg0, NULL_BLOCK);
}
public IRubyObject call(ThreadContext context, IRubyObject arg0, Block blockArg) {
return body.call(context, this, arg0, blockArg);
@@ -202,7 +204,7 @@ public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0) {
return body.yieldSpecific(context, this, arg0);
}
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
return body.call(context, this, arg0, arg1);
return body.call(context, this, arg0, arg1, NULL_BLOCK);
}
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block blockArg) {
return body.call(context, this, arg0, arg1, blockArg);
@@ -211,7 +213,7 @@ public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyO
return body.yieldSpecific(context, this, arg0, arg1);
}
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
return body.call(context, this, arg0, arg1, arg2);
return body.call(context, this, arg0, arg1, arg2, NULL_BLOCK);
}
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block blockArg) {
return body.call(context, this, arg0, arg1, arg2, blockArg);
@@ -221,23 +223,23 @@ public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyO
}

public IRubyObject yield(ThreadContext context, IRubyObject value) {
return body.yield(context, this, value);
return body.yield(context, this, value, null, NULL_BLOCK);
}

public IRubyObject yieldNonArray(ThreadContext context, IRubyObject value, IRubyObject self) {
return body.yield(context, this, new IRubyObject[] { value }, self);
return body.yield(context, this, arrayOf(value), self, NULL_BLOCK);
}

public IRubyObject yieldArray(ThreadContext context, IRubyObject value, IRubyObject self) {
// SSS FIXME: Later on, we can move this code into IR insructions or
// introduce a specialized entry-point when we know that this block has
// explicit call protocol IR instructions.
IRubyObject[] args = IRRuntimeHelpers.singleBlockArgToArray(value);
return body.yield(context, this, args, self);
return body.yield(context, this, args, self, NULL_BLOCK);
}

public IRubyObject yieldValues(ThreadContext context, IRubyObject[] args) {
return body.yield(context, this, args, null);
return body.yield(context, this, args, null, NULL_BLOCK);
}

public Block cloneBlock() {
Loading