< prev index next >

src/hotspot/share/classfile/verificationType.hpp

Print this page
@@ -66,25 +66,28 @@
        ITEM_Long_2nd, ITEM_Double_2nd
      };
  
      // Enum for the _data field
      enum : uint {
-       // Bottom two bits determine if the type is a reference, primitive,
-       // uninitialized or a query-type.
-       TypeMask           = 0x00000003,
+       // Bottom three bits determine if the type is a reference, inline type,
+       // primitive, uninitialized or a query-type.
+       TypeMask           = 0x00000007,
  
        // Topmost types encoding
-       Reference          = 0x0,        // _sym contains the name
+       Reference          = 0x0,        // _sym contains the name of an object
        Primitive          = 0x1,        // see below for primitive list
        Uninitialized      = 0x2,        // 0x00ffff00 contains bci
        TypeQuery          = 0x3,        // Meta-types used for category testing
+       InlineType         = 0x4,        // _sym contains the name of an inline type
  
        // Utility flags
        ReferenceFlag      = 0x00,       // For reference query types
        Category1Flag      = 0x01,       // One-word values
        Category2Flag      = 0x02,       // First word of a two-word value
        Category2_2ndFlag  = 0x04,       // Second word of a two-word value
+       InlineTypeFlag     = 0x08,       // For inline type query types
+       NonScalarFlag      = 0x10,       // For either inline type or reference queries
  
        // special reference values
        Null               = 0x00000000, // A reference with a 0 sym is null
  
        // Primitives categories (the second byte determines the category)

@@ -112,11 +115,13 @@
  
        // Query values
        ReferenceQuery     = (ReferenceFlag     << 1 * BitsPerByte) | TypeQuery,
        Category1Query     = (Category1Flag     << 1 * BitsPerByte) | TypeQuery,
        Category2Query     = (Category2Flag     << 1 * BitsPerByte) | TypeQuery,
-       Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery
+       Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery,
+       InlineTypeQuery    = (InlineTypeFlag    << 1 * BitsPerByte) | TypeQuery,
+       NonScalarQuery     = (NonScalarFlag     << 1 * BitsPerByte) | TypeQuery
      };
  
    VerificationType(uintptr_t raw_data) {
      _u._data = raw_data;
    }

@@ -145,30 +150,45 @@
    // to anything, but the specified types are assignable to a "check".  For
    // example, any category1 primitive is assignable to category1_check and
    // any reference is assignable to reference_check.
    static VerificationType reference_check()
      { return VerificationType(ReferenceQuery); }
+   static VerificationType inline_type_check()
+     { return VerificationType(InlineTypeQuery); }
    static VerificationType category1_check()
      { return VerificationType(Category1Query); }
    static VerificationType category2_check()
      { return VerificationType(Category2Query); }
    static VerificationType category2_2nd_check()
      { return VerificationType(Category2_2ndQuery); }
+   static VerificationType nonscalar_check()
+     { return VerificationType(NonScalarQuery); }
  
    // For reference types, store the actual Symbol
    static VerificationType reference_type(Symbol* sh) {
-       assert(((uintptr_t)sh & 0x3) == 0, "Symbols must be aligned");
+       assert(((uintptr_t)sh & TypeMask) == 0, "Symbols must be aligned");
        // If the above assert fails in the future because oop* isn't aligned,
        // then this type encoding system will have to change to have a tag value
        // to discriminate between oops and primitives.
        return VerificationType((uintptr_t)sh);
    }
    static VerificationType uninitialized_type(u2 bci)
      { return VerificationType(bci << 1 * BitsPerByte | Uninitialized); }
    static VerificationType uninitialized_this_type()
      { return uninitialized_type(BciForThis); }
  
+   // For inline types, store the actual Symbol* and set the 3rd bit.
+   // Provides a way for an inline type to be distinguished from a reference type.
+   static VerificationType inline_type(Symbol* sh) {
+       assert(((uintptr_t)sh & TypeMask) == 0, "Symbols must be aligned");
+       assert((uintptr_t)sh != 0, "Null is not a valid inline type");
+       // If the above assert fails in the future because oop* isn't aligned,
+       // then this type encoding system will have to change to have a tag value
+       // to discriminate between oops and primitives.
+       return VerificationType((uintptr_t)sh | InlineType);
+   }
+ 
    // Create based on u1 read from classfile
    static VerificationType from_tag(u1 tag);
  
    bool is_bogus() const     { return (_u._data == Bogus); }
    bool is_null() const      { return (_u._data == Null); }

@@ -180,15 +200,16 @@
    bool is_long() const      { return (_u._data == Long); }
    bool is_float() const     { return (_u._data == Float); }
    bool is_double() const    { return (_u._data == Double); }
    bool is_long2() const     { return (_u._data == Long_2nd); }
    bool is_double2() const   { return (_u._data == Double_2nd); }
