39 friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast |
39 friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast |
40 private: |
40 private: |
41 typeArrayOop _tags; // the tag array describing the constant pool's contents |
41 typeArrayOop _tags; // the tag array describing the constant pool's contents |
42 constantPoolCacheOop _cache; // the cache holding interpreter runtime information |
42 constantPoolCacheOop _cache; // the cache holding interpreter runtime information |
43 klassOop _pool_holder; // the corresponding class |
43 klassOop _pool_holder; // the corresponding class |
|
44 typeArrayOop _operands; // for variable-sized (InvokeDynamic) nodes, usually empty |
44 int _flags; // a few header bits to describe contents for GC |
45 int _flags; // a few header bits to describe contents for GC |
45 int _length; // number of elements in the array |
46 int _length; // number of elements in the array |
46 volatile bool _is_conc_safe; // if true, safe for concurrent |
47 volatile bool _is_conc_safe; // if true, safe for concurrent |
47 // GC processing |
48 // GC processing |
48 // only set to non-zero if constant pool is merged by RedefineClasses |
49 // only set to non-zero if constant pool is merged by RedefineClasses |
111 void set_cache(constantPoolCacheOop cache){ oop_store((oop*)&_cache, cache); } |
116 void set_cache(constantPoolCacheOop cache){ oop_store((oop*)&_cache, cache); } |
112 |
117 |
113 // Assembly code support |
118 // Assembly code support |
114 static int tags_offset_in_bytes() { return offset_of(constantPoolOopDesc, _tags); } |
119 static int tags_offset_in_bytes() { return offset_of(constantPoolOopDesc, _tags); } |
115 static int cache_offset_in_bytes() { return offset_of(constantPoolOopDesc, _cache); } |
120 static int cache_offset_in_bytes() { return offset_of(constantPoolOopDesc, _cache); } |
|
121 static int operands_offset_in_bytes() { return offset_of(constantPoolOopDesc, _operands); } |
116 static int pool_holder_offset_in_bytes() { return offset_of(constantPoolOopDesc, _pool_holder); } |
122 static int pool_holder_offset_in_bytes() { return offset_of(constantPoolOopDesc, _pool_holder); } |
117 |
123 |
118 // Storing constants |
124 // Storing constants |
119 |
125 |
120 void klass_at_put(int which, klassOop k) { |
126 void klass_at_put(int which, klassOop k) { |
154 void method_type_index_at_put(int which, int ref_index) { |
160 void method_type_index_at_put(int which, int ref_index) { |
155 tag_at_put(which, JVM_CONSTANT_MethodType); |
161 tag_at_put(which, JVM_CONSTANT_MethodType); |
156 *int_at_addr(which) = ref_index; |
162 *int_at_addr(which) = ref_index; |
157 } |
163 } |
158 |
164 |
159 void invoke_dynamic_at_put(int which, int bootstrap_method_index, int name_and_type_index) { |
165 void invoke_dynamic_at_put(int which, int operand_base, int operand_count) { |
160 tag_at_put(which, JVM_CONSTANT_InvokeDynamic); |
166 tag_at_put(which, JVM_CONSTANT_InvokeDynamic); |
161 *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index; |
167 *int_at_addr(which) = operand_base; // this is the real information |
162 } |
168 } |
|
169 #ifdef ASSERT |
|
170 bool check_invoke_dynamic_at(int which, |
|
171 int bootstrap_method_index, |
|
172 int name_and_type_index, |
|
173 int argument_count) { |
|
174 assert(invoke_dynamic_bootstrap_method_ref_index_at(which) == bootstrap_method_index, |
|
175 "already stored by caller"); |
|
176 assert(invoke_dynamic_name_and_type_ref_index_at(which) == name_and_type_index, |
|
177 "already stored by caller"); |
|
178 assert(invoke_dynamic_argument_count_at(which) == argument_count, |
|
179 "consistent argument count"); |
|
180 if (argument_count != 0) { |
|
181 invoke_dynamic_argument_index_at(which, 0); |
|
182 invoke_dynamic_argument_index_at(which, argument_count - 1); |
|
183 } |
|
184 return true; |
|
185 } |
|
186 #endif //ASSERT |
163 |
187 |
164 // Temporary until actual use |
188 // Temporary until actual use |
165 void unresolved_string_at_put(int which, symbolOop s) { |
189 void unresolved_string_at_put(int which, symbolOop s) { |
166 *obj_at_addr(which) = NULL; |
190 *obj_at_addr(which) = NULL; |
167 release_tag_at_put(which, JVM_CONSTANT_UnresolvedString); |
191 release_tag_at_put(which, JVM_CONSTANT_UnresolvedString); |
399 } |
423 } |
400 symbolOop method_type_signature_at(int which) { |
424 symbolOop method_type_signature_at(int which) { |
401 int sym = method_type_index_at(which); |
425 int sym = method_type_index_at(which); |
402 return symbol_at(sym); |
426 return symbol_at(sym); |
403 } |
427 } |
|
428 |
|
429 private: |
|
430 // some nodes (InvokeDynamic) have a variable number of operands, each a u2 value |
|
431 enum { _multi_operand_count_offset = -1, |
|
432 _multi_operand_base_offset = 0, |
|
433 _multi_operand_buffer_fill_pointer_offset = 0 // shared at front of operands array |
|
434 }; |
|
435 int multi_operand_buffer_length() { |
|
436 return operands() == NULL ? 0 : operands()->length(); |
|
437 } |
|
438 int multi_operand_buffer_fill_pointer() { |
|
439 return operands() == NULL |
|
440 ? _multi_operand_buffer_fill_pointer_offset + 1 |
|
441 : operands()->int_at(_multi_operand_buffer_fill_pointer_offset); |
|
442 } |
|
443 void multi_operand_buffer_grow(int min_length, TRAPS); |
|
444 void set_multi_operand_buffer_fill_pointer(int fillp) { |
|
445 assert(operands() != NULL, ""); |
|
446 operands()->int_at_put(_multi_operand_buffer_fill_pointer_offset, fillp); |
|
447 } |
|
448 int multi_operand_base_at(int which) { |
|
449 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
|
450 int op_base = *int_at_addr(which); |
|
451 assert(op_base > _multi_operand_buffer_fill_pointer_offset, "Corrupted operand base"); |
|
452 return op_base; |
|
453 } |
|
454 int multi_operand_count_at(int which) { |
|
455 int op_base = multi_operand_base_at(which); |
|
456 assert((uint)(op_base + _multi_operand_count_offset) < (uint)operands()->length(), "oob"); |
|
457 int count = operands()->int_at(op_base + _multi_operand_count_offset); |
|
458 return count; |
|
459 } |
|
460 int multi_operand_ref_at(int which, int i) { |
|
461 int op_base = multi_operand_base_at(which); |
|
462 assert((uint)i < (uint)multi_operand_count_at(which), "oob"); |
|
463 assert((uint)(op_base + _multi_operand_base_offset + i) < (uint)operands()->length(), "oob"); |
|
464 return operands()->int_at(op_base + _multi_operand_base_offset + i); |
|
465 } |
|
466 void set_multi_operand_ref_at(int which, int i, int ref) { |
|
467 DEBUG_ONLY(multi_operand_ref_at(which, i)); // trigger asserts |
|
468 int op_base = multi_operand_base_at(which); |
|
469 operands()->int_at_put(op_base + _multi_operand_base_offset + i, ref); |
|
470 } |
|
471 |
|
472 public: |
|
473 // layout of InvokeDynamic: |
|
474 enum { |
|
475 _indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm |
|
476 _indy_nt_offset = 1, // CONSTANT_NameAndType descr |
|
477 _indy_argc_offset = 2, // u2 argc |
|
478 _indy_argv_offset = 3 // u2 argv[argc] |
|
479 }; |
404 int invoke_dynamic_bootstrap_method_ref_index_at(int which) { |
480 int invoke_dynamic_bootstrap_method_ref_index_at(int which) { |
405 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
481 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
406 jint ref_index = *int_at_addr(which); |
482 return multi_operand_ref_at(which, _indy_bsm_offset); |
407 return extract_low_short_from_int(ref_index); |
|
408 } |
483 } |
409 int invoke_dynamic_name_and_type_ref_index_at(int which) { |
484 int invoke_dynamic_name_and_type_ref_index_at(int which) { |
410 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
485 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
411 jint ref_index = *int_at_addr(which); |
486 return multi_operand_ref_at(which, _indy_nt_offset); |
412 return extract_high_short_from_int(ref_index); |
487 } |
|
488 int invoke_dynamic_argument_count_at(int which) { |
|
489 assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); |
|
490 int argc = multi_operand_ref_at(which, _indy_argc_offset); |
|
491 DEBUG_ONLY(int op_count = multi_operand_count_at(which)); |
|
492 assert(_indy_argv_offset + argc == op_count, "consistent inner and outer counts"); |
|
493 return argc; |
|
494 } |
|
495 int invoke_dynamic_argument_index_at(int which, int j) { |
|
496 assert((uint)j < (uint)invoke_dynamic_argument_count_at(which), "oob"); |
|
497 return multi_operand_ref_at(which, _indy_argv_offset + j); |
413 } |
498 } |
414 |
499 |
415 // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, |
500 // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, |
416 // name_and_type_ref_index_at) all expect to be passed indices obtained |
501 // name_and_type_ref_index_at) all expect to be passed indices obtained |
417 // directly from the bytecode. |
502 // directly from the bytecode. |
446 void resolve_string_constants(TRAPS) { |
531 void resolve_string_constants(TRAPS) { |
447 constantPoolHandle h_this(THREAD, this); |
532 constantPoolHandle h_this(THREAD, this); |
448 resolve_string_constants_impl(h_this, CHECK); |
533 resolve_string_constants_impl(h_this, CHECK); |
449 } |
534 } |
450 |
535 |
|
536 private: |
|
537 enum { _no_index_sentinel = -1, _possible_index_sentinel = -2 }; |
|
538 public: |
|
539 |
451 // Resolve late bound constants. |
540 // Resolve late bound constants. |
452 oop resolve_constant_at(int index, TRAPS) { |
541 oop resolve_constant_at(int index, TRAPS) { |
453 constantPoolHandle h_this(THREAD, this); |
542 constantPoolHandle h_this(THREAD, this); |
454 return resolve_constant_at_impl(h_this, index, -1, THREAD); |
543 return resolve_constant_at_impl(h_this, index, _no_index_sentinel, THREAD); |
455 } |
544 } |
456 |
545 |
457 oop resolve_cached_constant_at(int cache_index, TRAPS) { |
546 oop resolve_cached_constant_at(int cache_index, TRAPS) { |
458 constantPoolHandle h_this(THREAD, this); |
547 constantPoolHandle h_this(THREAD, this); |
459 return resolve_constant_at_impl(h_this, -1, cache_index, THREAD); |
548 return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, THREAD); |
|
549 } |
|
550 |
|
551 oop resolve_possibly_cached_constant_at(int pool_index, TRAPS) { |
|
552 constantPoolHandle h_this(THREAD, this); |
|
553 return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, THREAD); |
460 } |
554 } |
461 |
555 |
462 // Klass name matches name at offset |
556 // Klass name matches name at offset |
463 bool klass_name_at_matches(instanceKlassHandle k, int which); |
557 bool klass_name_at_matches(instanceKlassHandle k, int which); |
464 |
558 |