1 /*
  2  * Copyright (c) 2023, 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_INLINE_HPP
 26 #define SHARE_OOPS_FIELDINFO_INLINE_HPP
 27 
 28 #include "oops/fieldInfo.hpp"
 29 
 30 #include "memory/metadataFactory.hpp"
 31 #include "oops/constantPool.hpp"
 32 #include "oops/symbol.hpp"
 33 #include "runtime/atomic.hpp"
 34 #include "utilities/checkedCast.hpp"
 35 
 36 inline Symbol* FieldInfo::name(ConstantPool* cp) const {
 37   int index = _name_index;
 38   if (_field_flags.is_injected()) {
 39     return lookup_symbol(index);
 40   }
 41   return cp->symbol_at(index);
 42 }
 43 
 44 inline Symbol* FieldInfo::signature(ConstantPool* cp) const {
 45   int index = _signature_index;
 46   if (_field_flags.is_injected()) {
 47     return lookup_symbol(index);
 48   }
 49   return cp->symbol_at(index);
 50 }
 51 
 52 inline Symbol* FieldInfo::lookup_symbol(int symbol_index) const {
 53   assert(_field_flags.is_injected(), "only injected fields");
 54   return Symbol::vm_symbol_at(static_cast<vmSymbolID>(symbol_index));
 55 }
 56 
 57 inline int FieldInfoStream::num_injected_java_fields(const Array<u1>* fis) {
 58   FieldInfoReader fir(fis);
 59   fir.skip(1);
 60   return fir.next_uint();
 61 }
 62 
 63 inline int FieldInfoStream::num_total_fields(const Array<u1>* fis) {
 64   FieldInfoReader fir(fis);
 65   return fir.next_uint() + fir.next_uint();
 66 }
 67 
 68 inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) { return FieldInfoReader(fis).next_uint(); }
 69 
 70 template<typename CON>
 71 inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
 72   _next_index++;  // pre-increment
 73   _consumer->accept_uint(fi.name_index());
 74   _consumer->accept_uint(fi.signature_index());
 75   _consumer->accept_uint(fi.offset());
 76   _consumer->accept_uint(fi.access_flags().as_int());
 77   _consumer->accept_uint(fi.field_flags().as_uint());
 78   if(fi.field_flags().has_any_optionals()) {
 79     if (fi.field_flags().is_initialized()) {
 80       _consumer->accept_uint(fi.initializer_index());
 81     }
 82     if (fi.field_flags().is_generic()) {
 83       _consumer->accept_uint(fi.generic_signature_index());
 84     }
 85     if (fi.field_flags().is_contended()) {
 86       _consumer->accept_uint(fi.contention_group());
 87     }
 88   } else {
 89     assert(fi.initializer_index() == 0, "");
 90     assert(fi.generic_signature_index() == 0, "");
 91     assert(fi.contention_group() == 0, "");
 92   }
 93 }
 94 
 95 
 96 inline FieldInfoReader::FieldInfoReader(const Array<u1>* fi)
 97   : _r(fi->data(), 0),
 98     _next_index(0) { }
 99 
100 inline void FieldInfoReader::read_field_info(FieldInfo& fi) {
101   fi._index = _next_index++;
102   fi._name_index = checked_cast<u2>(next_uint());
103   fi._signature_index = checked_cast<u2>(next_uint());
104   fi._offset = next_uint();
105   fi._access_flags = AccessFlags(next_uint());
106   fi._field_flags = FieldInfo::FieldFlags(next_uint());
107   if (fi._field_flags.is_initialized()) {
108     fi._initializer_index = checked_cast<u2>(next_uint());
109   } else {
110     fi._initializer_index = 0;
111   }
112   if (fi._field_flags.is_generic()) {
113     fi._generic_signature_index = checked_cast<u2>(next_uint());
114   } else {
115     fi._generic_signature_index = 0;
116   }
117   if (fi._field_flags.is_contended()) {
118     fi._contention_group = checked_cast<u2>(next_uint());
119   } else {
120     fi._contention_group = 0;
121   }
122 }
123 
124 inline FieldInfoReader&  FieldInfoReader::skip_field_info() {
125   _next_index++;
126   const int name_sig_af_off = 4;  // four items
127   skip(name_sig_af_off);
128   FieldInfo::FieldFlags ff(next_uint());
129   if (ff.has_any_optionals()) {
130     const int init_gen_cont = (ff.is_initialized() +
131                                 ff.is_generic() +
132                                 ff.is_contended());
133     skip(init_gen_cont);  // up to three items
134   }
135   return *this;
136 }
137 
138 // Skip to the nth field.  If the reader is freshly initialized to
139 // the zero index, this will call skip_field_info() n times.
140 inline FieldInfoReader& FieldInfoReader::skip_to_field_info(int n) {
141   assert(n >= _next_index, "already past that index");
142   const int count = n - _next_index;
143   for (int i = 0; i < count; i++)  skip_field_info();
144   assert(_next_index == n, "");
145   return *this;
146 }
147 
148 // for random access, if you know where to go up front:
149 inline FieldInfoReader& FieldInfoReader::set_position_and_next_index(int position, int next_index) {
150   _r.set_position(position);
151   _next_index = next_index;
152   return *this;
153 }
154 
155 inline void FieldStatus::atomic_set_bits(u1& flags, u1 mask) {
156   Atomic::fetch_then_or(&flags, mask);
157 }
158 
159 inline void FieldStatus::atomic_clear_bits(u1& flags, u1 mask) {
160   Atomic::fetch_then_and(&flags, (u1)(~mask));
161 }
162 
163 inline void FieldStatus::update_flag(FieldStatusBitPosition pos, bool z) {
164   if (z) atomic_set_bits(_flags, flag_mask(pos));
165   else atomic_clear_bits(_flags, flag_mask(pos));
166 }
167 
168 inline void FieldStatus::update_access_watched(bool z) { update_flag(_fs_access_watched, z); }
169 inline void FieldStatus::update_modification_watched(bool z) { update_flag(_fs_modification_watched, z); }
170 inline void FieldStatus::update_initialized_final_update(bool z) { update_flag(_initialized_final_update, z); }
171 
172 #endif // SHARE_OOPS_FIELDINFO_INLINE_HPP