1 /*
   2  * Copyright (c) 2019, 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.Type;
  29 import com.sun.tools.javac.code.Types;
  30 import com.sun.tools.javac.code.Types.UniqueType;
  31 import com.sun.tools.javac.util.List;
  32 import com.sun.tools.javac.util.Name;
  33 import com.sun.tools.javac.util.Pair;
  34 
  35 import java.util.Objects;
  36 import java.util.stream.Stream;
  37 
  38 import com.sun.tools.javac.code.Symbol;
  39 
  40 /**
  41  * This interface models all javac entities that can be used to represent constant pool entries.
  42  * A pool constant entity must (i) be associated with a constant pool entry tag and have a function
  43  * which generates a key for the desired pool entry (so as to avoid duplicate entries when writing the
  44  * constant pool).
  45  */
  46 public interface PoolConstant {
  47 
  48     /**
  49      * The constant pool entry key.
  50      */
  51     default Object poolKey(Types types) { return this; }
  52 
  53     /**
  54      * The constant pool entry tag.
  55      */
  56     int poolTag();
  57 
  58     /**
  59      * The root of pool constants that can be loaded (e.g. with {@code ldc}, or appear as static
  60      * arguments to a bootstrap method.
  61      */
  62     interface LoadableConstant extends PoolConstant {
  63 
  64         /**
  65          * Create a pool constant describing a given {@code int} value.
  66          */
  67         static LoadableConstant Int(int i) {
  68             return new BasicConstant(ClassFile.CONSTANT_Integer, i);
  69         }
  70 
  71         /**
  72          * Create a pool constant describing a given {@code float} value.
  73          */
  74         static LoadableConstant Float(float f) {
  75             return new BasicConstant(ClassFile.CONSTANT_Float, f);
  76         }
  77 
  78         /**
  79          * Create a pool constant describing a given {@code long} value.
  80          */
  81         static LoadableConstant Long(long l) {
  82             return new BasicConstant(ClassFile.CONSTANT_Long, l);
  83         }
  84 
  85         /**
  86          * Create a pool constant describing a given {@code double} value.
  87          */
  88         static LoadableConstant Double(double d) {
  89             return new BasicConstant(ClassFile.CONSTANT_Double, d);
  90         }
  91 
  92         /**
  93          * Create a pool constant describing a given {@code String} value.
  94          */
  95         static LoadableConstant String(String s) {
  96             return new BasicConstant(ClassFile.CONSTANT_String, s);
  97         }
  98 
  99         /**
 100          * This class models a pool constant of given basic type, one of {@code int}, {@code float},
 101          * {@code long}, {@code double} or {@code String}.
 102          */
 103         class BasicConstant implements LoadableConstant {
 104             int tag;
 105             Object data;
 106 
 107             private BasicConstant(int tag, Object data) {
 108                 this.tag = tag;
 109                 this.data = data;
 110             }
 111 
 112             @Override
 113             public int poolTag() {
 114                 return tag;
 115             }
 116 
 117             @Override
 118             public Object poolKey(Types types) {
 119                 return data;
 120             }
 121         }
 122     }
 123 
 124     /**
 125      * This interface models a dynamic pool constant (either of kind {@code InvokeDynamic} or
 126      * {@code ConstantDynamic}). In addition to the functionalities provided by the base interface,
 127      * a dynamic pool constant must expose its dynamic type, bootstrap method and static argument list.
 128      * Finally, a dynamic constant must have a way to compute a bootstrap method key - that is,
 129      * a unique key for the bootstrap method entry it refers to, to avoid duplicates when writing
 130      * the {@code BootstrapMethods} attribute.
 131      */
 132     interface Dynamic extends PoolConstant {
 133 
 134         /**
 135          * The dynamic constant's dynamic type.
 136          */
 137         PoolConstant dynamicType();
 138 
 139         /**
 140          * The dynamic constant's static argument list.
 141          */
 142         LoadableConstant[] staticArgs();
 143 
 144         /**
 145          * The dynamic constant's bootstrap method.
 146          */
 147         LoadableConstant bootstrapMethod();
 148 
 149         default BsmKey bsmKey(Types types) {
 150             return new BsmKey(types, bootstrapMethod(), staticArgs());
 151         }
 152 
 153         @Override
 154         default Object poolKey(Types types) {
 155             return new Pair<>(bsmKey(types), dynamicType().poolKey(types));
 156         }
 157 
 158         /**
 159          * A class modelling a bootstrap method key.
 160          */
 161         class BsmKey {
 162             /**
 163              * The key's bootstrap method constant.
 164              */
 165             public final LoadableConstant bsm;
 166 
 167             /**
 168              * The key's static argument list.
 169              */
 170             public final LoadableConstant[] staticArgs;
 171 
 172             private final Object bsmKey;
 173             private final List<?> staticArgKeys;
 174 
 175             private BsmKey(Types types, LoadableConstant bsm, LoadableConstant[] staticArgs) {
 176                 this.bsm = bsm;
 177                 this.bsmKey = bsm.poolKey(types);
 178                 this.staticArgs = staticArgs;
 179                 this.staticArgKeys = Stream.of(staticArgs)
 180                         .map(p -> p.poolKey(types))
 181                         .collect(List.collector());
 182             }
 183 
 184             @Override
 185             public int hashCode() {
 186                 return bsmKey.hashCode() +
 187                         staticArgKeys.hashCode();
 188             }
 189 
 190             @Override
 191             public boolean equals(Object obj) {
 192                 if (obj instanceof BsmKey) {
 193                     BsmKey other = (BsmKey)obj;
 194                     return Objects.equals(bsmKey, other.bsmKey) &&
 195                             Objects.equals(staticArgKeys, other.staticArgKeys);
 196                 } else {
 197                     return false;
 198                 }
 199             }
 200         }
 201     }
 202 
 203     /**
 204      * A pool constant implememntation describing a name and type pool entry.
 205      */
 206     final class NameAndType implements PoolConstant {
 207 
 208         final Name name;
 209         final Type type;
 210 
 211         NameAndType(Name name, Type type) {
 212             this.name = name;
 213             this.type = type;
 214         }
 215 
 216         @Override
 217         public int poolTag() {
 218             return ClassFile.CONSTANT_NameandType;
 219         }
 220 
 221         @Override
 222         public Object poolKey(Types types) {
 223             return new Pair<>(name, new UniqueType(type, types));
 224         }
 225     }
 226 }