1/*
2 * Copyright (c) 2011, 2019, 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/typeArrayOop.hpp"
30#include "classfile/vmSymbols.hpp"
31
32// This class represents the field information contained in the fields
33// array of an InstanceKlass. Currently it's laid on top an array of
34// Java shorts but in the future it could simply be used as a real
35// array type. FieldInfo generally shouldn't be used directly.
36// Fields should be queried either through InstanceKlass or through
37// the various FieldStreams.
38class FieldInfo {
39 friend class fieldDescriptor;
40 friend class JavaFieldStream;
41 friend class ClassFileParser;
42
43 public:
44 // fields
45 // Field info extracted from the class file and stored
46 // as an array of 6 shorts.
47
48#define FIELDINFO_TAG_SIZE 2
49#define FIELDINFO_TAG_BLANK 0
50#define FIELDINFO_TAG_OFFSET 1
51#define FIELDINFO_TAG_TYPE_PLAIN 2
52#define FIELDINFO_TAG_TYPE_CONTENDED 3
53#define FIELDINFO_TAG_MASK 3
54
55 // Packed field has the tag, and can be either of:
56 // hi bits <--------------------------- lo bits
57 // |---------high---------|---------low---------|
58 // ..........................................00 - blank
59 // [------------------offset----------------]01 - real field offset
60 // ......................[-------type-------]10 - plain field with type
61 // [--contention_group--][-------type-------]11 - contended field with type and contention group
62 enum FieldOffset {
63 access_flags_offset = 0,
64 name_index_offset = 1,
65 signature_index_offset = 2,
66 initval_index_offset = 3,
67 low_packed_offset = 4,
68 high_packed_offset = 5,
69 field_slots = 6
70 };
71
72 private:
73 u2 _shorts[field_slots];
74
75 void set_name_index(u2 val) { _shorts[name_index_offset] = val; }
76 void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; }
77 void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; }
78
79 u2 name_index() const { return _shorts[name_index_offset]; }
80 u2 signature_index() const { return _shorts[signature_index_offset]; }
81 u2 initval_index() const { return _shorts[initval_index_offset]; }
82
83 public:
84 static FieldInfo* from_field_array(Array<u2>* fields, int index) {
85 return ((FieldInfo*)fields->adr_at(index * field_slots));
86 }
87 static FieldInfo* from_field_array(u2* fields, int index) {
88 return ((FieldInfo*)(fields + index * field_slots));
89 }
90
91 void initialize(u2 access_flags,
92 u2 name_index,
93 u2 signature_index,
94 u2 initval_index) {
95 _shorts[access_flags_offset] = access_flags;
96 _shorts[name_index_offset] = name_index;
97 _shorts[signature_index_offset] = signature_index;
98 _shorts[initval_index_offset] = initval_index;
99 _shorts[low_packed_offset] = 0;
100 _shorts[high_packed_offset] = 0;
101 }
102
103 u2 access_flags() const { return _shorts[access_flags_offset]; }
104 u4 offset() const {
105 u2 lo = _shorts[low_packed_offset];
106 switch(lo & FIELDINFO_TAG_MASK) {
107 case FIELDINFO_TAG_OFFSET:
108 return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE;
109#ifndef PRODUCT
110 case FIELDINFO_TAG_TYPE_PLAIN:
111 fatal("Asking offset for the plain type field");
112 case FIELDINFO_TAG_TYPE_CONTENDED:
113 fatal("Asking offset for the contended type field");
114 case FIELDINFO_TAG_BLANK:
115 fatal("Asking offset for the blank field");
116#endif
117 }
118 ShouldNotReachHere();
119 return 0;
120 }
121
122 bool is_contended() const {
123 u2 lo = _shorts[low_packed_offset];
124 switch(lo & FIELDINFO_TAG_MASK) {
125 case FIELDINFO_TAG_TYPE_PLAIN:
126 return false;
127 case FIELDINFO_TAG_TYPE_CONTENDED:
128 return true;
129#ifndef PRODUCT
130 case FIELDINFO_TAG_OFFSET:
131 fatal("Asking contended flag for the field with offset");
132 case FIELDINFO_TAG_BLANK:
133 fatal("Asking contended flag for the blank field");
134#endif
135 }
136 ShouldNotReachHere();
137 return false;
138 }
139
140 u2 contended_group() const {
141 u2 lo = _shorts[low_packed_offset];
142 switch(lo & FIELDINFO_TAG_MASK) {
143 case FIELDINFO_TAG_TYPE_PLAIN:
144 return 0;
145 case FIELDINFO_TAG_TYPE_CONTENDED:
146 return _shorts[high_packed_offset];
147#ifndef PRODUCT
148 case FIELDINFO_TAG_OFFSET:
149 fatal("Asking the contended group for the field with offset");
150 case FIELDINFO_TAG_BLANK:
151 fatal("Asking the contended group for the blank field");
152#endif
153 }
154 ShouldNotReachHere();
155 return 0;
156 }
157
158 u2 allocation_type() const {
159 u2 lo = _shorts[low_packed_offset];
160 switch(lo & FIELDINFO_TAG_MASK) {
161 case FIELDINFO_TAG_TYPE_PLAIN:
162 case FIELDINFO_TAG_TYPE_CONTENDED:
163 return (lo >> FIELDINFO_TAG_SIZE);
164#ifndef PRODUCT
165 case FIELDINFO_TAG_OFFSET:
166 fatal("Asking the field type for field with offset");
167 case FIELDINFO_TAG_BLANK:
168 fatal("Asking the field type for the blank field");
169#endif
170 }
171 ShouldNotReachHere();
172 return 0;
173 }
174
175 bool is_offset_set() const {
176 return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET;
177 }
178
179 Symbol* name(const constantPoolHandle& cp) const {
180 int index = name_index();
181 if (is_internal()) {
182 return lookup_symbol(index);
183 }
184 return cp->symbol_at(index);
185 }
186
187 Symbol* signature(const constantPoolHandle& cp) const {
188 int index = signature_index();
189 if (is_internal()) {
190 return lookup_symbol(index);
191 }
192 return cp->symbol_at(index);
193 }
194
195 void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; }
196 void set_offset(u4 val) {
197 val = val << FIELDINFO_TAG_SIZE; // make room for tag
198 _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET;
199 _shorts[high_packed_offset] = extract_high_short_from_int(val);
200 }
201
202 void set_allocation_type(int type) {
203 u2 lo = _shorts[low_packed_offset];
204 switch(lo & FIELDINFO_TAG_MASK) {
205 case FIELDINFO_TAG_BLANK:
206 _shorts[low_packed_offset] = ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF;
207 _shorts[low_packed_offset] &= ~FIELDINFO_TAG_MASK;
208 _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN;
209 return;
210#ifndef PRODUCT
211 case FIELDINFO_TAG_TYPE_PLAIN:
212 case FIELDINFO_TAG_TYPE_CONTENDED:
213 case FIELDINFO_TAG_OFFSET:
214 fatal("Setting the field type with overwriting");
215#endif
216 }
217 ShouldNotReachHere();
218 }
219
220 void set_contended_group(u2 val) {
221 u2 lo = _shorts[low_packed_offset];
222 switch(lo & FIELDINFO_TAG_MASK) {
223 case FIELDINFO_TAG_TYPE_PLAIN:
224 _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED;
225 _shorts[high_packed_offset] = val;
226 return;
227#ifndef PRODUCT
228 case FIELDINFO_TAG_TYPE_CONTENDED:
229 fatal("Overwriting contended group");
230 case FIELDINFO_TAG_BLANK:
231 fatal("Setting contended group for the blank field");
232 case FIELDINFO_TAG_OFFSET:
233 fatal("Setting contended group for field with offset");
234#endif
235 }
236 ShouldNotReachHere();
237 }
238
239 bool is_internal() const {
240 return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0;
241 }
242
243 bool is_stable() const {
244 return (access_flags() & JVM_ACC_FIELD_STABLE) != 0;
245 }
246 void set_stable(bool z) {
247 if (z) _shorts[access_flags_offset] |= JVM_ACC_FIELD_STABLE;
248 else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE;
249 }
250
251 Symbol* lookup_symbol(int symbol_index) const {
252 assert(is_internal(), "only internal fields");
253 return vmSymbols::symbol_at((vmSymbols::SID)symbol_index);
254 }
255};
256
257#endif // SHARE_OOPS_FIELDINFO_HPP
258