/* * Copyright (c) 1994, 2013, 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 sun.tools.asm; import sun.tools.java.*; import sun.tools.tree.StringExpression; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.io.IOException; import java.io.DataOutputStream; /** * A table of constants * * WARNING: The contents of this source file are not part of any * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */ public final class ConstantPool implements RuntimeConstants { Hashtable<Object, ConstantPoolData> hash = new Hashtable<>(101); /** * Find an entry, may return 0 */ public int index(Object obj) { return hash.get(obj).index; } /** * Add an entry */ public void put(Object obj) { ConstantPoolData data = hash.get(obj); if (data == null) { if (obj instanceof String) { data = new StringConstantData(this, (String)obj); } else if (obj instanceof StringExpression) { data = new StringExpressionConstantData(this, (StringExpression)obj); } else if (obj instanceof ClassDeclaration) { data = new ClassConstantData(this, (ClassDeclaration)obj); } else if (obj instanceof Type) { data = new ClassConstantData(this, (Type)obj); } else if (obj instanceof MemberDefinition) { data = new FieldConstantData(this, (MemberDefinition)obj); } else if (obj instanceof NameAndTypeData) { data = new NameAndTypeConstantData(this, (NameAndTypeData)obj); } else if (obj instanceof Number) { data = new NumberConstantData(this, (Number)obj); } hash.put(obj, data); } } /** * Write to output */ public void write(Environment env, DataOutputStream out) throws IOException { ConstantPoolData list[] = new ConstantPoolData[hash.size()]; String keys[] = new String[list.length]; int index = 1, count = 0; // Make a list of all the constant pool items for (int n = 0 ; n < 5 ; n++) { int first = count; for (Enumeration<ConstantPoolData> e = hash.elements() ; e.hasMoreElements() ;) { ConstantPoolData data = e.nextElement(); if (data.order() == n) { keys[count] = sortKey(data); list[count++] = data; } } xsort(list, keys, first, count-1); } // Assign an index to each constant pool item for (int n = 0 ; n < list.length ; n++) { ConstantPoolData data = list[n]; data.index = index; index += data.width(); } // Write length out.writeShort(index); // Write each constant pool item for (int n = 0 ; n < count ; n++) { list[n].write(env, out, this); } } private static String sortKey(ConstantPoolData f) { if (f instanceof NumberConstantData) { Number num = ((NumberConstantData)f).num; String str = num.toString(); int key = 3; if (num instanceof Integer) key = 0; else if (num instanceof Float) key = 1; else if (num instanceof Long) key = 2; return "\0" + (char)(str.length() + key<<8) + str; } if (f instanceof StringExpressionConstantData) return (String)((StringExpressionConstantData)f).str.getValue(); if (f instanceof FieldConstantData) { MemberDefinition fd = ((FieldConstantData)f).field; return fd.getName()+" "+fd.getType().getTypeSignature() +" "+fd.getClassDeclaration().getName(); } if (f instanceof NameAndTypeConstantData) return ((NameAndTypeConstantData)f).name+ " "+((NameAndTypeConstantData)f).type; if (f instanceof ClassConstantData) return ((ClassConstantData)f).name; return ((StringConstantData)f).str; } /** * Quick sort an array of pool entries and a corresponding array of Strings * that are the sort keys for the field. */ private static void xsort(ConstantPoolData ff[], String ss[], int left, int right) { if (left >= right) return; String pivot = ss[left]; int l = left; int r = right; while (l < r) { while (l <= right && ss[l].compareTo(pivot) <= 0) l++; while (r >= left && ss[r].compareTo(pivot) > 0) r--; if (l < r) { // swap items at l and at r ConstantPoolData def = ff[l]; String name = ss[l]; ff[l] = ff[r]; ff[r] = def; ss[l] = ss[r]; ss[r] = name; } } int middle = r; // swap left and middle ConstantPoolData def = ff[left]; String name = ss[left]; ff[left] = ff[middle]; ff[middle] = def; ss[left] = ss[middle]; ss[middle] = name; xsort(ff, ss, left, middle-1); xsort(ff, ss, middle + 1, right); } }