/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.compiler.assembler; import java.util.HashMap; import java.util.Map.Entry; /** * Constant pool abstraction to handle the Java bytecode limitation on constant entries per class. */ abstract class ConstantPool { private final HashMap<Object, Integer> constantsMap = new HashMap<>(64); private ConstantPool next; private int integers = 0; private int longs = 0; private int floats = 0; private int doubles = 0; private int strings = 0; protected final Code code; private final int limit; protected ConstantPool(Code code, int limit) { assert 0 <= limit && limit <= Short.MAX_VALUE; this.code = code; this.limit = limit; } /** * Returns this pool's integer constants. * * @return the integer constants */ protected final Integer[] getIntegers() { Integer[] constants = new Integer[integers]; for (Entry<Object, Integer> entry : constantsMap.entrySet()) { if (entry.getKey() instanceof Integer) { constants[entry.getValue()] = (Integer) entry.getKey(); } } return constants; } /** * Returns this pool's long constants. * * @return the long constants */ protected final Long[] getLongs() { Long[] constants = new Long[longs]; for (Entry<Object, Integer> entry : constantsMap.entrySet()) { if (entry.getKey() instanceof Long) { constants[entry.getValue()] = (Long) entry.getKey(); } } return constants; } /** * Returns this pool's float constants. * * @return the float constants */ protected final Float[] getFloats() { Float[] constants = new Float[floats]; for (Entry<Object, Integer> entry : constantsMap.entrySet()) { if (entry.getKey() instanceof Float) { constants[entry.getValue()] = (Float) entry.getKey(); } } return constants; } /** * Returns this pool's double constants. * * @return the double constants */ protected final Double[] getDoubles() { Double[] constants = new Double[doubles]; for (Entry<Object, Integer> entry : constantsMap.entrySet()) { if (entry.getKey() instanceof Double) { constants[entry.getValue()] = (Double) entry.getKey(); } } return constants; } /** * Returns this pool's string constants. * * @return the string constants */ protected final String[] getStrings() { String[] constants = new String[strings]; for (Entry<Object, Integer> entry : constantsMap.entrySet()) { if (entry.getKey() instanceof String) { constants[entry.getValue()] = (String) entry.getKey(); } } return constants; } private boolean isConstantPoolFull() { return constantsMap.size() >= limit; } private int getConstantIndex(Object cst) { Integer index = constantsMap.get(cst); return index != null ? index : -1; } private void putConstant(Object cst, int index) { constantsMap.put(cst, index); } private ConstantPool getNext() { if (next == null) { next = newConstantPool(); } return next; } public final void iconst(InstructionAssembler assembler, Integer cst) { int index = getConstantIndex(cst); if (index < 0) { if (isConstantPoolFull()) { getNext().iconst(assembler, cst); return; } putConstant(cst, index = integers++); } iconst(assembler, cst, index); } public final void lconst(InstructionAssembler assembler, Long cst) { int index = getConstantIndex(cst); if (index < 0) { if (isConstantPoolFull()) { getNext().lconst(assembler, cst); return; } putConstant(cst, index = longs++); } lconst(assembler, cst, index); } public final void fconst(InstructionAssembler assembler, Float cst) { int index = getConstantIndex(cst); if (index < 0) { if (isConstantPoolFull()) { getNext().fconst(assembler, cst); return; } putConstant(cst, index = floats++); } fconst(assembler, cst, index); } public final void dconst(InstructionAssembler assembler, Double cst) { int index = getConstantIndex(cst); if (index < 0) { if (isConstantPoolFull()) { getNext().dconst(assembler, cst); return; } putConstant(cst, index = doubles++); } dconst(assembler, cst, index); } public final void aconst(InstructionAssembler assembler, String cst) { int index = getConstantIndex(cst); if (index < 0) { if (isConstantPoolFull()) { getNext().aconst(assembler, cst); return; } putConstant(cst, index = strings++); } aconst(assembler, cst, index); } /** * Closes this constant pool. */ protected abstract void close(); /** * Creates a new constant pool when this pool's limit has been exceeded. * * @return the new constant pool */ protected abstract ConstantPool newConstantPool(); /** * Loads the indexed integer constant {@code cst} for the given method. * * @param assembler * the instruction assembler * @param cst * the integer constant * @param index * the constant index */ protected abstract void iconst(InstructionAssembler assembler, Integer cst, int index); /** * Loads the indexed long constant {@code cst} for the given method. * * @param assembler * the instruction assembler * @param cst * the long constant * @param index * the constant index */ protected abstract void lconst(InstructionAssembler assembler, Long cst, int index); /** * Loads the indexed float constant {@code cst} for the given method. * * @param assembler * the instruction assembler * @param cst * the float constant * @param index * the constant index */ protected abstract void fconst(InstructionAssembler assembler, Float cst, int index); /** * Loads the indexed double constant {@code cst} for the given method. * * @param assembler * the instruction assembler * @param cst * the double constant * @param index * the constant index */ protected abstract void dconst(InstructionAssembler assembler, Double cst, int index); /** * Loads the indexed string constant {@code cst} for the given method. * * @param assembler * the instruction assembler * @param cst * the string constant * @param index * the constant index */ protected abstract void aconst(InstructionAssembler assembler, String cst, int index); }