--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp Sat Oct 30 12:19:07 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp Sat Oct 30 13:08:23 2010 -0700
@@ -41,6 +41,7 @@
typeArrayOop _tags; // the tag array describing the constant pool's contents
constantPoolCacheOop _cache; // the cache holding interpreter runtime information
klassOop _pool_holder; // the corresponding class
+ typeArrayOop _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
int _flags; // a few header bits to describe contents for GC
int _length; // number of elements in the array
volatile bool _is_conc_safe; // if true, safe for concurrent
@@ -52,6 +53,8 @@
void tag_at_put(int which, jbyte t) { tags()->byte_at_put(which, t); }
void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); }
+ void set_operands(typeArrayOop operands) { oop_store_without_check((oop*)&_operands, operands); }
+
enum FlagBit {
FB_has_invokedynamic = 1,
FB_has_pseudo_string = 2
@@ -67,6 +70,7 @@
intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(constantPoolOopDesc)); }
oop* tags_addr() { return (oop*)&_tags; }
oop* cache_addr() { return (oop*)&_cache; }
+ oop* operands_addr() { return (oop*)&_operands; }
oop* obj_at_addr(int which) const {
assert(is_within_bounds(which), "index out of bounds");
@@ -95,6 +99,7 @@
public:
typeArrayOop tags() const { return _tags; }
+ typeArrayOop operands() const { return _operands; }
bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); }
@@ -113,6 +118,7 @@
// Assembly code support
static int tags_offset_in_bytes() { return offset_of(constantPoolOopDesc, _tags); }
static int cache_offset_in_bytes() { return offset_of(constantPoolOopDesc, _cache); }
+ static int operands_offset_in_bytes() { return offset_of(constantPoolOopDesc, _operands); }
static int pool_holder_offset_in_bytes() { return offset_of(constantPoolOopDesc, _pool_holder); }
// Storing constants
@@ -156,10 +162,28 @@
*int_at_addr(which) = ref_index;
}
- void invoke_dynamic_at_put(int which, int bootstrap_method_index, int name_and_type_index) {
+ void invoke_dynamic_at_put(int which, int operand_base, int operand_count) {
tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
- *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index;
+ *int_at_addr(which) = operand_base; // this is the real information
}
+#ifdef ASSERT
+ bool check_invoke_dynamic_at(int which,
+ int bootstrap_method_index,
+ int name_and_type_index,
+ int argument_count) {
+ assert(invoke_dynamic_bootstrap_method_ref_index_at(which) == bootstrap_method_index,
+ "already stored by caller");
+ assert(invoke_dynamic_name_and_type_ref_index_at(which) == name_and_type_index,
+ "already stored by caller");
+ assert(invoke_dynamic_argument_count_at(which) == argument_count,
+ "consistent argument count");
+ if (argument_count != 0) {
+ invoke_dynamic_argument_index_at(which, 0);
+ invoke_dynamic_argument_index_at(which, argument_count - 1);
+ }
+ return true;
+ }
+#endif //ASSERT
// Temporary until actual use
void unresolved_string_at_put(int which, symbolOop s) {
@@ -401,15 +425,76 @@
int sym = method_type_index_at(which);
return symbol_at(sym);
}
+
+ private:
+ // some nodes (InvokeDynamic) have a variable number of operands, each a u2 value
+ enum { _multi_operand_count_offset = -1,
+ _multi_operand_base_offset = 0,
+ _multi_operand_buffer_fill_pointer_offset = 0 // shared at front of operands array
+ };
+ int multi_operand_buffer_length() {
+ return operands() == NULL ? 0 : operands()->length();
+ }
+ int multi_operand_buffer_fill_pointer() {
+ return operands() == NULL
+ ? _multi_operand_buffer_fill_pointer_offset + 1
+ : operands()->int_at(_multi_operand_buffer_fill_pointer_offset);
+ }
+ void multi_operand_buffer_grow(int min_length, TRAPS);
+ void set_multi_operand_buffer_fill_pointer(int fillp) {
+ assert(operands() != NULL, "");
+ operands()->int_at_put(_multi_operand_buffer_fill_pointer_offset, fillp);
+ }
+ int multi_operand_base_at(int which) {
+ assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+ int op_base = *int_at_addr(which);
+ assert(op_base > _multi_operand_buffer_fill_pointer_offset, "Corrupted operand base");
+ return op_base;
+ }
+ int multi_operand_count_at(int which) {
+ int op_base = multi_operand_base_at(which);
+ assert((uint)(op_base + _multi_operand_count_offset) < (uint)operands()->length(), "oob");
+ int count = operands()->int_at(op_base + _multi_operand_count_offset);
+ return count;
+ }
+ int multi_operand_ref_at(int which, int i) {
+ int op_base = multi_operand_base_at(which);
+ assert((uint)i < (uint)multi_operand_count_at(which), "oob");
+ assert((uint)(op_base + _multi_operand_base_offset + i) < (uint)operands()->length(), "oob");
+ return operands()->int_at(op_base + _multi_operand_base_offset + i);
+ }
+ void set_multi_operand_ref_at(int which, int i, int ref) {
+ DEBUG_ONLY(multi_operand_ref_at(which, i)); // trigger asserts
+ int op_base = multi_operand_base_at(which);
+ operands()->int_at_put(op_base + _multi_operand_base_offset + i, ref);
+ }
+
+ public:
+ // layout of InvokeDynamic:
+ enum {
+ _indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm
+ _indy_nt_offset = 1, // CONSTANT_NameAndType descr
+ _indy_argc_offset = 2, // u2 argc
+ _indy_argv_offset = 3 // u2 argv[argc]
+ };
int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
- jint ref_index = *int_at_addr(which);
- return extract_low_short_from_int(ref_index);
+ return multi_operand_ref_at(which, _indy_bsm_offset);
}
int invoke_dynamic_name_and_type_ref_index_at(int which) {
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
- jint ref_index = *int_at_addr(which);
- return extract_high_short_from_int(ref_index);
+ return multi_operand_ref_at(which, _indy_nt_offset);
+ }
+ int invoke_dynamic_argument_count_at(int which) {
+ assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+ int argc = multi_operand_ref_at(which, _indy_argc_offset);
+ DEBUG_ONLY(int op_count = multi_operand_count_at(which));
+ assert(_indy_argv_offset + argc == op_count, "consistent inner and outer counts");
+ return argc;
+ }
+ int invoke_dynamic_argument_index_at(int which, int j) {
+ assert((uint)j < (uint)invoke_dynamic_argument_count_at(which), "oob");
+ return multi_operand_ref_at(which, _indy_argv_offset + j);
}
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
@@ -448,15 +533,24 @@
resolve_string_constants_impl(h_this, CHECK);
}
+ private:
+ enum { _no_index_sentinel = -1, _possible_index_sentinel = -2 };
+ public:
+
// Resolve late bound constants.
oop resolve_constant_at(int index, TRAPS) {
constantPoolHandle h_this(THREAD, this);
- return resolve_constant_at_impl(h_this, index, -1, THREAD);
+ return resolve_constant_at_impl(h_this, index, _no_index_sentinel, THREAD);
}
oop resolve_cached_constant_at(int cache_index, TRAPS) {
constantPoolHandle h_this(THREAD, this);
- return resolve_constant_at_impl(h_this, -1, cache_index, THREAD);
+ return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, THREAD);
+ }
+
+ oop resolve_possibly_cached_constant_at(int pool_index, TRAPS) {
+ constantPoolHandle h_this(THREAD, this);
+ return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, THREAD);
}
// Klass name matches name at offset