1 /* 2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package vm.mlvm.meth.share.transform.v2; 25 26 import java.lang.invoke.MethodHandle; 27 import java.lang.invoke.MethodHandles; 28 import java.lang.invoke.MethodType; 29 30 import vm.mlvm.meth.share.Argument; 31 import vm.mlvm.meth.share.Arguments; 32 import vm.mlvm.meth.share.SimpleOpMethodHandles; 33 import vm.mlvm.share.Env; 34 35 public class MHThrowCatchTFPair extends MHTFPair { 36 37 private final String id; 38 private final Argument testArg; 39 private final Object testValue2; 40 private final boolean testEq; 41 private final Throwable _exception; 42 43 private class ThrowTF extends MHDropTF { 44 45 public ThrowTF(MHCall outboundCall) { 46 super(outboundCall, 0, new Argument[] { testArg }); 47 } 48 49 @Override 50 protected MethodHandle computeInboundMH(MethodHandle targetMH) { 51 try { 52 Argument testArg = MHThrowCatchTFPair.this.testArg; 53 54 MethodType targetType = targetMH.type().insertParameterTypes(0, testArg.getType()); 55 56 MHMacroTF mTF = new MHMacroTF("throwCatch throw part"); 57 mTF.addOutboundCall(getTargetCall()); 58 /* 59 MHCall testCall = 60 mTF.addTransformation(new MHInsertTF( 61 mTF.addTransformation(new MHExplicitCastTF( 62 mTF.addTransformation(new MHEqualityTestTF(testArg)), 63 boolean.class, new Class<?>[] { testArg.getType(), testArg.getType() })), 64 0, new Argument[] { testArg }, false)); 65 */ 66 MethodHandle testMH = MethodHandles.insertArguments( 67 MethodHandles.explicitCastArguments( 68 SimpleOpMethodHandles.eqMH(), 69 MethodType.methodType(boolean.class, testArg.getType(), testArg.getType())), 70 0, testArg.getValue()); 71 72 MethodHandle normalBranchMH = MethodHandles.dropArguments(targetMH, 0, testArg.getType()); 73 74 MethodHandle throwingBranchMH = 75 MethodHandles.dropArguments( 76 MethodHandles.insertArguments( 77 MethodHandles.throwException(targetType.returnType(), _exception.getClass()), 78 0, _exception), 79 0, targetType.parameterArray()); 80 81 MethodHandle thenMH, elseMH; 82 if ( MHThrowCatchTFPair.this.testEq ) { 83 thenMH = throwingBranchMH; 84 elseMH = normalBranchMH; 85 } else { 86 testMH = MethodHandles.filterReturnValue(testMH, SimpleOpMethodHandles.notMH()); 87 elseMH = throwingBranchMH; 88 thenMH = normalBranchMH; 89 } 90 91 Env.traceDebug("ThrowCatchTFPair: targetMH=%s; testMH=%s; thenMH=%s; elseMH=%s", 92 targetMH.type(), testMH.type(), thenMH.type(), elseMH.type()); 93 94 return MethodHandles.guardWithTest(testMH, thenMH, elseMH); 95 } catch ( Throwable t ) { 96 throw (IllegalArgumentException) (new IllegalArgumentException("Can't create throw/catch TF")).initCause(t); 97 } 98 } 99 } 100 101 private class CatchTF extends MHInsertTF { 102 103 public CatchTF(MHCall target, int argIdx) { 104 super(target, argIdx, new Argument[] { testArg }, true); 105 } 106 107 @Override 108 protected MethodHandle computeInboundMH(MethodHandle targetMH) { 109 try { 110 MethodHandle catchTargetMH = MethodHandles.insertArguments(targetMH, this.pos, MHThrowCatchTFPair.this.testArg.getValue()); 111 MethodHandle catchHandlerMH = MethodHandles.dropArguments( 112 MethodHandles.insertArguments(targetMH, this.pos, MHThrowCatchTFPair.this.testValue2), 113 0, _exception.getClass()); 114 115 return MethodHandles.catchException(catchTargetMH, _exception.getClass(), catchHandlerMH); 116 } catch ( Throwable t ) { 117 IllegalArgumentException e = new IllegalArgumentException("Can't create a transformation"); 118 e.initCause(t); 119 throw e; 120 } 121 } 122 } 123 public MHThrowCatchTFPair(MHCall outboundTarget, Argument testArg, Object testValue2, boolean testEq, Throwable exc) { 124 super(outboundTarget); 125 this.id = "ThrowCatch_" + hashCode(); 126 127 this.testArg = testArg.clone(); 128 this.testArg.setPreserved(true); 129 this.testArg.setTag(this.id); 130 131 this.testValue2 = testValue2; 132 this.testEq = testEq; 133 _exception = exc; 134 } 135 136 @Override 137 public MHTF getOutboundTF() { 138 return new ThrowTF(this.outboundTarget); 139 } 140 141 @Override 142 public MHTF getInboundTF(MHCall inboundTarget) { 143 int[] tagged = Arguments.findTag(inboundTarget.getArgs(), this.id); 144 145 if ( tagged.length != 1 ) { 146 throw new IllegalArgumentException("Can't find exactly one argument tagged " + this.id 147 + " from inner transformation (found indexes: " + tagged + ")"); 148 } 149 150 return new CatchTF(inboundTarget, tagged[0]); 151 } 152 153 }