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

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

author
asaha
date
Tue, 22 Dec 2015 10:56:12 -0800
changeset 1712
e9b46178f2e3
parent 963
e2497b11a021
child 1205
4112748288bb
permissions
-rw-r--r--

Added tag jdk8u71-b15 for changeset c577bcadb46d

     1 /*
     2  * Copyright (c) 2010, 2013, 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 /*
    27  * This file is available under and governed by the GNU General Public
    28  * License version 2 only, as published by the Free Software Foundation.
    29  * However, the following notice accompanied the original version of this
    30  * file, and Oracle licenses the original version of this file under the BSD
    31  * license:
    32  */
    33 /*
    34    Copyright 2009-2013 Attila Szegedi
    36    Licensed under both the Apache License, Version 2.0 (the "Apache License")
    37    and the BSD License (the "BSD License"), with licensee being free to
    38    choose either of the two at their discretion.
    40    You may not use this file except in compliance with either the Apache
    41    License or the BSD License.
    43    If you choose to use this file in compliance with the Apache License, the
    44    following notice applies to you:
    46        You may obtain a copy of the Apache License at
    48            http://www.apache.org/licenses/LICENSE-2.0
    50        Unless required by applicable law or agreed to in writing, software
    51        distributed under the License is distributed on an "AS IS" BASIS,
    52        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    53        implied. See the License for the specific language governing
    54        permissions and limitations under the License.
    56    If you choose to use this file in compliance with the BSD License, the
    57    following notice applies to you:
    59        Redistribution and use in source and binary forms, with or without
    60        modification, are permitted provided that the following conditions are
    61        met:
    62        * Redistributions of source code must retain the above copyright
    63          notice, this list of conditions and the following disclaimer.
    64        * Redistributions in binary form must reproduce the above copyright
    65          notice, this list of conditions and the following disclaimer in the
    66          documentation and/or other materials provided with the distribution.
    67        * Neither the name of the copyright holder nor the names of
    68          contributors may be used to endorse or promote products derived from
    69          this software without specific prior written permission.
    71        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    72        IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    73        TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    74        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
    75        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    76        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    77        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    78        BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    79        WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    80        OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    82 */
    84 package jdk.internal.dynalink.support;
    86 import java.io.Serializable;
    87 import java.util.Collections;
    88 import java.util.LinkedList;
    89 import java.util.List;
    90 import jdk.internal.dynalink.linker.GuardedInvocation;
    91 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
    92 import jdk.internal.dynalink.linker.LinkRequest;
    93 import jdk.internal.dynalink.linker.LinkerServices;
    94 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
    96 /**
    97  * A composite type-based guarding dynamic linker. When a receiver of a not yet seen class is encountered, all linkers
    98  * are queried sequentially on their {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} method. The linkers
    99  * returning true are then bound to the class, and next time a receiver of same type is encountered, the linking is
   100  * delegated to those linkers only, speeding up dispatch.
   101  *
   102  * @author Attila Szegedi
   103  */
   104 public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker, Serializable {
   105     private static final long serialVersionUID = 1L;
   107     // Using a separate static class instance so there's no strong reference from the class value back to the composite
   108     // linker.
   109     private static class ClassToLinker extends ClassValue<List<TypeBasedGuardingDynamicLinker>> {
   110         private static final List<TypeBasedGuardingDynamicLinker> NO_LINKER = Collections.emptyList();
   111         private final TypeBasedGuardingDynamicLinker[] linkers;
   112         private final List<TypeBasedGuardingDynamicLinker>[] singletonLinkers;
   114         @SuppressWarnings({"unchecked", "rawtypes"})
   115         ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) {
   116             this.linkers = linkers;
   117             singletonLinkers = new List[linkers.length];
   118             for(int i = 0; i < linkers.length; ++i) {
   119                 singletonLinkers[i] = Collections.singletonList(linkers[i]);
   120             }
   121         }
   123         @SuppressWarnings("fallthrough")
   124         @Override
   125         protected List<TypeBasedGuardingDynamicLinker> computeValue(final Class<?> clazz) {
   126             List<TypeBasedGuardingDynamicLinker> list = NO_LINKER;
   127             for(int i = 0; i < linkers.length; ++i) {
   128                 final TypeBasedGuardingDynamicLinker linker = linkers[i];
   129                 if(linker.canLinkType(clazz)) {
   130                     switch(list.size()) {
   131                         case 0: {
   132                             list = singletonLinkers[i];
   133                             break;
   134                         }
   135                         case 1: {
   136                             list = new LinkedList<>(list);
   137                         }
   138                         default: {
   139                             list.add(linker);
   140                         }
   141                     }
   142                 }
   143             }
   144             return list;
   145         }
   146     }
   148     private final ClassValue<List<TypeBasedGuardingDynamicLinker>> classToLinker;
   150     /**
   151      * Creates a new composite type-based linker.
   152      *
   153      * @param linkers the component linkers
   154      */
   155     public CompositeTypeBasedGuardingDynamicLinker(final Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
   156         final List<TypeBasedGuardingDynamicLinker> l = new LinkedList<>();
   157         for(final TypeBasedGuardingDynamicLinker linker: linkers) {
   158             l.add(linker);
   159         }
   160         this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()]));
   161     }
   163     @Override
   164     public boolean canLinkType(final Class<?> type) {
   165         return !classToLinker.get(type).isEmpty();
   166     }
   168     @Override
   169     public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
   170             throws Exception {
   171         final Object obj = linkRequest.getReceiver();
   172         if(obj == null) {
   173             return null;
   174         }
   175         for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
   176             final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
   177             if(invocation != null) {
   178                 return invocation;
   179             }
   180         }
   181         return null;
   182     }
   184     /**
   185      * Optimizes a list of type-based linkers. If a group of adjacent linkers in the list all implement
   186      * {@link TypeBasedGuardingDynamicLinker}, they will be replaced with a single instance of
   187      * {@link CompositeTypeBasedGuardingDynamicLinker} that contains them.
   188      *
   189      * @param linkers the list of linkers to optimize
   190      * @return the optimized list
   191      */
   192     public static List<GuardingDynamicLinker> optimize(final Iterable<? extends GuardingDynamicLinker> linkers) {
   193         final List<GuardingDynamicLinker> llinkers = new LinkedList<>();
   194         final List<TypeBasedGuardingDynamicLinker> tblinkers = new LinkedList<>();
   195         for(final GuardingDynamicLinker linker: linkers) {
   196             if(linker instanceof TypeBasedGuardingDynamicLinker) {
   197                 tblinkers.add((TypeBasedGuardingDynamicLinker)linker);
   198             } else {
   199                 addTypeBased(llinkers, tblinkers);
   200                 llinkers.add(linker);
   201             }
   202         }
   203         addTypeBased(llinkers, tblinkers);
   204         return llinkers;
   205     }
   207     private static void addTypeBased(final List<GuardingDynamicLinker> llinkers,
   208             final List<TypeBasedGuardingDynamicLinker> tblinkers) {
   209         switch(tblinkers.size()) {
   210             case 0: {
   211                 break;
   212             }
   213             case 1: {
   214                 llinkers.addAll(tblinkers);
   215                 tblinkers.clear();
   216                 break;
   217             }
   218             default: {
   219                 llinkers.add(new CompositeTypeBasedGuardingDynamicLinker(tblinkers));
   220                 tblinkers.clear();
   221                 break;
   222             }
   223         }
   224     }
   225 }

mercurial