Tue, 25 Sep 2012 11:53:18 +0100
7194586: Add back-end support for invokedynamic
Summary: Add support for invokedynamic bytecode instruction; includes suppot for generation of all related classfile attributes
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1999, 2008, 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 */
26 package com.sun.tools.javac.jvm;
28 import com.sun.tools.javac.code.Flags;
29 import com.sun.tools.javac.code.Kinds;
30 import java.util.*;
32 import com.sun.tools.javac.code.Symbol;
33 import com.sun.tools.javac.code.Symbol.*;
34 import com.sun.tools.javac.code.Type;
35 import com.sun.tools.javac.util.Assert;
36 import com.sun.tools.javac.util.Filter;
37 import com.sun.tools.javac.util.Name;
38 import com.sun.tools.javac.util.Names;
40 /** An internal structure that corresponds to the constant pool of a classfile.
41 *
42 * <p><b>This is NOT part of any supported API.
43 * If you write code that depends on this, you do so at your own risk.
44 * This code and its internal interfaces are subject to change or
45 * deletion without notice.</b>
46 */
47 public class Pool {
49 public static final int MAX_ENTRIES = 0xFFFF;
50 public static final int MAX_STRING_LENGTH = 0xFFFF;
52 /** Index of next constant to be entered.
53 */
54 int pp;
56 /** The initial pool buffer.
57 */
58 Object[] pool;
60 /** A hashtable containing all constants in the pool.
61 */
62 Map<Object,Integer> indices;
64 /** Construct a pool with given number of elements and element array.
65 */
66 public Pool(int pp, Object[] pool) {
67 this.pp = pp;
68 this.pool = pool;
69 this.indices = new HashMap<Object,Integer>(pool.length);
70 for (int i = 1; i < pp; i++) {
71 if (pool[i] != null) indices.put(pool[i], i);
72 }
73 }
75 /** Construct an empty pool.
76 */
77 public Pool() {
78 this(1, new Object[64]);
79 }
81 /** Return the number of entries in the constant pool.
82 */
83 public int numEntries() {
84 return pp;
85 }
87 /** Remove everything from this pool.
88 */
89 public void reset() {
90 pp = 1;
91 indices.clear();
92 }
94 /** Double pool buffer in size.
95 */
96 private void doublePool() {
97 Object[] newpool = new Object[pool.length * 2];
98 System.arraycopy(pool, 0, newpool, 0, pool.length);
99 pool = newpool;
100 }
102 /** Place an object in the pool, unless it is already there.
103 * If object is a symbol also enter its owner unless the owner is a
104 * package. Return the object's index in the pool.
105 */
106 public int put(Object value) {
107 if (value instanceof MethodSymbol)
108 value = new Method((MethodSymbol)value);
109 else if (value instanceof VarSymbol)
110 value = new Variable((VarSymbol)value);
111 // assert !(value instanceof Type.TypeVar);
112 Integer index = indices.get(value);
113 if (index == null) {
114 // System.err.println("put " + value + " " + value.getClass());//DEBUG
115 index = pp;
116 indices.put(value, index);
117 if (pp == pool.length) doublePool();
118 pool[pp++] = value;
119 if (value instanceof Long || value instanceof Double) {
120 if (pp == pool.length) doublePool();
121 pool[pp++] = null;
122 }
123 }
124 return index.intValue();
125 }
127 /** Return the given object's index in the pool,
128 * or -1 if object is not in there.
129 */
130 public int get(Object o) {
131 Integer n = indices.get(o);
132 return n == null ? -1 : n.intValue();
133 }
135 static class Method extends DelegatedSymbol {
136 MethodSymbol m;
137 Method(MethodSymbol m) {
138 super(m);
139 this.m = m;
140 }
141 public boolean equals(Object other) {
142 if (!(other instanceof Method)) return false;
143 MethodSymbol o = ((Method)other).m;
144 return
145 o.name == m.name &&
146 o.owner == m.owner &&
147 o.type.equals(m.type);
148 }
149 public int hashCode() {
150 return
151 m.name.hashCode() * 33 +
152 m.owner.hashCode() * 9 +
153 m.type.hashCode();
154 }
155 }
157 static class Variable extends DelegatedSymbol {
158 VarSymbol v;
159 Variable(VarSymbol v) {
160 super(v);
161 this.v = v;
162 }
163 public boolean equals(Object other) {
164 if (!(other instanceof Variable)) return false;
165 VarSymbol o = ((Variable)other).v;
166 return
167 o.name == v.name &&
168 o.owner == v.owner &&
169 o.type.equals(v.type);
170 }
171 public int hashCode() {
172 return
173 v.name.hashCode() * 33 +
174 v.owner.hashCode() * 9 +
175 v.type.hashCode();
176 }
177 }
179 public static class MethodHandle {
181 /** Reference kind - see ClassFile */
182 int refKind;
184 /** Reference symbol */
185 Symbol refSym;
187 /** Reference to the name table */
188 Names names;
190 public MethodHandle(int refKind, Symbol refSym, Names names) {
191 this.refKind = refKind;
192 this.refSym = refSym;
193 this.names = names;
194 checkConsistent();
195 }
196 public boolean equals(Object other) {
197 if (!(other instanceof MethodHandle)) return false;
198 MethodHandle mr = (MethodHandle) other;
199 if (mr.refKind != refKind) return false;
200 Symbol o = mr.refSym;
201 return
202 o.name == refSym.name &&
203 o.owner == refSym.owner &&
204 o.type.equals(refSym.type);
205 }
206 public int hashCode() {
207 return
208 refKind * 65 +
209 refSym.name.hashCode() * 33 +
210 refSym.owner.hashCode() * 9 +
211 refSym.type.hashCode();
212 }
214 /**
215 * Check consistency of reference kind and symbol (see JVMS 4.4.8)
216 */
217 @SuppressWarnings("fallthrough")
218 private void checkConsistent() {
219 boolean staticOk = false;
220 int expectedKind = -1;
221 Filter<Name> nameFilter = nonInitFilter;
222 boolean interfaceOwner = false;
223 switch (refKind) {
224 case ClassFile.REF_getStatic:
225 case ClassFile.REF_putStatic:
226 staticOk = true;
227 case ClassFile.REF_getField:
228 case ClassFile.REF_putField:
229 expectedKind = Kinds.VAR;
230 break;
231 case ClassFile.REF_newInvokeSpecial:
232 nameFilter = initFilter;
233 expectedKind = Kinds.MTH;
234 break;
235 case ClassFile.REF_invokeInterface:
236 interfaceOwner = true;
237 expectedKind = Kinds.MTH;
238 break;
239 case ClassFile.REF_invokeStatic:
240 staticOk = true;
241 case ClassFile.REF_invokeVirtual:
242 case ClassFile.REF_invokeSpecial:
243 expectedKind = Kinds.MTH;
244 break;
245 }
246 Assert.check(!refSym.isStatic() || staticOk);
247 Assert.check(refSym.kind == expectedKind);
248 Assert.check(nameFilter.accepts(refSym.name));
249 Assert.check(!refSym.owner.isInterface() || interfaceOwner);
250 }
251 //where
252 Filter<Name> nonInitFilter = new Filter<Name>() {
253 public boolean accepts(Name n) {
254 return n != names.init && n != names.clinit;
255 }
256 };
258 Filter<Name> initFilter = new Filter<Name>() {
259 public boolean accepts(Name n) {
260 return n == names.init;
261 }
262 };
263 }
264 }