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

Tue, 25 Sep 2012 11:53:18 +0100

author
mcimadamore
date
Tue, 25 Sep 2012 11:53:18 +0100
changeset 1336
26d93df3905a
parent 581
f2fdd52e4e87
child 1339
0e5899f09dab
permissions
-rw-r--r--

7194586: Add back-end support for invokedynamic
Summary: Add support for invokedynamic bytecode instruction; includes suppot for generation of all related classfile attributes
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 1999, 2008, 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.Flags;
    29 import com.sun.tools.javac.code.Kinds;
    30 import java.util.*;
    32 import com.sun.tools.javac.code.Symbol;
    33 import com.sun.tools.javac.code.Symbol.*;
    34 import com.sun.tools.javac.code.Type;
    35 import com.sun.tools.javac.util.Assert;
    36 import com.sun.tools.javac.util.Filter;
    37 import com.sun.tools.javac.util.Name;
    38 import com.sun.tools.javac.util.Names;
    40 /** An internal structure that corresponds to the constant pool of a classfile.
    41  *
    42  *  <p><b>This is NOT part of any supported API.
    43  *  If you write code that depends on this, you do so at your own risk.
    44  *  This code and its internal interfaces are subject to change or
    45  *  deletion without notice.</b>
    46  */
    47 public class Pool {
    49     public static final int MAX_ENTRIES = 0xFFFF;
    50     public static final int MAX_STRING_LENGTH = 0xFFFF;
    52     /** Index of next constant to be entered.
    53      */
    54     int pp;
    56     /** The initial pool buffer.
    57      */
    58     Object[] pool;
    60     /** A hashtable containing all constants in the pool.
    61      */
    62     Map<Object,Integer> indices;
    64     /** Construct a pool with given number of elements and element array.
    65      */
    66     public Pool(int pp, Object[] pool) {
    67         this.pp = pp;
    68         this.pool = pool;
    69         this.indices = new HashMap<Object,Integer>(pool.length);
    70         for (int i = 1; i < pp; i++) {
    71             if (pool[i] != null) indices.put(pool[i], i);
    72         }
    73     }
    75     /** Construct an empty pool.
    76      */
    77     public Pool() {
    78         this(1, new Object[64]);
    79     }
    81     /** Return the number of entries in the constant pool.
    82      */
    83     public int numEntries() {
    84         return pp;
    85     }
    87     /** Remove everything from this pool.
    88      */
    89     public void reset() {
    90         pp = 1;
    91         indices.clear();
    92     }
    94     /** Double pool buffer in size.
    95      */
    96     private void doublePool() {
    97         Object[] newpool = new Object[pool.length * 2];
    98         System.arraycopy(pool, 0, newpool, 0, pool.length);
    99         pool = newpool;
   100     }
   102     /** Place an object in the pool, unless it is already there.
   103      *  If object is a symbol also enter its owner unless the owner is a
   104      *  package.  Return the object's index in the pool.
   105      */
   106     public int put(Object value) {
   107         if (value instanceof MethodSymbol)
   108             value = new Method((MethodSymbol)value);
   109         else if (value instanceof VarSymbol)
   110             value = new Variable((VarSymbol)value);
   111 //      assert !(value instanceof Type.TypeVar);
   112         Integer index = indices.get(value);
   113         if (index == null) {
   114 //          System.err.println("put " + value + " " + value.getClass());//DEBUG
   115             index = pp;
   116             indices.put(value, index);
   117             if (pp == pool.length) doublePool();
   118             pool[pp++] = value;
   119             if (value instanceof Long || value instanceof Double) {
   120                 if (pp == pool.length) doublePool();
   121                 pool[pp++] = null;
   122             }
   123         }
   124         return index.intValue();
   125     }
   127     /** Return the given object's index in the pool,
   128      *  or -1 if object is not in there.
   129      */
   130     public int get(Object o) {
   131         Integer n = indices.get(o);
   132         return n == null ? -1 : n.intValue();
   133     }
   135     static class Method extends DelegatedSymbol {
   136         MethodSymbol m;
   137         Method(MethodSymbol m) {
   138             super(m);
   139             this.m = m;
   140         }
   141         public boolean equals(Object other) {
   142             if (!(other instanceof Method)) return false;
   143             MethodSymbol o = ((Method)other).m;
   144             return
   145                 o.name == m.name &&
   146                 o.owner == m.owner &&
   147                 o.type.equals(m.type);
   148         }
   149         public int hashCode() {
   150             return
   151                 m.name.hashCode() * 33 +
   152                 m.owner.hashCode() * 9 +
   153                 m.type.hashCode();
   154         }
   155     }
   157     static class Variable extends DelegatedSymbol {
   158         VarSymbol v;
   159         Variable(VarSymbol v) {
   160             super(v);
   161             this.v = v;
   162         }
   163         public boolean equals(Object other) {
   164             if (!(other instanceof Variable)) return false;
   165             VarSymbol o = ((Variable)other).v;
   166             return
   167                 o.name == v.name &&
   168                 o.owner == v.owner &&
   169                 o.type.equals(v.type);
   170         }
   171         public int hashCode() {
   172             return
   173                 v.name.hashCode() * 33 +
   174                 v.owner.hashCode() * 9 +
   175                 v.type.hashCode();
   176         }
   177     }
   179     public static class MethodHandle {
   181         /** Reference kind - see ClassFile */
   182         int refKind;
   184         /** Reference symbol */
   185         Symbol refSym;
   187         /** Reference to the name table */
   188         Names names;
   190         public MethodHandle(int refKind, Symbol refSym, Names names) {
   191             this.refKind = refKind;
   192             this.refSym = refSym;
   193             this.names = names;
   194             checkConsistent();
   195         }
   196         public boolean equals(Object other) {
   197             if (!(other instanceof MethodHandle)) return false;
   198             MethodHandle mr = (MethodHandle) other;
   199             if (mr.refKind != refKind)  return false;
   200             Symbol o = mr.refSym;
   201             return
   202                 o.name == refSym.name &&
   203                 o.owner == refSym.owner &&
   204                 o.type.equals(refSym.type);
   205         }
   206         public int hashCode() {
   207             return
   208                 refKind * 65 +
   209                 refSym.name.hashCode() * 33 +
   210                 refSym.owner.hashCode() * 9 +
   211                 refSym.type.hashCode();
   212         }
   214         /**
   215          * Check consistency of reference kind and symbol (see JVMS 4.4.8)
   216          */
   217         @SuppressWarnings("fallthrough")
   218         private void checkConsistent() {
   219             boolean staticOk = false;
   220             int expectedKind = -1;
   221             Filter<Name> nameFilter = nonInitFilter;
   222             boolean interfaceOwner = false;
   223             switch (refKind) {
   224                 case ClassFile.REF_getStatic:
   225                 case ClassFile.REF_putStatic:
   226                     staticOk = true;
   227                 case ClassFile.REF_getField:
   228                 case ClassFile.REF_putField:
   229                     expectedKind = Kinds.VAR;
   230                     break;
   231                 case ClassFile.REF_newInvokeSpecial:
   232                     nameFilter = initFilter;
   233                     expectedKind = Kinds.MTH;
   234                     break;
   235                 case ClassFile.REF_invokeInterface:
   236                     interfaceOwner = true;
   237                     expectedKind = Kinds.MTH;
   238                     break;
   239                 case ClassFile.REF_invokeStatic:
   240                     staticOk = true;
   241                 case ClassFile.REF_invokeVirtual:
   242                 case ClassFile.REF_invokeSpecial:
   243                     expectedKind = Kinds.MTH;
   244                     break;
   245             }
   246             Assert.check(!refSym.isStatic() || staticOk);
   247             Assert.check(refSym.kind == expectedKind);
   248             Assert.check(nameFilter.accepts(refSym.name));
   249             Assert.check(!refSym.owner.isInterface() || interfaceOwner);
   250         }
   251         //where
   252                 Filter<Name> nonInitFilter = new Filter<Name>() {
   253                     public boolean accepts(Name n) {
   254                         return n != names.init && n != names.clinit;
   255                     }
   256                 };
   258                 Filter<Name> initFilter = new Filter<Name>() {
   259                     public boolean accepts(Name n) {
   260                         return n == names.init;
   261                     }
   262                 };
   263     }
   264 }

mercurial