src/share/classes/com/sun/tools/javac/jvm/Pool.java

Sun, 17 Feb 2013 16:44:55 -0500

author
dholmes
date
Sun, 17 Feb 2013 16:44:55 -0500
changeset 1571
af8417e590f4
parent 1541
4cc73ec94686
child 1617
d0178bd8125c
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 1999, 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 package com.sun.tools.javac.jvm;
    28 import com.sun.tools.javac.code.Kinds;
    29 import com.sun.tools.javac.code.Symbol;
    30 import com.sun.tools.javac.code.Symbol.*;
    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;
    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;
    40 import java.util.*;
    42 /** An internal structure that corresponds to the constant pool of a classfile.
    43  *
    44  *  <p><b>This is NOT part of any supported API.
    45  *  If you write code that depends on this, you do so at your own risk.
    46  *  This code and its internal interfaces are subject to change or
    47  *  deletion without notice.</b>
    48  */
    49 public class Pool {
    51     public static final int MAX_ENTRIES = 0xFFFF;
    52     public static final int MAX_STRING_LENGTH = 0xFFFF;
    54     /** Index of next constant to be entered.
    55      */
    56     int pp;
    58     /** The initial pool buffer.
    59      */
    60     Object[] pool;
    62     /** A hashtable containing all constants in the pool.
    63      */
    64     Map<Object,Integer> indices;
    66     Types types;
    68     /** Construct a pool with given number of elements and element array.
    69      */
    70     public Pool(int pp, Object[] pool, Types types) {
    71         this.pp = pp;
    72         this.pool = pool;
    73         this.types = types;
    74         this.indices = new HashMap<Object,Integer>(pool.length);
    75         for (int i = 1; i < pp; i++) {
    76             if (pool[i] != null) indices.put(pool[i], i);
    77         }
    78     }
    80     /** Construct an empty pool.
    81      */
    82     public Pool(Types types) {
    83         this(1, new Object[64], types);
    84     }
    86     /** Return the number of entries in the constant pool.
    87      */
    88     public int numEntries() {
    89         return pp;
    90     }
    92     /** Remove everything from this pool.
    93      */
    94     public void reset() {
    95         pp = 1;
    96         indices.clear();
    97     }
    99     /** Place an object in the pool, unless it is already there.
   100      *  If object is a symbol also enter its owner unless the owner is a
   101      *  package.  Return the object's index in the pool.
   102      */
   103     public int put(Object value) {
   104         value = makePoolValue(value);
   105 //      assert !(value instanceof Type.TypeVar);
   106         Integer index = indices.get(value);
   107         if (index == null) {
   108 //          System.err.println("put " + value + " " + value.getClass());//DEBUG
   109             index = pp;
   110             indices.put(value, index);
   111             pool = ArrayUtils.ensureCapacity(pool, pp);
   112             pool[pp++] = value;
   113             if (value instanceof Long || value instanceof Double) {
   114                 pool = ArrayUtils.ensureCapacity(pool, pp);
   115                 pool[pp++] = null;
   116             }
   117         }
   118         return index.intValue();
   119     }
   121     Object makePoolValue(Object o) {
   122         if (o instanceof DynamicMethodSymbol) {
   123             return new DynamicMethod((DynamicMethodSymbol)o, types);
   124         } else if (o instanceof MethodSymbol) {
   125             return new Method((MethodSymbol)o, types);
   126         } else if (o instanceof VarSymbol) {
   127             return new Variable((VarSymbol)o, types);
   128         } else if (o instanceof Type) {
   129             return new UniqueType((Type)o, types);
   130         } else {
   131             return o;
   132         }
   133     }
   135     /** Return the given object's index in the pool,
   136      *  or -1 if object is not in there.
   137      */
   138     public int get(Object o) {
   139         Integer n = indices.get(o);
   140         return n == null ? -1 : n.intValue();
   141     }
   143     static class Method extends DelegatedSymbol<MethodSymbol> {
   144         UniqueType uniqueType;
   145         Method(MethodSymbol m, Types types) {
   146             super(m);
   147             this.uniqueType = new UniqueType(m.type, types);
   148         }
   149         public boolean equals(Object any) {
   150             if (!(any instanceof Method)) return false;
   151             MethodSymbol o = ((Method)any).other;
   152             MethodSymbol m = this.other;
   153             return
   154                 o.name == m.name &&
   155                 o.owner == m.owner &&
   156                 ((Method)any).uniqueType.equals(uniqueType);
   157         }
   158         public int hashCode() {
   159             MethodSymbol m = this.other;
   160             return
   161                 m.name.hashCode() * 33 +
   162                 m.owner.hashCode() * 9 +
   163                 uniqueType.hashCode();
   164         }
   165     }
   167     static class DynamicMethod extends Method {
   168         public Object[] uniqueStaticArgs;
   170         DynamicMethod(DynamicMethodSymbol m, Types types) {
   171             super(m, types);
   172             uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
   173         }
   175         @Override
   176         public boolean equals(Object any) {
   177             if (!super.equals(any)) return false;
   178             if (!(any instanceof DynamicMethod)) return false;
   179             DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other;
   180             DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other;
   181             return dm1.bsm == dm2.bsm &&
   182                         dm1.bsmKind == dm2.bsmKind &&
   183                         Arrays.equals(uniqueStaticArgs,
   184                             ((DynamicMethod)any).uniqueStaticArgs);
   185         }
   187         @Override
   188         public int hashCode() {
   189             int hash = super.hashCode();
   190             DynamicMethodSymbol dm = (DynamicMethodSymbol)other;
   191             hash += dm.bsmKind * 7 +
   192                     dm.bsm.hashCode() * 11;
   193             for (int i = 0; i < dm.staticArgs.length; i++) {
   194                 hash += (uniqueStaticArgs[i].hashCode() * 23);
   195             }
   196             return hash;
   197         }
   199         private Object[] getUniqueTypeArray(Object[] objects, Types types) {
   200             Object[] result = new Object[objects.length];
   201             for (int i = 0; i < objects.length; i++) {
   202                 if (objects[i] instanceof Type) {
   203                     result[i] = new UniqueType((Type)objects[i], types);
   204                 } else {
   205                     result[i] = objects[i];
   206                 }
   207             }
   208             return result;
   209         }
   210     }
   212     static class Variable extends DelegatedSymbol<VarSymbol> {
   213         UniqueType uniqueType;
   214         Variable(VarSymbol v, Types types) {
   215             super(v);
   216             this.uniqueType = new UniqueType(v.type, types);
   217         }
   218         public boolean equals(Object any) {
   219             if (!(any instanceof Variable)) return false;
   220             VarSymbol o = ((Variable)any).other;
   221             VarSymbol v = other;
   222             return
   223                 o.name == v.name &&
   224                 o.owner == v.owner &&
   225                 ((Variable)any).uniqueType.equals(uniqueType);
   226         }
   227         public int hashCode() {
   228             VarSymbol v = other;
   229             return
   230                 v.name.hashCode() * 33 +
   231                 v.owner.hashCode() * 9 +
   232                 uniqueType.hashCode();
   233         }
   234     }
   236     public static class MethodHandle {
   238         /** Reference kind - see ClassFile */
   239         int refKind;
   241         /** Reference symbol */
   242         Symbol refSym;
   244         UniqueType uniqueType;
   246         public MethodHandle(int refKind, Symbol refSym, Types types) {
   247             this.refKind = refKind;
   248             this.refSym = refSym;
   249             this.uniqueType = new UniqueType(this.refSym.type, types);
   250             checkConsistent();
   251         }
   252         public boolean equals(Object other) {
   253             if (!(other instanceof MethodHandle)) return false;
   254             MethodHandle mr = (MethodHandle) other;
   255             if (mr.refKind != refKind)  return false;
   256             Symbol o = mr.refSym;
   257             return
   258                 o.name == refSym.name &&
   259                 o.owner == refSym.owner &&
   260                 ((MethodHandle)other).uniqueType.equals(uniqueType);
   261         }
   262         public int hashCode() {
   263             return
   264                 refKind * 65 +
   265                 refSym.name.hashCode() * 33 +
   266                 refSym.owner.hashCode() * 9 +
   267                 uniqueType.hashCode();
   268         }
   270         /**
   271          * Check consistency of reference kind and symbol (see JVMS 4.4.8)
   272          */
   273         @SuppressWarnings("fallthrough")
   274         private void checkConsistent() {
   275             boolean staticOk = false;
   276             int expectedKind = -1;
   277             Filter<Name> nameFilter = nonInitFilter;
   278             boolean interfaceOwner = false;
   279             switch (refKind) {
   280                 case ClassFile.REF_getStatic:
   281                 case ClassFile.REF_putStatic:
   282                     staticOk = true;
   283                 case ClassFile.REF_getField:
   284                 case ClassFile.REF_putField:
   285                     expectedKind = Kinds.VAR;
   286                     break;
   287                 case ClassFile.REF_newInvokeSpecial:
   288                     nameFilter = initFilter;
   289                     expectedKind = Kinds.MTH;
   290                     break;
   291                 case ClassFile.REF_invokeInterface:
   292                     interfaceOwner = true;
   293                     expectedKind = Kinds.MTH;
   294                     break;
   295                 case ClassFile.REF_invokeStatic:
   296                     staticOk = true;
   297                 case ClassFile.REF_invokeVirtual:
   298                 case ClassFile.REF_invokeSpecial:
   299                     expectedKind = Kinds.MTH;
   300                     break;
   301             }
   302             Assert.check(!refSym.isStatic() || staticOk);
   303             Assert.check(refSym.kind == expectedKind);
   304             Assert.check(nameFilter.accepts(refSym.name));
   305             Assert.check(!refSym.owner.isInterface() || interfaceOwner);
   306         }
   307         //where
   308                 Filter<Name> nonInitFilter = new Filter<Name>() {
   309                     public boolean accepts(Name n) {
   310                         return n != n.table.names.init && n != n.table.names.clinit;
   311                     }
   312                 };
   314                 Filter<Name> initFilter = new Filter<Name>() {
   315                     public boolean accepts(Name n) {
   316                         return n == n.table.names.init;
   317                     }
   318                 };
   319     }
   320 }

mercurial