Mercurial > hg > truffle
comparison agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 38fd165da001 |
children | 18fb7da42534 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
32 import sun.jvm.hotspot.utilities.*; | 32 import sun.jvm.hotspot.utilities.*; |
33 | 33 |
34 // A ConstantPool is an oop containing class constants | 34 // A ConstantPool is an oop containing class constants |
35 // as described in the class file | 35 // as described in the class file |
36 | 36 |
37 public class ConstantPool extends Oop implements ClassConstants { | 37 public class ConstantPool extends Metadata implements ClassConstants { |
38 | |
39 public class CPSlot { | 38 public class CPSlot { |
40 private Address ptr; | 39 private Address ptr; |
41 | 40 |
42 CPSlot(Address ptr) { | 41 CPSlot(Address ptr) { |
43 this.ptr = ptr; | 42 this.ptr = ptr; |
44 } | 43 } |
45 CPSlot(Symbol sym) { | 44 CPSlot(Symbol sym) { |
46 this.ptr = sym.getAddress().orWithMask(1); | 45 this.ptr = sym.getAddress().orWithMask(1); |
47 } | 46 } |
48 | 47 |
49 public boolean isOop() { | 48 public boolean isResolved() { |
50 return (ptr.minus(null) & 1) == 0; | 49 return (ptr.minus(null) & 1) == 0; |
51 } | 50 } |
52 public boolean isMetaData() { | 51 public boolean isUnresolved() { |
53 return (ptr.minus(null) & 1) == 1; | 52 return (ptr.minus(null) & 1) == 1; |
54 } | 53 } |
55 | 54 |
56 public Symbol getSymbol() { | 55 public Symbol getSymbol() { |
57 if (isMetaData()) { | 56 if (!isUnresolved()) throw new InternalError("not a symbol"); |
58 return Symbol.create(ptr.xorWithMask(1)); | 57 return Symbol.create(ptr.xorWithMask(1)); |
59 } | 58 } |
60 throw new InternalError("not a symbol"); | 59 public Klass getKlass() { |
61 } | 60 if (!isResolved()) throw new InternalError("not klass"); |
62 public Oop getOop() { | 61 return (Klass)Metadata.instantiateWrapperFor(ptr); |
63 if (isOop()) { | |
64 return VM.getVM().getObjectHeap().newOop(ptr.addOffsetToAsOopHandle(0)); | |
65 } | |
66 throw new InternalError("not an oop"); | |
67 } | 62 } |
68 } | 63 } |
69 | 64 |
70 // Used for debugging this code | 65 // Used for debugging this code |
71 private static final boolean DEBUG = false; | 66 private static final boolean DEBUG = false; |
81 } | 76 } |
82 }); | 77 }); |
83 } | 78 } |
84 | 79 |
85 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { | 80 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { |
86 Type type = db.lookupType("constantPoolOopDesc"); | 81 Type type = db.lookupType("ConstantPool"); |
87 tags = new OopField(type.getOopField("_tags"), 0); | 82 tags = type.getAddressField("_tags"); |
88 operands = new OopField(type.getOopField("_operands"), 0); | 83 operands = type.getAddressField("_operands"); |
89 cache = new OopField(type.getOopField("_cache"), 0); | 84 cache = type.getAddressField("_cache"); |
90 poolHolder = new OopField(type.getOopField("_pool_holder"), 0); | 85 poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0); |
91 length = new CIntField(type.getCIntegerField("_length"), 0); | 86 length = new CIntField(type.getCIntegerField("_length"), 0); |
87 resolvedReferences = type.getAddressField("_resolved_references"); | |
88 referenceMap = type.getAddressField("_reference_map"); | |
92 headerSize = type.getSize(); | 89 headerSize = type.getSize(); |
93 elementSize = 0; | 90 elementSize = 0; |
94 // fetch constants: | 91 // fetch constants: |
95 INDY_BSM_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_bsm_offset").intValue(); | 92 INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); |
96 INDY_ARGC_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argc_offset").intValue(); | 93 INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); |
97 INDY_ARGV_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argv_offset").intValue(); | 94 INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); |
98 } | 95 } |
99 | 96 |
100 ConstantPool(OopHandle handle, ObjectHeap heap) { | 97 public ConstantPool(Address addr) { |
101 super(handle, heap); | 98 super(addr); |
102 } | 99 } |
103 | 100 |
104 public boolean isConstantPool() { return true; } | 101 public boolean isConstantPool() { return true; } |
105 | 102 |
106 private static OopField tags; | 103 private static AddressField tags; |
107 private static OopField operands; | 104 private static AddressField operands; |
108 private static OopField cache; | 105 private static AddressField cache; |
109 private static OopField poolHolder; | 106 private static MetadataField poolHolder; |
110 private static CIntField length; // number of elements in oop | 107 private static CIntField length; // number of elements in oop |
108 private static AddressField resolvedReferences; | |
109 private static AddressField referenceMap; | |
111 | 110 |
112 private static long headerSize; | 111 private static long headerSize; |
113 private static long elementSize; | 112 private static long elementSize; |
114 | 113 |
115 private static int INDY_BSM_OFFSET; | 114 private static int INDY_BSM_OFFSET; |
116 private static int INDY_ARGC_OFFSET; | 115 private static int INDY_ARGC_OFFSET; |
117 private static int INDY_ARGV_OFFSET; | 116 private static int INDY_ARGV_OFFSET; |
118 | 117 |
119 public TypeArray getTags() { return (TypeArray) tags.getValue(this); } | 118 public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); } |
120 public TypeArray getOperands() { return (TypeArray) operands.getValue(this); } | 119 public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); } |
121 public ConstantPoolCache getCache() { return (ConstantPoolCache) cache.getValue(this); } | 120 public ConstantPoolCache getCache() { |
121 Address addr = cache.getValue(getAddress()); | |
122 return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr); | |
123 } | |
122 public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); } | 124 public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); } |
123 public int getLength() { return (int)length.getValue(this); } | 125 public int getLength() { return (int)length.getValue(getAddress()); } |
126 public Oop getResolvedReferences() { | |
127 Address handle = resolvedReferences.getValue(getAddress()); | |
128 if (handle != null) { | |
129 // Load through the handle | |
130 OopHandle refs = handle.getOopHandleAt(0); | |
131 return VM.getVM().getObjectHeap().newOop(refs); | |
132 } | |
133 return null; | |
134 } | |
135 | |
136 public U2Array referenceMap() { | |
137 return new U2Array(referenceMap.getValue(getAddress())); | |
138 } | |
139 | |
140 public int objectToCPIndex(int index) { | |
141 return referenceMap().at(index); | |
142 } | |
124 | 143 |
125 private long getElementSize() { | 144 private long getElementSize() { |
126 if (elementSize !=0 ) { | 145 if (elementSize !=0 ) { |
127 return elementSize; | 146 return elementSize; |
128 } else { | 147 } else { |
137 } | 156 } |
138 return (index * getElementSize()) + headerSize; | 157 return (index * getElementSize()) + headerSize; |
139 } | 158 } |
140 | 159 |
141 public ConstantTag getTagAt(long index) { | 160 public ConstantTag getTagAt(long index) { |
142 return new ConstantTag(getTags().getByteAt((int) index)); | 161 return new ConstantTag((byte)getTags().at((int) index)); |
143 } | 162 } |
144 | 163 |
145 public CPSlot getSlotAt(long index) { | 164 public CPSlot getSlotAt(long index) { |
146 return new CPSlot(getHandle().getAddressAt(indexOffset(index))); | 165 return new CPSlot(getAddressAtRaw(index)); |
147 } | 166 } |
148 | 167 |
149 public Oop getObjAtRaw(long index){ | 168 public Address getAddressAtRaw(long index) { |
150 return getHeap().newOop(getHandle().getOopHandleAt(indexOffset(index))); | 169 return getAddress().getAddressAt(indexOffset(index)); |
151 } | 170 } |
152 | 171 |
153 public Symbol getSymbolAt(long index) { | 172 public Symbol getSymbolAt(long index) { |
154 CPSlot slot = getSlotAt(index); | 173 return Symbol.create(getAddressAtRaw(index)); |
155 return slot.getSymbol(); | |
156 } | 174 } |
157 | 175 |
158 public int getIntAt(long index){ | 176 public int getIntAt(long index){ |
159 return getHandle().getJIntAt(indexOffset(index)); | 177 return getAddress().getJIntAt(indexOffset(index)); |
160 } | 178 } |
161 | 179 |
162 public float getFloatAt(long index){ | 180 public float getFloatAt(long index){ |
163 return getHandle().getJFloatAt(indexOffset(index)); | 181 return getAddress().getJFloatAt(indexOffset(index)); |
164 } | 182 } |
165 | 183 |
166 public long getLongAt(long index) { | 184 public long getLongAt(long index) { |
167 int oneHalf = getHandle().getJIntAt(indexOffset(index + 1)); | 185 int oneHalf = getAddress().getJIntAt(indexOffset(index + 1)); |
168 int otherHalf = getHandle().getJIntAt(indexOffset(index)); | 186 int otherHalf = getAddress().getJIntAt(indexOffset(index)); |
169 // buildLongFromIntsPD accepts higher address value, lower address value | 187 // buildLongFromIntsPD accepts higher address value, lower address value |
170 // in that order. | 188 // in that order. |
171 return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); | 189 return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); |
172 } | 190 } |
173 | 191 |
183 ConstantPoolCache cache = getCache(); | 201 ConstantPoolCache cache = getCache(); |
184 if (cache == null) { | 202 if (cache == null) { |
185 i = which; | 203 i = which; |
186 } else { | 204 } else { |
187 // change byte-ordering and go via cache | 205 // change byte-ordering and go via cache |
188 i = cache.getEntryAt(0xFFFF & VM.getVM().getBytes().swapShort((short) which)).getConstantPoolIndex(); | 206 i = cache.getEntryAt(0xFFFF & which).getConstantPoolIndex(); |
189 } | 207 } |
190 if (Assert.ASSERTS_ENABLED) { | 208 if (Assert.ASSERTS_ENABLED) { |
191 Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); | 209 Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); |
192 } | 210 } |
193 if (DEBUG) { | 211 if (DEBUG) { |
200 return res; | 218 return res; |
201 } | 219 } |
202 | 220 |
203 public int[] getNameAndTypeAt(int which) { | 221 public int[] getNameAndTypeAt(int which) { |
204 if (Assert.ASSERTS_ENABLED) { | 222 if (Assert.ASSERTS_ENABLED) { |
205 Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool"); | 223 Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool: " + which + " " + getTagAt(which)); |
206 } | 224 } |
207 int i = getIntAt(which); | 225 int i = getIntAt(which); |
208 if (DEBUG) { | 226 if (DEBUG) { |
209 System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i); | 227 System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i); |
210 } | 228 } |
211 return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) }; | 229 return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) }; |
212 } | 230 } |
213 | 231 |
214 public Symbol getNameRefAt(int which) { | 232 public Symbol getNameRefAt(int which) { |
215 return implGetNameRefAt(which, false); | 233 return implGetNameRefAt(which, false); |
234 } | |
235 | |
236 public Symbol uncachedGetNameRefAt(int which) { | |
237 return implGetNameRefAt(which, true); | |
216 } | 238 } |
217 | 239 |
218 private Symbol implGetNameRefAt(int which, boolean uncached) { | 240 private Symbol implGetNameRefAt(int which, boolean uncached) { |
219 int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); | 241 int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); |
220 return getSymbolAt(signatureIndex); | 242 return getSymbolAt(signatureIndex); |
222 | 244 |
223 public Symbol getSignatureRefAt(int which) { | 245 public Symbol getSignatureRefAt(int which) { |
224 return implGetSignatureRefAt(which, false); | 246 return implGetSignatureRefAt(which, false); |
225 } | 247 } |
226 | 248 |
249 public Symbol uncachedGetSignatureRefAt(int which) { | |
250 return implGetSignatureRefAt(which, true); | |
251 } | |
252 | |
227 private Symbol implGetSignatureRefAt(int which, boolean uncached) { | 253 private Symbol implGetSignatureRefAt(int which, boolean uncached) { |
228 int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); | 254 int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); |
229 return getSymbolAt(signatureIndex); | 255 return getSymbolAt(signatureIndex); |
230 } | 256 } |
231 | 257 |
258 public static boolean isInvokedynamicIndex(int i) { return (i < 0); } | |
259 | |
260 public static int decodeInvokedynamicIndex(int i) { Assert.that(isInvokedynamicIndex(i), ""); return ~i; } | |
261 | |
262 // The invokedynamic points at the object index. The object map points at | |
263 // the cpCache index and the cpCache entry points at the original constant | |
264 // pool index. | |
265 public int invokedynamicCPCacheIndex(int index) { | |
266 Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index"); | |
267 int rawIndex = decodeInvokedynamicIndex(index); | |
268 return referenceMap().at(rawIndex); | |
269 } | |
270 | |
271 ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) { | |
272 // decode index that invokedynamic points to. | |
273 int cpCacheIndex = invokedynamicCPCacheIndex(index); | |
274 return getCache().getEntryAt(cpCacheIndex); | |
275 } | |
232 | 276 |
233 private int implNameAndTypeRefIndexAt(int which, boolean uncached) { | 277 private int implNameAndTypeRefIndexAt(int which, boolean uncached) { |
234 int i = which; | 278 int i = which; |
235 if (!uncached && getCache() != null) { | 279 if (!uncached && getCache() != null) { |
236 if (ConstantPoolCache.isSecondaryIndex(which)) { | 280 if (isInvokedynamicIndex(which)) { |
237 // Invokedynamic index. | 281 // Invokedynamic index is index into resolved_references |
238 int pool_index = getCache().getMainEntryAt(which).getConstantPoolIndex(); | 282 int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex(); |
239 pool_index = invokeDynamicNameAndTypeRefIndexAt(pool_index); | 283 poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex); |
240 // assert(tagAt(pool_index).isNameAndType(), ""); | 284 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); |
241 return pool_index; | 285 return poolIndex; |
242 } | 286 } |
243 // change byte-ordering and go via cache | 287 // change byte-ordering and go via cache |
244 i = remapInstructionOperandFromCache(which); | 288 i = remapInstructionOperandFromCache(which); |
245 } else { | 289 } else { |
246 if (getTagAt(which).isInvokeDynamic()) { | 290 if (getTagAt(which).isInvokeDynamic()) { |
247 int pool_index = invokeDynamicNameAndTypeRefIndexAt(which); | 291 int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which); |
248 // assert(tag_at(pool_index).is_name_and_type(), ""); | 292 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); |
249 return pool_index; | 293 return poolIndex; |
250 } | 294 } |
251 } | 295 } |
252 // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); | 296 // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); |
253 // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); | 297 // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); |
254 int ref_index = getIntAt(i); | 298 int refIndex = getIntAt(i); |
255 return extractHighShortFromInt(ref_index); | 299 return extractHighShortFromInt(refIndex); |
256 } | 300 } |
257 | 301 |
258 private int remapInstructionOperandFromCache(int operand) { | 302 private int remapInstructionOperandFromCache(int operand) { |
259 int cpc_index = operand; | 303 int cpc_index = operand; |
260 // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG); | 304 // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG); |
267 // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); | 311 // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
268 return extractHighShortFromInt(getIntAt(which)); | 312 return extractHighShortFromInt(getIntAt(which)); |
269 } | 313 } |
270 | 314 |
271 // returns null, if not resolved. | 315 // returns null, if not resolved. |
272 public Klass getKlassRefAt(int which) { | 316 public Klass getKlassAt(int which) { |
273 if( ! getTagAt(which).isKlass()) return null; | 317 if( ! getTagAt(which).isKlass()) return null; |
274 return (Klass) getObjAtRaw(which); | 318 return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); |
319 } | |
320 | |
321 public Symbol getKlassNameAt(int which) { | |
322 CPSlot entry = getSlotAt(which); | |
323 if (entry.isResolved()) { | |
324 return entry.getKlass().getName(); | |
325 } else { | |
326 return entry.getSymbol(); | |
327 } | |
328 } | |
329 | |
330 public Symbol getUnresolvedStringAt(int which) { | |
331 return getSymbolAt(which); | |
275 } | 332 } |
276 | 333 |
277 // returns null, if not resolved. | 334 // returns null, if not resolved. |
278 public InstanceKlass getFieldOrMethodKlassRefAt(int which) { | 335 public InstanceKlass getFieldOrMethodKlassRefAt(int which) { |
279 int refIndex = getFieldOrMethodAt(which); | 336 int refIndex = getFieldOrMethodAt(which); |
280 int klassIndex = extractLowShortFromInt(refIndex); | 337 int klassIndex = extractLowShortFromInt(refIndex); |
281 return (InstanceKlass) getKlassRefAt(klassIndex); | 338 return (InstanceKlass) getKlassAt(klassIndex); |
282 } | 339 } |
283 | 340 |
284 // returns null, if not resolved. | 341 // returns null, if not resolved. |
285 public Method getMethodRefAt(int which) { | 342 public Method getMethodRefAt(int which) { |
286 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); | 343 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); |
369 public short[] getBootstrapSpecifierAt(int i) { | 426 public short[] getBootstrapSpecifierAt(int i) { |
370 if (Assert.ASSERTS_ENABLED) { | 427 if (Assert.ASSERTS_ENABLED) { |
371 Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); | 428 Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); |
372 } | 429 } |
373 int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); | 430 int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); |
374 TypeArray operands = getOperands(); | 431 U2Array operands = getOperands(); |
375 if (operands == null) return null; // safety first | 432 if (operands == null) return null; // safety first |
376 int basePos = VM.getVM().buildIntFromShorts(operands.getShortAt(bsmSpec * 2 + 0), | 433 int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0), |
377 operands.getShortAt(bsmSpec * 2 + 1)); | 434 operands.at(bsmSpec * 2 + 1)); |
378 int argv = basePos + INDY_ARGV_OFFSET; | 435 int argv = basePos + INDY_ARGV_OFFSET; |
379 int argc = operands.getShortAt(basePos + INDY_ARGC_OFFSET); | 436 int argc = operands.at(basePos + INDY_ARGC_OFFSET); |
380 int endPos = argv + argc; | 437 int endPos = argv + argc; |
381 short[] values = new short[endPos - basePos]; | 438 short[] values = new short[endPos - basePos]; |
382 for (int j = 0; j < values.length; j++) { | 439 for (int j = 0; j < values.length; j++) { |
383 values[j] = operands.getShortAt(basePos+j); | 440 values[j] = operands.at(basePos+j); |
384 } | 441 } |
385 return values; | 442 return values; |
386 } | 443 } |
387 | 444 |
388 final private static String[] nameForTag = new String[] { | 445 final private static String[] nameForTag = new String[] { |
405 case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; | 462 case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; |
406 case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; | 463 case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; |
407 case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; | 464 case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; |
408 case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; | 465 case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; |
409 case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; | 466 case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; |
467 case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; | |
468 case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; | |
410 case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; | 469 case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; |
411 case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; | 470 case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; |
412 case JVM_CONSTANT_UnresolvedString: return "JVM_CONSTANT_UnresolvedString"; | 471 case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; |
413 case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; | 472 case JVM_CONSTANT_Object: return "JVM_CONSTANT_Object"; |
414 } | 473 } |
415 throw new InternalError("Unknown tag: " + tag); | 474 throw new InternalError("Unknown tag: " + tag); |
416 } | 475 } |
417 | 476 |
418 public void iterateFields(OopVisitor visitor, boolean doVMFields) { | 477 public void iterateFields(MetadataVisitor visitor) { |
419 super.iterateFields(visitor, doVMFields); | 478 super.iterateFields(visitor); |
420 if (doVMFields) { | 479 visitor.doMetadata(poolHolder, true); |
421 visitor.doOop(tags, true); | |
422 visitor.doOop(cache, true); | |
423 visitor.doOop(poolHolder, true); | |
424 | 480 |
425 final int length = (int) getLength(); | 481 final int length = (int) getLength(); |
426 // zero'th pool entry is always invalid. ignore it. | 482 // zero'th pool entry is always invalid. ignore it. |
427 for (int index = 1; index < length; index++) { | 483 for (int index = 1; index < length; index++) { |
428 int ctag = (int) getTags().getByteAt((int) index); | 484 int ctag = (int) getTags().at((int) index); |
429 switch (ctag) { | 485 switch (ctag) { |
430 case JVM_CONSTANT_ClassIndex: | 486 case JVM_CONSTANT_ClassIndex: |
431 case JVM_CONSTANT_StringIndex: | 487 case JVM_CONSTANT_StringIndex: |
432 case JVM_CONSTANT_Integer: | 488 case JVM_CONSTANT_Integer: |
433 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); | 489 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); |
450 break; | 506 break; |
451 | 507 |
452 case JVM_CONSTANT_UnresolvedClassInError: | 508 case JVM_CONSTANT_UnresolvedClassInError: |
453 case JVM_CONSTANT_UnresolvedClass: | 509 case JVM_CONSTANT_UnresolvedClass: |
454 case JVM_CONSTANT_Class: | 510 case JVM_CONSTANT_Class: |
455 case JVM_CONSTANT_UnresolvedString: | |
456 case JVM_CONSTANT_Utf8: | 511 case JVM_CONSTANT_Utf8: |
457 visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); | 512 visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); |
458 break; | 513 break; |
459 | 514 |
460 case JVM_CONSTANT_Fieldref: | 515 case JVM_CONSTANT_Fieldref: |
467 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); | 522 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); |
468 break; | 523 break; |
469 } | 524 } |
470 } | 525 } |
471 } | 526 } |
472 /* | |
473 int length = getLength(); | |
474 for (int index = 0; index < length; index++) { | |
475 long offset = baseOffset + (index + typeDataBase.getOopSize()); | |
476 visitor.doOop(new IndexableField(index, offset, false), getObjAt(index)); | |
477 } | |
478 */ | |
479 } | |
480 | 527 |
481 public void writeBytes(OutputStream os) throws IOException { | 528 public void writeBytes(OutputStream os) throws IOException { |
482 // Map between any modified UTF-8 and it's constant pool index. | 529 // Map between any modified UTF-8 and it's constant pool index. |
483 Map utf8ToIndex = new HashMap(); | 530 Map utf8ToIndex = new HashMap(); |
484 DataOutputStream dos = new DataOutputStream(os); | 531 DataOutputStream dos = new DataOutputStream(os); |
485 TypeArray tags = getTags(); | 532 U1Array tags = getTags(); |
486 int len = (int)getLength(); | 533 int len = (int)getLength(); |
487 int ci = 0; // constant pool index | 534 int ci = 0; // constant pool index |
488 | 535 |
489 // collect all modified UTF-8 Strings from Constant Pool | 536 // collect all modified UTF-8 Strings from Constant Pool |
490 | 537 |
491 for (ci = 1; ci < len; ci++) { | 538 for (ci = 1; ci < len; ci++) { |
492 byte cpConstType = tags.getByteAt(ci); | 539 int cpConstType = tags.at(ci); |
493 if(cpConstType == JVM_CONSTANT_Utf8) { | 540 if(cpConstType == JVM_CONSTANT_Utf8) { |
494 Symbol sym = getSymbolAt(ci); | 541 Symbol sym = getSymbolAt(ci); |
495 utf8ToIndex.put(sym.asString(), new Short((short) ci)); | 542 utf8ToIndex.put(sym.asString(), new Short((short) ci)); |
496 } | 543 } |
497 else if(cpConstType == JVM_CONSTANT_Long || | 544 else if(cpConstType == JVM_CONSTANT_Long || |
500 } | 547 } |
501 } | 548 } |
502 | 549 |
503 | 550 |
504 for(ci = 1; ci < len; ci++) { | 551 for(ci = 1; ci < len; ci++) { |
505 int cpConstType = (int)tags.getByteAt(ci); | 552 int cpConstType = tags.at(ci); |
506 // write cp_info | 553 // write cp_info |
507 // write constant type | 554 // write constant type |
508 switch(cpConstType) { | 555 switch(cpConstType) { |
509 case JVM_CONSTANT_Utf8: { | 556 case JVM_CONSTANT_Utf8: { |
510 dos.writeByte(cpConstType); | 557 dos.writeByte(cpConstType); |
546 ci++; | 593 ci++; |
547 break; | 594 break; |
548 | 595 |
549 case JVM_CONSTANT_Class: { | 596 case JVM_CONSTANT_Class: { |
550 dos.writeByte(cpConstType); | 597 dos.writeByte(cpConstType); |
551 // Klass already resolved. ConstantPool constains klassOop. | 598 // Klass already resolved. ConstantPool constains Klass*. |
552 Klass refKls = (Klass) getObjAtRaw(ci); | 599 Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci)); |
553 String klassName = refKls.getName().asString(); | 600 String klassName = refKls.getName().asString(); |
554 Short s = (Short) utf8ToIndex.get(klassName); | 601 Short s = (Short) utf8ToIndex.get(klassName); |
555 dos.writeShort(s.shortValue()); | 602 dos.writeShort(s.shortValue()); |
556 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); | 603 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); |
557 break; | 604 break; |
568 break; | 615 break; |
569 } | 616 } |
570 | 617 |
571 case JVM_CONSTANT_String: { | 618 case JVM_CONSTANT_String: { |
572 dos.writeByte(cpConstType); | 619 dos.writeByte(cpConstType); |
573 String str = OopUtilities.stringOopToString(getObjAtRaw(ci)); | 620 String str = getUnresolvedStringAt(ci).asString(); |
574 Short s = (Short) utf8ToIndex.get(str); | 621 Short s = (Short) utf8ToIndex.get(str); |
575 dos.writeShort(s.shortValue()); | |
576 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); | |
577 break; | |
578 } | |
579 | |
580 // case JVM_CONSTANT_StringIndex: | |
581 case JVM_CONSTANT_UnresolvedString: { | |
582 dos.writeByte(JVM_CONSTANT_String); | |
583 String val = getSymbolAt(ci).asString(); | |
584 | |
585 Short s = (Short) utf8ToIndex.get(val); | |
586 dos.writeShort(s.shortValue()); | 622 dos.writeShort(s.shortValue()); |
587 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); | 623 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); |
588 break; | 624 break; |
589 } | 625 } |
590 | 626 |
616 } | 652 } |
617 | 653 |
618 case JVM_CONSTANT_MethodHandle: { | 654 case JVM_CONSTANT_MethodHandle: { |
619 dos.writeByte(cpConstType); | 655 dos.writeByte(cpConstType); |
620 int value = getIntAt(ci); | 656 int value = getIntAt(ci); |
621 short nameIndex = (short) extractLowShortFromInt(value); | 657 byte refKind = (byte) extractLowShortFromInt(value); |
622 short signatureIndex = (short) extractHighShortFromInt(value); | 658 short memberIndex = (short) extractHighShortFromInt(value); |
623 dos.writeShort(nameIndex); | 659 dos.writeByte(refKind); |
624 dos.writeShort(signatureIndex); | 660 dos.writeShort(memberIndex); |
625 if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex | 661 if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " + |
626 + ", type = " + signatureIndex); | 662 refKind + ", mem = " + memberIndex); |
663 break; | |
664 } | |
665 | |
666 case JVM_CONSTANT_MethodType: { | |
667 dos.writeByte(cpConstType); | |
668 int value = getIntAt(ci); | |
669 short refIndex = (short) value; | |
670 dos.writeShort(refIndex); | |
671 if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); | |
627 break; | 672 break; |
628 } | 673 } |
629 | 674 |
630 case JVM_CONSTANT_InvokeDynamic: { | 675 case JVM_CONSTANT_InvokeDynamic: { |
631 dos.writeByte(cpConstType); | 676 dos.writeByte(cpConstType); |
632 int value = getIntAt(ci); | 677 int value = getIntAt(ci); |
633 short bsmIndex = (short) extractLowShortFromInt(value); | 678 short bsmIndex = (short) extractLowShortFromInt(value); |
634 short nameAndTypeIndex = (short) extractHighShortFromInt(value); | 679 short nameAndTypeIndex = (short) extractHighShortFromInt(value); |
635 dos.writeShort(bsmIndex); | 680 dos.writeShort(bsmIndex); |
636 dos.writeShort(nameAndTypeIndex); | 681 dos.writeShort(nameAndTypeIndex); |
637 if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bsmIndex | 682 if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " + |
638 + ", N&T = " + nameAndTypeIndex); | 683 bsmIndex + ", N&T = " + nameAndTypeIndex); |
639 break; | 684 break; |
640 } | 685 } |
641 | 686 |
642 default: | 687 default: |
643 throw new InternalError("unknown tag: " + cpConstType); | 688 throw new InternalError("Unknown tag: " + cpConstType); |
644 } // switch | 689 } // switch |
645 } | 690 } |
646 dos.flush(); | 691 dos.flush(); |
647 return; | 692 return; |
648 } | 693 } |
649 | 694 |
650 public void printValueOn(PrintStream tty) { | 695 public void printValueOn(PrintStream tty) { |
651 Oop holder = poolHolder.getValue(this); | 696 tty.print("ConstantPool for " + getPoolHolder().getName().asString()); |
652 if (holder instanceof Klass) { | 697 } |
653 tty.print("ConstantPool for " + ((Klass)holder).getName().asString()); | 698 |
654 } else { | 699 public long getSize() { |
655 tty.print("ConstantPool for partially loaded class"); | 700 return Oop.alignObjectSize(headerSize + getLength()); |
656 } | |
657 } | |
658 | |
659 public long getObjectSize() { | |
660 return alignObjectSize(headerSize + (getLength() * getElementSize())); | |
661 } | 701 } |
662 | 702 |
663 //---------------------------------------------------------------------- | 703 //---------------------------------------------------------------------- |
664 // Internals only below this point | 704 // Internals only below this point |
665 // | 705 // |
666 | 706 |
667 private static int extractHighShortFromInt(int val) { | 707 private static int extractHighShortFromInt(int val) { |
668 // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. | 708 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. |
669 return (val >> 16) & 0xFFFF; | 709 return (val >> 16) & 0xFFFF; |
670 } | 710 } |
671 | 711 |
672 private static int extractLowShortFromInt(int val) { | 712 private static int extractLowShortFromInt(int val) { |
673 // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. | 713 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. |
674 return val & 0xFFFF; | 714 return val & 0xFFFF; |
675 } | 715 } |
676 } | 716 } |