src/share/vm/oops/constantPoolOop.hpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2508
b92c45f2bc75
child 2698
38fea01eb669
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

duke@435 1 /*
jrose@1934 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #ifndef SHARE_VM_OOPS_CONSTANTPOOLOOP_HPP
stefank@2314 26 #define SHARE_VM_OOPS_CONSTANTPOOLOOP_HPP
stefank@2314 27
stefank@2314 28 #include "oops/arrayOop.hpp"
stefank@2314 29 #include "oops/cpCacheOop.hpp"
coleenp@2497 30 #include "oops/symbol.hpp"
stefank@2314 31 #include "oops/typeArrayOop.hpp"
stefank@2314 32 #include "utilities/constantTag.hpp"
stefank@2314 33 #ifdef TARGET_ARCH_x86
stefank@2314 34 # include "bytes_x86.hpp"
stefank@2314 35 #endif
stefank@2314 36 #ifdef TARGET_ARCH_sparc
stefank@2314 37 # include "bytes_sparc.hpp"
stefank@2314 38 #endif
stefank@2314 39 #ifdef TARGET_ARCH_zero
stefank@2314 40 # include "bytes_zero.hpp"
stefank@2314 41 #endif
bobv@2508 42 #ifdef TARGET_ARCH_arm
bobv@2508 43 # include "bytes_arm.hpp"
bobv@2508 44 #endif
bobv@2508 45 #ifdef TARGET_ARCH_ppc
bobv@2508 46 # include "bytes_ppc.hpp"
bobv@2508 47 #endif
stefank@2314 48
duke@435 49 // A constantPool is an array containing class constants as described in the
duke@435 50 // class file.
duke@435 51 //
duke@435 52 // Most of the constant pool entries are written during class parsing, which
duke@435 53 // is safe. For klass and string types, the constant pool entry is
duke@435 54 // modified when the entry is resolved. If a klass or string constant pool
duke@435 55 // entry is read without a lock, only the resolved state guarantees that
duke@435 56 // the entry in the constant pool is a klass or String object and
coleenp@2497 57 // not a Symbol*.
duke@435 58
duke@435 59 class SymbolHashMap;
duke@435 60
coleenp@2497 61 class CPSlot VALUE_OBJ_CLASS_SPEC {
coleenp@2497 62 intptr_t _ptr;
coleenp@2497 63 public:
coleenp@2497 64 CPSlot(intptr_t ptr): _ptr(ptr) {}
coleenp@2497 65 CPSlot(void* ptr): _ptr((intptr_t)ptr) {}
coleenp@2497 66 CPSlot(oop ptr): _ptr((intptr_t)ptr) {}
coleenp@2497 67 CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | 1) {}
coleenp@2497 68
coleenp@2497 69 intptr_t value() { return _ptr; }
coleenp@2497 70 bool is_oop() { return (_ptr & 1) == 0; }
coleenp@2497 71 bool is_metadata() { return (_ptr & 1) == 1; }
coleenp@2497 72
coleenp@2497 73 oop get_oop() {
coleenp@2497 74 assert(is_oop(), "bad call");
coleenp@2497 75 return oop(_ptr);
coleenp@2497 76 }
coleenp@2497 77 Symbol* get_symbol() {
coleenp@2497 78 assert(is_metadata(), "bad call");
coleenp@2497 79 return (Symbol*)(_ptr & ~1);
coleenp@2497 80 }
coleenp@2497 81 };
coleenp@2497 82
coleenp@548 83 class constantPoolOopDesc : public oopDesc {
duke@435 84 friend class VMStructs;
duke@435 85 friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast
duke@435 86 private:
duke@435 87 typeArrayOop _tags; // the tag array describing the constant pool's contents
duke@435 88 constantPoolCacheOop _cache; // the cache holding interpreter runtime information
duke@435 89 klassOop _pool_holder; // the corresponding class
jrose@2268 90 typeArrayOop _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
jrose@866 91 int _flags; // a few header bits to describe contents for GC
coleenp@548 92 int _length; // number of elements in the array
jmasa@953 93 volatile bool _is_conc_safe; // if true, safe for concurrent
jmasa@953 94 // GC processing
duke@435 95 // only set to non-zero if constant pool is merged by RedefineClasses
duke@435 96 int _orig_length;
duke@435 97
duke@435 98 void set_tags(typeArrayOop tags) { oop_store_without_check((oop*)&_tags, tags); }
duke@435 99 void tag_at_put(int which, jbyte t) { tags()->byte_at_put(which, t); }
duke@435 100 void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); }
duke@435 101
jrose@2268 102 void set_operands(typeArrayOop operands) { oop_store_without_check((oop*)&_operands, operands); }
jrose@2268 103
jrose@866 104 enum FlagBit {
jrose@1161 105 FB_has_invokedynamic = 1,
jrose@866 106 FB_has_pseudo_string = 2
jrose@866 107 };
jrose@866 108
jrose@866 109 int flags() const { return _flags; }
jrose@866 110 void set_flags(int f) { _flags = f; }
jrose@866 111 bool flag_at(FlagBit fb) const { return (_flags & (1 << (int)fb)) != 0; }
jrose@866 112 void set_flag_at(FlagBit fb);
jrose@866 113 // no clear_flag_at function; they only increase
jrose@866 114
duke@435 115 private:
duke@435 116 intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(constantPoolOopDesc)); }
duke@435 117 oop* tags_addr() { return (oop*)&_tags; }
duke@435 118 oop* cache_addr() { return (oop*)&_cache; }
jrose@2268 119 oop* operands_addr() { return (oop*)&_operands; }
duke@435 120
coleenp@2497 121 CPSlot slot_at(int which) {
coleenp@2497 122 assert(is_within_bounds(which), "index out of bounds");
coleenp@2497 123 // There's a transitional value of zero when converting from
coleenp@2497 124 // Symbol->0->Klass for G1 when resolving classes and strings.
coleenp@2497 125 // wait for the value to be non-zero (this is temporary)
coleenp@2497 126 volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
coleenp@2497 127 if (adr == 0 && which != 0) {
coleenp@2497 128 constantTag t = tag_at(which);
coleenp@2497 129 if (t.is_unresolved_klass() || t.is_klass() ||
coleenp@2497 130 t.is_unresolved_string() || t.is_string()) {
coleenp@2497 131 while ((adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))) == 0);
coleenp@2497 132 }
coleenp@2497 133 }
coleenp@2497 134 return CPSlot(adr);
coleenp@2497 135 }
coleenp@2497 136
coleenp@2497 137 void slot_at_put(int which, CPSlot s) const {
coleenp@2497 138 assert(is_within_bounds(which), "index out of bounds");
coleenp@2497 139 *(intptr_t*)&base()[which] = s.value();
coleenp@2497 140 }
coleenp@2497 141 oop* obj_at_addr_raw(int which) const {
duke@435 142 assert(is_within_bounds(which), "index out of bounds");
duke@435 143 return (oop*) &base()[which];
duke@435 144 }
duke@435 145
coleenp@2497 146 void obj_at_put_without_check(int which, oop o) {
coleenp@2497 147 assert(is_within_bounds(which), "index out of bounds");
coleenp@2497 148 oop_store_without_check((volatile oop *)obj_at_addr_raw(which), o);
coleenp@2497 149 }
coleenp@2497 150
coleenp@2497 151 void obj_at_put(int which, oop o) const {
coleenp@2497 152 assert(is_within_bounds(which), "index out of bounds");
coleenp@2497 153 oop_store((volatile oop*)obj_at_addr_raw(which), o);
coleenp@2497 154 }
coleenp@2497 155
duke@435 156 jint* int_at_addr(int which) const {
duke@435 157 assert(is_within_bounds(which), "index out of bounds");
duke@435 158 return (jint*) &base()[which];
duke@435 159 }
duke@435 160
duke@435 161 jlong* long_at_addr(int which) const {
duke@435 162 assert(is_within_bounds(which), "index out of bounds");
duke@435 163 return (jlong*) &base()[which];
duke@435 164 }
duke@435 165
duke@435 166 jfloat* float_at_addr(int which) const {
duke@435 167 assert(is_within_bounds(which), "index out of bounds");
duke@435 168 return (jfloat*) &base()[which];
duke@435 169 }
duke@435 170
duke@435 171 jdouble* double_at_addr(int which) const {
duke@435 172 assert(is_within_bounds(which), "index out of bounds");
duke@435 173 return (jdouble*) &base()[which];
duke@435 174 }
duke@435 175
duke@435 176 public:
duke@435 177 typeArrayOop tags() const { return _tags; }
jrose@2268 178 typeArrayOop operands() const { return _operands; }
duke@435 179
jrose@866 180 bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
jrose@1161 181 bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); }
jrose@866 182 void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); }
jrose@1161 183 void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); }
jrose@866 184
duke@435 185 // Klass holding pool
duke@435 186 klassOop pool_holder() const { return _pool_holder; }
duke@435 187 void set_pool_holder(klassOop k) { oop_store_without_check((oop*)&_pool_holder, (oop) k); }
duke@435 188 oop* pool_holder_addr() { return (oop*)&_pool_holder; }
duke@435 189
duke@435 190 // Interpreter runtime support
duke@435 191 constantPoolCacheOop cache() const { return _cache; }
duke@435 192 void set_cache(constantPoolCacheOop cache){ oop_store((oop*)&_cache, cache); }
duke@435 193
duke@435 194 // Assembly code support
duke@435 195 static int tags_offset_in_bytes() { return offset_of(constantPoolOopDesc, _tags); }
duke@435 196 static int cache_offset_in_bytes() { return offset_of(constantPoolOopDesc, _cache); }
jrose@2268 197 static int operands_offset_in_bytes() { return offset_of(constantPoolOopDesc, _operands); }
duke@435 198 static int pool_holder_offset_in_bytes() { return offset_of(constantPoolOopDesc, _pool_holder); }
duke@435 199
duke@435 200 // Storing constants
duke@435 201
duke@435 202 void klass_at_put(int which, klassOop k) {
coleenp@2497 203 // Overwrite the old index with a GC friendly value so
coleenp@2497 204 // that if G1 looks during the transition during oop_store it won't
coleenp@2497 205 // assert the symbol is not an oop.
coleenp@2497 206 *obj_at_addr_raw(which) = NULL;
coleenp@2497 207 assert(k != NULL, "resolved class shouldn't be null");
coleenp@2497 208 obj_at_put_without_check(which, k);
duke@435 209 // The interpreter assumes when the tag is stored, the klass is resolved
coleenp@2497 210 // and the klassOop is a klass rather than a Symbol*, so we need
duke@435 211 // hardware store ordering here.
duke@435 212 release_tag_at_put(which, JVM_CONSTANT_Class);
duke@435 213 if (UseConcMarkSweepGC) {
duke@435 214 // In case the earlier card-mark was consumed by a concurrent
duke@435 215 // marking thread before the tag was updated, redirty the card.
coleenp@2497 216 obj_at_put_without_check(which, k);
duke@435 217 }
duke@435 218 }
duke@435 219
duke@435 220 // For temporary use while constructing constant pool
duke@435 221 void klass_index_at_put(int which, int name_index) {
duke@435 222 tag_at_put(which, JVM_CONSTANT_ClassIndex);
duke@435 223 *int_at_addr(which) = name_index;
duke@435 224 }
duke@435 225
duke@435 226 // Temporary until actual use
coleenp@2497 227 void unresolved_klass_at_put(int which, Symbol* s) {
duke@435 228 release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
coleenp@2497 229 slot_at_put(which, s);
duke@435 230 }
duke@435 231
jrose@1957 232 void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
jrose@1957 233 tag_at_put(which, JVM_CONSTANT_MethodHandle);
jrose@1957 234 *int_at_addr(which) = ((jint) ref_index<<16) | ref_kind;
jrose@1957 235 }
jrose@1957 236
jrose@1957 237 void method_type_index_at_put(int which, int ref_index) {
jrose@1957 238 tag_at_put(which, JVM_CONSTANT_MethodType);
jrose@1957 239 *int_at_addr(which) = ref_index;
jrose@1957 240 }
jrose@1957 241
jrose@2353 242 void invoke_dynamic_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) {
jrose@2015 243 tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
jrose@2353 244 *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
jrose@2015 245 }
jrose@2353 246
jrose@2353 247 void invoke_dynamic_trans_at_put(int which, int bootstrap_method_index, int name_and_type_index) {
jrose@2353 248 tag_at_put(which, JVM_CONSTANT_InvokeDynamicTrans);
jrose@2353 249 *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index;
jrose@2353 250 assert(AllowTransitionalJSR292, "");
jrose@2268 251 }
jrose@2015 252
duke@435 253 // Temporary until actual use
coleenp@2497 254 void unresolved_string_at_put(int which, Symbol* s) {
duke@435 255 release_tag_at_put(which, JVM_CONSTANT_UnresolvedString);
coleenp@2497 256 slot_at_put(which, s);
duke@435 257 }
duke@435 258
duke@435 259 void int_at_put(int which, jint i) {
duke@435 260 tag_at_put(which, JVM_CONSTANT_Integer);
duke@435 261 *int_at_addr(which) = i;
duke@435 262 }
duke@435 263
duke@435 264 void long_at_put(int which, jlong l) {
duke@435 265 tag_at_put(which, JVM_CONSTANT_Long);
duke@435 266 // *long_at_addr(which) = l;
duke@435 267 Bytes::put_native_u8((address)long_at_addr(which), *((u8*) &l));
duke@435 268 }
duke@435 269
duke@435 270 void float_at_put(int which, jfloat f) {
duke@435 271 tag_at_put(which, JVM_CONSTANT_Float);
duke@435 272 *float_at_addr(which) = f;
duke@435 273 }
duke@435 274
duke@435 275 void double_at_put(int which, jdouble d) {
duke@435 276 tag_at_put(which, JVM_CONSTANT_Double);
duke@435 277 // *double_at_addr(which) = d;
duke@435 278 // u8 temp = *(u8*) &d;
duke@435 279 Bytes::put_native_u8((address) double_at_addr(which), *((u8*) &d));
duke@435 280 }
duke@435 281
coleenp@2497 282 Symbol** symbol_at_addr(int which) const {
coleenp@2497 283 assert(is_within_bounds(which), "index out of bounds");
coleenp@2497 284 return (Symbol**) &base()[which];
coleenp@2497 285 }
coleenp@2497 286
coleenp@2497 287 void symbol_at_put(int which, Symbol* s) {
coleenp@2497 288 assert(s->refcount() != 0, "should have nonzero refcount");
duke@435 289 tag_at_put(which, JVM_CONSTANT_Utf8);
coleenp@2497 290 slot_at_put(which, s);
duke@435 291 }
duke@435 292
duke@435 293 void string_at_put(int which, oop str) {
coleenp@2497 294 // Overwrite the old index with a GC friendly value so
coleenp@2497 295 // that if G1 looks during the transition during oop_store it won't
coleenp@2497 296 // assert the symbol is not an oop.
coleenp@2497 297 *obj_at_addr_raw(which) = NULL;
coleenp@2497 298 assert(str != NULL, "resolved string shouldn't be null");
coleenp@2497 299 obj_at_put(which, str);
duke@435 300 release_tag_at_put(which, JVM_CONSTANT_String);
duke@435 301 if (UseConcMarkSweepGC) {
duke@435 302 // In case the earlier card-mark was consumed by a concurrent
duke@435 303 // marking thread before the tag was updated, redirty the card.
coleenp@2497 304 obj_at_put_without_check(which, str);
duke@435 305 }
duke@435 306 }
duke@435 307
twisti@1573 308 void object_at_put(int which, oop str) {
coleenp@2497 309 obj_at_put(which, str);
twisti@1573 310 release_tag_at_put(which, JVM_CONSTANT_Object);
twisti@1573 311 if (UseConcMarkSweepGC) {
twisti@1573 312 // In case the earlier card-mark was consumed by a concurrent
twisti@1573 313 // marking thread before the tag was updated, redirty the card.
coleenp@2497 314 obj_at_put_without_check(which, str);
twisti@1573 315 }
twisti@1573 316 }
twisti@1573 317
duke@435 318 // For temporary use while constructing constant pool
duke@435 319 void string_index_at_put(int which, int string_index) {
duke@435 320 tag_at_put(which, JVM_CONSTANT_StringIndex);
duke@435 321 *int_at_addr(which) = string_index;
duke@435 322 }
duke@435 323
duke@435 324 void field_at_put(int which, int class_index, int name_and_type_index) {
duke@435 325 tag_at_put(which, JVM_CONSTANT_Fieldref);
duke@435 326 *int_at_addr(which) = ((jint) name_and_type_index<<16) | class_index;
duke@435 327 }
duke@435 328
duke@435 329 void method_at_put(int which, int class_index, int name_and_type_index) {
duke@435 330 tag_at_put(which, JVM_CONSTANT_Methodref);
duke@435 331 *int_at_addr(which) = ((jint) name_and_type_index<<16) | class_index;
duke@435 332 }
duke@435 333
duke@435 334 void interface_method_at_put(int which, int class_index, int name_and_type_index) {
duke@435 335 tag_at_put(which, JVM_CONSTANT_InterfaceMethodref);
duke@435 336 *int_at_addr(which) = ((jint) name_and_type_index<<16) | class_index; // Not so nice
duke@435 337 }
duke@435 338
duke@435 339 void name_and_type_at_put(int which, int name_index, int signature_index) {
duke@435 340 tag_at_put(which, JVM_CONSTANT_NameAndType);
duke@435 341 *int_at_addr(which) = ((jint) signature_index<<16) | name_index; // Not so nice
duke@435 342 }
duke@435 343
duke@435 344 // Tag query
duke@435 345
duke@435 346 constantTag tag_at(int which) const { return (constantTag)tags()->byte_at_acquire(which); }
duke@435 347
duke@435 348 // Whether the entry is a pointer that must be GC'd.
duke@435 349 bool is_pointer_entry(int which) {
duke@435 350 constantTag tag = tag_at(which);
duke@435 351 return tag.is_klass() ||
twisti@1573 352 tag.is_string() ||
twisti@1573 353 tag.is_object();
duke@435 354 }
duke@435 355
coleenp@2497 356 // Whether the entry points to an object for ldc (resolved or not)
coleenp@2497 357 bool is_object_entry(int which) {
coleenp@2497 358 constantTag tag = tag_at(which);
coleenp@2497 359 return is_pointer_entry(which) ||
coleenp@2497 360 tag.is_unresolved_klass() ||
coleenp@2497 361 tag.is_unresolved_string() ||
coleenp@2497 362 tag.is_symbol();
coleenp@2497 363 }
coleenp@2497 364
duke@435 365 // Fetching constants
duke@435 366
duke@435 367 klassOop klass_at(int which, TRAPS) {
duke@435 368 constantPoolHandle h_this(THREAD, this);
duke@435 369 return klass_at_impl(h_this, which, CHECK_NULL);
duke@435 370 }
duke@435 371
coleenp@2497 372 Symbol* klass_name_at(int which); // Returns the name, w/o resolving.
duke@435 373
duke@435 374 klassOop resolved_klass_at(int which) { // Used by Compiler
duke@435 375 guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
duke@435 376 // Must do an acquire here in case another thread resolved the klass
duke@435 377 // behind our back, lest we later load stale values thru the oop.
coleenp@2497 378 return klassOop(CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_oop());
duke@435 379 }
duke@435 380
duke@435 381 // This method should only be used with a cpool lock or during parsing or gc
coleenp@2497 382 Symbol* unresolved_klass_at(int which) { // Temporary until actual use
coleenp@2497 383 Symbol* s = CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
duke@435 384 // check that the klass is still unresolved.
duke@435 385 assert(tag_at(which).is_unresolved_klass(), "Corrupted constant pool");
duke@435 386 return s;
duke@435 387 }
duke@435 388
duke@435 389 // RedefineClasses() API support:
coleenp@2497 390 Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
duke@435 391
duke@435 392 jint int_at(int which) {
duke@435 393 assert(tag_at(which).is_int(), "Corrupted constant pool");
duke@435 394 return *int_at_addr(which);
duke@435 395 }
duke@435 396
duke@435 397 jlong long_at(int which) {
duke@435 398 assert(tag_at(which).is_long(), "Corrupted constant pool");
duke@435 399 // return *long_at_addr(which);
duke@435 400 u8 tmp = Bytes::get_native_u8((address)&base()[which]);
duke@435 401 return *((jlong*)&tmp);
duke@435 402 }
duke@435 403
duke@435 404 jfloat float_at(int which) {
duke@435 405 assert(tag_at(which).is_float(), "Corrupted constant pool");
duke@435 406 return *float_at_addr(which);
duke@435 407 }
duke@435 408
duke@435 409 jdouble double_at(int which) {
duke@435 410 assert(tag_at(which).is_double(), "Corrupted constant pool");
duke@435 411 u8 tmp = Bytes::get_native_u8((address)&base()[which]);
duke@435 412 return *((jdouble*)&tmp);
duke@435 413 }
duke@435 414
coleenp@2497 415 Symbol* symbol_at(int which) {
duke@435 416 assert(tag_at(which).is_utf8(), "Corrupted constant pool");
coleenp@2497 417 return slot_at(which).get_symbol();
duke@435 418 }
duke@435 419
duke@435 420 oop string_at(int which, TRAPS) {
duke@435 421 constantPoolHandle h_this(THREAD, this);
duke@435 422 return string_at_impl(h_this, which, CHECK_NULL);
duke@435 423 }
duke@435 424
twisti@1573 425 oop object_at(int which) {
twisti@1573 426 assert(tag_at(which).is_object(), "Corrupted constant pool");
coleenp@2497 427 return slot_at(which).get_oop();
twisti@1573 428 }
twisti@1573 429
jrose@866 430 // A "pseudo-string" is an non-string oop that has found is way into
jrose@866 431 // a String entry.
jrose@866 432 // Under AnonymousClasses this can happen if the user patches a live
jrose@866 433 // object into a CONSTANT_String entry of an anonymous class.
jrose@866 434 // Method oops internally created for method handles may also
jrose@866 435 // use pseudo-strings to link themselves to related metaobjects.
jrose@866 436
jrose@866 437 bool is_pseudo_string_at(int which);
jrose@866 438
jrose@866 439 oop pseudo_string_at(int which) {
jrose@866 440 assert(tag_at(which).is_string(), "Corrupted constant pool");
coleenp@2497 441 return slot_at(which).get_oop();
jrose@866 442 }
jrose@866 443
jrose@866 444 void pseudo_string_at_put(int which, oop x) {
jrose@866 445 assert(AnonymousClasses, "");
jrose@866 446 set_pseudo_string(); // mark header
jrose@866 447 assert(tag_at(which).is_string() || tag_at(which).is_unresolved_string(), "Corrupted constant pool");
jrose@866 448 string_at_put(which, x); // this works just fine
jrose@866 449 }
jrose@866 450
duke@435 451 // only called when we are sure a string entry is already resolved (via an
duke@435 452 // earlier string_at call.
duke@435 453 oop resolved_string_at(int which) {
duke@435 454 assert(tag_at(which).is_string(), "Corrupted constant pool");
duke@435 455 // Must do an acquire here in case another thread resolved the klass
duke@435 456 // behind our back, lest we later load stale values thru the oop.
coleenp@2497 457 return CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_oop();
duke@435 458 }
duke@435 459
duke@435 460 // This method should only be used with a cpool lock or during parsing or gc
coleenp@2497 461 Symbol* unresolved_string_at(int which) { // Temporary until actual use
coleenp@2497 462 Symbol* s = CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
duke@435 463 // check that the string is still unresolved.
duke@435 464 assert(tag_at(which).is_unresolved_string(), "Corrupted constant pool");
duke@435 465 return s;
duke@435 466 }
duke@435 467
duke@435 468 // Returns an UTF8 for a CONSTANT_String entry at a given index.
duke@435 469 // UTF8 char* representation was chosen to avoid conversion of
coleenp@2497 470 // java_lang_Strings at resolved entries into Symbol*s
duke@435 471 // or vice versa.
jrose@866 472 // Caller is responsible for checking for pseudo-strings.
duke@435 473 char* string_at_noresolve(int which);
duke@435 474
duke@435 475 jint name_and_type_at(int which) {
duke@435 476 assert(tag_at(which).is_name_and_type(), "Corrupted constant pool");
duke@435 477 return *int_at_addr(which);
duke@435 478 }
duke@435 479
jrose@1957 480 int method_handle_ref_kind_at(int which) {
jrose@1957 481 assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
jrose@1957 482 return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits
jrose@1957 483 }
jrose@1957 484 int method_handle_index_at(int which) {
jrose@1957 485 assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
jrose@1957 486 return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits
jrose@1957 487 }
jrose@1957 488 int method_type_index_at(int which) {
jrose@1957 489 assert(tag_at(which).is_method_type(), "Corrupted constant pool");
jrose@1957 490 return *int_at_addr(which);
jrose@1957 491 }
jrose@1957 492 // Derived queries:
coleenp@2497 493 Symbol* method_handle_name_ref_at(int which) {
jrose@1957 494 int member = method_handle_index_at(which);
jrose@1957 495 return impl_name_ref_at(member, true);
jrose@1957 496 }
coleenp@2497 497 Symbol* method_handle_signature_ref_at(int which) {
jrose@1957 498 int member = method_handle_index_at(which);
jrose@1957 499 return impl_signature_ref_at(member, true);
jrose@1957 500 }
jrose@1957 501 int method_handle_klass_index_at(int which) {
jrose@1957 502 int member = method_handle_index_at(which);
jrose@1957 503 return impl_klass_ref_index_at(member, true);
jrose@1957 504 }
coleenp@2497 505 Symbol* method_type_signature_at(int which) {
jrose@1957 506 int sym = method_type_index_at(which);
jrose@1957 507 return symbol_at(sym);
jrose@1957 508 }
jrose@2268 509
jrose@2353 510 int invoke_dynamic_name_and_type_ref_index_at(int which) {
jrose@2353 511 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
jrose@2353 512 return extract_high_short_from_int(*int_at_addr(which));
jrose@2268 513 }
jrose@2353 514 int invoke_dynamic_bootstrap_specifier_index(int which) {
jrose@2353 515 assert(tag_at(which).value() == JVM_CONSTANT_InvokeDynamic, "Corrupted constant pool");
jrose@2353 516 return extract_low_short_from_int(*int_at_addr(which));
jrose@2268 517 }
jrose@2353 518 int invoke_dynamic_operand_base(int which) {
jrose@2353 519 int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which);
jrose@2353 520 return operand_offset_at(operands(), bootstrap_specifier_index);
jrose@2268 521 }
jrose@2353 522 // The first part of the operands array consists of an index into the second part.
jrose@2353 523 // Extract a 32-bit index value from the first part.
jrose@2353 524 static int operand_offset_at(typeArrayOop operands, int bootstrap_specifier_index) {
jrose@2353 525 int n = (bootstrap_specifier_index * 2);
jrose@2353 526 assert(n >= 0 && n+2 <= operands->length(), "oob");
jrose@2353 527 // The first 32-bit index points to the beginning of the second part
jrose@2353 528 // of the operands array. Make sure this index is in the first part.
jrose@2353 529 DEBUG_ONLY(int second_part = build_int_from_shorts(operands->short_at(0),
jrose@2353 530 operands->short_at(1)));
jrose@2353 531 assert(second_part == 0 || n+2 <= second_part, "oob (2)");
jrose@2353 532 int offset = build_int_from_shorts(operands->short_at(n+0),
jrose@2353 533 operands->short_at(n+1));
jrose@2353 534 // The offset itself must point into the second part of the array.
jrose@2353 535 assert(offset == 0 || offset >= second_part && offset <= operands->length(), "oob (3)");
jrose@2353 536 return offset;
jrose@2268 537 }
jrose@2353 538 static void operand_offset_at_put(typeArrayOop operands, int bootstrap_specifier_index, int offset) {
jrose@2353 539 int n = bootstrap_specifier_index * 2;
jrose@2353 540 assert(n >= 0 && n+2 <= operands->length(), "oob");
jrose@2353 541 operands->short_at_put(n+0, extract_low_short_from_int(offset));
jrose@2353 542 operands->short_at_put(n+1, extract_high_short_from_int(offset));
jrose@2268 543 }
jrose@2353 544 static int operand_array_length(typeArrayOop operands) {
jrose@2353 545 if (operands == NULL || operands->length() == 0) return 0;
jrose@2353 546 int second_part = operand_offset_at(operands, 0);
jrose@2353 547 return (second_part / 2);
jrose@2268 548 }
jrose@2268 549
jrose@2353 550 #ifdef ASSERT
jrose@2353 551 // operand tuples fit together exactly, end to end
jrose@2353 552 static int operand_limit_at(typeArrayOop operands, int bootstrap_specifier_index) {
jrose@2353 553 int nextidx = bootstrap_specifier_index + 1;
jrose@2353 554 if (nextidx == operand_array_length(operands))
jrose@2353 555 return operands->length();
jrose@2353 556 else
jrose@2353 557 return operand_offset_at(operands, nextidx);
jrose@2353 558 }
jrose@2353 559 int invoke_dynamic_operand_limit(int which) {
jrose@2353 560 int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which);
jrose@2353 561 return operand_limit_at(operands(), bootstrap_specifier_index);
jrose@2353 562 }
jrose@2353 563 #endif //ASSERT
jrose@2353 564
jrose@2353 565 // layout of InvokeDynamic bootstrap method specifier (in second part of operands array):
jrose@2268 566 enum {
jrose@2268 567 _indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm
jrose@2353 568 _indy_argc_offset = 1, // u2 argc
jrose@2353 569 _indy_argv_offset = 2 // u2 argv[argc]
jrose@2268 570 };
jrose@2015 571 int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
jrose@2015 572 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
jrose@2353 573 if (tag_at(which).value() == JVM_CONSTANT_InvokeDynamicTrans)
jrose@2353 574 return extract_low_short_from_int(*int_at_addr(which));
jrose@2353 575 int op_base = invoke_dynamic_operand_base(which);
jrose@2353 576 return operands()->short_at(op_base + _indy_bsm_offset);
jrose@2268 577 }
jrose@2268 578 int invoke_dynamic_argument_count_at(int which) {
jrose@2268 579 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
jrose@2353 580 if (tag_at(which).value() == JVM_CONSTANT_InvokeDynamicTrans)
jrose@2353 581 return 0;
jrose@2353 582 int op_base = invoke_dynamic_operand_base(which);
jrose@2353 583 int argc = operands()->short_at(op_base + _indy_argc_offset);
jrose@2353 584 DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc;
jrose@2353 585 int next_offset = invoke_dynamic_operand_limit(which));
jrose@2353 586 assert(end_offset == next_offset, "matched ending");
jrose@2268 587 return argc;
jrose@2268 588 }
jrose@2268 589 int invoke_dynamic_argument_index_at(int which, int j) {
jrose@2353 590 int op_base = invoke_dynamic_operand_base(which);
jrose@2353 591 DEBUG_ONLY(int argc = operands()->short_at(op_base + _indy_argc_offset));
jrose@2353 592 assert((uint)j < (uint)argc, "oob");
jrose@2353 593 return operands()->short_at(op_base + _indy_argv_offset + j);
jrose@2015 594 }
jrose@1957 595
jrose@1161 596 // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
jrose@1494 597 // name_and_type_ref_index_at) all expect to be passed indices obtained
jrose@2265 598 // directly from the bytecode.
jrose@1494 599 // If the indices are meant to refer to fields or methods, they are
jrose@2265 600 // actually rewritten constant pool cache indices.
jrose@1494 601 // The routine remap_instruction_operand_from_cache manages the adjustment
jrose@1494 602 // of these values back to constant pool indices.
jrose@1161 603
jrose@1494 604 // There are also "uncached" versions which do not adjust the operand index; see below.
duke@435 605
jrose@2265 606 // FIXME: Consider renaming these with a prefix "cached_" to make the distinction clear.
jrose@2265 607 // In a few cases (the verifier) there are uses before a cpcache has been built,
jrose@2265 608 // which are handled by a dynamic check in remap_instruction_operand_from_cache.
jrose@2265 609 // FIXME: Remove the dynamic check, and adjust all callers to specify the correct mode.
jrose@2265 610
duke@435 611 // Lookup for entries consisting of (klass_index, name_and_type index)
duke@435 612 klassOop klass_ref_at(int which, TRAPS);
coleenp@2497 613 Symbol* klass_ref_at_noresolve(int which);
coleenp@2497 614 Symbol* name_ref_at(int which) { return impl_name_ref_at(which, false); }
coleenp@2497 615 Symbol* signature_ref_at(int which) { return impl_signature_ref_at(which, false); }
duke@435 616
jrose@1161 617 int klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, false); }
jrose@1161 618 int name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, false); }
duke@435 619
duke@435 620 // Lookup for entries consisting of (name_index, signature_index)
jrose@1161 621 int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt)
jrose@1161 622 int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt)
duke@435 623
duke@435 624 BasicType basic_type_for_signature_at(int which);
duke@435 625
duke@435 626 // Resolve string constants (to prevent allocation during compilation)
duke@435 627 void resolve_string_constants(TRAPS) {
duke@435 628 constantPoolHandle h_this(THREAD, this);
duke@435 629 resolve_string_constants_impl(h_this, CHECK);
duke@435 630 }
duke@435 631
jrose@2268 632 private:
jrose@2268 633 enum { _no_index_sentinel = -1, _possible_index_sentinel = -2 };
jrose@2268 634 public:
jrose@2268 635
jrose@1957 636 // Resolve late bound constants.
jrose@1957 637 oop resolve_constant_at(int index, TRAPS) {
jrose@1957 638 constantPoolHandle h_this(THREAD, this);
jrose@2268 639 return resolve_constant_at_impl(h_this, index, _no_index_sentinel, THREAD);
jrose@1957 640 }
jrose@1957 641
jrose@1957 642 oop resolve_cached_constant_at(int cache_index, TRAPS) {
jrose@1957 643 constantPoolHandle h_this(THREAD, this);
jrose@2268 644 return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, THREAD);
jrose@2268 645 }
jrose@2268 646
jrose@2268 647 oop resolve_possibly_cached_constant_at(int pool_index, TRAPS) {
jrose@2268 648 constantPoolHandle h_this(THREAD, this);
jrose@2268 649 return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, THREAD);
jrose@1957 650 }
jrose@1957 651
duke@435 652 // Klass name matches name at offset
duke@435 653 bool klass_name_at_matches(instanceKlassHandle k, int which);
duke@435 654
duke@435 655 // Sizing
coleenp@548 656 int length() const { return _length; }
coleenp@548 657 void set_length(int length) { _length = length; }
coleenp@548 658
coleenp@548 659 // Tells whether index is within bounds.
coleenp@548 660 bool is_within_bounds(int index) const {
coleenp@548 661 return 0 <= index && index < length();
coleenp@548 662 }
coleenp@548 663
duke@435 664 static int header_size() { return sizeof(constantPoolOopDesc)/HeapWordSize; }
duke@435 665 static int object_size(int length) { return align_object_size(header_size() + length); }
duke@435 666 int object_size() { return object_size(length()); }
duke@435 667
jmasa@953 668 bool is_conc_safe() { return _is_conc_safe; }
jmasa@953 669 void set_is_conc_safe(bool v) { _is_conc_safe = v; }
jmasa@953 670
duke@435 671 friend class constantPoolKlass;
duke@435 672 friend class ClassFileParser;
duke@435 673 friend class SystemDictionary;
duke@435 674
duke@435 675 // Used by compiler to prevent classloading.
duke@435 676 static klassOop klass_at_if_loaded (constantPoolHandle this_oop, int which);
duke@435 677 static klassOop klass_ref_at_if_loaded (constantPoolHandle this_oop, int which);
duke@435 678 // Same as above - but does LinkResolving.
duke@435 679 static klassOop klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS);
duke@435 680
duke@435 681 // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
jrose@2265 682 // future by other Java code. These take constant pool indices rather than
duke@435 683 // constant pool cache indices as do the peer methods above.
coleenp@2497 684 Symbol* uncached_klass_ref_at_noresolve(int which);
coleenp@2497 685 Symbol* uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
coleenp@2497 686 Symbol* uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); }
jrose@1161 687 int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); }
jrose@1161 688 int uncached_name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, true); }
duke@435 689
duke@435 690 // Sharing
duke@435 691 int pre_resolve_shared_klasses(TRAPS);
coleenp@2497 692 void shared_symbols_iterate(SymbolClosure* closure0);
duke@435 693 void shared_tags_iterate(OopClosure* closure0);
duke@435 694 void shared_strings_iterate(OopClosure* closure0);
duke@435 695
duke@435 696 // Debugging
duke@435 697 const char* printable_name_at(int which) PRODUCT_RETURN0;
duke@435 698
jrose@1920 699 #ifdef ASSERT
jrose@1920 700 enum { CPCACHE_INDEX_TAG = 0x10000 }; // helps keep CP cache indices distinct from CP indices
jrose@1957 701 #else
jrose@1957 702 enum { CPCACHE_INDEX_TAG = 0 }; // in product mode, this zero value is a no-op
jrose@1920 703 #endif //ASSERT
jrose@1920 704
duke@435 705 private:
duke@435 706
coleenp@2497 707 Symbol* impl_name_ref_at(int which, bool uncached);
coleenp@2497 708 Symbol* impl_signature_ref_at(int which, bool uncached);
jrose@1161 709 int impl_klass_ref_index_at(int which, bool uncached);
jrose@1161 710 int impl_name_and_type_ref_index_at(int which, bool uncached);
jrose@1161 711
jrose@1920 712 int remap_instruction_operand_from_cache(int operand); // operand must be biased by CPCACHE_INDEX_TAG
duke@435 713
duke@435 714 // Used while constructing constant pool (only by ClassFileParser)
duke@435 715 jint klass_index_at(int which) {
duke@435 716 assert(tag_at(which).is_klass_index(), "Corrupted constant pool");
duke@435 717 return *int_at_addr(which);
duke@435 718 }
duke@435 719
duke@435 720 jint string_index_at(int which) {
duke@435 721 assert(tag_at(which).is_string_index(), "Corrupted constant pool");
duke@435 722 return *int_at_addr(which);
duke@435 723 }
duke@435 724
duke@435 725 // Performs the LinkResolver checks
duke@435 726 static void verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle klass, TRAPS);
duke@435 727
duke@435 728 // Implementation of methods that needs an exposed 'this' pointer, in order to
duke@435 729 // handle GC while executing the method
duke@435 730 static klassOop klass_at_impl(constantPoolHandle this_oop, int which, TRAPS);
duke@435 731 static oop string_at_impl(constantPoolHandle this_oop, int which, TRAPS);
duke@435 732
duke@435 733 // Resolve string constants (to prevent allocation during compilation)
duke@435 734 static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
duke@435 735
jrose@1957 736 static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
jrose@1957 737
duke@435 738 public:
duke@435 739 // Merging constantPoolOop support:
duke@435 740 bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
jrose@2353 741 void copy_cp_to(int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS) {
jrose@2353 742 constantPoolHandle h_this(THREAD, this);
jrose@2353 743 copy_cp_to_impl(h_this, start_i, end_i, to_cp, to_i, THREAD);
jrose@2353 744 }
jrose@2353 745 static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
jrose@2353 746 static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
duke@435 747 int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
duke@435 748 int orig_length() const { return _orig_length; }
duke@435 749 void set_orig_length(int orig_length) { _orig_length = orig_length; }
duke@435 750
coleenp@2497 751 // Decrease ref counts of symbols that are in the constant pool
coleenp@2497 752 // when the holder class is unloaded
coleenp@2497 753 void unreference_symbols();
duke@435 754
duke@435 755 // JVMTI accesss - GetConstantPool, RetransformClasses, ...
duke@435 756 friend class JvmtiConstantPoolReconstituter;
duke@435 757
duke@435 758 private:
duke@435 759 jint cpool_entry_size(jint idx);
duke@435 760 jint hash_entries_to(SymbolHashMap *symmap, SymbolHashMap *classmap);
duke@435 761
duke@435 762 // Copy cpool bytes into byte array.
duke@435 763 // Returns:
duke@435 764 // int > 0, count of the raw cpool bytes that have been copied
duke@435 765 // 0, OutOfMemory error
duke@435 766 // -1, Internal error
duke@435 767 int copy_cpool_bytes(int cpool_size,
duke@435 768 SymbolHashMap* tbl,
duke@435 769 unsigned char *bytes);
duke@435 770 };
duke@435 771
duke@435 772 class SymbolHashMapEntry : public CHeapObj {
duke@435 773 private:
duke@435 774 unsigned int _hash; // 32-bit hash for item
duke@435 775 SymbolHashMapEntry* _next; // Next element in the linked list for this bucket
coleenp@2497 776 Symbol* _symbol; // 1-st part of the mapping: symbol => value
duke@435 777 u2 _value; // 2-nd part of the mapping: symbol => value
duke@435 778
duke@435 779 public:
duke@435 780 unsigned int hash() const { return _hash; }
duke@435 781 void set_hash(unsigned int hash) { _hash = hash; }
duke@435 782
duke@435 783 SymbolHashMapEntry* next() const { return _next; }
duke@435 784 void set_next(SymbolHashMapEntry* next) { _next = next; }
duke@435 785
coleenp@2497 786 Symbol* symbol() const { return _symbol; }
coleenp@2497 787 void set_symbol(Symbol* sym) { _symbol = sym; }
duke@435 788
duke@435 789 u2 value() const { return _value; }
duke@435 790 void set_value(u2 value) { _value = value; }
duke@435 791
coleenp@2497 792 SymbolHashMapEntry(unsigned int hash, Symbol* symbol, u2 value)
duke@435 793 : _hash(hash), _symbol(symbol), _value(value), _next(NULL) {}
duke@435 794
duke@435 795 }; // End SymbolHashMapEntry class
duke@435 796
duke@435 797
duke@435 798 class SymbolHashMapBucket : public CHeapObj {
duke@435 799
duke@435 800 private:
duke@435 801 SymbolHashMapEntry* _entry;
duke@435 802
duke@435 803 public:
duke@435 804 SymbolHashMapEntry* entry() const { return _entry; }
duke@435 805 void set_entry(SymbolHashMapEntry* entry) { _entry = entry; }
duke@435 806 void clear() { _entry = NULL; }
duke@435 807
duke@435 808 }; // End SymbolHashMapBucket class
duke@435 809
duke@435 810
duke@435 811 class SymbolHashMap: public CHeapObj {
duke@435 812
duke@435 813 private:
duke@435 814 // Default number of entries in the table
duke@435 815 enum SymbolHashMap_Constants {
duke@435 816 _Def_HashMap_Size = 256
duke@435 817 };
duke@435 818
duke@435 819 int _table_size;
duke@435 820 SymbolHashMapBucket* _buckets;
duke@435 821
duke@435 822 void initialize_table(int table_size) {
duke@435 823 _table_size = table_size;
duke@435 824 _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size);
duke@435 825 for (int index = 0; index < table_size; index++) {
duke@435 826 _buckets[index].clear();
duke@435 827 }
duke@435 828 }
duke@435 829
duke@435 830 public:
duke@435 831
duke@435 832 int table_size() const { return _table_size; }
duke@435 833
duke@435 834 SymbolHashMap() { initialize_table(_Def_HashMap_Size); }
duke@435 835 SymbolHashMap(int table_size) { initialize_table(table_size); }
duke@435 836
duke@435 837 // hash P(31) from Kernighan & Ritchie
duke@435 838 static unsigned int compute_hash(const char* str, int len) {
duke@435 839 unsigned int hash = 0;
duke@435 840 while (len-- > 0) {
duke@435 841 hash = 31*hash + (unsigned) *str;
duke@435 842 str++;
duke@435 843 }
duke@435 844 return hash;
duke@435 845 }
duke@435 846
duke@435 847 SymbolHashMapEntry* bucket(int i) {
duke@435 848 return _buckets[i].entry();
duke@435 849 }
duke@435 850
coleenp@2497 851 void add_entry(Symbol* sym, u2 value);
coleenp@2497 852 SymbolHashMapEntry* find_entry(Symbol* sym);
duke@435 853
coleenp@2497 854 u2 symbol_to_value(Symbol* sym) {
duke@435 855 SymbolHashMapEntry *entry = find_entry(sym);
duke@435 856 return (entry == NULL) ? 0 : entry->value();
duke@435 857 }
duke@435 858
duke@435 859 ~SymbolHashMap() {
duke@435 860 SymbolHashMapEntry* next;
duke@435 861 for (int i = 0; i < _table_size; i++) {
duke@435 862 for (SymbolHashMapEntry* cur = bucket(i); cur != NULL; cur = next) {
duke@435 863 next = cur->next();
duke@435 864 delete(cur);
duke@435 865 }
duke@435 866 }
duke@435 867 delete _buckets;
duke@435 868 }
duke@435 869 }; // End SymbolHashMap class
stefank@2314 870
stefank@2314 871 #endif // SHARE_VM_OOPS_CONSTANTPOOLOOP_HPP

mercurial