/* * 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]); } }