1 /*
  2  * Copyright (c) 2023, 2025, 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 #include "oops/fieldInfo.inline.hpp"
 26 #include "runtime/atomic.hpp"
 27 
 28 void FieldInfo::print(outputStream* os, ConstantPool* cp) {
 29   os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d "
 30                "AccessFlags=%d FieldFlags=%d "
 31                "initval_index=%d gen_signature_index=%d, gen_signature=%s contended_group=%d",
 32                 index(),
 33                 name_index(), name(cp)->as_utf8(),
 34                 signature_index(), signature(cp)->as_utf8(),
 35                 offset(),
 36                 access_flags().as_field_flags(),
 37                 field_flags().as_uint(),
 38                 initializer_index(),
 39                 generic_signature_index(),
 40                 _field_flags.is_injected() ? lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8(),
 41                 contended_group());
 42 }
 43 
 44 void FieldInfo::print_from_growable_array(outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp) {
 45   for (int i = 0; i < array->length(); i++) {
 46     array->adr_at(i)->print(os, cp);
 47   }
 48 }
 49 
 50 Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields,
 51                                                           ClassLoaderData* loader_data, TRAPS) {
 52   // The stream format described in fieldInfo.hpp is:
 53   //   FieldInfoStream := j=num_java_fields k=num_injected_fields Field[j+k] End
 54   //   Field := name sig offset access flags Optionals(flags)
 55   //   Optionals(i) := initval?[i&is_init]     // ConstantValue attr
 56   //                   gsig?[i&is_generic]     // signature attr
 57   //                   group?[i&is_contended]  // Contended anno (group)
 58   //   End = 0
 59 
 60   using StreamSizer = UNSIGNED5::Sizer<>;
 61   using StreamFieldSizer = Mapper<StreamSizer>;
 62   StreamSizer s;
 63   StreamFieldSizer sizer(&s);
 64 
 65   sizer.consumer()->accept_uint(java_fields);
 66   sizer.consumer()->accept_uint(injected_fields);
 67   for (int i = 0; i < fields->length(); i++) {
 68     FieldInfo* fi = fields->adr_at(i);
 69     sizer.map_field_info(*fi);
 70   }
 71   int storage_size = sizer.consumer()->position() + 1;
 72   Array<u1>* const fis = MetadataFactory::new_array<u1>(loader_data, storage_size, CHECK_NULL);
 73 
 74   using StreamWriter = UNSIGNED5::Writer<Array<u1>*, int, ArrayHelper<Array<u1>*, int>>;
 75   using StreamFieldWriter = Mapper<StreamWriter>;
 76   StreamWriter w(fis);
 77   StreamFieldWriter writer(&w);
 78 
 79   writer.consumer()->accept_uint(java_fields);
 80   writer.consumer()->accept_uint(injected_fields);
 81   for (int i = 0; i < fields->length(); i++) {
 82     FieldInfo* fi = fields->adr_at(i);
 83     writer.map_field_info(*fi);
 84   }
 85 
 86 #ifdef ASSERT
 87   FieldInfoReader r(fis);
 88   int jfc = r.next_uint();
 89   assert(jfc == java_fields, "Must be");
 90   int ifc = r.next_uint();
 91   assert(ifc == injected_fields, "Must be");
 92   for (int i = 0; i < jfc + ifc; i++) {
 93     FieldInfo fi;
 94     r.read_field_info(fi);
 95     FieldInfo* fi_ref = fields->adr_at(i);
 96     assert(fi_ref->name_index() == fi.name_index(), "Must be");
 97     assert(fi_ref->signature_index() == fi.signature_index(), "Must be");
 98     assert(fi_ref->offset() == fi.offset(), "Must be");
 99     assert(fi_ref->access_flags().as_field_flags() == fi.access_flags().as_field_flags(), "Must be");
100     assert(fi_ref->field_flags().as_uint() == fi.field_flags().as_uint(), " Must be");
101     if(fi_ref->field_flags().is_initialized()) {
102       assert(fi_ref->initializer_index() == fi.initializer_index(), "Must be");
103     }
104     if (fi_ref->field_flags().is_generic()) {
105       assert(fi_ref->generic_signature_index() == fi.generic_signature_index(), "Must be");
106     }
107     if (fi_ref->field_flags().is_contended()) {
108       assert(fi_ref->contended_group() == fi.contended_group(), "Must be");
109     }
110   }
111 #endif // ASSERT
112 
113   return fis;
114 }
115 
116 GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
117   int length = FieldInfoStream::num_total_fields(fis);
118   GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
119   FieldInfoReader r(fis);
120   *java_fields_count = r.next_uint();
121   *injected_fields_count = r.next_uint();
122   while (r.has_next()) {
123     FieldInfo fi;
124     r.read_field_info(fi);
125     array->append(fi);
126   }
127   assert(array->length() == length, "Must be");
128   assert(array->length() == *java_fields_count + *injected_fields_count, "Must be");
129   return array;
130 }
131 
132 void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) {
133   int length = FieldInfoStream::num_total_fields(fis);
134   FieldInfoReader r(fis);
135   int java_field_count = r.next_uint();
136   int injected_fields_count = r.next_uint();
137   while (r.has_next()) {
138     FieldInfo fi;
139     r.read_field_info(fi);
140     fi.print(os, cp);
141   }
142 }