Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8171392

Move Klass pointers outside of ConstantPool entries so ConstantPool can be read-only

    Details

    • Type: Enhancement
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 9
    • Fix Version/s: 10
    • Component/s: hotspot
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b21

      Description

      As of JDK9, after a ConstantPool is initialized, most of its entries are not modified at run time, even if constant pool resolution takes place. For example, when a FieldRef entry is resolved, additional data is written into the ConstantPoolCache, while the ConstantPool itself is unmodified.

      The only exception is Class entries. When a Class entry is resolved in ConstantPool::klass_at_impl, the content of the entry is modified from a Symbol* to a Klass*. This causes a store into the address &ConstantPool::base[which] -- see the function ConstantPool::slot_at_put() in the JDK9 source code.

      Outline:

      A class constant is represented in the classfile as a CONSTANT_ClassIndex entry, which has a 2 byte value (an index to a CONSTANT_Utf8 entry, which is the name of the class).

      During class file parsing, CONSTANT_ClassIndex entries are rewritten to CONSTANT_UnresolvedClass entries. In JDK 9, A CONSTANT_UnresolvedClass entry is represented by a Symbol* (with some lower bits set .. see CPSlot in constantPool.hpp). After class resolution, the CONSTANT_UnresolvedClass entry is changed to a CONSTANT_Class entry, and its content is changed to a Klass*.

      The proposal is to change the representation of both CONSTANT_UnresolvedClass and CONSTANT_Class to be a pair of 16-bit unsigned integers:

      class ConstantPool {
        Array<Klass*>* _resolved_klass;

        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.
          int value = *int_at_addr(which);
          int resolved_klass_index = extract_low_short_from_int(value);
          int name_index = extract_high_short_from_int(value);
          assert(tag_at(name_index).is_symbol(), "sanity");

          Klass** adr = _resolved_klasses->adr_at(resolved_klass_index);
          return (Klass*)OrderAccess::load_ptr_acquire(adr);
        }

      The name_index is the same value as in the original CONSTANT_ClassIndex entry -- i.e., the name of the class.

      The resolved_klass_index is an unique index in the _resolved_klass for this particular entry. _resolved_klass is allocated during class file parsing, and its length equals to the number of CONSTANT_ClassIndex entries in the input class file.

      + If the class is not yet resolved, _resolved_klasses[resolved_klass_index] is NULL.

      + If the class is successfully resolved, _resolved_klasses[resolved_klass_index] contains the Klass pointer to this class.

      Note that the value of this entry (i.e., *int_at_addr(which)), is unchanged during resolution of this entry.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                iklam Ioi Lam
                Reporter:
                iklam Ioi Lam
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: