1 /*
2 * Copyright (c) 2023, 2026, 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_RESOLVEDFIELDENTRY_HPP
26 #define SHARE_OOPS_RESOLVEDFIELDENTRY_HPP
27
28 #include "interpreter/bytecodes.hpp"
29 #include "runtime/atomicAccess.hpp"
30 #include "utilities/checkedCast.hpp"
31 #include "utilities/sizes.hpp"
32
33 // ResolvedFieldEntry contains the resolution information for field related bytecodes like
34 // like getfield, putfield, getstatic, and putstatic. A member of this class can be initialized
35 // with the constant pool index associated with the bytecode before any resolution is done, where
36 // "resolution" refers to populating the getcode and putcode fields and other relevant information.
37 // The field's type (TOS), offset, holder klass, and index within that class can all be acquired
38 // together and are used to populate this structure. These entries are contained
39 // within the ConstantPoolCache and are accessed with indices added to the bytecode after
40 // rewriting.
41
42 // Field bytecodes start with a constant pool index as their operand, which is then rewritten to
43 // a "field index", which is an index into the array of ResolvedFieldEntry.
44
45 // The explicit paddings are necessary for generating deterministic CDS archives. They prevent
46 // the C++ compiler from potentially inserting random values in unused gaps.
47
48 class InstanceKlass;
49
50 class ResolvedFieldEntry {
51 friend class VMStructs;
52
53 InstanceKlass* _field_holder; // Field holder klass
54 int _field_offset; // Field offset in bytes
55 u2 _field_index; // Index into field information in holder InstanceKlass
56 u2 _cpool_index; // Constant pool index
57 u1 _tos_state; // TOS state
58 u1 _flags; // Flags: [0000|00|is_final|is_volatile]
59 u1 _get_code, _put_code; // Get and Put bytecodes of the field
60 #ifdef _LP64
61 u4 _padding;
62 #endif
63
64 public:
65 ResolvedFieldEntry(u2 cpi) :
66 _field_holder(nullptr),
67 _field_offset(0),
68 _field_index(0),
69 _cpool_index(cpi),
70 _tos_state(0),
71 _flags(0),
72 _get_code(0),
73 _put_code(0)
74 #ifdef _LP64
75 , _padding(0)
76 #endif
77 {}
78
79 ResolvedFieldEntry() :
80 ResolvedFieldEntry(0) {}
81
82 // Bit shift to get flags
83 // Note: Only two flags exists at the moment but more could be added
84 enum {
85 is_volatile_shift = 0,
86 is_final_shift = 1, // unused
87 max_flag_shift = is_final_shift
88 };
89
90 // Getters
91 InstanceKlass* field_holder() const { return _field_holder; }
92 int field_offset() const { return _field_offset; }
93 u2 field_index() const { return _field_index; }
94 u2 constant_pool_index() const { return _cpool_index; }
95 u1 tos_state() const { return _tos_state; }
96 u1 get_code() const { return AtomicAccess::load_acquire(&_get_code); }
97 u1 put_code() const { return AtomicAccess::load_acquire(&_put_code); }
98 bool is_final() const { return (_flags & (1 << is_final_shift)) != 0; }
99 bool is_volatile () const { return (_flags & (1 << is_volatile_shift)) != 0; }
100 bool is_resolved(Bytecodes::Code code) const {
101 switch(code) {
102 case Bytecodes::_getstatic:
103 case Bytecodes::_getfield:
104 return (get_code() == code);
105 case Bytecodes::_putstatic:
106 case Bytecodes::_putfield:
107 return (put_code() == code);
108 default:
109 ShouldNotReachHere();
110 return false;
111 }
112 }
113
114 // Printing
115 void print_on(outputStream* st) const;
116
117 private:
118 void set_flags(bool is_final_flag, bool is_volatile_flag) {
119 int new_flags = (is_final_flag << is_final_shift) | static_cast<int>(is_volatile_flag);
120 _flags = checked_cast<u1>(new_flags);
121 assert(is_final() == is_final_flag, "Must be");
122 assert(is_volatile() == is_volatile_flag, "Must be");
123 }
124
125 inline void set_bytecode(u1* code, u1 new_code) {
126 #ifdef ASSERT
127 // Read once.
128 volatile Bytecodes::Code c = (Bytecodes::Code)*code;
129 assert(c == 0 || c == new_code || new_code == 0, "update must be consistent");
130 #endif
131 AtomicAccess::release_store(code, new_code);
132 }
133
134 // Debug help
135 void assert_is_valid() const NOT_DEBUG_RETURN;
136
137 public:
138 // Populate the strucutre with resolution information
139 void fill_in(const fieldDescriptor& info, u1 tos_state, u1 get_code, u1 put_code);
140
141 // CDS
142 #if INCLUDE_CDS
143 void remove_unshareable_info();
144 void mark_and_relocate();
145 #endif
146
147 // Offsets
148 static ByteSize field_holder_offset() { return byte_offset_of(ResolvedFieldEntry, _field_holder); }
149 static ByteSize field_offset_offset() { return byte_offset_of(ResolvedFieldEntry, _field_offset); }
150 static ByteSize field_index_offset() { return byte_offset_of(ResolvedFieldEntry, _field_index); }
151 static ByteSize get_code_offset() { return byte_offset_of(ResolvedFieldEntry, _get_code); }
152 static ByteSize put_code_offset() { return byte_offset_of(ResolvedFieldEntry, _put_code); }
153 static ByteSize type_offset() { return byte_offset_of(ResolvedFieldEntry, _tos_state); }
154 static ByteSize flags_offset() { return byte_offset_of(ResolvedFieldEntry, _flags); }
155 };
156
157 #endif //SHARE_OOPS_RESOLVEDFIELDENTRY_HPP