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