< prev index next >

src/hotspot/share/classfile/verificationType.hpp

Print this page

        

*** 67,91 **** ITEM_Long_2nd, ITEM_Double_2nd }; // Enum for the _data field enum { ! // Bottom two bits determine if the type is a reference, primitive, ! // uninitialized or a query-type. ! TypeMask = 0x00000003, // Topmost types encoding ! Reference = 0x0, // _sym contains the name Primitive = 0x1, // see below for primitive list Uninitialized = 0x2, // 0x00ffff00 contains bci TypeQuery = 0x3, // Meta-types used for category testing // 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 // special reference values Null = 0x00000000, // A reference with a 0 sym is null // Primitives categories (the second byte determines the category) --- 67,94 ---- ITEM_Long_2nd, ITEM_Double_2nd }; // Enum for the _data field enum { ! // Bottom three bits determine if the type is a reference, value type, ! // primitive, uninitialized or a query-type. ! TypeMask = 0x00000007, // Topmost types encoding ! 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 + ValueType = 0x4, // _sym contains the name of a value 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 + ValueTypeFlag = 0x08, // For value type query types + NonScalarFlag = 0x10, // For either value 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)
*** 113,123 **** // Query values ReferenceQuery = (ReferenceFlag << 1 * BitsPerByte) | TypeQuery, Category1Query = (Category1Flag << 1 * BitsPerByte) | TypeQuery, Category2Query = (Category2Flag << 1 * BitsPerByte) | TypeQuery, ! Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery }; VerificationType(uintptr_t raw_data) { _u._data = raw_data; } --- 116,128 ---- // Query values ReferenceQuery = (ReferenceFlag << 1 * BitsPerByte) | TypeQuery, Category1Query = (Category1Flag << 1 * BitsPerByte) | TypeQuery, Category2Query = (Category2Flag << 1 * BitsPerByte) | TypeQuery, ! Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery, ! ValueTypeQuery = (ValueTypeFlag << 1 * BitsPerByte) | TypeQuery, ! NonScalarQuery = (NonScalarFlag << 1 * BitsPerByte) | TypeQuery }; VerificationType(uintptr_t raw_data) { _u._data = raw_data; }
*** 146,175 **** // 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 category1_check() { return VerificationType(Category1Query); } static VerificationType category2_check() { return VerificationType(Category2Query); } static VerificationType category2_2nd_check() { return VerificationType(Category2_2ndQuery); } // For reference types, store the actual Symbol static VerificationType reference_type(Symbol* sh) { ! assert(((uintptr_t)sh & 0x3) == 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 descriminate 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); } // 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); } --- 151,195 ---- // 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 valuetype_check() + { return VerificationType(ValueTypeQuery); } 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 & 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 descriminate 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 value types, store the actual Symbol* and set the 3rd bit. + // Provides a way for a value type to be distinguished from a reference type. + static VerificationType valuetype_type(Symbol* sh) { + assert(((uintptr_t)sh & TypeMask) == 0, "Symbols must be aligned"); + assert((uintptr_t)sh != 0, "Null is not a valid value 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 descriminate between oops and primitives. + return VerificationType((uintptr_t)sh | ValueType); + } + // 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); }
*** 181,195 **** 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_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 // 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 noone 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); --- 201,216 ---- 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) && !is_valuetype_check()); } ! bool is_valuetype() const { return ((_u._data & TypeMask) == ValueType); } bool is_category1() const { // This should return true for all one-word types, which are category1 ! // primitives, references (including uninitialized refs) and value 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 noone 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);
*** 199,208 **** --- 220,231 ---- 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_valuetype_check() const { return _u._data == ValueTypeQuery; } + 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; }
*** 216,228 **** --- 239,254 ---- bool is_short_array() const { return is_x_array('S'); } bool is_long_array() const { return is_x_array('J'); } bool is_float_array() const { return is_x_array('F'); } bool is_double_array() const { return is_x_array('D'); } bool is_object_array() const { return is_x_array('L'); } + bool is_value_array() const { return is_x_array('Q'); } bool is_array_array() const { return is_x_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() || is_value_array(); } bool is_object() const { return (is_reference() && !is_null() && name()->utf8_length() >= 1 && name()->char_at(0) != '['); } bool is_array() const { return (is_reference() && !is_null() && name()->utf8_length() >= 2 &&
*** 235,258 **** VerificationType to_category2_2nd() const { assert(is_category2(), "Must be a double word"); return VerificationType(is_long() ? Long_2nd : Double_2nd); } 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; } 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())); } bool operator ==(const VerificationType& t) const { return equals(t); } --- 261,292 ---- 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_valuetype(VerificationType ref) { + assert(ref.is_reference(), "Bad arg"); + assert(!ref.is_null(), "Unexpected NULL"); + return valuetype_type(ref.name()); + } + u2 bci() const { assert(is_uninitialized(), "Must be uninitialized type"); return ((_u._data & BciMask) >> 1 * BitsPerByte); } Symbol* name() const { ! assert(!is_null() && (is_reference() || is_valuetype()), "Must be a non-null reference or a value type"); ! return (is_reference() ? _u._sym : ((Symbol*)(_u._data & ~(uintptr_t)ValueType))); } bool equals(const VerificationType& t) const { return (_u._data == t._u._data || ! (((is_reference() && t.is_reference()) || ! (is_valuetype() && t.is_valuetype())) && ! !is_null() && !t.is_null() && name() == t.name())); ! } bool operator ==(const VerificationType& t) const { return equals(t); }
*** 277,294 **** return from.is_category2(); case Category2_2ndQuery: return from.is_category2_2nd(); case ReferenceQuery: return from.is_reference() || from.is_uninitialized(); 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()) { return is_reference_assignable_from(from, context, from_field_is_protected, THREAD); } else { return false; --- 311,337 ---- 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_valuetype(); + case ValueTypeQuery: + return from.is_valuetype(); 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_valuetype()) { ! return is_valuetype_assignable_from(from); ! } else if (is_reference() && from.is_valuetype()) { ! return is_ref_assignable_from_value_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;
*** 332,341 **** --- 375,389 ---- bool is_reference_assignable_from( const VerificationType&, ClassVerifier*, bool from_field_is_protected, TRAPS) const; + bool is_valuetype_assignable_from(const VerificationType& from) const; + + bool is_ref_assignable_from_value_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 >