< prev index next >

src/share/vm/oops/constantPool.hpp

Print this page

@@ -44,31 +44,51 @@
 // the entry in the constant pool is a klass object and not a Symbol*.
 
 class SymbolHashMap;
 
 class CPSlot VALUE_OBJ_CLASS_SPEC {
+ friend class ConstantPool;
   intptr_t _ptr;
+  enum TagBits  {_pseudo_bit = 1};
  public:
-  enum TagBits  { _resolved_value = 0, _symbol_bit = 1, _pseudo_bit = 2, _symbol_mask = 3 };
 
   CPSlot(intptr_t ptr): _ptr(ptr) {}
-  CPSlot(Klass* ptr): _ptr((intptr_t)ptr) {}
-  CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | _symbol_bit) {}
-  CPSlot(Symbol* ptr, int tag_bits): _ptr((intptr_t)ptr | tag_bits) {}
+  CPSlot(Symbol* ptr, int tag_bits = 0): _ptr((intptr_t)ptr | tag_bits) {}
 
   intptr_t value()   { return _ptr; }
-  bool is_resolved()      { return (_ptr & _symbol_bit ) == _resolved_value; }
-  bool is_unresolved()    { return (_ptr & _symbol_bit ) != _resolved_value; }
-  bool is_pseudo_string() { return (_ptr & _symbol_mask) == _symbol_bit + _pseudo_bit; }
+  bool is_pseudo_string() { return (_ptr & _pseudo_bit) != 0; }
 
   Symbol* get_symbol() {
-    assert(is_unresolved(), "bad call");
-    return (Symbol*)(_ptr & ~_symbol_mask);
+    return (Symbol*)(_ptr & ~_pseudo_bit);
   }
-  Klass* get_klass() {
-    assert(is_resolved(), "bad call");
-    return (Klass*)_ptr;
+};
+
+// This represents a JVM_CONSTANT_Class, JVM_CONSTANT_UnresolvedClass, or
+// JVM_CONSTANT_UnresolvedClassInError slot in the constant pool.
+class CPKlassSlot VALUE_OBJ_CLASS_SPEC {
+  // cp->symbol_at(_name_index) gives the name of the class.
+  int _name_index;
+
+  // cp->_resolved_klasses->at(_resolved_klass_index) gives the Klass* for the class.
+  int _resolved_klass_index;
+public:
+  enum {
+    // This is used during constant pool merging where the resolved klass index is
+    // not yet known, and will be computed at a later stage (during a call to
+    // initialize_unresolved_klasses()).
+    _temp_resolved_klass_index = 0xffff
+  };
+  CPKlassSlot(int n, int rk) {
+    _name_index = n;
+    _resolved_klass_index = rk;
+  }
+  int name_index() const {
+    return _name_index;
+  }
+  int resolved_klass_index() const {
+    assert(_resolved_klass_index != _temp_resolved_klass_index, "constant pool merging was incomplete");
+    return _resolved_klass_index;
   }
 };
 
 class KlassSizeStats;
 

@@ -81,18 +101,17 @@
   Array<u1>*           _tags;        // the tag array describing the constant pool's contents
   ConstantPoolCache*   _cache;       // the cache holding interpreter runtime information
   InstanceKlass*       _pool_holder; // the corresponding class
   Array<u2>*           _operands;    // for variable-sized (InvokeDynamic) nodes, usually empty
 
-  // Array of resolved objects from the constant pool and map from resolved
-  // object index to original constant pool index
-  jobject              _resolved_references;
-  Array<u2>*           _reference_map;
+  // ... will be changed to support compressed pointers
+  Array<Klass*>*       _resolved_klasses;
 
   enum {
     _has_preresolution = 1,           // Flags
-    _on_stack          = 2
+    _on_stack          = 2,
+    _is_shared         = 4
   };
 
   int                  _flags;  // old fashioned bit twiddling
   int                  _length; // number of elements in the array
 

@@ -117,10 +136,11 @@
  private:
   intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }
 
   CPSlot slot_at(int which) const {
     assert(is_within_bounds(which), "index out of bounds");
+    assert(!tag_at(which).is_unresolved_klass() && !tag_at(which).is_unresolved_klass_in_error(), "Corrupted constant pool");
     // Uses volatile because the klass slot changes without a lock.
     volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
     assert(adr != 0 || which == 0, "cp entry for klass should not be zero");
     return CPSlot(adr);
   }

