Skip to content

Commit

Permalink
Showing 9 changed files with 79 additions and 66 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/instructions/CallBase.java
Original file line number Diff line number Diff line change
@@ -425,7 +425,7 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco
IRubyObject[] values = prepareArguments(context, self, currScope, dynamicScope, temp);
Block preparedBlock = prepareBlock(context, self, currScope, dynamicScope, temp);

if (getClosureArg() != null) {
if (hasLiteralClosure()) {
try {
return callSite.call(context, self, object, values, preparedBlock);
} finally {
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@
*/
public class ArrayDerefInvokeSite extends NormalInvokeSite {
public ArrayDerefInvokeSite(MethodType type, String file, int line) {
super(type, "[]", file, line);
super(type, "[]", false, file, line);
}

public static final Handle BOOTSTRAP = new Handle(Opcodes.H_INVOKESTATIC, p(ArrayDerefInvokeSite.class), "bootstrap", sig(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, String.class, int.class));
Original file line number Diff line number Diff line change
@@ -361,9 +361,10 @@ public org.objectweb.asm.Label newLabel() {
*
* @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 receivesClosure whether a closure will be on the stack for passing
* @param literalClosure whether the closure is passed directly as a literal block
*/
public abstract void invokeOther(String file, int line, String name, int arity, boolean hasClosure, boolean isPotentiallyRefined);
public abstract void invokeOther(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, boolean isPotentiallyRefined);

/**
* Invoke the array dereferencing method ([]) on an object other than self.
@@ -405,9 +406,10 @@ public org.objectweb.asm.Label newLabel() {
* @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 callType
*/
public abstract void invokeSelf(String file, int line, String name, int arity, boolean hasClosure, CallType callType, boolean isPotentiallyRefined);
public abstract void invokeSelf(String file, int line, String name, int arity, boolean hasClosure, boolean literalClosure, CallType callType, boolean isPotentiallyRefined);

/**
* Invoke a superclass method from an instance context.
32 changes: 16 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,8 @@ public void run() {
});
}

public void invokeOther(String file, int line, String name, int arity, boolean hasClosure, boolean isPotentiallyRefined) {
invoke(file, line, name, arity, hasClosure, CallType.NORMAL, isPotentiallyRefined);
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);
}

public void invokeArrayDeref(String file, int line) {
@@ -410,14 +410,14 @@ 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 hasClosure, CallType callType, boolean isPotentiallyRefined) {
public void invoke(String file, int lineNumber, String name, int arity, boolean receivesClosure, boolean literalClosure, 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 (hasClosure) {
if (receivesClosure) {
switch (arity) {
case -1:
incomingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY, Block.class));
@@ -478,29 +478,29 @@ public void invoke(String file, int lineNumber, String name, int arity, boolean
case -1:
case 1:
adapter2.aload(3);
if (hasClosure) adapter2.aload(4);
if (receivesClosure) adapter2.aload(4);
break;
case 0:
if (hasClosure) adapter2.aload(3);
if (receivesClosure) adapter2.aload(3);
break;
case 2:
adapter2.aload(3);
adapter2.aload(4);
if (hasClosure) adapter2.aload(5);
if (receivesClosure) adapter2.aload(5);
break;
case 3:
adapter2.aload(3);
adapter2.aload(4);
adapter2.aload(5);
if (hasClosure) adapter2.aload(6);
if (receivesClosure) adapter2.aload(6);
break;
default:
buildArrayFromLocals(adapter2, 3, arity);
if (hasClosure) adapter2.aload(3 + arity);
if (receivesClosure) adapter2.aload(3 + arity);
break;
}

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

@@ -533,9 +533,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);
invokeOther(file, line, name, 1, false, false,false);
} else {
invokeSelf(file, line, name, 1, false, callType, false);
invokeSelf(file, line, name, 1, false, false, callType, false);
}
return;
}
@@ -589,9 +589,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);
invokeOther(file, line, name, 1, false, false, false);
} else {
invokeSelf(file, line, name, 1, false, callType, false);
invokeSelf(file, line, name, 1, false, false, callType, false);
}
return;
}
@@ -641,10 +641,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 hasClosure, CallType callType, boolean isPotentiallyRefined) {
public void invokeSelf(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, 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, hasClosure, callType, isPotentiallyRefined);
invoke(file, line, name, arity, receivesClosure, literalClosure, 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 hasClosure, boolean isPotentiallyRefined) {
public void invokeOther(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, 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, hasClosure, isPotentiallyRefined);
super.invokeOther(file, line, name, arity, receivesClosure, literalClosure, isPotentiallyRefined);
return;
}

if (hasClosure) {
if (receivesClosure) {
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, 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, literalClosure, file, line);
} else {
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), NormalInvokeSite.BOOTSTRAP, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), NormalInvokeSite.BOOTSTRAP, literalClosure, 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, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)), NormalInvokeSite.BOOTSTRAP, literalClosure, file, line);
} else {
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), NormalInvokeSite.BOOTSTRAP, file, line);
adapter.invokedynamic("invoke:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), NormalInvokeSite.BOOTSTRAP, literalClosure, 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);
invokeOther(file, line, name, 1, false, false,false);
} else {
invokeSelf(file, line, name, 1, false, callType, false);
invokeSelf(file, line, name, 1, false, false, 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);
invokeOther(file, line, name, 1, false, false, false);
} else {
invokeSelf(file, line, name, 1, false, callType, false);
invokeSelf(file, line, name, 1, false, false, 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 hasClosure, CallType callType, boolean isPotentiallyRefined) {
public void invokeSelf(String file, int line, String name, int arity, boolean receivesClosure, boolean literalClosure, 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, hasClosure, callType, isPotentiallyRefined);
super.invokeSelf(file, line, name, arity, receivesClosure, literalClosure, callType, isPotentiallyRefined);
return;
}

String action = callType == CallType.FUNCTIONAL ? "callFunctional" : "callVariable";
if (hasClosure) {
if (receivesClosure) {
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, 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, literalClosure, file, line);
} else {
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), SelfInvokeSite.BOOTSTRAP, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, arity + 2, Block.class)), SelfInvokeSite.BOOTSTRAP, literalClosure, 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, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT_ARRAY)), SelfInvokeSite.BOOTSTRAP, literalClosure, file, line);
} else {
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), SelfInvokeSite.BOOTSTRAP, file, line);
adapter.invokedynamic(action + ":" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), SelfInvokeSite.BOOTSTRAP, literalClosure, file, line);
}
}
}
18 changes: 11 additions & 7 deletions core/src/main/java/org/jruby/ir/targets/InvokeSite.java
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ public abstract class InvokeSite extends MutableCallSite {
protected final String file;
protected final int line;
private boolean boundOnce;
private boolean closure;
private boolean literalClosure;
CacheEntry cache = CacheEntry.NULL_CACHE;

private static final Logger LOG = LoggerFactory.getLogger(InvokeSite.class);
@@ -68,9 +68,14 @@ public String name() {
public final CallType callType;

public InvokeSite(MethodType type, String name, CallType callType, String file, int line) {
this(type, name, callType, false, file, line);
}

public InvokeSite(MethodType type, String name, CallType callType, boolean literalClosure, String file, int line) {
super(type);
this.methodName = name;
this.callType = callType;
this.literalClosure = literalClosure;
this.file = file;
this.line = line;

@@ -99,7 +104,6 @@ public InvokeSite(MethodType type, String name, CallType callType, String file,
}
startSig = startSig.appendArg("block", Block.class);
fullSignature = signature = startSig;
closure = true;
} else {
arity = type.parameterCount() - argOffset;

@@ -145,15 +149,15 @@ public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject

MethodHandle mh = getHandle(self, selfClass, method);

if (closure) {
if (literalClosure) {
mh = Binder.from(mh.type())
.tryFinally(getBlockEscape(signature))
.invoke(mh);
}

updateInvocationTarget(mh, self, selfClass, entry.method, switchPoint);

if (closure) {
if (literalClosure) {
try {
return method.call(context, self, selfClass, methodName, args, block);
} finally {
@@ -314,7 +318,7 @@ public Binder prepareBinder(boolean varargs) {
MethodHandle getHandle(IRubyObject self, RubyClass dispatchClass, DynamicMethod method) throws Throwable {
boolean blockGiven = signature.lastArgType() == Block.class;

MethodHandle mh = buildNewInstanceHandle(method, self, blockGiven);
MethodHandle mh = buildNewInstanceHandle(method, self);
if (mh == null) mh = Bootstrap.buildNativeHandle(this, method, blockGiven);
if (mh == null) mh = Bootstrap.buildIndyHandle(this, method, method.getImplementationClass());
if (mh == null) mh = Bootstrap.buildJittedHandle(this, method, blockGiven);
@@ -326,14 +330,14 @@ MethodHandle getHandle(IRubyObject self, RubyClass dispatchClass, DynamicMethod
return mh;
}

MethodHandle buildNewInstanceHandle(DynamicMethod method, IRubyObject self, boolean blockGiven) {
MethodHandle buildNewInstanceHandle(DynamicMethod method, IRubyObject self) {
MethodHandle mh = null;

if (method == self.getRuntime().getBaseNewMethod()) {
RubyClass recvClass = (RubyClass) self;

// Bind a second site as a dynamic invoker to guard against changes in new object's type
CallSite initSite = SelfInvokeSite.bootstrap(lookup(), "callFunctional:initialize", type(), file, line);
CallSite initSite = SelfInvokeSite.bootstrap(lookup(), "callFunctional:initialize", type(), literalClosure ? 1 : 0, file, line);
MethodHandle initHandle = initSite.dynamicInvoker();

MethodHandle allocFilter = Binder.from(IRubyObject.class, IRubyObject.class)
Loading

0 comments on commit 9d5dcee

Please sign in to comment.