Mercurial > hg > truffle
annotate src/share/vm/oops/cpCacheOop.hpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.
Reviewed-by: apetrusenko, jcoomes
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | d1605aabd0a1 |
children | 9a25e0c45327 |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. |
0 | 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 // A ConstantPoolCacheEntry describes an individual entry of the constant | |
26 // pool cache. There's 2 principal kinds of entries: field entries for in- | |
27 // stance & static field access, and method entries for invokes. Some of | |
28 // the entry layout is shared and looks as follows: | |
29 // | |
30 // bit number |31 0| | |
31 // bit length |-8--|-8--|---16----| | |
32 // -------------------------------- | |
33 // _indices [ b2 | b1 | index ] | |
34 // _f1 [ entry specific ] | |
35 // _f2 [ entry specific ] | |
36 // _flags [t|f|vf|v|m|h|unused|field_index] (for field entries) | |
37 // bit length |4|1|1 |1|1|0|---7--|----16-----] | |
38 // _flags [t|f|vf|v|m|h|unused|eidx|psze] (for method entries) | |
39 // bit length |4|1|1 |1|1|1|---7--|-8--|-8--] | |
40 | |
41 // -------------------------------- | |
42 // | |
43 // with: | |
44 // index = original constant pool index | |
45 // b1 = bytecode 1 | |
46 // b2 = bytecode 2 | |
47 // psze = parameters size (method entries only) | |
48 // eidx = interpreter entry index (method entries only) | |
49 // field_index = index into field information in holder instanceKlass | |
50 // The index max is 0xffff (max number of fields in constant pool) | |
51 // and is multiplied by (instanceKlass::next_offset) when accessing. | |
52 // t = TosState (see below) | |
53 // f = field is marked final (see below) | |
54 // vf = virtual, final (method entries only : is_vfinal()) | |
55 // v = field is volatile (see below) | |
56 // m = invokeinterface used for method in class Object (see below) | |
57 // h = RedefineClasses/Hotswap bit (see below) | |
58 // | |
59 // The flags after TosState have the following interpretation: | |
60 // bit 27: f flag true if field is marked final | |
61 // bit 26: vf flag true if virtual final method | |
62 // bit 25: v flag true if field is volatile (only for fields) | |
63 // bit 24: m flag true if invokeinterface used for method in class Object | |
64 // bit 23: 0 for fields, 1 for methods | |
65 // | |
66 // The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the | |
67 // following mapping to the TosState states: | |
68 // | |
69 // btos: 0 | |
70 // ctos: 1 | |
71 // stos: 2 | |
72 // itos: 3 | |
73 // ltos: 4 | |
74 // ftos: 5 | |
75 // dtos: 6 | |
76 // atos: 7 | |
77 // vtos: 8 | |
78 // | |
79 // Entry specific: field entries: | |
80 // _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index | |
81 // _f1 = field holder | |
82 // _f2 = field offset in words | |
83 // _flags = field type information, original field index in field holder | |
84 // (field_index section) | |
85 // | |
86 // Entry specific: method entries: | |
87 // _indices = invoke code for f1 (b1 section), invoke code for f2 (b2 section), | |
88 // original constant pool index | |
89 // _f1 = method for all but virtual calls, unused by virtual calls | |
90 // (note: for interface calls, which are essentially virtual, | |
91 // contains klassOop for the corresponding interface. | |
92 // _f2 = method/vtable index for virtual calls only, unused by all other | |
93 // calls. The vf flag indicates this is a method pointer not an | |
94 // index. | |
95 // _flags = field type info (f section), | |
96 // virtual final entry (vf), | |
97 // interpreter entry index (eidx section), | |
98 // parameter size (psze section) | |
99 // | |
100 // Note: invokevirtual & invokespecial bytecodes can share the same constant | |
101 // pool entry and thus the same constant pool cache entry. All invoke | |
102 // bytecodes but invokevirtual use only _f1 and the corresponding b1 | |
103 // bytecode, while invokevirtual uses only _f2 and the corresponding | |
104 // b2 bytecode. The value of _flags is shared for both types of entries. | |
105 // | |
106 // The fields are volatile so that they are stored in the order written in the | |
107 // source code. The _indices field with the bytecode must be written last. | |
108 | |
109 class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { | |
110 friend class VMStructs; | |
111 private: | |
112 volatile intx _indices; // constant pool index & rewrite bytecodes | |
113 volatile oop _f1; // entry specific oop field | |
114 volatile intx _f2; // entry specific int/oop field | |
115 volatile intx _flags; // flags | |
116 | |
117 | |
118 #ifdef ASSERT | |
119 bool same_methodOop(oop cur_f1, oop f1); | |
120 #endif | |
121 | |
122 void set_bytecode_1(Bytecodes::Code code); | |
123 void set_bytecode_2(Bytecodes::Code code); | |
124 void set_f1(oop f1) { | |
125 oop existing_f1 = _f1; // read once | |
126 assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); | |
127 oop_store(&_f1, f1); | |
128 } | |
129 void set_f2(intx f2) { assert(_f2 == 0 || _f2 == f2, "illegal field change"); _f2 = f2; } | |
130 int as_flags(TosState state, bool is_final, bool is_vfinal, bool is_volatile, | |
131 bool is_method_interface, bool is_method); | |
132 void set_flags(intx flags) { _flags = flags; } | |
133 | |
134 public: | |
135 // specific bit values in flag field | |
136 // Note: the interpreter knows this layout! | |
137 enum FlagBitValues { | |
138 hotSwapBit = 23, | |
139 methodInterface = 24, | |
140 volatileField = 25, | |
141 vfinalMethod = 26, | |
142 finalField = 27 | |
143 }; | |
144 | |
145 enum { field_index_mask = 0xFFFF }; | |
146 | |
147 // start of type bits in flags | |
148 // Note: the interpreter knows this layout! | |
149 enum FlagValues { | |
150 tosBits = 28 | |
151 }; | |
152 | |
153 // Initialization | |
154 void set_initial_state(int index); // sets entry to initial state | |
155 | |
156 void set_field( // sets entry to resolved field state | |
157 Bytecodes::Code get_code, // the bytecode used for reading the field | |
158 Bytecodes::Code put_code, // the bytecode used for writing the field | |
159 KlassHandle field_holder, // the object/klass holding the field | |
160 int orig_field_index, // the original field index in the field holder | |
161 int field_offset, // the field offset in words in the field holder | |
162 TosState field_type, // the (machine) field type | |
163 bool is_final, // the field is final | |
164 bool is_volatile // the field is volatile | |
165 ); | |
166 | |
167 void set_method( // sets entry to resolved method entry | |
168 Bytecodes::Code invoke_code, // the bytecode used for invoking the method | |
169 methodHandle method, // the method/prototype if any (NULL, otherwise) | |
170 int vtable_index // the vtable index if any, else negative | |
171 ); | |
172 | |
173 void set_interface_call( | |
174 methodHandle method, // Resolved method | |
175 int index // Method index into interface | |
176 ); | |
177 | |
178 void set_parameter_size(int value) { | |
179 assert(parameter_size() == 0 || parameter_size() == value, | |
180 "size must not change"); | |
181 // Setting the parameter size by itself is only safe if the | |
182 // current value of _flags is 0, otherwise another thread may have | |
183 // updated it and we don't want to overwrite that value. Don't | |
184 // bother trying to update it once it's nonzero but always make | |
185 // sure that the final parameter size agrees with what was passed. | |
186 if (_flags == 0) { | |
187 Atomic::cmpxchg_ptr((value & 0xFF), &_flags, 0); | |
188 } | |
189 guarantee(parameter_size() == value, "size must not change"); | |
190 } | |
191 | |
192 // Which bytecode number (1 or 2) in the index field is valid for this bytecode? | |
193 // Returns -1 if neither is valid. | |
194 static int bytecode_number(Bytecodes::Code code) { | |
195 switch (code) { | |
196 case Bytecodes::_getstatic : // fall through | |
197 case Bytecodes::_getfield : // fall through | |
198 case Bytecodes::_invokespecial : // fall through | |
199 case Bytecodes::_invokestatic : // fall through | |
200 case Bytecodes::_invokeinterface : return 1; | |
201 case Bytecodes::_putstatic : // fall through | |
202 case Bytecodes::_putfield : // fall through | |
203 case Bytecodes::_invokevirtual : return 2; | |
204 default : break; | |
205 } | |
206 return -1; | |
207 } | |
208 | |
209 // Has this bytecode been resolved? Only valid for invokes and get/put field/static. | |
210 bool is_resolved(Bytecodes::Code code) const { | |
211 switch (bytecode_number(code)) { | |
212 case 1: return (bytecode_1() == code); | |
213 case 2: return (bytecode_2() == code); | |
214 } | |
215 return false; // default: not resolved | |
216 } | |
217 | |
218 // Accessors | |
219 int constant_pool_index() const { return _indices & 0xFFFF; } | |
220 Bytecodes::Code bytecode_1() const { return Bytecodes::cast((_indices >> 16) & 0xFF); } | |
221 Bytecodes::Code bytecode_2() const { return Bytecodes::cast((_indices >> 24) & 0xFF); } | |
222 volatile oop f1() const { return _f1; } | |
223 intx f2() const { return _f2; } | |
224 int field_index() const; | |
225 int parameter_size() const { return _flags & 0xFF; } | |
226 bool is_vfinal() const { return ((_flags & (1 << vfinalMethod)) == (1 << vfinalMethod)); } | |
227 bool is_volatile() const { return ((_flags & (1 << volatileField)) == (1 << volatileField)); } | |
228 bool is_methodInterface() const { return ((_flags & (1 << methodInterface)) == (1 << methodInterface)); } | |
229 bool is_byte() const { return (((uintx) _flags >> tosBits) == btos); } | |
230 bool is_char() const { return (((uintx) _flags >> tosBits) == ctos); } | |
231 bool is_short() const { return (((uintx) _flags >> tosBits) == stos); } | |
232 bool is_int() const { return (((uintx) _flags >> tosBits) == itos); } | |
233 bool is_long() const { return (((uintx) _flags >> tosBits) == ltos); } | |
234 bool is_float() const { return (((uintx) _flags >> tosBits) == ftos); } | |
235 bool is_double() const { return (((uintx) _flags >> tosBits) == dtos); } | |
236 bool is_object() const { return (((uintx) _flags >> tosBits) == atos); } | |
237 TosState flag_state() const { assert( ( (_flags >> tosBits) & 0x0F ) < number_of_states, "Invalid state in as_flags"); | |
238 return (TosState)((_flags >> tosBits) & 0x0F); } | |
239 | |
240 // Code generation support | |
241 static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); } | |
242 static ByteSize indices_offset() { return byte_offset_of(ConstantPoolCacheEntry, _indices); } | |
243 static ByteSize f1_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f1); } | |
244 static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); } | |
245 static ByteSize flags_offset() { return byte_offset_of(ConstantPoolCacheEntry, _flags); } | |
246 | |
247 // GC Support | |
248 void oops_do(void f(oop*)); | |
249 void oop_iterate(OopClosure* blk); | |
250 void oop_iterate_m(OopClosure* blk, MemRegion mr); | |
251 void follow_contents(); | |
252 void adjust_pointers(); | |
253 | |
254 #ifndef SERIALGC | |
255 // Parallel Old | |
256 void follow_contents(ParCompactionManager* cm); | |
257 #endif // SERIALGC | |
258 | |
259 void update_pointers(); | |
260 void update_pointers(HeapWord* beg_addr, HeapWord* end_addr); | |
261 | |
262 // RedefineClasses() API support: | |
263 // If this constantPoolCacheEntry refers to old_method then update it | |
264 // to refer to new_method. | |
265 // trace_name_printed is set to true if the current call has | |
266 // printed the klass name so that other routines in the adjust_* | |
267 // group don't print the klass name. | |
268 bool adjust_method_entry(methodOop old_method, methodOop new_method, | |
269 bool * trace_name_printed); | |
270 bool is_interesting_method_entry(klassOop k); | |
271 bool is_field_entry() const { return (_flags & (1 << hotSwapBit)) == 0; } | |
272 bool is_method_entry() const { return (_flags & (1 << hotSwapBit)) != 0; } | |
273 | |
274 // Debugging & Printing | |
275 void print (outputStream* st, int index) const; | |
276 void verify(outputStream* st) const; | |
277 | |
278 static void verify_tosBits() { | |
279 assert(tosBits == 28, "interpreter now assumes tosBits is 28"); | |
280 } | |
281 }; | |
282 | |
283 | |
284 // A constant pool cache is a runtime data structure set aside to a constant pool. The cache | |
285 // holds interpreter runtime information for all field access and invoke bytecodes. The cache | |
286 // is created and initialized before a class is actively used (i.e., initialized), the indivi- | |
287 // dual cache entries are filled at resolution (i.e., "link") time (see also: rewriter.*). | |
288 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
289 class constantPoolCacheOopDesc: public oopDesc { |
0 | 290 friend class VMStructs; |
291 private: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
292 int _length; |
0 | 293 constantPoolOop _constant_pool; // the corresponding constant pool |
294 | |
295 // Sizing | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
296 debug_only(friend class ClassVerifier;) |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
297 int length() const { return _length; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
298 void set_length(int length) { _length = length; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
299 |
0 | 300 static int header_size() { return sizeof(constantPoolCacheOopDesc) / HeapWordSize; } |
301 static int object_size(int length) { return align_object_size(header_size() + length * in_words(ConstantPoolCacheEntry::size())); } | |
302 int object_size() { return object_size(length()); } | |
303 | |
304 // Helpers | |
305 constantPoolOop* constant_pool_addr() { return &_constant_pool; } | |
306 ConstantPoolCacheEntry* base() const { return (ConstantPoolCacheEntry*)((address)this + in_bytes(base_offset())); } | |
307 | |
308 friend class constantPoolCacheKlass; | |
309 | |
310 public: | |
311 // Initialization | |
312 void initialize(intArray& inverse_index_map); | |
313 | |
314 // Accessors | |
315 void set_constant_pool(constantPoolOop pool) { oop_store_without_check((oop*)&_constant_pool, (oop)pool); } | |
316 constantPoolOop constant_pool() const { return _constant_pool; } | |
317 ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; } | |
318 | |
319 // Code generation | |
320 static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); } | |
321 | |
322 // RedefineClasses() API support: | |
323 // If any entry of this constantPoolCache points to any of | |
324 // old_methods, replace it with the corresponding new_method. | |
325 // trace_name_printed is set to true if the current call has | |
326 // printed the klass name so that other routines in the adjust_* | |
327 // group don't print the klass name. | |
328 void adjust_method_entries(methodOop* old_methods, methodOop* new_methods, | |
329 int methods_length, bool * trace_name_printed); | |
330 }; |