1 /*
  2  * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_OOPS_FIELDINFO_HPP
 26 #define SHARE_OOPS_FIELDINFO_HPP
 27 
 28 #include "oops/constantPool.hpp"
 29 #include "oops/symbol.hpp"
 30 #include "oops/typeArrayOop.hpp"
 31 #include "utilities/vmEnums.hpp"
 32 
 33 // This class represents the field information contained in the fields
 34 // array of an InstanceKlass.  Currently it's laid on top an array of
 35 // Java shorts but in the future it could simply be used as a real
 36 // array type.  FieldInfo generally shouldn't be used directly.
 37 // Fields should be queried either through InstanceKlass or through
 38 // the various FieldStreams.
 39 class FieldInfo {
 40   friend class fieldDescriptor;
 41   friend class JavaFieldStream;
 42   friend class ClassFileParser;
 43 
 44  public:
 45   // fields
 46   // Field info extracted from the class file and stored
 47   // as an array of 6 shorts.
 48 
 49 #define FIELDINFO_TAG_SIZE             2
 50 #define FIELDINFO_TAG_OFFSET           1 << 0
 51 #define FIELDINFO_TAG_CONTENDED        1 << 1
 52 
 53   // Packed field has the tag, and can be either of:
 54   //    hi bits <--------------------------- lo bits
 55   //   |---------high---------|---------low---------|
 56   //    ..........................................CO
 57   //    ..........................................00  - non-contended field
 58   //    [--contention_group--]....................10  - contended field with contention group
 59   //    [------------------offset----------------]01  - real field offset
 60 
 61   // Bit O indicates if the packed field contains an offset (O=1) or not (O=0)
 62   // Bit C indicates if the field is contended (C=1) or not (C=0)
 63   //       (if it is contended, the high packed field contains the contention group)
 64 
 65   enum FieldOffset {
 66     access_flags_offset      = 0,
 67     name_index_offset        = 1,
 68     signature_index_offset   = 2,
 69     initval_index_offset     = 3,
 70     low_packed_offset        = 4,
 71     high_packed_offset       = 5,
 72     field_slots              = 6
 73   };
 74 
 75  private:
 76   u2 _shorts[field_slots];
 77 
 78   void set_name_index(u2 val)                    { _shorts[name_index_offset] = val;         }
 79   void set_signature_index(u2 val)               { _shorts[signature_index_offset] = val;    }
 80   void set_initval_index(u2 val)                 { _shorts[initval_index_offset] = val;      }
 81 
 82   u2 name_index() const                          { return _shorts[name_index_offset];        }
 83   u2 signature_index() const                     { return _shorts[signature_index_offset];   }
 84   u2 initval_index() const                       { return _shorts[initval_index_offset];     }
 85 
 86  public:
 87   static FieldInfo* from_field_array(Array<u2>* fields, int index) {
 88     return ((FieldInfo*)fields->adr_at(index * field_slots));
 89   }
 90   static FieldInfo* from_field_array(u2* fields, int index) {
 91     return ((FieldInfo*)(fields + index * field_slots));
 92   }
 93 
 94   void initialize(u2 access_flags,
 95                   u2 name_index,
 96                   u2 signature_index,
 97                   u2 initval_index) {
 98     _shorts[access_flags_offset] = access_flags;
 99     _shorts[name_index_offset] = name_index;
100     _shorts[signature_index_offset] = signature_index;
101     _shorts[initval_index_offset] = initval_index;
102     _shorts[low_packed_offset] = 0;
103     _shorts[high_packed_offset] = 0;
104   }
105 
106   u2 access_flags() const                        { return _shorts[access_flags_offset];            }
107   u4 offset() const {
108     assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) != 0, "Offset must have been set");
109     return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE;
110   }
111 
112   bool is_contended() const {
113     return (_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) != 0;
114   }
115 
116   u2 contended_group() const {
117     assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) == 0, "Offset must not have been set");
118     assert((_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) != 0, "Field must be contended");
119     return _shorts[high_packed_offset];
120  }
121 
122   bool is_offset_set() const {
123     return (_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET)!= 0;
124   }
125 
126   Symbol* name(ConstantPool* cp) const {
127     int index = name_index();
128     if (is_internal()) {
129       return lookup_symbol(index);
130     }
131     return cp->symbol_at(index);
132   }
133 
134   Symbol* signature(ConstantPool* cp) const {
135     int index = signature_index();
136     if (is_internal()) {
137       return lookup_symbol(index);
138     }
139     return cp->symbol_at(index);
140   }
141 
142   void set_access_flags(u2 val)                  { _shorts[access_flags_offset] = val;             }
143   void set_offset(u4 val)                        {
144     val = val << FIELDINFO_TAG_SIZE; // make room for tag
145     _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET;
146     _shorts[high_packed_offset] = extract_high_short_from_int(val);
147   }
148 
149   void set_contended_group(u2 val) {
150     assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) == 0, "Offset must not have been set");
151     assert((_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) == 0, "Overwritting contended group");
152     _shorts[low_packed_offset] |= FIELDINFO_TAG_CONTENDED;
153     _shorts[high_packed_offset] = val;
154   }
155 
156   bool is_internal() const {
157     return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0;
158   }
159 
160   bool is_stable() const {
161     return (access_flags() & JVM_ACC_FIELD_STABLE) != 0;
162   }
163   void set_stable(bool z) {
164     if (z) _shorts[access_flags_offset] |=  JVM_ACC_FIELD_STABLE;
165     else   _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE;
166   }
167 
168   Symbol* lookup_symbol(int symbol_index) const {
169     assert(is_internal(), "only internal fields");
170     return Symbol::vm_symbol_at(static_cast<vmSymbolID>(symbol_index));
171   }
172 };
173 
174 #endif // SHARE_OOPS_FIELDINFO_HPP