com.tangosol.dev.assembler.ConstantPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.dev.assembler;
import com.tangosol.util.Filter;
import com.tangosol.util.FilterEnumerator;
import com.tangosol.util.NullFilter;
import com.tangosol.util.Tree;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
/**
* Implements the constant pool section of a Java .class structure.
*
* @version 0.50, 05/12/98, assembler/dis-assembler
* @author Cameron Purdy
*/
public class ConstantPool extends VMStructure implements Constants
{
// ----- constructors ---------------------------------------------------
/**
* Construct a new ConstantPool object associated to the provided {@link
* ClassFile}.
*
* @param cf the associated ClassFile
*/
public ConstantPool(ClassFile cf)
{
init();
// hold a reference to the ClassFile this Constant Pool is associated to
m_classFile = cf;
}
// ----- VMStructure operations -----------------------------------------
/**
* The disassembly process reads the structure from the passed input
* stream and uses the constant pool to dereference any constant
* references.
*
* @param stream the stream implementing java.io.DataInput from which
* to read the assembled VM structure
* @param pool the constant pool for the class which contains any
* constants referenced by this VM structure
*/
protected void disassemble(DataInput stream, ConstantPool pool)
throws IOException
{
init();
// read the number of constant elements (see note in the assemble()
// method)
int cConst = stream.readUnsignedShort();
// load the constant pool from the stream
int i = 1;
while (i < cConst)
{
Constant constant = Constant.loadConstant(stream, this);
add(constant);
// some constants take up two elements
i += constant.getElementSize();
}
// convert indexes into constant references
Enumeration enmr = m_vectConst.elements();
while (enmr.hasMoreElements())
{
Constant constant = (Constant) enmr.nextElement();
if (constant != null)
{
constant.postdisassemble(this);
}
}
}
/**
* The pre-assembly step collects the necessary entries for the constant
* pool. During this step, all constants used by this VM structure and
* any sub-structures are registered with (but not yet bound by position
* in) the constant pool.
*
* @param pool the constant pool for the class which needs to be
* populated with the constants required to build this
* VM structure
*/
protected void preassemble(ConstantPool pool)
{
// register all constants
Enumeration enmr = constants();
while (enmr.hasMoreElements())
{
pool.registerConstant((Constant) enmr.nextElement());
}
}
/**
* The assembly process assembles and writes the structure to the passed
* output stream, resolving any dependencies using the passed constant
* pool.
*
* @param stream the stream implementing java.io.DataOutput to which to
* write the assembled VM structure
* @param pool the constant pool for the class which by this point
* contains the entire set of constants required to build
* this VM structure
*/
protected void assemble(DataOutput stream, ConstantPool pool)
throws IOException
{
// write out the number of constant elements (the size of the array
// used to hold the constants which is not equal to the number of
// constants because [0] is reserved and long/double constants "use"
// two elements)
stream.writeShort(m_vectConst.size());
// stream constants
Enumeration enmr = m_vectConst.elements();
while (enmr.hasMoreElements())
{
Constant constant = (Constant) enmr.nextElement();
if (constant != null)
{
constant.assemble(stream, pool);
}
}
}
/**
* Determine if the VM structure (or any contained VM structure) has been
* modified.
*
* @return true if the VM structure has been modified
*/
public boolean isModified()
{
return m_fModified;
}
/**
* Reset the modified state of the VM structure.
*/
protected void resetModified()
{
m_fModified = false;
}
// ----- Object operations ----------------------------------------------
/**
* Produce a human-readable string describing the constant pool.
*
* @return a string describing the constant pool
*/
public String toString()
{
return "Constant Pool contains " + m_vectConst.size() + " elements";
}
// ----- ConstantPool operations ----------------------------------------
/**
* Register a constant in the pool (if it does not already exist).
*
* @param constant the constant to find/register
*
* @return the constant's index
*/
public int registerConstant(Constant constant)
{
if (constant == null)
{
return 0;
}
int iConst = findConstant(constant);
if (iConst < 1)
{
// add the constant and assign an index
iConst = add(constant);
// register any constants referenced by the constant that was
// just registered
constant.preassemble(this);
}
return iConst;
}
/**
* Search for a constant in the pool.
*
* @param constant the constant to search for
*
* @return the constant index or -1 if not found
*/
public int findConstant(Constant constant)
{
if (constant == null)
{
return 0;
}
ensureLookup();
int iConst = constant.m_iLastKnownLocation;
if (iConst > 0)
{
Constant constantFound = getConstant(iConst);
if (constantFound != null && constant.equals(constantFound))
{
return iConst;
}
}
Integer index = (Integer) m_atblConst[constant.getTag()].get(constant);
if (index != null)
{
iConst = index.intValue();
constant.m_iLastKnownLocation = iConst;
return iConst;
}
return -1;
}
/**
* Get a constant from the pool using the constant's index.
*
* @param iConst the constant index
*
* @return the constant or null if the specified constant does not exist
*/
public Constant getConstant(int iConst)
{
try
{
return (Constant) m_vectConst.get(iConst);
}
catch (ArrayIndexOutOfBoundsException e)
{
return null;
}
}
/**
* Create an enumerator that is independent of the constant pool's own
* storage. This is necessary in cases where constants could be added
* while being enumerated, since a change to a vector, which is used
* to store the constants, will cause the vector's enumerator to throw
* an exception.
*
* @return an enumerator of the constants in the constant pool
*/
public Enumeration constants()
{
Constant[] aconst = new Constant[m_vectConst.size()];
m_vectConst.copyInto(aconst);
return new FilterEnumerator(aconst, NULL_FILTER);
}
/**
* Reorder the contents of the pool for neatness and as a dependency
* optimization.
*/
protected void sort()
{
azzert(!isOrderImportant());
// get the ordered index of all registered constants
ensureLookup();
Tree[] atblConst = m_atblConst;
// re-build the pool in order based on the index
init();
int[] aiTag = CONSTANT_ORDER;
int cTags = aiTag.length;
for (int i = 0; i < cTags; ++i)
{
Enumeration enmr = atblConst[aiTag[i]].keys();
while (enmr.hasMoreElements())
{
add((Constant) enmr.nextElement());
}
}
}
/**
* Determine if the current order of the pool is important.
*
* @return true if the pool should not allow itself to be re-ordered
*/
public boolean isOrderImportant()
{
return m_fOrderImportant;
}
/**
* Specify that the current order of the pool is important or not.
*
* @param fOrderImportant true if the pool should not allow itself to
* be re-ordered
*/
public void setOrderImportant(boolean fOrderImportant)
{
m_fOrderImportant = fOrderImportant;
}
/**
* Return the {@link ClassFile} this ConstantPool is associated to or null
* if this pool has become detached from a ClassFile.
*
* @return the ClassFile this ConstantPool is associated to or null
*/
public ClassFile getClassFile()
{
return m_classFile;
}
/**
* Set the {@link ClassFile} this ConstantPool is associated to.
*
* @param classFile the ClassFile this ConstantPool is associated to
*/
protected void setClassFile(ClassFile classFile)
{
m_classFile = classFile;
}
// ----- internal operations --------------------------------------------
/**
* (Internal) Initialize the constant pool information.
*/
protected void init()
{
// create constant pool (accessed by index)
m_vectConst = new Vector();
m_vectConst.add(null); // constant 0 always n/a
// reset lookup by constant
m_atblConst = null;
// default order un-important (only unknown attributes make it
// important; see Attribute.loadAttribute)
m_fOrderImportant = false;
}
/**
* (Internal) Add a constant to the constant pool.
*
* @param constant the constant to add top the pool
*/
protected int add(Constant constant)
{
// determine the constant index
int iConst = m_vectConst.size();
// append to constant pool
m_vectConst.add(constant);
if (constant.getElementSize() > 1)
{
// some constants take two slots
m_vectConst.add(null);
}
// update lookup
if (m_atblConst != null)
{
m_atblConst[constant.getTag()].put(constant, Integer.valueOf(iConst));
}
m_fModified = true;
return iConst;
}
/**
* (Internal) Initialize the constant pool lookup if it does not already
* exist.
*/
protected void ensureLookup()
{
if (m_atblConst == null)
{
// create lookup tables for constants
int[] acElements = CONSTANT_SIZE;
int cTags = acElements.length;
Tree[] atblConst = new Tree[cTags];
for (int i = 0; i < cTags; ++i)
{
if (acElements[i] > 0)
{
atblConst[i] = new Tree();
}
}
// populate
Enumeration enmr = m_vectConst.elements();
for (int i = 0; enmr.hasMoreElements(); ++i)
{
Constant constant = (Constant) enmr.nextElement();
if (constant != null)
{
atblConst[constant.getTag()].put(constant, Integer.valueOf(i));
}
}
m_atblConst = atblConst;
}
}
// ----- constants ------------------------------------------------------
/**
* Filter for hiding missing constants when enumerating.
*/
private static final Filter NULL_FILTER = NullFilter.getInstance();
// ----- data members ---------------------------------------------------
/**
* The constant pool, an array of constants accessed via integer index.
*/
private Vector m_vectConst;
/**
* Keeps track of modifications to the constant pool.
*/
private boolean m_fModified;
/**
* Keeps track of whether the constant pool order is important.
*/
private boolean m_fOrderImportant;
/**
* An array (indexed by constant type "tag") of ordered (aka searchable)
* constants in this constant pool.
*/
private Tree[] m_atblConst;
/**
* The ClassFile this Constant Pool is associated to.
*/
private ClassFile m_classFile;
}