Skip to content

Commit

Permalink
Final tweaks to LJE break fixes.
Browse files Browse the repository at this point in the history
* Add literal closure method to IR closure-accepting interface
* Replace double boolean in JIT code with enum
* Check for null in non-local return logic
headius committed Jun 28, 2017
1 parent cadbd91 commit b810412
Showing 7 changed files with 83 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -56,6 +56,8 @@ public Operand getClosureArg() {
return getOperand1();
}

public boolean hasLiteralClosure() { return getClosureArg() instanceof WrappedIRClosure; }

@Override
public void encode(IRWriterEncoder e) {
super.encode(e);
Original file line number Diff line number Diff line change
@@ -8,4 +8,5 @@
*/
public interface ClosureAcceptingInstr {
public Operand getClosureArg();
public boolean hasLiteralClosure();
}
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ public static void checkForLJE(ThreadContext context, DynamicScope dynScope, boo

// Create a jump for a non-local return which will return from nearest lambda (which may be itself) or method.
public static IRubyObject initiateNonLocalReturn(ThreadContext context, DynamicScope dynScope, Block block, IRubyObject returnValue) {
if (IRRuntimeHelpers.inLambda(block.type)) throw new IRWrappedLambdaReturnValue(returnValue);
if (block != null && IRRuntimeHelpers.inLambda(block.type)) throw new IRWrappedLambdaReturnValue(returnValue);

throw IRReturnJump.create(getContainingMethodOrLambdasDynamicScope(dynScope), returnValue);
}
36 changes: 30 additions & 6 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter.java
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.compiler.impl.SkinnyMethodAdapter;
import org.jruby.ir.instructions.ClosureAcceptingInstr;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.UndefinedValue;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.CallType;
@@ -361,10 +363,9 @@ public org.objectweb.asm.Label newLabel() {
*
* @param name name of the method to invoke
* @param arity arity of the call
* @param receivesClosure whether a closure will be on the stack for passing
* @param literalClosure whether the closure is passed directly as a literal block
* @param blockPassType what type of closure is passed
*/
public abstract void invokeOther(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, boolean isPotentiallyRefined);
public abstract void invokeOther(String file, int line, String name, int arity, BlockPassType blockPassType, boolean isPotentiallyRefined);

/**
* Invoke the array dereferencing method ([]) on an object other than self.
@@ -395,6 +396,30 @@ public org.objectweb.asm.Label newLabel() {
*/
public abstract void invokeOtherOneFloat(String file, int line, String name, double flote, CallType callType);

public enum BlockPassType {
NONE(false, false),
GIVEN(true, false),
LITERAL(true, true);

private final boolean given;
private final boolean literal;

BlockPassType(boolean given, boolean literal) {
this.given = given;
this.literal = literal;
}

public boolean given() {
return given;
}
public boolean literal() {
return literal;
}
public static BlockPassType fromIR(ClosureAcceptingInstr callInstr) {
Operand closure = callInstr.getClosureArg();
return closure != null ? ( callInstr.hasLiteralClosure() ? BlockPassType.LITERAL : BlockPassType.GIVEN) : BlockPassType.NONE;
}
}

/**
* Invoke a method on self.
@@ -405,11 +430,10 @@ public org.objectweb.asm.Label newLabel() {
* @param line the line number where this call appears
* @param name name of the method to invoke
* @param arity arity of the call
* @param hasClosure whether a closure will be on the stack for passing
* @param literalClosure whether the passed closure is a literal block
* @param blockPassType what type of closure is passed
* @param callType
*/
public abstract void invokeSelf(String file, int line, String name, int arity, boolean hasClosure, boolean literalClosure, CallType callType, boolean isPotentiallyRefined);
public abstract void invokeSelf(String file, int line, String name, int arity, BlockPassType blockPassType, CallType callType, boolean isPotentiallyRefined);

/**
* Invoke a superclass method from an instance context.
34 changes: 18 additions & 16 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
Original file line number Diff line number Diff line change
@@ -382,8 +382,9 @@ public void run() {
});
}

public void invokeOther(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, boolean isPotentiallyRefined) {
invoke(file, line, name, arity, receivesClosure, literalClosure, CallType.NORMAL, isPotentiallyRefined);
@Override
public void invokeOther(String file, int line, String name, int arity, BlockPassType blockPassType, boolean isPotentiallyRefined) {
invoke(file, line, name, arity, blockPassType, CallType.NORMAL, isPotentiallyRefined);
}

public void invokeArrayDeref(String file, int line) {
@@ -410,14 +411,15 @@ public void invokeArrayDeref(String file, int line) {
adapter.invokestatic(getClassData().clsName, methodName, incomingSig);
}

public void invoke(String file, int lineNumber, String name, int arity, boolean receivesClosure, boolean literalClosure, CallType callType, boolean isPotentiallyRefined) {
public void invoke(String file, int lineNumber, String name, int arity, BlockPassType blockPassType, CallType callType, boolean isPotentiallyRefined) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to `" + name + "' has more than " + MAX_ARGUMENTS + " arguments");

SkinnyMethodAdapter adapter2;
String incomingSig;
String outgoingSig;

if (receivesClosure) {
boolean blockGiven = blockPassType.given();
if (blockGiven) {
switch (arity) {
case -1:
incomingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class));
@@ -478,29 +480,29 @@ public void invoke(String file, int lineNumber, String name, int arity, boolean
case -1:
case 1:
adapter2.aload(3);
if (receivesClosure) adapter2.aload(4);
if (blockGiven) adapter2.aload(4);
break;
case 0:
if (receivesClosure) adapter2.aload(3);
if (blockGiven) adapter2.aload(3);
break;
case 2:
adapter2.aload(3);
adapter2.aload(4);
if (receivesClosure) adapter2.aload(5);
if (blockGiven) adapter2.aload(5);
break;
case 3:
adapter2.aload(3);
adapter2.aload(4);
adapter2.aload(5);
if (receivesClosure) adapter2.aload(6);
if (blockGiven) adapter2.aload(6);
break;
default:
buildArrayFromLocals(adapter2, 3, arity);
if (receivesClosure) adapter2.aload(3 + arity);
if (blockGiven) adapter2.aload(3 + arity);
break;
}

adapter2.invokevirtual(p(CachingCallSite.class), literalClosure ? "callIter" : "call", outgoingSig);
adapter2.invokevirtual(p(CachingCallSite.class), blockPassType.literal() ? "callIter" : "call", outgoingSig);
adapter2.areturn();
adapter2.end();

@@ -533,9 +535,9 @@ public void invokeOtherOneFixnum(String file, int line, String name, long fixnum
if (!MethodIndex.hasFastFixnumOps(name)) {
pushFixnum(fixnum);
if (callType == CallType.NORMAL) {
invokeOther(file, line, name, 1, false, false,false);
invokeOther(file, line, name, 1, BlockPassType.NONE, false);
} else {
invokeSelf(file, line, name, 1, false, false, callType, false);
invokeSelf(file, line, name, 1, BlockPassType.NONE, callType, false);
}
return;
}
@@ -589,9 +591,9 @@ public void invokeOtherOneFloat(String file, int line, String name, double flote
if (!MethodIndex.hasFastFloatOps(name)) {
pushFloat(flote);
if (callType == CallType.NORMAL) {
invokeOther(file, line, name, 1, false, false, false);
invokeOther(file, line, name, 1, BlockPassType.NONE, false);
} else {
invokeSelf(file, line, name, 1, false, false, callType, false);
invokeSelf(file, line, name, 1, BlockPassType.NONE, callType, false);
}
return;
}
@@ -641,10 +643,10 @@ public void invokeOtherOneFloat(String file, int line, String name, double flote
adapter.invokestatic(getClassData().clsName, methodName, incomingSig);
}

public void invokeSelf(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, CallType callType, boolean isPotentiallyRefined) {
public void invokeSelf(String file, int line, String name, int arity, BlockPassType blockPassType, CallType callType, boolean isPotentiallyRefined) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to `" + name + "' has more than " + MAX_ARGUMENTS + " arguments");

invoke(file, line, name, arity, receivesClosure, literalClosure, callType, isPotentiallyRefined);
invoke(file, line, name, arity, blockPassType, callType, isPotentiallyRefined);
}

public void invokeInstanceSuper(String file, int line, String name, int arity, boolean hasClosure, boolean[] splatmap) {
36 changes: 18 additions & 18 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter7.java
Original file line number Diff line number Diff line change
@@ -125,24 +125,24 @@ public void pushEncoding(Encoding encoding) {
adapter.invokedynamic("encoding", sig(RubyEncoding.class, ThreadContext.class), Bootstrap.contextValueString(), new String(encoding.getName()));
}

public void invokeOther(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, boolean isPotentiallyRefined) {
public void invokeOther(String file, int line, String name, int arity, BlockPassType blockPassType, boolean isPotentiallyRefined) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to `" + name + "' has more than " + MAX_ARGUMENTS + " arguments");
if (isPotentiallyRefined) {
super.invokeOther(file, line, name, arity, receivesClosure, literalClosure, isPotentiallyRefined);
super.invokeOther(file, line, name, arity, blockPassType, isPotentiallyRefined);
return;
}

if (receivesClosure) {
if (blockPassType.given()) {
if (arity == -1) {
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)), NormalInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)), NormalInvokeSite.BOOTSTRAP, blockPassType.literal(), file, line);
} else {
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), NormalInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), NormalInvokeSite.BOOTSTRAP, blockPassType.literal(), file, line);
}
} else {
if (arity == -1) {
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)), NormalInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)), NormalInvokeSite.BOOTSTRAP, false, file, line);
} else {
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), NormalInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), NormalInvokeSite.BOOTSTRAP, false, file, line);
}
}
}
@@ -156,9 +156,9 @@ public void invokeOtherOneFixnum(String file, int line, String name, long fixnum
if (!MethodIndex.hasFastFixnumOps(name)) {
pushFixnum(fixnum);
if (callType == CallType.NORMAL) {
invokeOther(file, line, name, 1, false, false,false);
invokeOther(file, line, name, 1, BlockPassType.NONE,false);
} else {
invokeSelf(file, line, name, 1, false, false, callType, false);
invokeSelf(file, line, name, 1, BlockPassType.NONE, callType, false);
}
return;
}
@@ -179,9 +179,9 @@ public void invokeOtherOneFloat(String file, int line, String name, double flote
if (!MethodIndex.hasFastFloatOps(name)) {
pushFloat(flote);
if (callType == CallType.NORMAL) {
invokeOther(file, line, name, 1, false, false, false);
invokeOther(file, line, name, 1, BlockPassType.NONE, false);
} else {
invokeSelf(file, line, name, 1, false, false, callType, false);
invokeSelf(file, line, name, 1, BlockPassType.NONE, callType, false);
}
return;
}
@@ -198,25 +198,25 @@ public void invokeOtherOneFloat(String file, int line, String name, double flote
0);
}

public void invokeSelf(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, CallType callType, boolean isPotentiallyRefined) {
public void invokeSelf(String file, int line, String name, int arity, BlockPassType blockPassType, CallType callType, boolean isPotentiallyRefined) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to `" + name + "' has more than " + MAX_ARGUMENTS + " arguments");
if (isPotentiallyRefined) {
super.invokeSelf(file, line, name, arity, receivesClosure, literalClosure, callType, isPotentiallyRefined);
super.invokeSelf(file, line, name, arity, blockPassType, callType, isPotentiallyRefined);
return;
}

String action = callType == CallType.FUNCTIONAL ? "callFunctional" : "callVariable";
if (receivesClosure) {
if (blockPassType != BlockPassType.NONE) {
if (arity == -1) {
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)), SelfInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class)), SelfInvokeSite.BOOTSTRAP, blockPassType.literal(), file, line);
} else {
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), SelfInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), SelfInvokeSite.BOOTSTRAP, blockPassType.literal(), file, line);
}
} else {
if (arity == -1) {
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)), SelfInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)), SelfInvokeSite.BOOTSTRAP, false, file, line);
} else {
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), SelfInvokeSite.BOOTSTRAP, literalClosure, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), SelfInvokeSite.BOOTSTRAP, false, file, line);
}
}
}
Loading

0 comments on commit b810412

Please sign in to comment.