diff src/share/vm/oops/constantPoolOop.hpp @ 1913:3b2dea75431e

6984311: JSR 292 needs optional bootstrap method parameters Summary: Allow CONSTANT_InvokeDynamic nodes to have any number of extra operands. Reviewed-by: twisti
author jrose
date Sat, 30 Oct 2010 13:08:23 -0700
parents d1896d1dda3e
children f95d63e2154a
line wrap: on
line diff
--- a/src/share/vm/oops/constantPoolOop.hpp	Sat Oct 30 12:19:07 2010 -0700
+++ b/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