@@ -164,19 +184,25 @@
 
   Array<u1>* tags() const                   { return _tags; }
   Array<u2>* operands() const               { return _operands; }
 
   bool has_preresolution() const            { return (_flags & _has_preresolution) != 0; }
-  void set_has_preresolution()              { _flags |= _has_preresolution; }
+  void set_has_preresolution() {
+    assert(!is_shared(), "should never be called on shared ConstantPools");
+    _flags |= _has_preresolution;
+  }
 
   // Redefine classes support.  If a method refering to this constant pool
   // is on the executing stack, or as a handle in vm code, this constant pool
   // can't be removed from the set of previous versions saved in the instance
   // class.
   bool on_stack() const                      { return (_flags &_on_stack) != 0; }
   void set_on_stack(const bool value);
 
+  // Faster than MetaspaceObj::is_shared() - used by set_on_stack()
+  bool is_shared() const                     { return (_flags & _is_shared) != 0; }
+
   // Klass holding pool
   InstanceKlass* pool_holder() const      { return _pool_holder; }
   void set_pool_holder(InstanceKlass* k)  { _pool_holder = k; }
   InstanceKlass** pool_holder_addr()      { return &_pool_holder; }
 

@@ -191,13 +217,18 @@
                                       TRAPS);
 
   // resolved strings, methodHandles and callsite objects from the constant pool
   objArrayOop resolved_references()  const;
   // mapping resolved object array indexes to cp indexes and back.
-  int object_to_cp_index(int index)         { return _reference_map->at(index); }
+  int object_to_cp_index(int index)         { return reference_map()->at(index); }
   int cp_to_object_index(int index);
 
+  void set_resolved_klasses(Array<Klass*>* rk)  { _resolved_klasses = rk; }
+  Array<Klass*>* resolved_klasses() const       { return _resolved_klasses; }
+  void allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS);
+  void initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS);
+
   // Invokedynamic indexes.
   // They must look completely different from normal indexes.
   // The main reason is that byte swapping is sometimes done on normal indexes.
   // Finally, it is helpful for debugging to tell the two apart.
   static bool is_invokedynamic_index(int i) { return (i < 0); }

@@ -221,34 +252,31 @@
 
   // Assembly code support
   static int tags_offset_in_bytes()         { return offset_of(ConstantPool, _tags); }
   static int cache_offset_in_bytes()        { return offset_of(ConstantPool, _cache); }
   static int pool_holder_offset_in_bytes()  { return offset_of(ConstantPool, _pool_holder); }
-  static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); }
+  static int resolved_klasses_offset_in_bytes()    { return offset_of(ConstantPool, _resolved_klasses); }
 
   // Storing constants
 
-  void klass_at_put(int which, Klass* k) {
-    assert(k != NULL, "resolved class shouldn't be null");
-    assert(is_within_bounds(which), "index out of bounds");
-    OrderAccess::release_store_ptr((Klass* volatile *)obj_at_addr_raw(which), k);
-    // The interpreter assumes when the tag is stored, the klass is resolved
-    // and the Klass* is a klass rather than a Symbol*, so we need
-    // hardware store ordering here.
-    release_tag_at_put(which, JVM_CONSTANT_Class);
-  }
-
   // For temporary use while constructing constant pool
   void klass_index_at_put(int which, int name_index) {
     tag_at_put(which, JVM_CONSTANT_ClassIndex);
     *int_at_addr(which) = name_index;
   }
 
