src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java
branchJDK-8200758-branch
changeset 57332 4649818834e0
parent 57331 221a589c52ee
parent 54580 79e95d8dd85d
child 57333 77109ab87402
equal deleted inserted replaced
57331:221a589c52ee 57332:4649818834e0
     1 /*
       
     2  * Copyright (c) 1999, 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.  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  */
       
    25 
       
    26 package com.sun.tools.javac.jvm;
       
    27 
       
    28 import com.sun.tools.javac.code.Symbol;
       
    29 import com.sun.tools.javac.code.Symbol.*;
       
    30 import com.sun.tools.javac.code.TypeTag;
       
    31 import com.sun.tools.javac.code.Type;
       
    32 import com.sun.tools.javac.code.Types;
       
    33 import com.sun.tools.javac.code.Types.UniqueType;
       
    34 
       
    35 import com.sun.tools.javac.util.ArrayUtils;
       
    36 import com.sun.tools.javac.util.Assert;
       
    37 import com.sun.tools.javac.util.Filter;
       
    38 import com.sun.tools.javac.util.Name;
       
    39 
       
    40 import java.util.*;
       
    41 
       
    42 import com.sun.tools.javac.util.DefinedBy;
       
    43 import com.sun.tools.javac.util.DefinedBy.Api;
       
    44 
       
    45 import static com.sun.tools.javac.code.Kinds.*;
       
    46 import static com.sun.tools.javac.code.Kinds.Kind.*;
       
    47 
       
    48 /** An internal structure that corresponds to the constant pool of a classfile.
       
    49  *
       
    50  *  <p><b>This is NOT part of any supported API.
       
    51  *  If you write code that depends on this, you do so at your own risk.
       
    52  *  This code and its internal interfaces are subject to change or
       
    53  *  deletion without notice.</b>
       
    54  */
       
    55 public class Pool {
       
    56 
       
    57     public static final int MAX_ENTRIES = 0xFFFF;
       
    58     public static final int MAX_STRING_LENGTH = 0xFFFF;
       
    59 
       
    60     /** Index of next constant to be entered.
       
    61      */
       
    62     int pp;
       
    63 
       
    64     /** The initial pool buffer.
       
    65      */
       
    66     Object[] pool;
       
    67 
       
    68     /** A hashtable containing all constants in the pool.
       
    69      */
       
    70     Map<Object,Integer> indices;
       
    71 
       
    72     Types types;
       
    73 
       
    74     /** Construct a pool with given number of elements and element array.
       
    75      */
       
    76     public Pool(int pp, Object[] pool, Types types) {
       
    77         this.pp = pp;
       
    78         this.pool = pool;
       
    79         this.types = types;
       
    80         this.indices = new HashMap<>(pool.length);
       
    81         for (int i = 1; i < pp; i++) {
       
    82             if (pool[i] != null) indices.put(pool[i], i);
       
    83         }
       
    84     }
       
    85 
       
    86     /** Construct an empty pool.
       
    87      */
       
    88     public Pool(Types types) {
       
    89         this(1, new Object[64], types);
       
    90     }
       
    91 
       
    92     /** Return the number of entries in the constant pool.
       
    93      */
       
    94     public int numEntries() {
       
    95         return pp;
       
    96     }
       
    97 
       
    98     /** Remove everything from this pool.
       
    99      */
       
   100     public void reset() {
       
   101         pp = 1;
       
   102         indices.clear();
       
   103     }
       
   104 
       
   105     /** Place an object in the pool, unless it is already there.
       
   106      *  If object is a symbol also enter its owner unless the owner is a
       
   107      *  package.  Return the object's index in the pool.
       
   108      */
       
   109     public int put(Object value) {
       
   110         value = makePoolValue(value);
       
   111         Assert.check(!(value instanceof Type.TypeVar));
       
   112         Assert.check(!(value instanceof Types.UniqueType &&
       
   113                        ((UniqueType) value).type instanceof Type.TypeVar));
       
   114         Integer index = indices.get(value);
       
   115         if (index == null) {
       
   116             index = pp;
       
   117             indices.put(value, index);
       
   118             pool = ArrayUtils.ensureCapacity(pool, pp);
       
   119             pool[pp++] = value;
       
   120             if (value instanceof Long || value instanceof Double) {
       
   121                 pool = ArrayUtils.ensureCapacity(pool, pp);
       
   122                 pool[pp++] = null;
       
   123             }
       
   124         }
       
   125         return index.intValue();
       
   126     }
       
   127 
       
   128     Object makePoolValue(Object o) {
       
   129         if (o instanceof DynamicMethodSymbol) {
       
   130             return new DynamicMethod((DynamicMethodSymbol)o, types);
       
   131         } else if (o instanceof MethodSymbol) {
       
   132             return new Method((MethodSymbol)o, types);
       
   133         } else if (o instanceof VarSymbol) {
       
   134             return new Variable((VarSymbol)o, types);
       
   135         } else if (o instanceof Type) {
       
   136             Type t = (Type)o;
       
   137             // ClassRefs can come from ClassSymbols or from Types.
       
   138             // Return the symbol for these types to avoid duplicates
       
   139             // in the constant pool
       
   140             if (t.hasTag(TypeTag.CLASS))
       
   141                 return t.tsym;
       
   142             else
       
   143                 return new UniqueType(t, types);
       
   144         } else {
       
   145             return o;
       
   146         }
       
   147     }
       
   148 
       
   149     /** Return the given object's index in the pool,
       
   150      *  or -1 if object is not in there.
       
   151      */
       
   152     public int get(Object o) {
       
   153         Integer n = indices.get(o);
       
   154         return n == null ? -1 : n.intValue();
       
   155     }
       
   156 
       
   157     static class Method extends DelegatedSymbol<MethodSymbol> {
       
   158         UniqueType uniqueType;
       
   159         Method(MethodSymbol m, Types types) {
       
   160             super(m);
       
   161             this.uniqueType = new UniqueType(m.type, types);
       
   162         }
       
   163         @DefinedBy(Api.LANGUAGE_MODEL)
       
   164         public boolean equals(Object any) {
       
   165             if (!(any instanceof Method)) return false;
       
   166             MethodSymbol o = ((Method)any).other;
       
   167             MethodSymbol m = this.other;
       
   168             return
       
   169                 o.name == m.name &&
       
   170                 o.owner == m.owner &&
       
   171                 ((Method)any).uniqueType.equals(uniqueType);
       
   172         }
       
   173         @DefinedBy(Api.LANGUAGE_MODEL)
       
   174         public int hashCode() {
       
   175             MethodSymbol m = this.other;
       
   176             return
       
   177                 m.name.hashCode() * 33 +
       
   178                 m.owner.hashCode() * 9 +
       
   179                 uniqueType.hashCode();
       
   180         }
       
   181     }
       
   182 
       
   183     public static class DynamicMethod extends Method {
       
   184         public Object[] uniqueStaticArgs;
       
   185 
       
   186         public DynamicMethod(DynamicMethodSymbol m, Types types) {
       
   187             super(m, types);
       
   188             uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
       
   189         }
       
   190 
       
   191         @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   192         public boolean equals(Object any) {
       
   193             return equalsImpl(any, true);
       
   194         }
       
   195 
       
   196         protected boolean equalsImpl(Object any, boolean includeDynamicArgs) {
       
   197             if (includeDynamicArgs && !super.equals(any)) return false;
       
   198             if (!(any instanceof DynamicMethod)) return false;
       
   199             DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other;
       
   200             DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other;
       
   201             return dm1.bsm == dm2.bsm &&
       
   202                         dm1.bsmKind == dm2.bsmKind &&
       
   203                         Arrays.equals(uniqueStaticArgs,
       
   204                             ((DynamicMethod)any).uniqueStaticArgs);
       
   205         }
       
   206 
       
   207         @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   208         public int hashCode() {
       
   209             return hashCodeImpl(true);
       
   210         }
       
   211 
       
   212         protected int hashCodeImpl(boolean includeDynamicArgs) {
       
   213             int hash = includeDynamicArgs ? super.hashCode() : 0;
       
   214             DynamicMethodSymbol dm = (DynamicMethodSymbol)other;
       
   215             hash += dm.bsmKind * 7 +
       
   216                     dm.bsm.hashCode() * 11;
       
   217             for (int i = 0; i < dm.staticArgs.length; i++) {
       
   218                 hash += (uniqueStaticArgs[i].hashCode() * 23);
       
   219             }
       
   220             return hash;
       
   221         }
       
   222 
       
   223         private Object[] getUniqueTypeArray(Object[] objects, Types types) {
       
   224             Object[] result = new Object[objects.length];
       
   225             for (int i = 0; i < objects.length; i++) {
       
   226                 if (objects[i] instanceof Type) {
       
   227                     result[i] = new UniqueType((Type)objects[i], types);
       
   228                 } else {
       
   229                     result[i] = objects[i];
       
   230                 }
       
   231             }
       
   232             return result;
       
   233         }
       
   234 
       
   235         static class BootstrapMethodsKey extends DynamicMethod {
       
   236             BootstrapMethodsKey(DynamicMethodSymbol m, Types types) {
       
   237                 super(m, types);
       
   238             }
       
   239 
       
   240             @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   241             public boolean equals(Object any) {
       
   242                 return equalsImpl(any, false);
       
   243             }
       
   244 
       
   245             @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   246             public int hashCode() {
       
   247                 return hashCodeImpl(false);
       
   248             }
       
   249 
       
   250             Object[] getUniqueArgs() {
       
   251                 return uniqueStaticArgs;
       
   252             }
       
   253         }
       
   254 
       
   255         static class BootstrapMethodsValue {
       
   256             final MethodHandle mh;
       
   257             final int index;
       
   258 
       
   259             public BootstrapMethodsValue(MethodHandle mh, int index) {
       
   260                 this.mh = mh;
       
   261                 this.index = index;
       
   262             }
       
   263         }
       
   264     }
       
   265 
       
   266     static class Variable extends DelegatedSymbol<VarSymbol> {
       
   267         UniqueType uniqueType;
       
   268         Variable(VarSymbol v, Types types) {
       
   269             super(v);
       
   270             this.uniqueType = new UniqueType(v.type, types);
       
   271         }
       
   272         @DefinedBy(Api.LANGUAGE_MODEL)
       
   273         public boolean equals(Object any) {
       
   274             if (!(any instanceof Variable)) return false;
       
   275             VarSymbol o = ((Variable)any).other;
       
   276             VarSymbol v = other;
       
   277             return
       
   278                 o.name == v.name &&
       
   279                 o.owner == v.owner &&
       
   280                 ((Variable)any).uniqueType.equals(uniqueType);
       
   281         }
       
   282         @DefinedBy(Api.LANGUAGE_MODEL)
       
   283         public int hashCode() {
       
   284             VarSymbol v = other;
       
   285             return
       
   286                 v.name.hashCode() * 33 +
       
   287                 v.owner.hashCode() * 9 +
       
   288                 uniqueType.hashCode();
       
   289         }
       
   290     }
       
   291 
       
   292     public static class MethodHandle {
       
   293 
       
   294         /** Reference kind - see ClassFile */
       
   295         int refKind;
       
   296 
       
   297         /** Reference symbol */
       
   298         Symbol refSym;
       
   299 
       
   300         UniqueType uniqueType;
       
   301 
       
   302         public MethodHandle(int refKind, Symbol refSym, Types types) {
       
   303             this.refKind = refKind;
       
   304             this.refSym = refSym;
       
   305             this.uniqueType = new UniqueType(this.refSym.type, types);
       
   306             checkConsistent();
       
   307         }
       
   308         public boolean equals(Object other) {
       
   309             if (!(other instanceof MethodHandle)) return false;
       
   310             MethodHandle mr = (MethodHandle) other;
       
   311             if (mr.refKind != refKind)  return false;
       
   312             Symbol o = mr.refSym;
       
   313             return
       
   314                 o.name == refSym.name &&
       
   315                 o.owner == refSym.owner &&
       
   316                 ((MethodHandle)other).uniqueType.equals(uniqueType);
       
   317         }
       
   318         public int hashCode() {
       
   319             return
       
   320                 refKind * 65 +
       
   321                 refSym.name.hashCode() * 33 +
       
   322                 refSym.owner.hashCode() * 9 +
       
   323                 uniqueType.hashCode();
       
   324         }
       
   325 
       
   326         /**
       
   327          * Check consistency of reference kind and symbol (see JVMS 4.4.8)
       
   328          */
       
   329         @SuppressWarnings("fallthrough")
       
   330         private void checkConsistent() {
       
   331             boolean staticOk = false;
       
   332             Kind expectedKind = null;
       
   333             Filter<Name> nameFilter = nonInitFilter;
       
   334             boolean interfaceOwner = false;
       
   335             switch (refKind) {
       
   336                 case ClassFile.REF_getStatic:
       
   337                 case ClassFile.REF_putStatic:
       
   338                     staticOk = true;
       
   339                 case ClassFile.REF_getField:
       
   340                 case ClassFile.REF_putField:
       
   341                     expectedKind = VAR;
       
   342                     break;
       
   343                 case ClassFile.REF_newInvokeSpecial:
       
   344                     nameFilter = initFilter;
       
   345                     expectedKind = MTH;
       
   346                     break;
       
   347                 case ClassFile.REF_invokeInterface:
       
   348                     interfaceOwner = true;
       
   349                     expectedKind = MTH;
       
   350                     break;
       
   351                 case ClassFile.REF_invokeStatic:
       
   352                     interfaceOwner = true;
       
   353                     staticOk = true;
       
   354                 case ClassFile.REF_invokeVirtual:
       
   355                     expectedKind = MTH;
       
   356                     break;
       
   357                 case ClassFile.REF_invokeSpecial:
       
   358                     interfaceOwner = true;
       
   359                     expectedKind = MTH;
       
   360                     break;
       
   361             }
       
   362             Assert.check(!refSym.isStatic() || staticOk);
       
   363             Assert.check(refSym.kind == expectedKind);
       
   364             Assert.check(nameFilter.accepts(refSym.name));
       
   365             Assert.check(!refSym.owner.isInterface() || interfaceOwner);
       
   366         }
       
   367         //where
       
   368                 Filter<Name> nonInitFilter = n -> (n != n.table.names.init && n != n.table.names.clinit);
       
   369 
       
   370                 Filter<Name> initFilter = n -> n == n.table.names.init;
       
   371     }
       
   372 }