blob: 36d7c5a11417248b0a86f61d21accdf3d2a320fb [file] [log] [blame]
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package vm.mlvm.meth.share.transform.v2;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import vm.mlvm.meth.share.Argument;
import vm.mlvm.meth.share.Arguments;
import vm.mlvm.meth.share.SimpleOpMethodHandles;
import vm.mlvm.share.Env;
public class MHThrowCatchTFPair extends MHTFPair {
private final String id;
private final Argument testArg;
private final Object testValue2;
private final boolean testEq;
private final Throwable _exception;
private class ThrowTF extends MHDropTF {
public ThrowTF(MHCall outboundCall) {
super(outboundCall, 0, new Argument[] { testArg });
}
@Override
protected MethodHandle computeInboundMH(MethodHandle targetMH) {
try {
Argument testArg = MHThrowCatchTFPair.this.testArg;
MethodType targetType = targetMH.type().insertParameterTypes(0, testArg.getType());
MHMacroTF mTF = new MHMacroTF("throwCatch throw part");
mTF.addOutboundCall(getTargetCall());
/*
MHCall testCall =
mTF.addTransformation(new MHInsertTF(
mTF.addTransformation(new MHExplicitCastTF(
mTF.addTransformation(new MHEqualityTestTF(testArg)),
boolean.class, new Class<?>[] { testArg.getType(), testArg.getType() })),
0, new Argument[] { testArg }, false));
*/
MethodHandle testMH = MethodHandles.insertArguments(
MethodHandles.explicitCastArguments(
SimpleOpMethodHandles.eqMH(),
MethodType.methodType(boolean.class, testArg.getType(), testArg.getType())),
0, testArg.getValue());
MethodHandle normalBranchMH = MethodHandles.dropArguments(targetMH, 0, testArg.getType());
MethodHandle throwingBranchMH =
MethodHandles.dropArguments(
MethodHandles.insertArguments(
MethodHandles.throwException(targetType.returnType(), _exception.getClass()),
0, _exception),
0, targetType.parameterArray());
MethodHandle thenMH, elseMH;
if ( MHThrowCatchTFPair.this.testEq ) {
thenMH = throwingBranchMH;
elseMH = normalBranchMH;
} else {
testMH = MethodHandles.filterReturnValue(testMH, SimpleOpMethodHandles.notMH());
elseMH = throwingBranchMH;
thenMH = normalBranchMH;
}
Env.traceDebug("ThrowCatchTFPair: targetMH=%s; testMH=%s; thenMH=%s; elseMH=%s",
targetMH.type(), testMH.type(), thenMH.type(), elseMH.type());
return MethodHandles.guardWithTest(testMH, thenMH, elseMH);
} catch ( Throwable t ) {
throw (IllegalArgumentException) (new IllegalArgumentException("Can't create throw/catch TF")).initCause(t);
}
}
}
private class CatchTF extends MHInsertTF {
public CatchTF(MHCall target, int argIdx) {
super(target, argIdx, new Argument[] { testArg }, true);
}
@Override
protected MethodHandle computeInboundMH(MethodHandle targetMH) {
try {
MethodHandle catchTargetMH = MethodHandles.insertArguments(targetMH, this.pos, MHThrowCatchTFPair.this.testArg.getValue());
MethodHandle catchHandlerMH = MethodHandles.dropArguments(
MethodHandles.insertArguments(targetMH, this.pos, MHThrowCatchTFPair.this.testValue2),
0, _exception.getClass());
return MethodHandles.catchException(catchTargetMH, _exception.getClass(), catchHandlerMH);
} catch ( Throwable t ) {
IllegalArgumentException e = new IllegalArgumentException("Can't create a transformation");
e.initCause(t);
throw e;
}
}
}
public MHThrowCatchTFPair(MHCall outboundTarget, Argument testArg, Object testValue2, boolean testEq, Throwable exc) {
super(outboundTarget);
this.id = "ThrowCatch_" + hashCode();
this.testArg = testArg.clone();
this.testArg.setPreserved(true);
this.testArg.setTag(this.id);
this.testValue2 = testValue2;
this.testEq = testEq;
_exception = exc;
}
@Override
public MHTF getOutboundTF() {
return new ThrowTF(this.outboundTarget);
}
@Override
public MHTF getInboundTF(MHCall inboundTarget) {
int[] tagged = Arguments.findTag(inboundTarget.getArgs(), this.id);
if ( tagged.length != 1 ) {
throw new IllegalArgumentException("Can't find exactly one argument tagged " + this.id
+ " from inner transformation (found indexes: " + tagged + ")");
}
return new CatchTF(inboundTarget, tagged[0]);
}
}