-  // Temporary until actual use
-  void unresolved_klass_at_put(int which, Symbol* s) {
+  // Anonymous class support:
+  void klass_at_put(int class_index, int name_index, int resolved_klass_index, Klass* k, Symbol* name);
+  void klass_at_put(int class_index, Klass* k);
+
+  void unresolved_klass_at_put(int which, int name_index, int resolved_klass_index) {
     release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
-    slot_at_put(which, s);
+
+    assert((name_index & 0xffff0000) == 0, "must be");
+    assert((resolved_klass_index & 0xffff0000) == 0, "must be");
+    *int_at_addr(which) =
+      build_int_from_shorts((jushort)resolved_klass_index, (jushort)name_index);
   }
 
   void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
     tag_at_put(which, JVM_CONSTANT_MethodHandle);
     *int_at_addr(which) = ((jint) ref_index<<16) | ref_kind;

@@ -264,11 +292,11 @@
     *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
   }
 
   void unresolved_string_at_put(int which, Symbol* s) {
     release_tag_at_put(which, JVM_CONSTANT_String);
-    slot_at_put(which, CPSlot(s, CPSlot::_symbol_bit));
+    slot_at_put(which, CPSlot(s));
   }
 
   void int_at_put(int which, jint i) {
     tag_at_put(which, JVM_CONSTANT_Integer);
     *int_at_addr(which) = i;

@@ -346,21 +374,42 @@
   Klass* klass_at_ignore_error(int which, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
     return klass_at_impl(h_this, which, false, THREAD);
   }
 
+  CPKlassSlot klass_slot_at(int which) const {
+    assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
+           "Corrupted constant pool");
+    int value = *int_at_addr(which);
+    int name_index = extract_high_short_from_int(value);
+    int resolved_klass_index = extract_low_short_from_int(value);
+    return CPKlassSlot(name_index, resolved_klass_index);
+  }
+
   Symbol* klass_name_at(int which) const;  // Returns the name, w/o resolving.
+  int klass_name_index_at(int which) const {
+    return klass_slot_at(which).name_index();
+  }
 
   Klass* resolved_klass_at(int which) const {  // Used by Compiler
     guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
     // Must do an acquire here in case another thread resolved the klass
     // behind our back, lest we later load stale values thru the oop.
-    return CPSlot((Klass*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_klass();
+    CPKlassSlot kslot = klass_slot_at(which);
+    assert(tag_at(kslot.name_index()).is_symbol(), "sanity");
+
+    Klass** adr = resolved_klasses()->adr_at(kslot.resolved_klass_index());
+    return (Klass*)OrderAccess::load_ptr_acquire(adr);
   }
 
   // RedefineClasses() API support:
   Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
+  void temp_unresolved_klass_at_put(int which, int name_index) {
+    // Used only during constant pool merging for class redefinition. The resolved klass index
+    // will be initialized later by a call to initialize_unresolved_klasses().
+    unresolved_klass_at_put(which, name_index, CPKlassSlot::_temp_resolved_klass_index);
+  }
 
   jint int_at(int which) {
     assert(tag_at(which).is_int(), "Corrupted constant pool");
     return *int_at_addr(which);
   }

@@ -426,11 +475,11 @@
   }
 
   void pseudo_string_at_put(int which, int obj_index, oop x) {
     assert(tag_at(which).is_string(), "Corrupted constant pool");
     Symbol* sym = unresolved_string_at(which);
-    slot_at_put(which, CPSlot(sym, (CPSlot::_symbol_bit | CPSlot::_pseudo_bit)));
+    slot_at_put(which, CPSlot(sym, CPSlot::_pseudo_bit));
     string_at_put(which, obj_index, x);    // this works just fine
   }
 
   // only called when we are sure a string entry is already resolved (via an
   // earlier string_at call.

@@ -757,13 +806,13 @@
       return raw_index - CPCACHE_INDEX_TAG;
   }
 
  private:
 
-  void set_resolved_references(jobject s) { _resolved_references = s; }
-  Array<u2>* reference_map() const        { return _reference_map; }
-  void set_reference_map(Array<u2>* o)    { _reference_map = o; }
+  void set_resolved_references(jobject s) { _cache->set_resolved_references(s); }
+  Array<u2>* reference_map() const        {  return (_cache == NULL) ? NULL :  _cache->reference_map(); }
+  void set_reference_map(Array<u2>* o)    { _cache->set_reference_map(o); }
 
   // patch JSR 292 resolved references after the class is linked.
   void patch_resolved_references(GrowableArray<Handle>* cp_patches);
 
   Symbol* impl_name_ref_at(int which, bool uncached);
< prev index next >