/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javac.jvm;

import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Pair;

import java.util.Objects;
import java.util.stream.Stream;

This interface models all javac entities that can be used to represent constant pool entries. A pool constant entity must (i) be associated with a constant pool entry tag and have a function which generates a key for the desired pool entry (so as to avoid duplicate entries when writing the constant pool).
/** * This interface models all javac entities that can be used to represent constant pool entries. * A pool constant entity must (i) be associated with a constant pool entry tag and have a function * which generates a key for the desired pool entry (so as to avoid duplicate entries when writing the * constant pool). */
public interface PoolConstant {
The constant pool entry key.
/** * The constant pool entry key. */
default Object poolKey(Types types) { return this; }
The constant pool entry tag.
/** * The constant pool entry tag. */
int poolTag();
The root of pool constants that can be loaded (e.g. with ldc, or appear as static arguments to a bootstrap method.
/** * The root of pool constants that can be loaded (e.g. with {@code ldc}, or appear as static * arguments to a bootstrap method. */
interface LoadableConstant extends PoolConstant {
Create a pool constant describing a given int value.
/** * Create a pool constant describing a given {@code int} value. */
static LoadableConstant Int(int i) { return new BasicConstant(ClassFile.CONSTANT_Integer, i); }
Create a pool constant describing a given float value.
/** * Create a pool constant describing a given {@code float} value. */
static LoadableConstant Float(float f) { return new BasicConstant(ClassFile.CONSTANT_Float, f); }
Create a pool constant describing a given long value.
/** * Create a pool constant describing a given {@code long} value. */
static LoadableConstant Long(long l) { return new BasicConstant(ClassFile.CONSTANT_Long, l); }
Create a pool constant describing a given double value.
/** * Create a pool constant describing a given {@code double} value. */
static LoadableConstant Double(double d) { return new BasicConstant(ClassFile.CONSTANT_Double, d); }
Create a pool constant describing a given String value.
/** * Create a pool constant describing a given {@code String} value. */
static LoadableConstant String(String s) { return new BasicConstant(ClassFile.CONSTANT_String, s); }
This class models a pool constant of given basic type, one of int, float, long, double or String.
/** * This class models a pool constant of given basic type, one of {@code int}, {@code float}, * {@code long}, {@code double} or {@code String}. */
class BasicConstant implements LoadableConstant { int tag; Object data; private BasicConstant(int tag, Object data) { this.tag = tag; this.data = data; } @Override public int poolTag() { return tag; } @Override public Object poolKey(Types types) { return data; } } }
This interface models a dynamic pool constant (either of kind InvokeDynamic or ConstantDynamic). In addition to the functionalities provided by the base interface, a dynamic pool constant must expose its dynamic type, bootstrap method and static argument list. Finally, a dynamic constant must have a way to compute a bootstrap method key - that is, a unique key for the bootstrap method entry it refers to, to avoid duplicates when writing the BootstrapMethods attribute.
/** * This interface models a dynamic pool constant (either of kind {@code InvokeDynamic} or * {@code ConstantDynamic}). In addition to the functionalities provided by the base interface, * a dynamic pool constant must expose its dynamic type, bootstrap method and static argument list. * Finally, a dynamic constant must have a way to compute a bootstrap method key - that is, * a unique key for the bootstrap method entry it refers to, to avoid duplicates when writing * the {@code BootstrapMethods} attribute. */
interface Dynamic extends PoolConstant {
The dynamic constant's dynamic type.
/** * The dynamic constant's dynamic type. */
PoolConstant dynamicType();
The dynamic constant's static argument list.
/** * The dynamic constant's static argument list. */
LoadableConstant[] staticArgs();
The dynamic constant's bootstrap method.
/** * The dynamic constant's bootstrap method. */
LoadableConstant bootstrapMethod(); default BsmKey bsmKey(Types types) { return new BsmKey(types, bootstrapMethod(), staticArgs()); } @Override default Object poolKey(Types types) { return new Pair<>(bsmKey(types), dynamicType().poolKey(types)); }
A class modelling a bootstrap method key.
/** * A class modelling a bootstrap method key. */
class BsmKey {
The key's bootstrap method constant.
/** * The key's bootstrap method constant. */
public final LoadableConstant bsm;
The key's static argument list.
/** * The key's static argument list. */
public final LoadableConstant[] staticArgs; private final Object bsmKey; private final List<?> staticArgKeys; private BsmKey(Types types, LoadableConstant bsm, LoadableConstant[] staticArgs) { this.bsm = bsm; this.bsmKey = bsm.poolKey(types); this.staticArgs = staticArgs; this.staticArgKeys = Stream.of(staticArgs) .map(p -> p.poolKey(types)) .collect(List.collector()); } @Override public int hashCode() { return bsmKey.hashCode() + staticArgKeys.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof BsmKey) { BsmKey other = (BsmKey)obj; return Objects.equals(bsmKey, other.bsmKey) && Objects.equals(staticArgKeys, other.staticArgKeys); } else { return false; } } } }
A pool constant implememntation describing a name and type pool entry.
/** * A pool constant implememntation describing a name and type pool entry. */
final class NameAndType implements PoolConstant { final Name name; final Type type; NameAndType(Name name, Type type) { this.name = name; this.type = type; } @Override public int poolTag() { return ClassFile.CONSTANT_NameandType; } @Override public Object poolKey(Types types) { return new Pair<>(name, new UniqueType(type, types)); } } }