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.WrongMethodTypeException;
  29 import java.util.Arrays;
  30 import java.util.HashSet;
  31 import java.util.Set;
  32 
  33 import nsk.share.test.TestUtils;
  34 
  35 import vm.mlvm.meth.share.Argument;
  36 import vm.mlvm.meth.share.MHUtils;
  37 
  38 public class MHFilterTF extends MHNaryTF {
  39 
  40     protected final MHCall _target, _filters[];
  41     protected final int _pos;
  42 
  43     public MHFilterTF(MHCall target, int pos, MHCall[] filters) {
  44         _target = target;
  45         _pos = pos;
  46         _filters = filters;
  47     }
  48 
  49     @Override
  50     protected void check() throws IllegalArgumentException {
  51         Argument[] targetArgs = _target.getArgs();
  52         for ( int i = 0; i < _filters.length; i++ ) {
  53             MHCall f = _filters[i];
  54             if ( f == null )
  55                 continue;
  56 
  57             int p = i + _pos;
  58 
  59             if ( f.getArgs().length != 1 )
  60                 throw new WrongMethodTypeException("Filter " + i + " should have exactly one argument, but has: " + f.getArgs());
  61 
  62             MHUtils.assertAssignableType("filter return type to target parameter " + i,
  63                     targetArgs[p].getType(),
  64                     f.getRetVal().getType());
  65         }
  66     }
  67 
  68     @Override
  69     protected Argument computeRetVal() {
  70         return _target.getRetVal();
  71     }
  72 
  73     @Override
  74     protected Argument[] computeInboundArgs() {
  75         Argument[] result = _target.getArgs().clone();
  76 
  77         for ( int i = 0; i < _filters.length; i++ ) {
  78             MHCall f = _filters[i];
  79             if ( f != null )
  80                 result[i + _pos] = f.getArgs()[0];
  81         }
  82 
  83         return result;
  84     }
  85 
  86     @Override
  87     protected MethodHandle computeInboundMH() {
  88         MethodHandle[] filterMHs = new MethodHandle[_filters.length];
  89         for ( int i = 0; i < _filters.length; i++ ) {
  90             MHCall f = _filters[i];
  91             if ( f != null )
  92                 filterMHs[i] = f.getTargetMH();
  93         }
  94         return MethodHandles.filterArguments(_target.getTargetMH(), _pos, filterMHs);
  95     }
  96 
  97     @Override
  98     public MHCall[] getOutboundCalls() {
  99         Set<MHCall> calls = new HashSet<MHCall>();
 100         calls.add(_target);
 101         calls.addAll(Arrays.asList(_filters));
 102         calls.remove(null);
 103         return calls.toArray(new MHCall[0]);
 104     }
 105 
 106     @Override
 107     protected String getName() {
 108         return "filterArguments";
 109     }
 110 
 111     @Override
 112     protected String getDescription() {
 113         return "pos=" + _pos + "; filters=" + Arrays.toString(_filters);
 114     }
 115 }