src/jdk/internal/dynalink/support/DefaultInternalObjectFilter.java

Tue, 22 Dec 2015 10:56:12 -0800

author
asaha
date
Tue, 22 Dec 2015 10:56:12 -0800
changeset 1712
e9b46178f2e3
parent 1239
e1146c9cc758
permissions
-rw-r--r--

Added tag jdk8u71-b15 for changeset c577bcadb46d

attila@1239 1 /*
attila@1239 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
attila@1239 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
attila@1239 4 *
attila@1239 5 * This code is free software; you can redistribute it and/or modify it
attila@1239 6 * under the terms of the GNU General Public License version 2 only, as
attila@1239 7 * published by the Free Software Foundation. Oracle designates this
attila@1239 8 * particular file as subject to the "Classpath" exception as provided
attila@1239 9 * by Oracle in the LICENSE file that accompanied this code.
attila@1239 10 *
attila@1239 11 * This code is distributed in the hope that it will be useful, but WITHOUT
attila@1239 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
attila@1239 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
attila@1239 14 * version 2 for more details (a copy is included in the LICENSE file that
attila@1239 15 * accompanied this code).
attila@1239 16 *
attila@1239 17 * You should have received a copy of the GNU General Public License version
attila@1239 18 * 2 along with this work; if not, write to the Free Software Foundation,
attila@1239 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
attila@1239 20 *
attila@1239 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
attila@1239 22 * or visit www.oracle.com if you need additional information or have any
attila@1239 23 * questions.
attila@1239 24 */
attila@1239 25
attila@1239 26 /*
attila@1239 27 * This file is available under and governed by the GNU General Public
attila@1239 28 * License version 2 only, as published by the Free Software Foundation.
attila@1239 29 * However, the following notice accompanied the original version of this
attila@1239 30 * file, and Oracle licenses the original version of this file under the BSD
attila@1239 31 * license:
attila@1239 32 */
attila@1239 33 /*
attila@1239 34 Copyright 2009-2015 Attila Szegedi
attila@1239 35
attila@1239 36 Licensed under both the Apache License, Version 2.0 (the "Apache License")
attila@1239 37 and the BSD License (the "BSD License"), with licensee being free to
attila@1239 38 choose either of the two at their discretion.
attila@1239 39
attila@1239 40 You may not use this file except in compliance with either the Apache
attila@1239 41 License or the BSD License.
attila@1239 42
attila@1239 43 If you choose to use this file in compliance with the Apache License, the
attila@1239 44 following notice applies to you:
attila@1239 45
attila@1239 46 You may obtain a copy of the Apache License at
attila@1239 47
attila@1239 48 http://www.apache.org/licenses/LICENSE-2.0
attila@1239 49
attila@1239 50 Unless required by applicable law or agreed to in writing, software
attila@1239 51 distributed under the License is distributed on an "AS IS" BASIS,
attila@1239 52 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
attila@1239 53 implied. See the License for the specific language governing
attila@1239 54 permissions and limitations under the License.
attila@1239 55
attila@1239 56 If you choose to use this file in compliance with the BSD License, the
attila@1239 57 following notice applies to you:
attila@1239 58
attila@1239 59 Redistribution and use in source and binary forms, with or without
attila@1239 60 modification, are permitted provided that the following conditions are
attila@1239 61 met:
attila@1239 62 * Redistributions of source code must retain the above copyright
attila@1239 63 notice, this list of conditions and the following disclaimer.
attila@1239 64 * Redistributions in binary form must reproduce the above copyright
attila@1239 65 notice, this list of conditions and the following disclaimer in the
attila@1239 66 documentation and/or other materials provided with the distribution.
attila@1239 67 * Neither the name of the copyright holder nor the names of
attila@1239 68 contributors may be used to endorse or promote products derived from
attila@1239 69 this software without specific prior written permission.
attila@1239 70
attila@1239 71 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
attila@1239 72 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
attila@1239 73 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
attila@1239 74 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
attila@1239 75 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
attila@1239 76 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
attila@1239 77 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
attila@1239 78 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
attila@1239 79 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
attila@1239 80 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
attila@1239 81 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
attila@1239 82 */
attila@1239 83
attila@1239 84 package jdk.internal.dynalink.support;
attila@1239 85
attila@1239 86 import java.lang.invoke.MethodHandle;
attila@1239 87 import java.lang.invoke.MethodHandles;
attila@1239 88 import java.lang.invoke.MethodType;
attila@1239 89 import jdk.internal.dynalink.DynamicLinkerFactory;
attila@1239 90 import jdk.internal.dynalink.linker.MethodHandleTransformer;
attila@1239 91
attila@1239 92 /**
attila@1239 93 * Default implementation for a {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer)}.
attila@1239 94 * Given a method handle of {@code Object(Object)} type for filtering parameter and another one of the same type for
attila@1239 95 * filtering return values, applies them to passed method handles where their parameter types and/or return value types
attila@1239 96 * are declared to be {@link Object}.
attila@1239 97 */
attila@1239 98 public class DefaultInternalObjectFilter implements MethodHandleTransformer {
attila@1239 99 private static final MethodHandle FILTER_VARARGS = new Lookup(MethodHandles.lookup()).findStatic(
attila@1239 100 DefaultInternalObjectFilter.class, "filterVarArgs", MethodType.methodType(Object[].class, MethodHandle.class, Object[].class));
attila@1239 101
attila@1239 102 private final MethodHandle parameterFilter;
attila@1239 103 private final MethodHandle returnFilter;
attila@1239 104 private final MethodHandle varArgFilter;
attila@1239 105
attila@1239 106 /**
attila@1239 107 * Creates a new filter.
attila@1239 108 * @param parameterFilter the filter for method parameters. Must be of type {@code Object(Object)}, or null.
attila@1239 109 * @param returnFilter the filter for return values. Must be of type {@code Object(Object)}, or null.
attila@1239 110 * @throws IllegalArgumentException if one or both filters are not of the expected type.
attila@1239 111 */
attila@1239 112 public DefaultInternalObjectFilter(final MethodHandle parameterFilter, final MethodHandle returnFilter) {
attila@1239 113 this.parameterFilter = checkHandle(parameterFilter, "parameterFilter");
attila@1239 114 this.returnFilter = checkHandle(returnFilter, "returnFilter");
attila@1239 115 this.varArgFilter = parameterFilter == null ? null : FILTER_VARARGS.bindTo(parameterFilter);
attila@1239 116 }
attila@1239 117
attila@1239 118 @Override
attila@1239 119 public MethodHandle transform(final MethodHandle target) {
attila@1239 120 assert target != null;
attila@1239 121 MethodHandle[] filters = null;
attila@1239 122 final MethodType type = target.type();
attila@1239 123 final boolean isVarArg = target.isVarargsCollector();
attila@1239 124 final int paramCount = type.parameterCount();
attila@1239 125 final MethodHandle paramsFiltered;
attila@1239 126 // Filter parameters
attila@1239 127 if (parameterFilter != null) {
attila@1239 128 int firstFilter = -1;
attila@1239 129 // Ignore receiver, start from argument 1
attila@1239 130 for(int i = 1; i < paramCount; ++i) {
attila@1239 131 final Class<?> paramType = type.parameterType(i);
attila@1239 132 final boolean filterVarArg = isVarArg && i == paramCount - 1 && paramType == Object[].class;
attila@1239 133 if (filterVarArg || paramType == Object.class) {
attila@1239 134 if (filters == null) {
attila@1239 135 firstFilter = i;
attila@1239 136 filters = new MethodHandle[paramCount - firstFilter];
attila@1239 137 }
attila@1239 138 filters[i - firstFilter] = filterVarArg ? varArgFilter : parameterFilter;
attila@1239 139 }
attila@1239 140 }
attila@1239 141 paramsFiltered = filters != null ? MethodHandles.filterArguments(target, firstFilter, filters) : target;
attila@1239 142 } else {
attila@1239 143 paramsFiltered = target;
attila@1239 144 }
attila@1239 145 // Filter return value if needed
attila@1239 146 final MethodHandle returnFiltered = returnFilter != null && type.returnType() == Object.class ? MethodHandles.filterReturnValue(paramsFiltered, returnFilter) : paramsFiltered;
attila@1239 147 // Preserve varargs collector state
attila@1239 148 return isVarArg && !returnFiltered.isVarargsCollector() ? returnFiltered.asVarargsCollector(type.parameterType(paramCount - 1)) : returnFiltered;
attila@1239 149
attila@1239 150 }
attila@1239 151
attila@1239 152 private static MethodHandle checkHandle(final MethodHandle handle, final String handleKind) {
attila@1239 153 if (handle != null) {
attila@1239 154 final MethodType objectObjectType = MethodType.methodType(Object.class, Object.class);
attila@1239 155 if (!handle.type().equals(objectObjectType)) {
attila@1239 156 throw new IllegalArgumentException("Method type for " + handleKind + " must be " + objectObjectType);
attila@1239 157 }
attila@1239 158 }
attila@1239 159 return handle;
attila@1239 160 }
attila@1239 161
attila@1239 162 @SuppressWarnings("unused")
attila@1239 163 private static Object[] filterVarArgs(final MethodHandle parameterFilter, final Object[] args) throws Throwable {
attila@1239 164 Object[] newArgs = null;
attila@1239 165 for(int i = 0; i < args.length; ++i) {
attila@1239 166 final Object arg = args[i];
attila@1239 167 final Object newArg = parameterFilter.invokeExact(arg);
attila@1239 168 if (arg != newArg) {
attila@1239 169 if (newArgs == null) {
attila@1239 170 newArgs = args.clone();
attila@1239 171 }
attila@1239 172 newArgs[i] = newArg;
attila@1239 173 }
attila@1239 174 }
attila@1239 175 return newArgs == null ? args : newArgs;
attila@1239 176 }
attila@1239 177 }

mercurial