Skip to content

Commit

Permalink
fix spread call wrapping for dgm helper and implement missing post/pr…
Browse files Browse the repository at this point in the history
…efix code part for indy
  • Loading branch information
blackdrag committed Oct 25, 2012
1 parent 37855cc commit 991c177
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 14 deletions.
10 changes: 5 additions & 5 deletions src/main/org/codehaus/groovy/classgen/asm/InvocationWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@

public class InvocationWriter {
// method invocation
protected static final MethodCallerMultiAdapter invokeMethodOnCurrent = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeMethodOnCurrent", true, false);
protected static final MethodCallerMultiAdapter invokeMethodOnSuper = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeMethodOnSuper", true, false);
protected static final MethodCallerMultiAdapter invokeMethod = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeMethod", true, false);
protected static final MethodCallerMultiAdapter invokeStaticMethod = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeStaticMethod", true, true);
protected static final MethodCaller invokeClosureMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeClosure");
public static final MethodCallerMultiAdapter invokeMethodOnCurrent = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeMethodOnCurrent", true, false);
public static final MethodCallerMultiAdapter invokeMethodOnSuper = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeMethodOnSuper", true, false);
public static final MethodCallerMultiAdapter invokeMethod = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeMethod", true, false);
public static final MethodCallerMultiAdapter invokeStaticMethod = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "invokeStaticMethod", true, true);
public static final MethodCaller invokeClosureMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeClosure");

private WriterController controller;

Expand Down
10 changes: 7 additions & 3 deletions src/main/org/codehaus/groovy/classgen/asm/WriterController.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,21 @@

public class WriterController {

private static Constructor indyWriter, indyCallSiteWriter;
private static Constructor indyWriter, indyCallSiteWriter, indyBinHelper;
static {
try {
ClassLoader cl = WriterController.class.getClassLoader();
Class indyClass = cl.loadClass("org.codehaus.groovy.classgen.asm.indy.InvokeDynamicWriter");
indyWriter = indyClass.getConstructor(WriterController.class);
indyClass = cl.loadClass("org.codehaus.groovy.classgen.asm.indy.IndyCallSiteWriter");
indyCallSiteWriter = indyClass.getConstructor(WriterController.class);
indyClass = cl.loadClass("org.codehaus.groovy.classgen.asm.indy.IndyBinHelper");
indyBinHelper = indyClass.getConstructor(WriterController.class);
} catch (Exception e) {
indyWriter = null;
indyCallSiteWriter = null;
}
indyBinHelper = null;
}
}
private AsmClassGenerator acg;
private MethodVisitor methodVisitor;
Expand Down Expand Up @@ -99,15 +102,16 @@ public void init(AsmClassGenerator asmClassGenerator, GeneratorContext gcon, Cla
try {
this.invocationWriter = (InvocationWriter) indyWriter.newInstance(this);
this.callSiteWriter = (CallSiteWriter) indyCallSiteWriter.newInstance(this);
this.binaryExpHelper = (BinaryExpressionHelper) indyBinHelper.newInstance(this);
} catch (Exception e) {
throw new GroovyRuntimeException("Cannot use invokedynamic, indy module was excluded from this build.");
}
} else {
this.callSiteWriter = new CallSiteWriter(this);
this.invocationWriter = new InvocationWriter(this);
this.binaryExpHelper = new BinaryExpressionHelper(this);
}

this.binaryExpHelper = new BinaryExpressionHelper(this);
this.unaryExpressionHelper = new UnaryExpressionHelper(this);
if (optimizeForInt) {
this.fastPathBinaryExpHelper = new BinaryExpressionMultiTypeDispatcher(this);
Expand Down
41 changes: 41 additions & 0 deletions src/main/org/codehaus/groovy/classgen/asm/indy/IndyBinHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2003-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.classgen.asm.indy;

import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.EmptyExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.classgen.asm.BinaryExpressionHelper;
import org.codehaus.groovy.classgen.asm.InvocationWriter;
import org.codehaus.groovy.classgen.asm.WriterController;

public class IndyBinHelper extends BinaryExpressionHelper {

public IndyBinHelper(WriterController wc) {
super(wc);
}

@Override
protected void writePostOrPrefixMethod(int op, String method, Expression expression, Expression orig) {
getController().getInvocationWriter().makeCall(
orig, EmptyExpression.INSTANCE,
new ConstantExpression(method),
MethodCallExpression.NO_ARGUMENTS,
InvocationWriter.invokeMethod,
false, false, false);
}
}
20 changes: 14 additions & 6 deletions src/main/org/codehaus/groovy/vmplugin/v7/Selector.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import static org.codehaus.groovy.vmplugin.v7.IndyInterface.*;

public abstract class Selector {
public Object[] args;
public Object[] args, originalArguments;
public MetaMethod method;
public MethodType targetType,currentType;
public String name;
Expand All @@ -62,6 +62,7 @@ public abstract class Selector {
public Class sender;
public boolean isVargs;
public boolean safeNavigation, safeNavigationOrig, spread, genericInvoker;
public boolean skipSpreadCollector;
public boolean thisCall;
public Class selectionBase;
public boolean catchException = true;
Expand Down Expand Up @@ -243,6 +244,7 @@ public MethodSelector(MutableCallSite callSite, Class sender, String methodName,
this.callType = callType;
this.targetType = callSite.type();
this.name = methodName;
this.originalArguments = arguments;
this.args = spread(arguments, spreadCall);
this.callSite = callSite;
this.sender = sender;
Expand Down Expand Up @@ -374,9 +376,11 @@ public void setHandleForMetaMethod() {
handle = META_METHOD_INVOKER;
handle = handle.bindTo(method);
if (LOG_ENABLED) LOG.info("bound method name to META_METHOD_INVOKER");
if (method.getNativeParameterTypes().length==1 &&
args.length==1)
{

if (
method.getNativeParameterTypes().length==1 &&
args.length==1
) {
// the method expects a parameter but we don't provide an
// argument for that. So we give in a Object[], containing
// a null value
Expand All @@ -386,7 +390,7 @@ public void setHandleForMetaMethod() {
// another one for the vargs call
handle = MethodHandles.insertArguments(handle, 1, new Object[]{new Object[]{null}});
if (LOG_ENABLED) LOG.info("null argument expansion");
} else if (method.isVargsMethod()) {
} else if (method.isVargsMethod() && !spread) {
// the method expects the arguments as Object[] in a Object[]
handle = handle.asCollector(Object[].class, 1);
handle = handle.asCollector(Object[].class, targetType.parameterCount()-1);
Expand All @@ -397,6 +401,10 @@ public void setHandleForMetaMethod() {
handle = handle.asCollector(Object[].class, targetType.parameterCount()-1);
currentType = MethodType.methodType(method.getReturnType(), method.getNativeParameterTypes());
currentType = currentType.insertParameterTypes(0, method.getDeclaringClass().getTheClass());
if (spread) {
args = originalArguments;
skipSpreadCollector = true;
}
if (LOG_ENABLED) LOG.info("normal dgm helper wrapping");
}
}
Expand Down Expand Up @@ -561,7 +569,7 @@ public void correctNullReceiver() {
}

public void correctSpreading() {
if (!spread || useMetaClass) return;
if (!spread || useMetaClass || skipSpreadCollector) return;
handle = handle.asSpreader(Object[].class, args.length-1);
}

Expand Down

0 comments on commit 991c177

Please sign in to comment.