-   bool is_reference() const { return ((_u._data & TypeMask) == Reference); }
+   bool is_reference() const { return (((_u._data & TypeMask) == Reference) && !is_inline_type_check()); }
+   bool is_inline_type() const { return ((_u._data & TypeMask) == InlineType); }
    bool is_category1() const {
      // This should return true for all one-word types, which are category1
-     // primitives, and references (including uninitialized refs).  Though
-     // the 'query' types should technically return 'false' here, if we
+     // primitives, references (including uninitialized refs) and inline types.
+     // Though the 'query' types should technically return 'false' here, if we
      // allow this to return true, we can perform the test using only
      // 2 operations rather than 8 (3 masks, 3 compares and 2 logical 'ands').
      // Since no one should call this on a query type anyway, this is ok.
      assert(!is_check(), "Must not be a check type (wrong value returned)");
      return ((_u._data & Category1) != Primitive);

@@ -198,10 +219,12 @@
    bool is_category2() const { return ((_u._data & Category2) == Category2); }
    bool is_category2_2nd() const {
      return ((_u._data & Category2_2nd) == Category2_2nd);
    }
    bool is_reference_check() const { return _u._data == ReferenceQuery; }
+   bool is_inline_type_check() const { return _u._data == InlineTypeQuery; }
+   bool is_nonscalar_check() const { return _u._data == NonScalarQuery; }
    bool is_category1_check() const { return _u._data == Category1Query; }
    bool is_category2_check() const { return _u._data == Category2Query; }
    bool is_category2_2nd_check() const { return _u._data == Category2_2ndQuery; }
    bool is_check() const { return (_u._data & TypeQuery) == TypeQuery; }
  

@@ -218,10 +241,12 @@
    bool is_double_array() const { return is_x_array(JVM_SIGNATURE_DOUBLE); }
    bool is_object_array() const { return is_x_array(JVM_SIGNATURE_CLASS); }
    bool is_array_array() const { return is_x_array(JVM_SIGNATURE_ARRAY); }
    bool is_reference_array() const
      { return is_object_array() || is_array_array(); }
+   bool is_nonscalar_array() const
+     { return is_object_array() || is_array_array(); }
    bool is_object() const
      { return (is_reference() && !is_null() && name()->utf8_length() >= 1 &&
                name()->char_at(0) != JVM_SIGNATURE_ARRAY); }
    bool is_array() const
      { return (is_reference() && !is_null() && name()->utf8_length() >= 2 &&

@@ -234,24 +259,32 @@
    VerificationType to_category2_2nd() const {
      assert(is_category2(), "Must be a double word");
      return VerificationType(is_long() ? Long_2nd : Double_2nd);
    }
  
+   static VerificationType change_ref_to_inline_type(VerificationType ref) {
+     assert(ref.is_reference(), "Bad arg");
+     assert(!ref.is_null(), "Unexpected nullptr");
+     return inline_type(ref.name());
+   }
+ 
    u2 bci() const {
      assert(is_uninitialized(), "Must be uninitialized type");
      return ((_u._data & BciMask) >> 1 * BitsPerByte);
    }
  
    Symbol* name() const {
-     assert(is_reference() && !is_null(), "Must be a non-null reference");
-     return _u._sym;
+     assert(!is_null() && (is_reference() || is_inline_type()), "Must be a non-null reference or an inline type");
+     return (is_reference() ? _u._sym : ((Symbol*)(_u._data & ~(uintptr_t)InlineType)));
    }
  
    bool equals(const VerificationType& t) const {
      return (_u._data == t._u._data ||
-       (is_reference() && t.is_reference() && !is_null() && !t.is_null() &&
-        name() == t.name()));
+             (((is_reference() && t.is_reference()) ||
+              (is_inline_type() && t.is_inline_type())) &&
+               !is_null() && !t.is_null() && name() == t.name()));
+ 
    }
  
    bool operator ==(const VerificationType& t) const {
      return equals(t);
    }

@@ -276,18 +309,27 @@
            return from.is_category2();
          case Category2_2ndQuery:
            return from.is_category2_2nd();
          case ReferenceQuery:
            return from.is_reference() || from.is_uninitialized();
+         case NonScalarQuery:
+           return from.is_reference() || from.is_uninitialized() ||
+                  from.is_inline_type();
+         case InlineTypeQuery:
+           return from.is_inline_type();
          case Boolean:
          case Byte:
          case Char:
          case Short:
            // An int can be assigned to boolean, byte, char or short values.
            return from.is_integer();
          default:
-           if (is_reference() && from.is_reference()) {
+           if (is_inline_type()) {
+             return is_inline_type_assignable_from(from);
+           } else if (is_reference() && from.is_inline_type()) {
+             return is_ref_assignable_from_inline_type(from, context, THREAD);
+           } else if (is_reference() && from.is_reference()) {
              return is_reference_assignable_from(from, context,
                                                  from_field_is_protected,
                                                  THREAD);
            } else {
              return false;

@@ -331,10 +373,15 @@
  
    bool is_reference_assignable_from(
      const VerificationType&, ClassVerifier*, bool from_field_is_protected,
      TRAPS) const;
  
+   bool is_inline_type_assignable_from(const VerificationType& from) const;
+ 
+   bool is_ref_assignable_from_inline_type(const VerificationType& from, ClassVerifier* context, TRAPS) const;
+ 
+ 
   public:
    static bool resolve_and_check_assignability(InstanceKlass* klass, Symbol* name,
                                                Symbol* from_name, bool from_field_is_protected,
                                                bool from_is_array, bool from_is_object,
                                                TRAPS);
< prev index next >