Mercurial > hg > truffle
annotate src/share/vm/opto/vectornode.cpp @ 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 | 3b5ac9e7e6ea |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 2007-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 #include "incls/_precompiled.incl" | |
25 #include "incls/_vectornode.cpp.incl" | |
26 | |
27 //------------------------------VectorNode-------------------------------------- | |
28 | |
29 // Return vector type for an element type and vector length. | |
30 const Type* VectorNode::vect_type(BasicType elt_bt, uint len) { | |
31 assert(len <= VectorNode::max_vlen(elt_bt), "len in range"); | |
32 switch(elt_bt) { | |
33 case T_BOOLEAN: | |
34 case T_BYTE: | |
35 switch(len) { | |
36 case 2: return TypeInt::CHAR; | |
37 case 4: return TypeInt::INT; | |
38 case 8: return TypeLong::LONG; | |
39 } | |
40 break; | |
41 case T_CHAR: | |
42 case T_SHORT: | |
43 switch(len) { | |
44 case 2: return TypeInt::INT; | |
45 case 4: return TypeLong::LONG; | |
46 } | |
47 break; | |
48 case T_INT: | |
49 switch(len) { | |
50 case 2: return TypeLong::LONG; | |
51 } | |
52 break; | |
53 case T_LONG: | |
54 break; | |
55 case T_FLOAT: | |
56 switch(len) { | |
57 case 2: return Type::DOUBLE; | |
58 } | |
59 break; | |
60 case T_DOUBLE: | |
61 break; | |
62 } | |
63 ShouldNotReachHere(); | |
64 return NULL; | |
65 } | |
66 | |
67 // Scalar promotion | |
68 VectorNode* VectorNode::scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t) { | |
69 BasicType bt = opd_t->array_element_basic_type(); | |
70 assert(vlen <= VectorNode::max_vlen(bt), "vlen in range"); | |
71 switch (bt) { | |
72 case T_BOOLEAN: | |
73 case T_BYTE: | |
74 if (vlen == 16) return new (C, 2) Replicate16BNode(s); | |
75 if (vlen == 8) return new (C, 2) Replicate8BNode(s); | |
76 if (vlen == 4) return new (C, 2) Replicate4BNode(s); | |
77 break; | |
78 case T_CHAR: | |
79 if (vlen == 8) return new (C, 2) Replicate8CNode(s); | |
80 if (vlen == 4) return new (C, 2) Replicate4CNode(s); | |
81 if (vlen == 2) return new (C, 2) Replicate2CNode(s); | |
82 break; | |
83 case T_SHORT: | |
84 if (vlen == 8) return new (C, 2) Replicate8SNode(s); | |
85 if (vlen == 4) return new (C, 2) Replicate4SNode(s); | |
86 if (vlen == 2) return new (C, 2) Replicate2SNode(s); | |
87 break; | |
88 case T_INT: | |
89 if (vlen == 4) return new (C, 2) Replicate4INode(s); | |
90 if (vlen == 2) return new (C, 2) Replicate2INode(s); | |
91 break; | |
92 case T_LONG: | |
93 if (vlen == 2) return new (C, 2) Replicate2LNode(s); | |
94 break; | |
95 case T_FLOAT: | |
96 if (vlen == 4) return new (C, 2) Replicate4FNode(s); | |
97 if (vlen == 2) return new (C, 2) Replicate2FNode(s); | |
98 break; | |
99 case T_DOUBLE: | |
100 if (vlen == 2) return new (C, 2) Replicate2DNode(s); | |
101 break; | |
102 } | |
103 ShouldNotReachHere(); | |
104 return NULL; | |
105 } | |
106 | |
107 // Return initial Pack node. Additional operands added with add_opd() calls. | |
108 PackNode* PackNode::make(Compile* C, Node* s, const Type* opd_t) { | |
109 BasicType bt = opd_t->array_element_basic_type(); | |
110 switch (bt) { | |
111 case T_BOOLEAN: | |
112 case T_BYTE: | |
113 return new (C, 2) PackBNode(s); | |
114 case T_CHAR: | |
115 return new (C, 2) PackCNode(s); | |
116 case T_SHORT: | |
117 return new (C, 2) PackSNode(s); | |
118 case T_INT: | |
119 return new (C, 2) PackINode(s); | |
120 case T_LONG: | |
121 return new (C, 2) PackLNode(s); | |
122 case T_FLOAT: | |
123 return new (C, 2) PackFNode(s); | |
124 case T_DOUBLE: | |
125 return new (C, 2) PackDNode(s); | |
126 } | |
127 ShouldNotReachHere(); | |
128 return NULL; | |
129 } | |
130 | |
131 // Create a binary tree form for Packs. [lo, hi) (half-open) range | |
132 Node* PackNode::binaryTreePack(Compile* C, int lo, int hi) { | |
133 int ct = hi - lo; | |
134 assert(is_power_of_2(ct), "power of 2"); | |
135 int mid = lo + ct/2; | |
136 Node* n1 = ct == 2 ? in(lo) : binaryTreePack(C, lo, mid); | |
137 Node* n2 = ct == 2 ? in(lo+1) : binaryTreePack(C, mid, hi ); | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
138 int rslt_bsize = ct * type2aelembytes(elt_basic_type()); |
0 | 139 if (bottom_type()->is_floatingpoint()) { |
140 switch (rslt_bsize) { | |
141 case 8: return new (C, 3) PackFNode(n1, n2); | |
142 case 16: return new (C, 3) PackDNode(n1, n2); | |
143 } | |
144 } else { | |
145 assert(bottom_type()->isa_int() || bottom_type()->isa_long(), "int or long"); | |
146 switch (rslt_bsize) { | |
147 case 2: return new (C, 3) Pack2x1BNode(n1, n2); | |
148 case 4: return new (C, 3) Pack2x2BNode(n1, n2); | |
149 case 8: return new (C, 3) PackINode(n1, n2); | |
150 case 16: return new (C, 3) PackLNode(n1, n2); | |
151 } | |
152 } | |
153 ShouldNotReachHere(); | |
154 return NULL; | |
155 } | |
156 | |
157 // Return the vector operator for the specified scalar operation | |
158 // and vector length. One use is to check if the code generator | |
159 // supports the vector operation. | |
160 int VectorNode::opcode(int sopc, uint vlen, const Type* opd_t) { | |
161 BasicType bt = opd_t->array_element_basic_type(); | |
162 if (!(is_power_of_2(vlen) && vlen <= max_vlen(bt))) | |
163 return 0; // unimplemented | |
164 switch (sopc) { | |
165 case Op_AddI: | |
166 switch (bt) { | |
167 case T_BOOLEAN: | |
168 case T_BYTE: return Op_AddVB; | |
169 case T_CHAR: return Op_AddVC; | |
170 case T_SHORT: return Op_AddVS; | |
171 case T_INT: return Op_AddVI; | |
172 } | |
173 ShouldNotReachHere(); | |
174 case Op_AddL: | |
175 assert(bt == T_LONG, "must be"); | |
176 return Op_AddVL; | |
177 case Op_AddF: | |
178 assert(bt == T_FLOAT, "must be"); | |
179 return Op_AddVF; | |
180 case Op_AddD: | |
181 assert(bt == T_DOUBLE, "must be"); | |
182 return Op_AddVD; | |
183 case Op_SubI: | |
184 switch (bt) { | |
185 case T_BOOLEAN: | |
186 case T_BYTE: return Op_SubVB; | |
187 case T_CHAR: return Op_SubVC; | |
188 case T_SHORT: return Op_SubVS; | |
189 case T_INT: return Op_SubVI; | |
190 } | |
191 ShouldNotReachHere(); | |
192 case Op_SubL: | |
193 assert(bt == T_LONG, "must be"); | |
194 return Op_SubVL; | |
195 case Op_SubF: | |
196 assert(bt == T_FLOAT, "must be"); | |
197 return Op_SubVF; | |
198 case Op_SubD: | |
199 assert(bt == T_DOUBLE, "must be"); | |
200 return Op_SubVD; | |
201 case Op_MulF: | |
202 assert(bt == T_FLOAT, "must be"); | |
203 return Op_MulVF; | |
204 case Op_MulD: | |
205 assert(bt == T_DOUBLE, "must be"); | |
206 return Op_MulVD; | |
207 case Op_DivF: | |
208 assert(bt == T_FLOAT, "must be"); | |
209 return Op_DivVF; | |
210 case Op_DivD: | |
211 assert(bt == T_DOUBLE, "must be"); | |
212 return Op_DivVD; | |
213 case Op_LShiftI: | |
214 switch (bt) { | |
215 case T_BOOLEAN: | |
216 case T_BYTE: return Op_LShiftVB; | |
217 case T_CHAR: return Op_LShiftVC; | |
218 case T_SHORT: return Op_LShiftVS; | |
219 case T_INT: return Op_LShiftVI; | |
220 } | |
221 ShouldNotReachHere(); | |
222 case Op_URShiftI: | |
223 switch (bt) { | |
224 case T_BOOLEAN: | |
225 case T_BYTE: return Op_URShiftVB; | |
226 case T_CHAR: return Op_URShiftVC; | |
227 case T_SHORT: return Op_URShiftVS; | |
228 case T_INT: return Op_URShiftVI; | |
229 } | |
230 ShouldNotReachHere(); | |
231 case Op_AndI: | |
232 case Op_AndL: | |
233 return Op_AndV; | |
234 case Op_OrI: | |
235 case Op_OrL: | |
236 return Op_OrV; | |
237 case Op_XorI: | |
238 case Op_XorL: | |
239 return Op_XorV; | |
240 | |
241 case Op_LoadB: | |
242 case Op_LoadC: | |
243 case Op_LoadS: | |
244 case Op_LoadI: | |
245 case Op_LoadL: | |
246 case Op_LoadF: | |
247 case Op_LoadD: | |
248 return VectorLoadNode::opcode(sopc, vlen); | |
249 | |
250 case Op_StoreB: | |
251 case Op_StoreC: | |
252 case Op_StoreI: | |
253 case Op_StoreL: | |
254 case Op_StoreF: | |
255 case Op_StoreD: | |
256 return VectorStoreNode::opcode(sopc, vlen); | |
257 } | |
258 return 0; // Unimplemented | |
259 } | |
260 | |
261 // Helper for above. | |
262 int VectorLoadNode::opcode(int sopc, uint vlen) { | |
263 switch (sopc) { | |
264 case Op_LoadB: | |
265 switch (vlen) { | |
266 case 2: return 0; // Unimplemented | |
267 case 4: return Op_Load4B; | |
268 case 8: return Op_Load8B; | |
269 case 16: return Op_Load16B; | |
270 } | |
271 break; | |
272 case Op_LoadC: | |
273 switch (vlen) { | |
274 case 2: return Op_Load2C; | |
275 case 4: return Op_Load4C; | |
276 case 8: return Op_Load8C; | |
277 } | |
278 break; | |
279 case Op_LoadS: | |
280 switch (vlen) { | |
281 case 2: return Op_Load2S; | |
282 case 4: return Op_Load4S; | |
283 case 8: return Op_Load8S; | |
284 } | |
285 break; | |
286 case Op_LoadI: | |
287 switch (vlen) { | |
288 case 2: return Op_Load2I; | |
289 case 4: return Op_Load4I; | |
290 } | |
291 break; | |
292 case Op_LoadL: | |
293 if (vlen == 2) return Op_Load2L; | |
294 break; | |
295 case Op_LoadF: | |
296 switch (vlen) { | |
297 case 2: return Op_Load2F; | |
298 case 4: return Op_Load4F; | |
299 } | |
300 break; | |
301 case Op_LoadD: | |
302 if (vlen == 2) return Op_Load2D; | |
303 break; | |
304 } | |
305 return 0; // Unimplemented | |
306 } | |
307 | |
308 // Helper for above | |
309 int VectorStoreNode::opcode(int sopc, uint vlen) { | |
310 switch (sopc) { | |
311 case Op_StoreB: | |
312 switch (vlen) { | |
313 case 2: return 0; // Unimplemented | |
314 case 4: return Op_Store4B; | |
315 case 8: return Op_Store8B; | |
316 case 16: return Op_Store16B; | |
317 } | |
318 break; | |
319 case Op_StoreC: | |
320 switch (vlen) { | |
321 case 2: return Op_Store2C; | |
322 case 4: return Op_Store4C; | |
323 case 8: return Op_Store8C; | |
324 } | |
325 break; | |
326 case Op_StoreI: | |
327 switch (vlen) { | |
328 case 2: return Op_Store2I; | |
329 case 4: return Op_Store4I; | |
330 } | |
331 break; | |
332 case Op_StoreL: | |
333 if (vlen == 2) return Op_Store2L; | |
334 break; | |
335 case Op_StoreF: | |
336 switch (vlen) { | |
337 case 2: return Op_Store2F; | |
338 case 4: return Op_Store4F; | |
339 } | |
340 break; | |
341 case Op_StoreD: | |
342 if (vlen == 2) return Op_Store2D; | |
343 break; | |
344 } | |
345 return 0; // Unimplemented | |
346 } | |
347 | |
348 // Return the vector version of a scalar operation node. | |
349 VectorNode* VectorNode::make(Compile* C, int sopc, Node* n1, Node* n2, uint vlen, const Type* opd_t) { | |
350 int vopc = opcode(sopc, vlen, opd_t); | |
351 | |
352 switch (vopc) { | |
353 case Op_AddVB: return new (C, 3) AddVBNode(n1, n2, vlen); | |
354 case Op_AddVC: return new (C, 3) AddVCNode(n1, n2, vlen); | |
355 case Op_AddVS: return new (C, 3) AddVSNode(n1, n2, vlen); | |
356 case Op_AddVI: return new (C, 3) AddVINode(n1, n2, vlen); | |
357 case Op_AddVL: return new (C, 3) AddVLNode(n1, n2, vlen); | |
358 case Op_AddVF: return new (C, 3) AddVFNode(n1, n2, vlen); | |
359 case Op_AddVD: return new (C, 3) AddVDNode(n1, n2, vlen); | |
360 | |
361 case Op_SubVB: return new (C, 3) SubVBNode(n1, n2, vlen); | |
362 case Op_SubVC: return new (C, 3) SubVCNode(n1, n2, vlen); | |
363 case Op_SubVS: return new (C, 3) SubVSNode(n1, n2, vlen); | |
364 case Op_SubVI: return new (C, 3) SubVINode(n1, n2, vlen); | |
365 case Op_SubVL: return new (C, 3) SubVLNode(n1, n2, vlen); | |
366 case Op_SubVF: return new (C, 3) SubVFNode(n1, n2, vlen); | |
367 case Op_SubVD: return new (C, 3) SubVDNode(n1, n2, vlen); | |
368 | |
369 case Op_MulVF: return new (C, 3) MulVFNode(n1, n2, vlen); | |
370 case Op_MulVD: return new (C, 3) MulVDNode(n1, n2, vlen); | |
371 | |
372 case Op_DivVF: return new (C, 3) DivVFNode(n1, n2, vlen); | |
373 case Op_DivVD: return new (C, 3) DivVDNode(n1, n2, vlen); | |
374 | |
375 case Op_LShiftVB: return new (C, 3) LShiftVBNode(n1, n2, vlen); | |
376 case Op_LShiftVC: return new (C, 3) LShiftVCNode(n1, n2, vlen); | |
377 case Op_LShiftVS: return new (C, 3) LShiftVSNode(n1, n2, vlen); | |
378 case Op_LShiftVI: return new (C, 3) LShiftVINode(n1, n2, vlen); | |
379 | |
380 case Op_URShiftVB: return new (C, 3) URShiftVBNode(n1, n2, vlen); | |
381 case Op_URShiftVC: return new (C, 3) URShiftVCNode(n1, n2, vlen); | |
382 case Op_URShiftVS: return new (C, 3) URShiftVSNode(n1, n2, vlen); | |
383 case Op_URShiftVI: return new (C, 3) URShiftVINode(n1, n2, vlen); | |
384 | |
385 case Op_AndV: return new (C, 3) AndVNode(n1, n2, vlen, opd_t->array_element_basic_type()); | |
386 case Op_OrV: return new (C, 3) OrVNode (n1, n2, vlen, opd_t->array_element_basic_type()); | |
387 case Op_XorV: return new (C, 3) XorVNode(n1, n2, vlen, opd_t->array_element_basic_type()); | |
388 } | |
389 ShouldNotReachHere(); | |
390 return NULL; | |
391 } | |
392 | |
393 // Return the vector version of a scalar load node. | |
394 VectorLoadNode* VectorLoadNode::make(Compile* C, int opc, Node* ctl, Node* mem, | |
395 Node* adr, const TypePtr* atyp, uint vlen) { | |
396 int vopc = opcode(opc, vlen); | |
397 | |
398 switch(vopc) { | |
399 case Op_Load16B: return new (C, 3) Load16BNode(ctl, mem, adr, atyp); | |
400 case Op_Load8B: return new (C, 3) Load8BNode(ctl, mem, adr, atyp); | |
401 case Op_Load4B: return new (C, 3) Load4BNode(ctl, mem, adr, atyp); | |
402 | |
403 case Op_Load8C: return new (C, 3) Load8CNode(ctl, mem, adr, atyp); | |
404 case Op_Load4C: return new (C, 3) Load4CNode(ctl, mem, adr, atyp); | |
405 case Op_Load2C: return new (C, 3) Load2CNode(ctl, mem, adr, atyp); | |
406 | |
407 case Op_Load8S: return new (C, 3) Load8SNode(ctl, mem, adr, atyp); | |
408 case Op_Load4S: return new (C, 3) Load4SNode(ctl, mem, adr, atyp); | |
409 case Op_Load2S: return new (C, 3) Load2SNode(ctl, mem, adr, atyp); | |
410 | |
411 case Op_Load4I: return new (C, 3) Load4INode(ctl, mem, adr, atyp); | |
412 case Op_Load2I: return new (C, 3) Load2INode(ctl, mem, adr, atyp); | |
413 | |
414 case Op_Load2L: return new (C, 3) Load2LNode(ctl, mem, adr, atyp); | |
415 | |
416 case Op_Load4F: return new (C, 3) Load4FNode(ctl, mem, adr, atyp); | |
417 case Op_Load2F: return new (C, 3) Load2FNode(ctl, mem, adr, atyp); | |
418 | |
419 case Op_Load2D: return new (C, 3) Load2DNode(ctl, mem, adr, atyp); | |
420 } | |
421 ShouldNotReachHere(); | |
422 return NULL; | |
423 } | |
424 | |
425 // Return the vector version of a scalar store node. | |
426 VectorStoreNode* VectorStoreNode::make(Compile* C, int opc, Node* ctl, Node* mem, | |
427 Node* adr, const TypePtr* atyp, VectorNode* val, | |
428 uint vlen) { | |
429 int vopc = opcode(opc, vlen); | |
430 | |
431 switch(vopc) { | |
432 case Op_Store16B: return new (C, 4) Store16BNode(ctl, mem, adr, atyp, val); | |
433 case Op_Store8B: return new (C, 4) Store8BNode(ctl, mem, adr, atyp, val); | |
434 case Op_Store4B: return new (C, 4) Store4BNode(ctl, mem, adr, atyp, val); | |
435 | |
436 case Op_Store8C: return new (C, 4) Store8CNode(ctl, mem, adr, atyp, val); | |
437 case Op_Store4C: return new (C, 4) Store4CNode(ctl, mem, adr, atyp, val); | |
438 case Op_Store2C: return new (C, 4) Store2CNode(ctl, mem, adr, atyp, val); | |
439 | |
440 case Op_Store4I: return new (C, 4) Store4INode(ctl, mem, adr, atyp, val); | |
441 case Op_Store2I: return new (C, 4) Store2INode(ctl, mem, adr, atyp, val); | |
442 | |
443 case Op_Store2L: return new (C, 4) Store2LNode(ctl, mem, adr, atyp, val); | |
444 | |
445 case Op_Store4F: return new (C, 4) Store4FNode(ctl, mem, adr, atyp, val); | |
446 case Op_Store2F: return new (C, 4) Store2FNode(ctl, mem, adr, atyp, val); | |
447 | |
448 case Op_Store2D: return new (C, 4) Store2DNode(ctl, mem, adr, atyp, val); | |
449 } | |
450 ShouldNotReachHere(); | |
451 return NULL; | |
452 } | |
453 | |
454 // Extract a scalar element of vector. | |
455 Node* ExtractNode::make(Compile* C, Node* v, uint position, const Type* opd_t) { | |
456 BasicType bt = opd_t->array_element_basic_type(); | |
457 assert(position < VectorNode::max_vlen(bt), "pos in range"); | |
458 ConINode* pos = ConINode::make(C, (int)position); | |
459 switch (bt) { | |
460 case T_BOOLEAN: | |
461 case T_BYTE: | |
462 return new (C, 3) ExtractBNode(v, pos); | |
463 case T_CHAR: | |
464 return new (C, 3) ExtractCNode(v, pos); | |
465 case T_SHORT: | |
466 return new (C, 3) ExtractSNode(v, pos); | |
467 case T_INT: | |
468 return new (C, 3) ExtractINode(v, pos); | |
469 case T_LONG: | |
470 return new (C, 3) ExtractLNode(v, pos); | |
471 case T_FLOAT: | |
472 return new (C, 3) ExtractFNode(v, pos); | |
473 case T_DOUBLE: | |
474 return new (C, 3) ExtractDNode(v, pos); | |
475 } | |
476 ShouldNotReachHere(); | |
477 return NULL; | |
478 } |