Mercurial > hg > truffle
comparison graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotConstantPool.java @ 21551:5324104ac4f3
moved com.oracle.graal.hotspot.jvmci classes to com.oracle.jvmci.hotspot module (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 26 May 2015 17:13:37 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
21550:f48a6cea31eb | 21551:5324104ac4f3 |
---|---|
1 /* | |
2 * Copyright (c) 2011, 2015, 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.jvmci.hotspot; | |
24 | |
25 import static com.oracle.jvmci.common.UnsafeAccess.*; | |
26 import static com.oracle.jvmci.hotspot.HotSpotJVMCIRuntime.*; | |
27 | |
28 import java.lang.invoke.*; | |
29 | |
30 import com.oracle.graal.api.meta.*; | |
31 import com.oracle.jvmci.common.*; | |
32 | |
33 /** | |
34 * Implementation of {@link ConstantPool} for HotSpot. | |
35 */ | |
36 public class HotSpotConstantPool implements ConstantPool, HotSpotProxified { | |
37 | |
38 /** | |
39 * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}. | |
40 */ | |
41 static class Bytecodes { | |
42 public static final int LDC = 18; // 0x12 | |
43 public static final int LDC_W = 19; // 0x13 | |
44 public static final int LDC2_W = 20; // 0x14 | |
45 public static final int GETSTATIC = 178; // 0xB2 | |
46 public static final int PUTSTATIC = 179; // 0xB3 | |
47 public static final int GETFIELD = 180; // 0xB4 | |
48 public static final int PUTFIELD = 181; // 0xB5 | |
49 public static final int INVOKEVIRTUAL = 182; // 0xB6 | |
50 public static final int INVOKESPECIAL = 183; // 0xB7 | |
51 public static final int INVOKESTATIC = 184; // 0xB8 | |
52 public static final int INVOKEINTERFACE = 185; // 0xB9 | |
53 public static final int INVOKEDYNAMIC = 186; // 0xBA | |
54 public static final int NEW = 187; // 0xBB | |
55 public static final int NEWARRAY = 188; // 0xBC | |
56 public static final int ANEWARRAY = 189; // 0xBD | |
57 public static final int CHECKCAST = 192; // 0xC0 | |
58 public static final int INSTANCEOF = 193; // 0xC1 | |
59 public static final int MULTIANEWARRAY = 197; // 0xC5 | |
60 | |
61 static boolean isInvoke(int opcode) { | |
62 switch (opcode) { | |
63 case INVOKEVIRTUAL: | |
64 case INVOKESPECIAL: | |
65 case INVOKESTATIC: | |
66 case INVOKEINTERFACE: | |
67 case INVOKEDYNAMIC: | |
68 return true; | |
69 default: | |
70 return false; | |
71 } | |
72 } | |
73 } | |
74 | |
75 /** | |
76 * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and | |
77 * internal ones. | |
78 */ | |
79 private enum JVM_CONSTANT { | |
80 // @formatter:off | |
81 Utf8(config().jvmConstantUtf8), | |
82 Integer(config().jvmConstantInteger), | |
83 Long(config().jvmConstantLong), | |
84 Float(config().jvmConstantFloat), | |
85 Double(config().jvmConstantDouble), | |
86 Class(config().jvmConstantClass), | |
87 UnresolvedClass(config().jvmConstantUnresolvedClass), | |
88 UnresolvedClassInError(config().jvmConstantUnresolvedClassInError), | |
89 String(config().jvmConstantString), | |
90 Fieldref(config().jvmConstantFieldref), | |
91 MethodRef(config().jvmConstantMethodref), | |
92 InterfaceMethodref(config().jvmConstantInterfaceMethodref), | |
93 NameAndType(config().jvmConstantNameAndType), | |
94 MethodHandle(config().jvmConstantMethodHandle), | |
95 MethodHandleInError(config().jvmConstantMethodHandleInError), | |
96 MethodType(config().jvmConstantMethodType), | |
97 MethodTypeInError(config().jvmConstantMethodTypeInError), | |
98 InvokeDynamic(config().jvmConstantInvokeDynamic); | |
99 // @formatter:on | |
100 | |
101 private final int tag; | |
102 | |
103 private static final int ExternalMax = config().jvmConstantExternalMax; | |
104 private static final int InternalMin = config().jvmConstantInternalMin; | |
105 private static final int InternalMax = config().jvmConstantInternalMax; | |
106 | |
107 private JVM_CONSTANT(int tag) { | |
108 this.tag = tag; | |
109 } | |
110 | |
111 private static HotSpotVMConfig config() { | |
112 return runtime().getConfig(); | |
113 } | |
114 | |
115 /** | |
116 * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy | |
117 * initialization. | |
118 */ | |
119 static class TagValueMap { | |
120 private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1]; | |
121 static { | |
122 assert InternalMin > ExternalMax; | |
123 for (JVM_CONSTANT e : values()) { | |
124 table[indexOf(e.tag)] = e; | |
125 } | |
126 } | |
127 | |
128 private static int indexOf(int tag) { | |
129 if (tag >= InternalMin) { | |
130 return tag - InternalMin + ExternalMax + 1; | |
131 } else { | |
132 assert tag <= ExternalMax; | |
133 } | |
134 return tag; | |
135 } | |
136 | |
137 static JVM_CONSTANT get(int tag) { | |
138 JVM_CONSTANT res = table[indexOf(tag)]; | |
139 if (res != null) { | |
140 return res; | |
141 } | |
142 throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag); | |
143 } | |
144 } | |
145 | |
146 public static JVM_CONSTANT getEnum(int tag) { | |
147 return TagValueMap.get(tag); | |
148 } | |
149 } | |
150 | |
151 private static class LookupTypeCacheElement { | |
152 int lastCpi = Integer.MIN_VALUE; | |
153 JavaType javaType; | |
154 | |
155 public LookupTypeCacheElement(int lastCpi, JavaType javaType) { | |
156 super(); | |
157 this.lastCpi = lastCpi; | |
158 this.javaType = javaType; | |
159 } | |
160 } | |
161 | |
162 /** | |
163 * Reference to the C++ ConstantPool object. | |
164 */ | |
165 private final long metaspaceConstantPool; | |
166 private final Object[] cache; | |
167 private volatile LookupTypeCacheElement lastLookupType; | |
168 | |
169 public HotSpotConstantPool(long metaspaceConstantPool) { | |
170 this.metaspaceConstantPool = metaspaceConstantPool; | |
171 cache = new Object[length()]; | |
172 } | |
173 | |
174 /** | |
175 * Gets the holder for this constant pool as {@link HotSpotResolvedObjectTypeImpl}. | |
176 * | |
177 * @return holder for this constant pool | |
178 */ | |
179 private HotSpotResolvedObjectType getHolder() { | |
180 final long metaspaceKlass = unsafe.getAddress(metaspaceConstantPool + runtime().getConfig().constantPoolHolderOffset); | |
181 return HotSpotResolvedObjectTypeImpl.fromMetaspaceKlass(metaspaceKlass); | |
182 } | |
183 | |
184 /** | |
185 * Converts a raw index from the bytecodes to a constant pool index by adding a | |
186 * {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}. | |
187 * | |
188 * @param rawIndex index from the bytecode | |
189 * @param opcode bytecode to convert the index for | |
190 * @return constant pool index | |
191 */ | |
192 private static int toConstantPoolIndex(int rawIndex, int opcode) { | |
193 int index; | |
194 if (opcode == Bytecodes.INVOKEDYNAMIC) { | |
195 index = rawIndex; | |
196 // See: ConstantPool::is_invokedynamic_index | |
197 assert index < 0 : "not an invokedynamic constant pool index " + index; | |
198 } else { | |
199 assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE || | |
200 opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode; | |
201 index = rawIndex + runtime().getConfig().constantPoolCpCacheIndexTag; | |
202 } | |
203 return index; | |
204 } | |
205 | |
206 /** | |
207 * Decode a constant pool cache index to a constant pool index. | |
208 * | |
209 * See {@code ConstantPool::decode_cpcache_index}. | |
210 * | |
211 * @param index constant pool cache index | |
212 * @return decoded index | |
213 */ | |
214 private static int decodeConstantPoolCacheIndex(int index) { | |
215 if (isInvokedynamicIndex(index)) { | |
216 return decodeInvokedynamicIndex(index); | |
217 } else { | |
218 return index - runtime().getConfig().constantPoolCpCacheIndexTag; | |
219 } | |
220 } | |
221 | |
222 /** | |
223 * See {@code ConstantPool::is_invokedynamic_index}. | |
224 */ | |
225 private static boolean isInvokedynamicIndex(int index) { | |
226 return index < 0; | |
227 } | |
228 | |
229 /** | |
230 * See {@code ConstantPool::decode_invokedynamic_index}. | |
231 */ | |
232 private static int decodeInvokedynamicIndex(int i) { | |
233 assert isInvokedynamicIndex(i) : i; | |
234 return ~i; | |
235 } | |
236 | |
237 /** | |
238 * Gets the constant pool tag at index {@code index}. | |
239 * | |
240 * @param index constant pool index | |
241 * @return constant pool tag | |
242 */ | |
243 private JVM_CONSTANT getTagAt(int index) { | |
244 assertBounds(index); | |
245 HotSpotVMConfig config = runtime().getConfig(); | |
246 final long metaspaceConstantPoolTags = unsafe.getAddress(metaspaceConstantPool + config.constantPoolTagsOffset); | |
247 final int tag = unsafe.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index); | |
248 if (tag == 0) { | |
249 return null; | |
250 } | |
251 return JVM_CONSTANT.getEnum(tag); | |
252 } | |
253 | |
254 /** | |
255 * Gets the constant pool entry at index {@code index}. | |
256 * | |
257 * @param index constant pool index | |
258 * @return constant pool entry | |
259 */ | |
260 private long getEntryAt(int index) { | |
261 assertBounds(index); | |
262 return unsafe.getAddress(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
263 } | |
264 | |
265 /** | |
266 * Gets the integer constant pool entry at index {@code index}. | |
267 * | |
268 * @param index constant pool index | |
269 * @return integer constant pool entry at index | |
270 */ | |
271 private int getIntAt(int index) { | |
272 assertTag(index, JVM_CONSTANT.Integer); | |
273 return unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
274 } | |
275 | |
276 /** | |
277 * Gets the long constant pool entry at index {@code index}. | |
278 * | |
279 * @param index constant pool index | |
280 * @return long constant pool entry | |
281 */ | |
282 private long getLongAt(int index) { | |
283 assertTag(index, JVM_CONSTANT.Long); | |
284 return unsafe.getLong(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
285 } | |
286 | |
287 /** | |
288 * Gets the float constant pool entry at index {@code index}. | |
289 * | |
290 * @param index constant pool index | |
291 * @return float constant pool entry | |
292 */ | |
293 private float getFloatAt(int index) { | |
294 assertTag(index, JVM_CONSTANT.Float); | |
295 return unsafe.getFloat(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
296 } | |
297 | |
298 /** | |
299 * Gets the double constant pool entry at index {@code index}. | |
300 * | |
301 * @param index constant pool index | |
302 * @return float constant pool entry | |
303 */ | |
304 private double getDoubleAt(int index) { | |
305 assertTag(index, JVM_CONSTANT.Double); | |
306 return unsafe.getDouble(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
307 } | |
308 | |
309 /** | |
310 * Gets the {@code JVM_CONSTANT_NameAndType} constant pool entry at index {@code index}. | |
311 * | |
312 * @param index constant pool index | |
313 * @return {@code JVM_CONSTANT_NameAndType} constant pool entry | |
314 */ | |
315 private int getNameAndTypeAt(int index) { | |
316 assertTag(index, JVM_CONSTANT.NameAndType); | |
317 return unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
318 } | |
319 | |
320 /** | |
321 * Gets the {@code JVM_CONSTANT_NameAndType} reference index constant pool entry at index | |
322 * {@code index}. | |
323 * | |
324 * @param index constant pool index | |
325 * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry | |
326 */ | |
327 private int getNameAndTypeRefIndexAt(int index) { | |
328 return runtime().getCompilerToVM().lookupNameAndTypeRefIndexInPool(metaspaceConstantPool, index); | |
329 } | |
330 | |
331 /** | |
332 * Gets the name of a {@code JVM_CONSTANT_NameAndType} constant pool entry at index | |
333 * {@code index}. | |
334 * | |
335 * @param index constant pool index | |
336 * @return name as {@link String} | |
337 */ | |
338 private String getNameRefAt(int index) { | |
339 return runtime().getCompilerToVM().lookupNameRefInPool(metaspaceConstantPool, index); | |
340 } | |
341 | |
342 /** | |
343 * Gets the name reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry at | |
344 * index {@code index}. | |
345 * | |
346 * @param index constant pool index | |
347 * @return name reference index | |
348 */ | |
349 private int getNameRefIndexAt(int index) { | |
350 final int refIndex = getNameAndTypeAt(index); | |
351 // name ref index is in the low 16-bits. | |
352 return refIndex & 0xFFFF; | |
353 } | |
354 | |
355 /** | |
356 * Gets the signature of a {@code JVM_CONSTANT_NameAndType} constant pool entry at index | |
357 * {@code index}. | |
358 * | |
359 * @param index constant pool index | |
360 * @return signature as {@link String} | |
361 */ | |
362 private String getSignatureRefAt(int index) { | |
363 return runtime().getCompilerToVM().lookupSignatureRefInPool(metaspaceConstantPool, index); | |
364 } | |
365 | |
366 /** | |
367 * Gets the signature reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry | |
368 * at index {@code index}. | |
369 * | |
370 * @param index constant pool index | |
371 * @return signature reference index | |
372 */ | |
373 private int getSignatureRefIndexAt(int index) { | |
374 final int refIndex = getNameAndTypeAt(index); | |
375 // signature ref index is in the high 16-bits. | |
376 return refIndex >>> 16; | |
377 } | |
378 | |
379 /** | |
380 * Gets the klass reference index constant pool entry at index {@code index}. | |
381 * | |
382 * @param index constant pool index | |
383 * @return klass reference index | |
384 */ | |
385 private int getKlassRefIndexAt(int index) { | |
386 return runtime().getCompilerToVM().lookupKlassRefIndexInPool(metaspaceConstantPool, index); | |
387 } | |
388 | |
389 /** | |
390 * Gets the uncached klass reference index constant pool entry at index {@code index}. See: | |
391 * {@code ConstantPool::uncached_klass_ref_index_at}. | |
392 * | |
393 * @param index constant pool index | |
394 * @return klass reference index | |
395 */ | |
396 private int getUncachedKlassRefIndexAt(int index) { | |
397 assert getTagAt(index) == JVM_CONSTANT.Fieldref || getTagAt(index) == JVM_CONSTANT.MethodRef || getTagAt(index) == JVM_CONSTANT.InterfaceMethodref; | |
398 final int refIndex = unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); | |
399 // klass ref index is in the low 16-bits. | |
400 return refIndex & 0xFFFF; | |
401 } | |
402 | |
403 /** | |
404 * Asserts that the constant pool index {@code index} is in the bounds of the constant pool. | |
405 * | |
406 * @param index constant pool index | |
407 */ | |
408 private void assertBounds(int index) { | |
409 assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length(); | |
410 } | |
411 | |
412 /** | |
413 * Asserts that the constant pool tag at index {@code index} is equal to {@code tag}. | |
414 * | |
415 * @param index constant pool index | |
416 * @param tag expected tag | |
417 */ | |
418 private void assertTag(int index, JVM_CONSTANT tag) { | |
419 assert getTagAt(index) == tag : "constant pool tag at index " + index + " is " + getTagAt(index) + " but expected " + tag; | |
420 } | |
421 | |
422 @Override | |
423 public int length() { | |
424 return unsafe.getInt(metaspaceConstantPool + runtime().getConfig().constantPoolLengthOffset); | |
425 } | |
426 | |
427 @Override | |
428 public Object lookupConstant(int cpi) { | |
429 assert cpi != 0; | |
430 final JVM_CONSTANT tag = getTagAt(cpi); | |
431 switch (tag) { | |
432 case Integer: | |
433 return JavaConstant.forInt(getIntAt(cpi)); | |
434 case Long: | |
435 return JavaConstant.forLong(getLongAt(cpi)); | |
436 case Float: | |
437 return JavaConstant.forFloat(getFloatAt(cpi)); | |
438 case Double: | |
439 return JavaConstant.forDouble(getDoubleAt(cpi)); | |
440 case Class: | |
441 case UnresolvedClass: | |
442 case UnresolvedClassInError: | |
443 final int opcode = -1; // opcode is not used | |
444 return lookupType(cpi, opcode); | |
445 case String: | |
446 Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(metaspaceConstantPool, cpi); | |
447 return HotSpotObjectConstantImpl.forObject(string); | |
448 case MethodHandle: | |
449 case MethodHandleInError: | |
450 case MethodType: | |
451 case MethodTypeInError: | |
452 Object obj = runtime().getCompilerToVM().resolveConstantInPool(metaspaceConstantPool, cpi); | |
453 return HotSpotObjectConstantImpl.forObject(obj); | |
454 default: | |
455 throw new JVMCIError("Unknown constant pool tag %s", tag); | |
456 } | |
457 } | |
458 | |
459 @Override | |
460 public String lookupUtf8(int cpi) { | |
461 assertTag(cpi, JVM_CONSTANT.Utf8); | |
462 return runtime().getCompilerToVM().getSymbol(getEntryAt(cpi)); | |
463 } | |
464 | |
465 @Override | |
466 public Signature lookupSignature(int cpi) { | |
467 return new HotSpotSignature(runtime(), lookupUtf8(cpi)); | |
468 } | |
469 | |
470 @Override | |
471 public JavaConstant lookupAppendix(int cpi, int opcode) { | |
472 assert Bytecodes.isInvoke(opcode); | |
473 final int index = toConstantPoolIndex(cpi, opcode); | |
474 Object result = runtime().getCompilerToVM().lookupAppendixInPool(metaspaceConstantPool, index); | |
475 if (result == null) { | |
476 return null; | |
477 } else { | |
478 return HotSpotObjectConstantImpl.forObject(result); | |
479 } | |
480 } | |
481 | |
482 /** | |
483 * Gets a {@link JavaType} corresponding a given metaspace Klass or a metaspace Symbol depending | |
484 * on the {@link HotSpotVMConfig#compilerToVMKlassTag tag}. | |
485 * | |
486 * @param metaspacePointer either a metaspace Klass or a metaspace Symbol | |
487 */ | |
488 private static JavaType getJavaType(final long metaspacePointer) { | |
489 HotSpotJVMCIRuntime runtime = runtime(); | |
490 HotSpotVMConfig config = runtime.getConfig(); | |
491 if ((metaspacePointer & config.compilerToVMSymbolTag) != 0) { | |
492 final long metaspaceSymbol = metaspacePointer & ~config.compilerToVMSymbolTag; | |
493 String name = runtime.getCompilerToVM().getSymbol(metaspaceSymbol); | |
494 return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";"); | |
495 } else { | |
496 assert (metaspacePointer & config.compilerToVMKlassTag) == 0; | |
497 return HotSpotResolvedObjectTypeImpl.fromMetaspaceKlass(metaspacePointer); | |
498 } | |
499 } | |
500 | |
501 @Override | |
502 public JavaMethod lookupMethod(int cpi, int opcode) { | |
503 if (opcode != Bytecodes.INVOKEDYNAMIC) { | |
504 Object result = cache[cpi]; | |
505 if (result != null) { | |
506 return (ResolvedJavaMethod) result; | |
507 } | |
508 } | |
509 final int index = toConstantPoolIndex(cpi, opcode); | |
510 final long metaspaceMethod = runtime().getCompilerToVM().lookupMethodInPool(metaspaceConstantPool, index, (byte) opcode); | |
511 if (metaspaceMethod != 0L) { | |
512 HotSpotResolvedJavaMethod result = HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod); | |
513 if (opcode != Bytecodes.INVOKEDYNAMIC) { | |
514 cache[cpi] = result; | |
515 } | |
516 return result; | |
517 } else { | |
518 // Get the method's name and signature. | |
519 String name = getNameRefAt(index); | |
520 HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureRefAt(index)); | |
521 if (opcode == Bytecodes.INVOKEDYNAMIC) { | |
522 HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class); | |
523 return new HotSpotMethodUnresolved(name, signature, holder); | |
524 } else { | |
525 final int klassIndex = getKlassRefIndexAt(index); | |
526 final long metaspacePointer = runtime().getCompilerToVM().lookupKlassInPool(metaspaceConstantPool, klassIndex); | |
527 JavaType holder = getJavaType(metaspacePointer); | |
528 return new HotSpotMethodUnresolved(name, signature, holder); | |
529 } | |
530 } | |
531 } | |
532 | |
533 @Override | |
534 public JavaType lookupType(int cpi, int opcode) { | |
535 final LookupTypeCacheElement elem = this.lastLookupType; | |
536 if (elem != null && elem.lastCpi == cpi) { | |
537 return elem.javaType; | |
538 } else { | |
539 final long metaspacePointer = runtime().getCompilerToVM().lookupKlassInPool(metaspaceConstantPool, cpi); | |
540 JavaType result = getJavaType(metaspacePointer); | |
541 if (result instanceof ResolvedJavaType) { | |
542 this.lastLookupType = new LookupTypeCacheElement(cpi, result); | |
543 } | |
544 return result; | |
545 } | |
546 } | |
547 | |
548 @Override | |
549 public JavaField lookupField(int cpi, int opcode) { | |
550 Object resolvedJavaField = cache[cpi]; | |
551 if (resolvedJavaField != null) { | |
552 return (ResolvedJavaField) resolvedJavaField; | |
553 } | |
554 final int index = toConstantPoolIndex(cpi, opcode); | |
555 final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index); | |
556 final int nameIndex = getNameRefIndexAt(nameAndTypeIndex); | |
557 String name = lookupUtf8(nameIndex); | |
558 final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex); | |
559 String typeName = lookupUtf8(typeIndex); | |
560 JavaType type = runtime().lookupType(typeName, getHolder(), false); | |
561 | |
562 final int holderIndex = getKlassRefIndexAt(index); | |
563 JavaType holder = lookupType(holderIndex, opcode); | |
564 | |
565 if (holder instanceof HotSpotResolvedObjectTypeImpl) { | |
566 long[] info = new long[2]; | |
567 long metaspaceKlass; | |
568 try { | |
569 metaspaceKlass = runtime().getCompilerToVM().resolveField(metaspaceConstantPool, index, (byte) opcode, info); | |
570 } catch (Throwable t) { | |
571 /* | |
572 * If there was an exception resolving the field we give up and return an unresolved | |
573 * field. | |
574 */ | |
575 return new HotSpotUnresolvedField(holder, name, type); | |
576 } | |
577 HotSpotResolvedObjectTypeImpl resolvedHolder = HotSpotResolvedObjectTypeImpl.fromMetaspaceKlass(metaspaceKlass); | |
578 final int flags = (int) info[0]; | |
579 final long offset = info[1]; | |
580 HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags); | |
581 if (type instanceof ResolvedJavaType) { | |
582 cache[cpi] = result; | |
583 } | |
584 return result; | |
585 } else { | |
586 return new HotSpotUnresolvedField(holder, name, type); | |
587 } | |
588 } | |
589 | |
590 @Override | |
591 public void loadReferencedType(int cpi, int opcode) { | |
592 int index; | |
593 switch (opcode) { | |
594 case Bytecodes.CHECKCAST: | |
595 case Bytecodes.INSTANCEOF: | |
596 case Bytecodes.NEW: | |
597 case Bytecodes.ANEWARRAY: | |
598 case Bytecodes.MULTIANEWARRAY: | |
599 case Bytecodes.LDC: | |
600 case Bytecodes.LDC_W: | |
601 case Bytecodes.LDC2_W: | |
602 index = cpi; | |
603 break; | |
604 case Bytecodes.INVOKEDYNAMIC: | |
605 // invokedynamic instructions point to a constant pool cache entry. | |
606 index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag; | |
607 index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index); | |
608 break; | |
609 default: | |
610 index = toConstantPoolIndex(cpi, opcode); | |
611 index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index); | |
612 } | |
613 | |
614 JVM_CONSTANT tag = getTagAt(index); | |
615 if (tag == null) { | |
616 assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long; | |
617 return; | |
618 } | |
619 switch (tag) { | |
620 case Fieldref: | |
621 case MethodRef: | |
622 case InterfaceMethodref: | |
623 index = getUncachedKlassRefIndexAt(index); | |
624 tag = getTagAt(index); | |
625 assert tag == JVM_CONSTANT.Class || tag == JVM_CONSTANT.UnresolvedClass || tag == JVM_CONSTANT.UnresolvedClassInError : tag; | |
626 // fall through | |
627 case Class: | |
628 case UnresolvedClass: | |
629 case UnresolvedClassInError: | |
630 final long metaspaceKlass = runtime().getCompilerToVM().constantPoolKlassAt(metaspaceConstantPool, index); | |
631 HotSpotResolvedObjectTypeImpl type = HotSpotResolvedObjectTypeImpl.fromMetaspaceKlass(metaspaceKlass); | |
632 Class<?> klass = type.mirror(); | |
633 if (!klass.isPrimitive() && !klass.isArray()) { | |
634 unsafe.ensureClassInitialized(klass); | |
635 } | |
636 break; | |
637 case InvokeDynamic: | |
638 if (isInvokedynamicIndex(cpi)) { | |
639 runtime().getCompilerToVM().resolveInvokeDynamic(metaspaceConstantPool, cpi); | |
640 } | |
641 break; | |
642 default: | |
643 // nothing | |
644 break; | |
645 } | |
646 } | |
647 | |
648 @Override | |
649 public String toString() { | |
650 HotSpotResolvedObjectType holder = getHolder(); | |
651 return "HotSpotConstantPool<" + holder.toJavaName() + ">"; | |
652 } | |
653 } |