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 import java.lang.invoke.WrongMethodTypeException; 30 import java.util.Arrays; 31 32 import nsk.share.test.LazyIntArrayToString; 33 import vm.mlvm.meth.share.Argument; 34 import vm.mlvm.meth.share.MHUtils; 35 import vm.mlvm.share.Env; 36 37 public class MHPermuteTF extends MHBasicUnaryTF { 38 39 private final int[] _reorderArray; 40 private final MethodType _sourceMT; 41 42 public MHPermuteTF(MHCall target, MethodType sourceMT, int[] reorderArray) { 43 super(target); 44 _reorderArray = reorderArray; 45 _sourceMT = sourceMT; 46 } 47 48 public MHPermuteTF(MHCall target, int[] reorderArray) { 49 this(target, getPermutedMT(target.getTargetMH().type(), reorderArray), reorderArray); 50 } 51 52 @Override 53 protected void check(Argument[] targetArgs) throws IllegalArgumentException { 54 super.check(targetArgs); 55 56 if ( _sourceMT.parameterCount() < _reorderArray.length ) { 57 throw new WrongMethodTypeException("reorderArray requires at least " 58 + _reorderArray.length + " target arguments, but only " 59 + _sourceMT.parameterCount() + " are given"); 60 } 61 62 for ( int i = 0; i < _reorderArray.length; i++ ) { 63 MHUtils.assertAssignableType("reorderArray element " + i, 64 targetArgs[i].getType(), 65 _sourceMT.parameterType(_reorderArray[i])); 66 } 67 } 68 69 @Override 70 protected MethodHandle computeInboundMH(MethodHandle targetMH) { 71 MethodHandle r = MethodHandles.permuteArguments(targetMH, _sourceMT, _reorderArray); 72 Env.traceDebug("permute: inType=%s; targetType=%s; reorder=%s", 73 r.type(), targetMH.type(), new LazyIntArrayToString(_reorderArray)); 74 return r; 75 } 76 77 @Override 78 protected Argument[] computeInboundArgs(Argument[] targetArgs) { 79 Argument[] resultArgs = new Argument[_sourceMT.parameterCount()]; 80 81 for ( int i = 0; i < targetArgs.length; i++ ) { 82 resultArgs[_reorderArray[i]] = targetArgs[i]; 83 } 84 85 for ( int i = 0; i < resultArgs.length; i++ ) { 86 if ( resultArgs[i] == null ) { 87 resultArgs[i] = new Argument(_sourceMT.parameterType(i), null); 88 } 89 } 90 91 return resultArgs; 92 } 93 94 @Override 95 protected String getName() { 96 return "permuteArguments"; 97 } 98 99 @Override 100 protected String getDescription() { 101 return "sourceMT=" + _sourceMT + "; reorder=" + Arrays.toString(_reorderArray); 102 } 103 104 public static MethodType getPermutedMT(MethodType targetMT, int[] reorderArray) { 105 int srcParamCount = 0; 106 for ( int t = 0; t < reorderArray.length; t++ ) 107 srcParamCount = Math.max(srcParamCount, reorderArray[t] + 1); 108 109 Class<?>[] paramTypes = new Class<?>[srcParamCount]; 110 111 for ( int t = 0; t < reorderArray.length; t++ ) 112 paramTypes[reorderArray[t]] = targetMT.parameterType(t); 113 114 for ( int s = 0; s < paramTypes.length; s++ ) 115 if ( paramTypes[s] == null ) 116 throw new IllegalArgumentException("Type of parameter #" + s + " is not defined"); 117 118 return MethodType.methodType(targetMT.returnType(), paramTypes); 119 } 120 121 public static int[] getIdentityPermuteArray(int argCount) { 122 int[] result = new int[argCount]; 123 for ( int i = 0; i < argCount; i++ ) 124 result[i] = i; 125 return result; 126 } 127 128 public static int[] moveArgsInPermuteArray(int[] array, int oldPos, int count, int newPos) { 129 if ( newPos == oldPos ) 130 return array; 131 132 int[] result = new int[array.length]; 133 134 if ( newPos < oldPos ) { 135 System.arraycopy(array, 0, result, 0, newPos); 136 System.arraycopy(array, newPos, result, newPos + count, oldPos - newPos); 137 System.arraycopy(array, oldPos + count, result, oldPos + count, array.length - oldPos - count); 138 } else { 139 System.arraycopy(array, 0, result, 0, oldPos); 140 System.arraycopy(array, oldPos + count, result, oldPos, newPos - oldPos - count); 141 System.arraycopy(array, newPos + count, result, newPos + count, array.length - newPos - count); 142 } 143 System.arraycopy(array, oldPos, result, newPos, count); 144 145 return result; 146 } 147 }