1/*
2 * Copyright (c) 1994, 2013, 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
26package sun.tools.asm;
27
28import sun.tools.java.*;
29import sun.tools.tree.StringExpression;
30import java.util.Enumeration;
31import java.util.Hashtable;
32import java.util.Vector;
33import java.io.IOException;
34import java.io.DataOutputStream;
35
36/**
37 * A table of constants
38 *
39 * WARNING: The contents of this source file are not part of any
40 * supported API.  Code that depends on them does so at its own risk:
41 * they are subject to change or removal without notice.
42 */
43public final
44class ConstantPool implements RuntimeConstants {
45    Hashtable<Object, ConstantPoolData> hash = new Hashtable<>(101);
46
47    /**
48     * Find an entry, may return 0
49     */
50    public int index(Object obj) {
51        return hash.get(obj).index;
52    }
53
54    /**
55     * Add an entry
56     */
57    public void put(Object obj) {
58        ConstantPoolData data = hash.get(obj);
59        if (data == null) {
60            if (obj instanceof String) {
61                data = new StringConstantData(this, (String)obj);
62            } else if (obj instanceof StringExpression) {
63                data = new StringExpressionConstantData(this, (StringExpression)obj);
64            } else if (obj instanceof ClassDeclaration) {
65                data = new ClassConstantData(this, (ClassDeclaration)obj);
66            } else if (obj instanceof Type) {
67                data = new ClassConstantData(this, (Type)obj);
68            } else if (obj instanceof MemberDefinition) {
69                data = new FieldConstantData(this, (MemberDefinition)obj);
70            } else if (obj instanceof NameAndTypeData) {
71                data = new NameAndTypeConstantData(this, (NameAndTypeData)obj);
72            } else if (obj instanceof Number) {
73                data = new NumberConstantData(this, (Number)obj);
74            }
75            hash.put(obj, data);
76        }
77    }
78
79    /**
80     * Write to output
81     */
82    public void write(Environment env, DataOutputStream out) throws IOException {
83        ConstantPoolData list[] = new ConstantPoolData[hash.size()];
84        String keys[] = new String[list.length];
85        int index = 1, count = 0;
86
87        // Make a list of all the constant pool items
88        for (int n = 0 ; n < 5 ; n++) {
89            int first = count;
90            for (Enumeration<ConstantPoolData> e = hash.elements() ; e.hasMoreElements() ;) {
91                ConstantPoolData data = e.nextElement();
92                if (data.order() == n) {
93                    keys[count] = sortKey(data);
94                    list[count++] = data;
95                }
96            }
97            xsort(list, keys, first, count-1);
98        }
99
100        // Assign an index to each constant pool item
101        for (int n = 0 ; n < list.length ; n++) {
102            ConstantPoolData data = list[n];
103            data.index = index;
104            index += data.width();
105        }
106
107        // Write length
108        out.writeShort(index);
109
110        // Write each constant pool item
111        for (int n = 0 ; n < count ; n++) {
112            list[n].write(env, out, this);
113        }
114    }
115
116    private
117    static String sortKey(ConstantPoolData f) {
118        if (f instanceof NumberConstantData) {
119            Number num = ((NumberConstantData)f).num;
120            String str = num.toString();
121            int key = 3;
122            if (num instanceof Integer)  key = 0;
123            else if (num instanceof Float)  key = 1;
124            else if (num instanceof Long)  key = 2;
125            return "\0" + (char)(str.length() + key<<8) + str;
126        }
127        if (f instanceof StringExpressionConstantData)
128            return (String)((StringExpressionConstantData)f).str.getValue();
129        if (f instanceof FieldConstantData) {
130            MemberDefinition fd = ((FieldConstantData)f).field;
131            return fd.getName()+" "+fd.getType().getTypeSignature()
132                +" "+fd.getClassDeclaration().getName();
133        }
134        if (f instanceof NameAndTypeConstantData)
135            return  ((NameAndTypeConstantData)f).name+
136                " "+((NameAndTypeConstantData)f).type;
137        if (f instanceof ClassConstantData)
138            return ((ClassConstantData)f).name;
139        return ((StringConstantData)f).str;
140    }
141
142    /**
143     * Quick sort an array of pool entries and a corresponding array of Strings
144     * that are the sort keys for the field.
145     */
146    private
147    static void xsort(ConstantPoolData ff[], String ss[], int left, int right) {
148        if (left >= right)
149            return;
150        String pivot = ss[left];
151        int l = left;
152        int r = right;
153        while (l < r) {
154            while (l <= right && ss[l].compareTo(pivot) <= 0)
155                l++;
156            while (r >= left && ss[r].compareTo(pivot) > 0)
157                r--;
158            if (l < r) {
159                // swap items at l and at r
160                ConstantPoolData def = ff[l];
161                String name = ss[l];
162                ff[l] = ff[r]; ff[r] = def;
163                ss[l] = ss[r]; ss[r] = name;
164            }
165        }
166        int middle = r;
167        // swap left and middle
168        ConstantPoolData def = ff[left];
169        String name = ss[left];
170        ff[left] = ff[middle]; ff[middle] = def;
171        ss[left] = ss[middle]; ss[middle] = name;
172        xsort(ff, ss, left, middle-1);
173        xsort(ff, ss, middle + 1, right);
174    }
175
176}
177