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 
26 package sun.tools.asm;
27 
28 import sun.tools.java.*;
29 import sun.tools.tree.StringExpression;
30 import java.util.Enumeration;
31 import java.util.Hashtable;
32 import java.util.Vector;
33 import java.io.IOException;
34 import 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  */
43 public final
44 class ConstantPool implements RuntimeConstants {
45     Hashtable<Object, ConstantPoolData> hash = new Hashtable<>(101);
46 
47     /**
48      * Find an entry, may return 0
49      */
index(Object obj)50     public int index(Object obj) {
51         return hash.get(obj).index;
52     }
53 
54     /**
55      * Add an entry
56      */
put(Object obj)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      */
write(Environment env, DataOutputStream out)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
sortKey(ConstantPoolData f)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
xsort(ConstantPoolData ff[], String ss[], int left, int right)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