1 | /* |
2 | * Copyright (c) 1999, 2018, 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 "precompiled.hpp" |
26 | #include "c1/c1_Canonicalizer.hpp" |
27 | #include "c1/c1_InstructionPrinter.hpp" |
28 | #include "c1/c1_ValueStack.hpp" |
29 | #include "ci/ciArray.hpp" |
30 | #include "runtime/sharedRuntime.hpp" |
31 | |
32 | |
33 | class PrintValueVisitor: public ValueVisitor { |
34 | void visit(Value* vp) { |
35 | (*vp)->print_line(); |
36 | } |
37 | }; |
38 | |
39 | void Canonicalizer::set_canonical(Value x) { |
40 | assert(x != NULL, "value must exist" ); |
41 | // Note: we can not currently substitute root nodes which show up in |
42 | // the instruction stream (because the instruction list is embedded |
43 | // in the instructions). |
44 | if (canonical() != x) { |
45 | #ifndef PRODUCT |
46 | if (!x->has_printable_bci()) { |
47 | x->set_printable_bci(bci()); |
48 | } |
49 | #endif |
50 | if (PrintCanonicalization) { |
51 | PrintValueVisitor do_print_value; |
52 | canonical()->input_values_do(&do_print_value); |
53 | canonical()->print_line(); |
54 | tty->print_cr("canonicalized to:" ); |
55 | x->input_values_do(&do_print_value); |
56 | x->print_line(); |
57 | tty->cr(); |
58 | } |
59 | assert(_canonical->type()->tag() == x->type()->tag(), "types must match" ); |
60 | _canonical = x; |
61 | } |
62 | } |
63 | |
64 | |
65 | void Canonicalizer::move_const_to_right(Op2* x) { |
66 | if (x->x()->type()->is_constant() && x->is_commutative()) x->swap_operands(); |
67 | } |
68 | |
69 | |
70 | void Canonicalizer::do_Op2(Op2* x) { |
71 | if (x->x() == x->y()) { |
72 | switch (x->op()) { |
73 | case Bytecodes::_isub: set_constant(0); return; |
74 | case Bytecodes::_lsub: set_constant(jlong_cast(0)); return; |
75 | case Bytecodes::_iand: // fall through |
76 | case Bytecodes::_land: // fall through |
77 | case Bytecodes::_ior : // fall through |
78 | case Bytecodes::_lor : set_canonical(x->x()); return; |
79 | case Bytecodes::_ixor: set_constant(0); return; |
80 | case Bytecodes::_lxor: set_constant(jlong_cast(0)); return; |
81 | default : break; |
82 | } |
83 | } |
84 | |
85 | if (x->x()->type()->is_constant() && x->y()->type()->is_constant()) { |
86 | // do constant folding for selected operations |
87 | switch (x->type()->tag()) { |
88 | case intTag: |
89 | { jint a = x->x()->type()->as_IntConstant()->value(); |
90 | jint b = x->y()->type()->as_IntConstant()->value(); |
91 | switch (x->op()) { |
92 | case Bytecodes::_iadd: set_constant(a + b); return; |
93 | case Bytecodes::_isub: set_constant(a - b); return; |
94 | case Bytecodes::_imul: set_constant(a * b); return; |
95 | case Bytecodes::_idiv: |
96 | if (b != 0) { |
97 | if (a == min_jint && b == -1) { |
98 | set_constant(min_jint); |
99 | } else { |
100 | set_constant(a / b); |
101 | } |
102 | return; |
103 | } |
104 | break; |
105 | case Bytecodes::_irem: |
106 | if (b != 0) { |
107 | if (a == min_jint && b == -1) { |
108 | set_constant(0); |
109 | } else { |
110 | set_constant(a % b); |
111 | } |
112 | return; |
113 | } |
114 | break; |
115 | case Bytecodes::_iand: set_constant(a & b); return; |
116 | case Bytecodes::_ior : set_constant(a | b); return; |
117 | case Bytecodes::_ixor: set_constant(a ^ b); return; |
118 | default : break; |
119 | } |
120 | } |
121 | break; |
122 | case longTag: |
123 | { jlong a = x->x()->type()->as_LongConstant()->value(); |
124 | jlong b = x->y()->type()->as_LongConstant()->value(); |
125 | switch (x->op()) { |
126 | case Bytecodes::_ladd: set_constant(a + b); return; |
127 | case Bytecodes::_lsub: set_constant(a - b); return; |
128 | case Bytecodes::_lmul: set_constant(a * b); return; |
129 | case Bytecodes::_ldiv: |
130 | if (b != 0) { |
131 | set_constant(SharedRuntime::ldiv(b, a)); |
132 | return; |
133 | } |
134 | break; |
135 | case Bytecodes::_lrem: |
136 | if (b != 0) { |
137 | set_constant(SharedRuntime::lrem(b, a)); |
138 | return; |
139 | } |
140 | break; |
141 | case Bytecodes::_land: set_constant(a & b); return; |
142 | case Bytecodes::_lor : set_constant(a | b); return; |
143 | case Bytecodes::_lxor: set_constant(a ^ b); return; |
144 | default : break; |
145 | } |
146 | } |
147 | break; |
148 | default: |
149 | // other cases not implemented (must be extremely careful with floats & doubles!) |
150 | break; |
151 | } |
152 | } |
153 | // make sure constant is on the right side, if any |
154 | move_const_to_right(x); |
155 | |
156 | if (x->y()->type()->is_constant()) { |
157 | // do constant folding for selected operations |
158 | switch (x->type()->tag()) { |
159 | case intTag: |
160 | if (x->y()->type()->as_IntConstant()->value() == 0) { |
161 | switch (x->op()) { |
162 | case Bytecodes::_iadd: set_canonical(x->x()); return; |
163 | case Bytecodes::_isub: set_canonical(x->x()); return; |
164 | case Bytecodes::_imul: set_constant(0); return; |
165 | // Note: for div and rem, make sure that C semantics |
166 | // corresponds to Java semantics! |
167 | case Bytecodes::_iand: set_constant(0); return; |
168 | case Bytecodes::_ior : set_canonical(x->x()); return; |
169 | default : break; |
170 | } |
171 | } |
172 | break; |
173 | case longTag: |
174 | if (x->y()->type()->as_LongConstant()->value() == (jlong)0) { |
175 | switch (x->op()) { |
176 | case Bytecodes::_ladd: set_canonical(x->x()); return; |
177 | case Bytecodes::_lsub: set_canonical(x->x()); return; |
178 | case Bytecodes::_lmul: set_constant((jlong)0); return; |
179 | // Note: for div and rem, make sure that C semantics |
180 | // corresponds to Java semantics! |
181 | case Bytecodes::_land: set_constant((jlong)0); return; |
182 | case Bytecodes::_lor : set_canonical(x->x()); return; |
183 | default : break; |
184 | } |
185 | } |
186 | break; |
187 | default: |
188 | break; |
189 | } |
190 | } |
191 | } |
192 | |
193 | |
194 | void Canonicalizer::do_Phi (Phi* x) {} |
195 | void Canonicalizer::do_Constant (Constant* x) {} |
196 | void Canonicalizer::do_Local (Local* x) {} |
197 | void Canonicalizer::do_LoadField (LoadField* x) {} |
198 | |
199 | // checks if v is in the block that is currently processed by |
200 | // GraphBuilder. This is the only block that has not BlockEnd yet. |
201 | static bool in_current_block(Value v) { |
202 | int max_distance = 4; |
203 | while (max_distance > 0 && v != NULL && v->as_BlockEnd() == NULL) { |
204 | v = v->next(); |
205 | max_distance--; |
206 | } |
207 | return v == NULL; |
208 | } |
209 | |
210 | void Canonicalizer::do_StoreField (StoreField* x) { |
211 | // If a value is going to be stored into a field or array some of |
212 | // the conversions emitted by javac are unneeded because the fields |
213 | // are packed to their natural size. |
214 | Convert* conv = x->value()->as_Convert(); |
215 | if (conv) { |
216 | Value value = NULL; |
217 | BasicType type = x->field()->type()->basic_type(); |
218 | switch (conv->op()) { |
219 | case Bytecodes::_i2b: if (type == T_BYTE) value = conv->value(); break; |
220 | case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) value = conv->value(); break; |
221 | case Bytecodes::_i2c: if (type == T_CHAR || type == T_BYTE) value = conv->value(); break; |
222 | default : break; |
223 | } |
224 | // limit this optimization to current block |
225 | if (value != NULL && in_current_block(conv)) { |
226 | set_canonical(new StoreField(x->obj(), x->offset(), x->field(), value, x->is_static(), |
227 | x->state_before(), x->needs_patching())); |
228 | return; |
229 | } |
230 | } |
231 | |
232 | } |
233 | |
234 | void Canonicalizer::do_ArrayLength (ArrayLength* x) { |
235 | NewArray* na; |
236 | Constant* ct; |
237 | LoadField* lf; |
238 | |
239 | if ((na = x->array()->as_NewArray()) != NULL) { |
240 | // New arrays might have the known length. |
241 | // Do not use the Constant itself, but create a new Constant |
242 | // with same value Otherwise a Constant is live over multiple |
243 | // blocks without being registered in a state array. |
244 | Constant* length; |
245 | if (na->length() != NULL && |
246 | (length = na->length()->as_Constant()) != NULL) { |
247 | assert(length->type()->as_IntConstant() != NULL, "array length must be integer" ); |
248 | set_constant(length->type()->as_IntConstant()->value()); |
249 | } |
250 | |
251 | } else if ((ct = x->array()->as_Constant()) != NULL) { |
252 | // Constant arrays have constant lengths. |
253 | ArrayConstant* cnst = ct->type()->as_ArrayConstant(); |
254 | if (cnst != NULL) { |
255 | set_constant(cnst->value()->length()); |
256 | } |
257 | |
258 | } else if ((lf = x->array()->as_LoadField()) != NULL) { |
259 | ciField* field = lf->field(); |
260 | if (field->is_static_constant()) { |
261 | // Constant field loads are usually folded during parsing. |
262 | // But it doesn't happen with PatchALot, ScavengeRootsInCode < 2, or when |
263 | // holder class is being initialized during parsing (for static fields). |
264 | ciObject* c = field->constant_value().as_object(); |
265 | if (!c->is_null_object()) { |
266 | set_constant(c->as_array()->length()); |
267 | } |
268 | } |
269 | } |
270 | } |
271 | |
272 | void Canonicalizer::do_LoadIndexed (LoadIndexed* x) { |
273 | StableArrayConstant* array = x->array()->type()->as_StableArrayConstant(); |
274 | IntConstant* index = x->index()->type()->as_IntConstant(); |
275 | |
276 | assert(array == NULL || FoldStableValues, "not enabled" ); |
277 | |
278 | // Constant fold loads from stable arrays. |
279 | if (!x->mismatched() && array != NULL && index != NULL) { |
280 | jint idx = index->value(); |
281 | if (idx < 0 || idx >= array->value()->length()) { |
282 | // Leave the load as is. The range check will handle it. |
283 | return; |
284 | } |
285 | |
286 | ciConstant field_val = array->value()->element_value(idx); |
287 | if (!field_val.is_null_or_zero()) { |
288 | jint dimension = array->dimension(); |
289 | assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info" ); |
290 | ValueType* value = NULL; |
291 | if (dimension > 1) { |
292 | // Preserve information about the dimension for the element. |
293 | assert(field_val.as_object()->is_array(), "not an array" ); |
294 | value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1); |
295 | } else { |
296 | assert(dimension == 1, "sanity" ); |
297 | value = as_ValueType(field_val); |
298 | } |
299 | set_canonical(new Constant(value)); |
300 | } |
301 | } |
302 | } |
303 | |
304 | void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { |
305 | // If a value is going to be stored into a field or array some of |
306 | // the conversions emitted by javac are unneeded because the fields |
307 | // are packed to their natural size. |
308 | Convert* conv = x->value()->as_Convert(); |
309 | if (conv) { |
310 | Value value = NULL; |
311 | BasicType type = x->elt_type(); |
312 | switch (conv->op()) { |
313 | case Bytecodes::_i2b: if (type == T_BYTE) value = conv->value(); break; |
314 | case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) value = conv->value(); break; |
315 | case Bytecodes::_i2c: if (type == T_CHAR || type == T_BYTE) value = conv->value(); break; |
316 | default : break; |
317 | } |
318 | // limit this optimization to current block |
319 | if (value != NULL && in_current_block(conv)) { |
320 | set_canonical(new StoreIndexed(x->array(), x->index(), x->length(), |
321 | x->elt_type(), value, x->state_before(), |
322 | x->check_boolean())); |
323 | return; |
324 | } |
325 | } |
326 | } |
327 | |
328 | |
329 | void Canonicalizer::do_NegateOp(NegateOp* x) { |
330 | ValueType* t = x->x()->type(); |
331 | if (t->is_constant()) { |
332 | switch (t->tag()) { |
333 | case intTag : set_constant(-t->as_IntConstant ()->value()); return; |
334 | case longTag : set_constant(-t->as_LongConstant ()->value()); return; |
335 | case floatTag : set_constant(-t->as_FloatConstant ()->value()); return; |
336 | case doubleTag: set_constant(-t->as_DoubleConstant()->value()); return; |
337 | default : ShouldNotReachHere(); |
338 | } |
339 | } |
340 | } |
341 | |
342 | |
343 | void Canonicalizer::do_ArithmeticOp (ArithmeticOp* x) { do_Op2(x); } |
344 | |
345 | |
346 | void Canonicalizer::do_ShiftOp (ShiftOp* x) { |
347 | ValueType* t = x->x()->type(); |
348 | ValueType* t2 = x->y()->type(); |
349 | if (t->is_constant()) { |
350 | switch (t->tag()) { |
351 | case intTag : if (t->as_IntConstant()->value() == 0) { set_constant(0); return; } break; |
352 | case longTag : if (t->as_LongConstant()->value() == (jlong)0) { set_constant(jlong_cast(0)); return; } break; |
353 | default : ShouldNotReachHere(); |
354 | } |
355 | if (t2->is_constant()) { |
356 | if (t->tag() == intTag) { |
357 | int value = t->as_IntConstant()->value(); |
358 | int shift = t2->as_IntConstant()->value() & 31; |
359 | jint mask = ~(~0 << (32 - shift)); |
360 | if (shift == 0) mask = ~0; |
361 | switch (x->op()) { |
362 | case Bytecodes::_ishl: set_constant(value << shift); return; |
363 | case Bytecodes::_ishr: set_constant(value >> shift); return; |
364 | case Bytecodes::_iushr: set_constant((value >> shift) & mask); return; |
365 | default: break; |
366 | } |
367 | } else if (t->tag() == longTag) { |
368 | jlong value = t->as_LongConstant()->value(); |
369 | int shift = t2->as_IntConstant()->value() & 63; |
370 | jlong mask = ~(~jlong_cast(0) << (64 - shift)); |
371 | if (shift == 0) mask = ~jlong_cast(0); |
372 | switch (x->op()) { |
373 | case Bytecodes::_lshl: set_constant(value << shift); return; |
374 | case Bytecodes::_lshr: set_constant(value >> shift); return; |
375 | case Bytecodes::_lushr: set_constant((value >> shift) & mask); return; |
376 | default: break; |
377 | } |
378 | } |
379 | } |
380 | } |
381 | if (t2->is_constant()) { |
382 | switch (t2->tag()) { |
383 | case intTag : if (t2->as_IntConstant()->value() == 0) set_canonical(x->x()); return; |
384 | case longTag : if (t2->as_LongConstant()->value() == (jlong)0) set_canonical(x->x()); return; |
385 | default : ShouldNotReachHere(); return; |
386 | } |
387 | } |
388 | } |
389 | |
390 | |
391 | void Canonicalizer::do_LogicOp (LogicOp* x) { do_Op2(x); } |
392 | void Canonicalizer::do_CompareOp (CompareOp* x) { |
393 | if (x->x() == x->y()) { |
394 | switch (x->x()->type()->tag()) { |
395 | case longTag: set_constant(0); break; |
396 | case floatTag: { |
397 | FloatConstant* fc = x->x()->type()->as_FloatConstant(); |
398 | if (fc) { |
399 | if (g_isnan(fc->value())) { |
400 | set_constant(x->op() == Bytecodes::_fcmpl ? -1 : 1); |
401 | } else { |
402 | set_constant(0); |
403 | } |
404 | } |
405 | break; |
406 | } |
407 | case doubleTag: { |
408 | DoubleConstant* dc = x->x()->type()->as_DoubleConstant(); |
409 | if (dc) { |
410 | if (g_isnan(dc->value())) { |
411 | set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1); |
412 | } else { |
413 | set_constant(0); |
414 | } |
415 | } |
416 | break; |
417 | } |
418 | default: |
419 | break; |
420 | } |
421 | } else if (x->x()->type()->is_constant() && x->y()->type()->is_constant()) { |
422 | switch (x->x()->type()->tag()) { |
423 | case longTag: { |
424 | jlong vx = x->x()->type()->as_LongConstant()->value(); |
425 | jlong vy = x->y()->type()->as_LongConstant()->value(); |
426 | if (vx == vy) |
427 | set_constant(0); |
428 | else if (vx < vy) |
429 | set_constant(-1); |
430 | else |
431 | set_constant(1); |
432 | break; |
433 | } |
434 | |
435 | case floatTag: { |
436 | float vx = x->x()->type()->as_FloatConstant()->value(); |
437 | float vy = x->y()->type()->as_FloatConstant()->value(); |
438 | if (g_isnan(vx) || g_isnan(vy)) |
439 | set_constant(x->op() == Bytecodes::_fcmpl ? -1 : 1); |
440 | else if (vx == vy) |
441 | set_constant(0); |
442 | else if (vx < vy) |
443 | set_constant(-1); |
444 | else |
445 | set_constant(1); |
446 | break; |
447 | } |
448 | |
449 | case doubleTag: { |
450 | double vx = x->x()->type()->as_DoubleConstant()->value(); |
451 | double vy = x->y()->type()->as_DoubleConstant()->value(); |
452 | if (g_isnan(vx) || g_isnan(vy)) |
453 | set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1); |
454 | else if (vx == vy) |
455 | set_constant(0); |
456 | else if (vx < vy) |
457 | set_constant(-1); |
458 | else |
459 | set_constant(1); |
460 | break; |
461 | } |
462 | |
463 | default: |
464 | break; |
465 | } |
466 | } |
467 | } |
468 | |
469 | |
470 | void Canonicalizer::do_IfInstanceOf(IfInstanceOf* x) {} |
471 | |
472 | void Canonicalizer::do_IfOp(IfOp* x) { |
473 | // Caution: do not use do_Op2(x) here for now since |
474 | // we map the condition to the op for now! |
475 | move_const_to_right(x); |
476 | } |
477 | |
478 | |
479 | void Canonicalizer::do_Intrinsic (Intrinsic* x) { |
480 | switch (x->id()) { |
481 | case vmIntrinsics::_floatToRawIntBits : { |
482 | FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant(); |
483 | if (c != NULL) { |
484 | JavaValue v; |
485 | v.set_jfloat(c->value()); |
486 | set_constant(v.get_jint()); |
487 | } |
488 | break; |
489 | } |
490 | case vmIntrinsics::_intBitsToFloat : { |
491 | IntConstant* c = x->argument_at(0)->type()->as_IntConstant(); |
492 | if (c != NULL) { |
493 | JavaValue v; |
494 | v.set_jint(c->value()); |
495 | set_constant(v.get_jfloat()); |
496 | } |
497 | break; |
498 | } |
499 | case vmIntrinsics::_doubleToRawLongBits : { |
500 | DoubleConstant* c = x->argument_at(0)->type()->as_DoubleConstant(); |
501 | if (c != NULL) { |
502 | JavaValue v; |
503 | v.set_jdouble(c->value()); |
504 | set_constant(v.get_jlong()); |
505 | } |
506 | break; |
507 | } |
508 | case vmIntrinsics::_longBitsToDouble : { |
509 | LongConstant* c = x->argument_at(0)->type()->as_LongConstant(); |
510 | if (c != NULL) { |
511 | JavaValue v; |
512 | v.set_jlong(c->value()); |
513 | set_constant(v.get_jdouble()); |
514 | } |
515 | break; |
516 | } |
517 | case vmIntrinsics::_isInstance : { |
518 | assert(x->number_of_arguments() == 2, "wrong type" ); |
519 | |
520 | InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); |
521 | if (c != NULL && !c->value()->is_null_object()) { |
522 | // ciInstance::java_mirror_type() returns non-NULL only for Java mirrors |
523 | ciType* t = c->value()->java_mirror_type(); |
524 | if (t->is_klass()) { |
525 | // substitute cls.isInstance(obj) of a constant Class into |
526 | // an InstantOf instruction |
527 | InstanceOf* i = new InstanceOf(t->as_klass(), x->argument_at(1), x->state_before()); |
528 | set_canonical(i); |
529 | // and try to canonicalize even further |
530 | do_InstanceOf(i); |
531 | } else { |
532 | assert(t->is_primitive_type(), "should be a primitive type" ); |
533 | // cls.isInstance(obj) always returns false for primitive classes |
534 | set_constant(0); |
535 | } |
536 | } |
537 | break; |
538 | } |
539 | case vmIntrinsics::_isPrimitive : { |
540 | assert(x->number_of_arguments() == 1, "wrong type" ); |
541 | |
542 | // Class.isPrimitive is known on constant classes: |
543 | InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); |
544 | if (c != NULL && !c->value()->is_null_object()) { |
545 | ciType* t = c->value()->java_mirror_type(); |
546 | set_constant(t->is_primitive_type()); |
547 | } |
548 | break; |
549 | } |
550 | default: |
551 | break; |
552 | } |
553 | } |
554 | |
555 | void Canonicalizer::do_Convert (Convert* x) { |
556 | if (x->value()->type()->is_constant()) { |
557 | switch (x->op()) { |
558 | case Bytecodes::_i2b: set_constant((int)((x->value()->type()->as_IntConstant()->value() << 24) >> 24)); break; |
559 | case Bytecodes::_i2s: set_constant((int)((x->value()->type()->as_IntConstant()->value() << 16) >> 16)); break; |
560 | case Bytecodes::_i2c: set_constant((int)(x->value()->type()->as_IntConstant()->value() & ((1<<16)-1))); break; |
561 | case Bytecodes::_i2l: set_constant((jlong)(x->value()->type()->as_IntConstant()->value())); break; |
562 | case Bytecodes::_i2f: set_constant((float)(x->value()->type()->as_IntConstant()->value())); break; |
563 | case Bytecodes::_i2d: set_constant((double)(x->value()->type()->as_IntConstant()->value())); break; |
564 | case Bytecodes::_l2i: set_constant((int)(x->value()->type()->as_LongConstant()->value())); break; |
565 | case Bytecodes::_l2f: set_constant(SharedRuntime::l2f(x->value()->type()->as_LongConstant()->value())); break; |
566 | case Bytecodes::_l2d: set_constant(SharedRuntime::l2d(x->value()->type()->as_LongConstant()->value())); break; |
567 | case Bytecodes::_f2d: set_constant((double)(x->value()->type()->as_FloatConstant()->value())); break; |
568 | case Bytecodes::_f2i: set_constant(SharedRuntime::f2i(x->value()->type()->as_FloatConstant()->value())); break; |
569 | case Bytecodes::_f2l: set_constant(SharedRuntime::f2l(x->value()->type()->as_FloatConstant()->value())); break; |
570 | case Bytecodes::_d2f: set_constant((float)(x->value()->type()->as_DoubleConstant()->value())); break; |
571 | case Bytecodes::_d2i: set_constant(SharedRuntime::d2i(x->value()->type()->as_DoubleConstant()->value())); break; |
572 | case Bytecodes::_d2l: set_constant(SharedRuntime::d2l(x->value()->type()->as_DoubleConstant()->value())); break; |
573 | default: |
574 | ShouldNotReachHere(); |
575 | } |
576 | } |
577 | |
578 | Value value = x->value(); |
579 | BasicType type = T_ILLEGAL; |
580 | LoadField* lf = value->as_LoadField(); |
581 | if (lf) { |
582 | type = lf->field_type(); |
583 | } else { |
584 | LoadIndexed* li = value->as_LoadIndexed(); |
585 | if (li) { |
586 | type = li->elt_type(); |
587 | } else { |
588 | Convert* conv = value->as_Convert(); |
589 | if (conv) { |
590 | switch (conv->op()) { |
591 | case Bytecodes::_i2b: type = T_BYTE; break; |
592 | case Bytecodes::_i2s: type = T_SHORT; break; |
593 | case Bytecodes::_i2c: type = T_CHAR; break; |
594 | default : break; |
595 | } |
596 | } |
597 | } |
598 | } |
599 | if (type != T_ILLEGAL) { |
600 | switch (x->op()) { |
601 | case Bytecodes::_i2b: if (type == T_BYTE) set_canonical(x->value()); break; |
602 | case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) set_canonical(x->value()); break; |
603 | case Bytecodes::_i2c: if (type == T_CHAR) set_canonical(x->value()); break; |
604 | default : break; |
605 | } |
606 | } else { |
607 | Op2* op2 = x->value()->as_Op2(); |
608 | if (op2 && op2->op() == Bytecodes::_iand && op2->y()->type()->is_constant()) { |
609 | jint safebits = 0; |
610 | jint mask = op2->y()->type()->as_IntConstant()->value(); |
611 | switch (x->op()) { |
612 | case Bytecodes::_i2b: safebits = 0x7f; break; |
613 | case Bytecodes::_i2s: safebits = 0x7fff; break; |
614 | case Bytecodes::_i2c: safebits = 0xffff; break; |
615 | default : break; |
616 | } |
617 | // When casting a masked integer to a smaller signed type, if |
618 | // the mask doesn't include the sign bit the cast isn't needed. |
619 | if (safebits && (mask & ~safebits) == 0) { |
620 | set_canonical(x->value()); |
621 | } |
622 | } |
623 | } |
624 | |
625 | } |
626 | |
627 | void Canonicalizer::do_NullCheck (NullCheck* x) { |
628 | if (x->obj()->as_NewArray() != NULL || x->obj()->as_NewInstance() != NULL) { |
629 | set_canonical(x->obj()); |
630 | } else { |
631 | Constant* con = x->obj()->as_Constant(); |
632 | if (con) { |
633 | ObjectType* c = con->type()->as_ObjectType(); |
634 | if (c && c->is_loaded()) { |
635 | ObjectConstant* oc = c->as_ObjectConstant(); |
636 | if (!oc || !oc->value()->is_null_object()) { |
637 | set_canonical(con); |
638 | } |
639 | } |
640 | } |
641 | } |
642 | } |
643 | |
644 | void Canonicalizer::do_TypeCast (TypeCast* x) {} |
645 | void Canonicalizer::do_Invoke (Invoke* x) {} |
646 | void Canonicalizer::do_NewInstance (NewInstance* x) {} |
647 | void Canonicalizer::do_NewTypeArray (NewTypeArray* x) {} |
648 | void Canonicalizer::do_NewObjectArray (NewObjectArray* x) {} |
649 | void Canonicalizer::do_NewMultiArray (NewMultiArray* x) {} |
650 | void Canonicalizer::do_CheckCast (CheckCast* x) { |
651 | if (x->klass()->is_loaded()) { |
652 | Value obj = x->obj(); |
653 | ciType* klass = obj->exact_type(); |
654 | if (klass == NULL) { |
655 | klass = obj->declared_type(); |
656 | } |
657 | if (klass != NULL && klass->is_loaded()) { |
658 | bool is_interface = klass->is_instance_klass() && |
659 | klass->as_instance_klass()->is_interface(); |
660 | // Interface casts can't be statically optimized away since verifier doesn't |
661 | // enforce interface types in bytecode. |
662 | if (!is_interface && klass->is_subtype_of(x->klass())) { |
663 | set_canonical(obj); |
664 | return; |
665 | } |
666 | } |
667 | // checkcast of null returns null |
668 | if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) { |
669 | set_canonical(obj); |
670 | } |
671 | } |
672 | } |
673 | void Canonicalizer::do_InstanceOf (InstanceOf* x) { |
674 | if (x->klass()->is_loaded()) { |
675 | Value obj = x->obj(); |
676 | ciType* exact = obj->exact_type(); |
677 | if (exact != NULL && exact->is_loaded() && (obj->as_NewInstance() || obj->as_NewArray())) { |
678 | set_constant(exact->is_subtype_of(x->klass()) ? 1 : 0); |
679 | return; |
680 | } |
681 | // instanceof null returns false |
682 | if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) { |
683 | set_constant(0); |
684 | } |
685 | } |
686 | |
687 | } |
688 | void Canonicalizer::do_MonitorEnter (MonitorEnter* x) {} |
689 | void Canonicalizer::do_MonitorExit (MonitorExit* x) {} |
690 | void Canonicalizer::do_BlockBegin (BlockBegin* x) {} |
691 | void Canonicalizer::do_Goto (Goto* x) {} |
692 | |
693 | |
694 | static bool is_true(jlong x, If::Condition cond, jlong y) { |
695 | switch (cond) { |
696 | case If::eql: return x == y; |
697 | case If::neq: return x != y; |
698 | case If::lss: return x < y; |
699 | case If::leq: return x <= y; |
700 | case If::gtr: return x > y; |
701 | case If::geq: return x >= y; |
702 | default: |
703 | ShouldNotReachHere(); |
704 | return false; |
705 | } |
706 | } |
707 | |
708 | static bool is_safepoint(BlockEnd* x, BlockBegin* sux) { |
709 | // An Instruction with multiple successors, x, is replaced by a Goto |
710 | // to a single successor, sux. Is a safepoint check needed = was the |
711 | // instruction being replaced a safepoint and the single remaining |
712 | // successor a back branch? |
713 | return x->is_safepoint() && (sux->bci() < x->state_before()->bci()); |
714 | } |
715 | |
716 | void Canonicalizer::do_If(If* x) { |
717 | // move const to right |
718 | if (x->x()->type()->is_constant()) x->swap_operands(); |
719 | // simplify |
720 | const Value l = x->x(); ValueType* lt = l->type(); |
721 | const Value r = x->y(); ValueType* rt = r->type(); |
722 | |
723 | if (l == r && !lt->is_float_kind()) { |
724 | // pattern: If (a cond a) => simplify to Goto |
725 | BlockBegin* sux = NULL; |
726 | switch (x->cond()) { |
727 | case If::eql: sux = x->sux_for(true); break; |
728 | case If::neq: sux = x->sux_for(false); break; |
729 | case If::lss: sux = x->sux_for(false); break; |
730 | case If::leq: sux = x->sux_for(true); break; |
731 | case If::gtr: sux = x->sux_for(false); break; |
732 | case If::geq: sux = x->sux_for(true); break; |
733 | default: ShouldNotReachHere(); |
734 | } |
735 | // If is a safepoint then the debug information should come from the state_before of the If. |
736 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); |
737 | return; |
738 | } |
739 | |
740 | if (lt->is_constant() && rt->is_constant()) { |
741 | if (x->x()->as_Constant() != NULL) { |
742 | // pattern: If (lc cond rc) => simplify to: Goto |
743 | BlockBegin* sux = x->x()->as_Constant()->compare(x->cond(), x->y(), |
744 | x->sux_for(true), |
745 | x->sux_for(false)); |
746 | if (sux != NULL) { |
747 | // If is a safepoint then the debug information should come from the state_before of the If. |
748 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); |
749 | } |
750 | } |
751 | } else if (rt->as_IntConstant() != NULL) { |
752 | // pattern: If (l cond rc) => investigate further |
753 | const jint rc = rt->as_IntConstant()->value(); |
754 | if (l->as_CompareOp() != NULL) { |
755 | // pattern: If ((a cmp b) cond rc) => simplify to: If (x cond y) or: Goto |
756 | CompareOp* cmp = l->as_CompareOp(); |
757 | bool unordered_is_less = cmp->op() == Bytecodes::_fcmpl || cmp->op() == Bytecodes::_dcmpl; |
758 | BlockBegin* lss_sux = x->sux_for(is_true(-1, x->cond(), rc)); // successor for a < b |
759 | BlockBegin* eql_sux = x->sux_for(is_true( 0, x->cond(), rc)); // successor for a = b |
760 | BlockBegin* gtr_sux = x->sux_for(is_true(+1, x->cond(), rc)); // successor for a > b |
761 | BlockBegin* nan_sux = unordered_is_less ? lss_sux : gtr_sux ; // successor for unordered |
762 | // Note: At this point all successors (lss_sux, eql_sux, gtr_sux, nan_sux) are |
763 | // equal to x->tsux() or x->fsux(). Furthermore, nan_sux equals either |
764 | // lss_sux or gtr_sux. |
765 | if (lss_sux == eql_sux && eql_sux == gtr_sux) { |
766 | // all successors identical => simplify to: Goto |
767 | set_canonical(new Goto(lss_sux, x->state_before(), x->is_safepoint())); |
768 | } else { |
769 | // two successors differ and two successors are the same => simplify to: If (x cmp y) |
770 | // determine new condition & successors |
771 | If::Condition cond = If::eql; |
772 | BlockBegin* tsux = NULL; |
773 | BlockBegin* fsux = NULL; |
774 | if (lss_sux == eql_sux) { cond = If::leq; tsux = lss_sux; fsux = gtr_sux; } |
775 | else if (lss_sux == gtr_sux) { cond = If::neq; tsux = lss_sux; fsux = eql_sux; } |
776 | else if (eql_sux == gtr_sux) { cond = If::geq; tsux = eql_sux; fsux = lss_sux; } |
777 | else { ShouldNotReachHere(); } |
778 | If* canon = new If(cmp->x(), cond, nan_sux == tsux, cmp->y(), tsux, fsux, cmp->state_before(), x->is_safepoint()); |
779 | if (cmp->x() == cmp->y()) { |
780 | do_If(canon); |
781 | } else { |
782 | if (compilation()->profile_branches() || compilation()->count_backedges()) { |
783 | // TODO: If profiling, leave floating point comparisons unoptimized. |
784 | // We currently do not support profiling of the unordered case. |
785 | switch(cmp->op()) { |
786 | case Bytecodes::_fcmpl: case Bytecodes::_fcmpg: |
787 | case Bytecodes::_dcmpl: case Bytecodes::_dcmpg: |
788 | set_canonical(x); |
789 | return; |
790 | default: |
791 | break; |
792 | } |
793 | } |
794 | set_bci(cmp->state_before()->bci()); |
795 | set_canonical(canon); |
796 | } |
797 | } |
798 | } else if (l->as_InstanceOf() != NULL) { |
799 | // NOTE: Code permanently disabled for now since it leaves the old InstanceOf |
800 | // instruction in the graph (it is pinned). Need to fix this at some point. |
801 | // It should also be left in the graph when generating a profiled method version or Goto |
802 | // has to know that it was an InstanceOf. |
803 | return; |
804 | // pattern: If ((obj instanceof klass) cond rc) => simplify to: IfInstanceOf or: Goto |
805 | InstanceOf* inst = l->as_InstanceOf(); |
806 | BlockBegin* is_inst_sux = x->sux_for(is_true(1, x->cond(), rc)); // successor for instanceof == 1 |
807 | BlockBegin* no_inst_sux = x->sux_for(is_true(0, x->cond(), rc)); // successor for instanceof == 0 |
808 | if (is_inst_sux == no_inst_sux && inst->is_loaded()) { |
809 | // both successors identical and klass is loaded => simplify to: Goto |
810 | set_canonical(new Goto(is_inst_sux, x->state_before(), x->is_safepoint())); |
811 | } else { |
812 | // successors differ => simplify to: IfInstanceOf |
813 | set_canonical(new IfInstanceOf(inst->klass(), inst->obj(), true, inst->state_before()->bci(), is_inst_sux, no_inst_sux)); |
814 | } |
815 | } |
816 | } else if (rt == objectNull && |
817 | (l->as_NewInstance() || l->as_NewArray() || |
818 | (l->as_Local() && l->as_Local()->is_receiver()))) { |
819 | if (x->cond() == Instruction::eql) { |
820 | BlockBegin* sux = x->fsux(); |
821 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); |
822 | } else { |
823 | assert(x->cond() == Instruction::neq, "only other valid case" ); |
824 | BlockBegin* sux = x->tsux(); |
825 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); |
826 | } |
827 | } |
828 | } |
829 | |
830 | |
831 | void Canonicalizer::do_TableSwitch(TableSwitch* x) { |
832 | if (x->tag()->type()->is_constant()) { |
833 | int v = x->tag()->type()->as_IntConstant()->value(); |
834 | BlockBegin* sux = x->default_sux(); |
835 | if (v >= x->lo_key() && v <= x->hi_key()) { |
836 | sux = x->sux_at(v - x->lo_key()); |
837 | } |
838 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); |
839 | } else if (x->number_of_sux() == 1) { |
840 | // NOTE: Code permanently disabled for now since the switch statement's |
841 | // tag expression may produce side-effects in which case it must |
842 | // be executed. |
843 | return; |
844 | // simplify to Goto |
845 | set_canonical(new Goto(x->default_sux(), x->state_before(), x->is_safepoint())); |
846 | } else if (x->number_of_sux() == 2) { |
847 | // NOTE: Code permanently disabled for now since it produces two new nodes |
848 | // (Constant & If) and the Canonicalizer cannot return them correctly |
849 | // yet. For now we copied the corresponding code directly into the |
850 | // GraphBuilder (i.e., we should never reach here). |
851 | return; |
852 | // simplify to If |
853 | assert(x->lo_key() == x->hi_key(), "keys must be the same" ); |
854 | Constant* key = new Constant(new IntConstant(x->lo_key())); |
855 | set_canonical(new If(x->tag(), If::eql, true, key, x->sux_at(0), x->default_sux(), x->state_before(), x->is_safepoint())); |
856 | } |
857 | } |
858 | |
859 | |
860 | void Canonicalizer::do_LookupSwitch(LookupSwitch* x) { |
861 | if (x->tag()->type()->is_constant()) { |
862 | int v = x->tag()->type()->as_IntConstant()->value(); |
863 | BlockBegin* sux = x->default_sux(); |
864 | for (int i = 0; i < x->length(); i++) { |
865 | if (v == x->key_at(i)) { |
866 | sux = x->sux_at(i); |
867 | } |
868 | } |
869 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); |
870 | } else if (x->number_of_sux() == 1) { |
871 | // NOTE: Code permanently disabled for now since the switch statement's |
872 | // tag expression may produce side-effects in which case it must |
873 | // be executed. |
874 | return; |
875 | // simplify to Goto |
876 | set_canonical(new Goto(x->default_sux(), x->state_before(), x->is_safepoint())); |
877 | } else if (x->number_of_sux() == 2) { |
878 | // NOTE: Code permanently disabled for now since it produces two new nodes |
879 | // (Constant & If) and the Canonicalizer cannot return them correctly |
880 | // yet. For now we copied the corresponding code directly into the |
881 | // GraphBuilder (i.e., we should never reach here). |
882 | return; |
883 | // simplify to If |
884 | assert(x->length() == 1, "length must be the same" ); |
885 | Constant* key = new Constant(new IntConstant(x->key_at(0))); |
886 | set_canonical(new If(x->tag(), If::eql, true, key, x->sux_at(0), x->default_sux(), x->state_before(), x->is_safepoint())); |
887 | } |
888 | } |
889 | |
890 | |
891 | void Canonicalizer::do_Return (Return* x) {} |
892 | void Canonicalizer::do_Throw (Throw* x) {} |
893 | void Canonicalizer::do_Base (Base* x) {} |
894 | void Canonicalizer::do_OsrEntry (OsrEntry* x) {} |
895 | void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {} |
896 | |
897 | static bool match_index_and_scale(Instruction* instr, |
898 | Instruction** index, |
899 | int* log2_scale) { |
900 | // Skip conversion ops. This works only on 32bit because of the implicit l2i that the |
901 | // unsafe performs. |
902 | #ifndef _LP64 |
903 | Convert* convert = instr->as_Convert(); |
904 | if (convert != NULL && convert->op() == Bytecodes::_i2l) { |
905 | assert(convert->value()->type() == intType, "invalid input type" ); |
906 | instr = convert->value(); |
907 | } |
908 | #endif |
909 | |
910 | ShiftOp* shift = instr->as_ShiftOp(); |
911 | if (shift != NULL) { |
912 | if (shift->op() == Bytecodes::_lshl) { |
913 | assert(shift->x()->type() == longType, "invalid input type" ); |
914 | } else { |
915 | #ifndef _LP64 |
916 | if (shift->op() == Bytecodes::_ishl) { |
917 | assert(shift->x()->type() == intType, "invalid input type" ); |
918 | } else { |
919 | return false; |
920 | } |
921 | #else |
922 | return false; |
923 | #endif |
924 | } |
925 | |
926 | |
927 | // Constant shift value? |
928 | Constant* con = shift->y()->as_Constant(); |
929 | if (con == NULL) return false; |
930 | // Well-known type and value? |
931 | IntConstant* val = con->type()->as_IntConstant(); |
932 | assert(val != NULL, "Should be an int constant" ); |
933 | |
934 | *index = shift->x(); |
935 | int tmp_scale = val->value(); |
936 | if (tmp_scale >= 0 && tmp_scale < 4) { |
937 | *log2_scale = tmp_scale; |
938 | return true; |
939 | } else { |
940 | return false; |
941 | } |
942 | } |
943 | |
944 | ArithmeticOp* arith = instr->as_ArithmeticOp(); |
945 | if (arith != NULL) { |
946 | // See if either arg is a known constant |
947 | Constant* con = arith->x()->as_Constant(); |
948 | if (con != NULL) { |
949 | *index = arith->y(); |
950 | } else { |
951 | con = arith->y()->as_Constant(); |
952 | if (con == NULL) return false; |
953 | *index = arith->x(); |
954 | } |
955 | long const_value; |
956 | // Check for integer multiply |
957 | if (arith->op() == Bytecodes::_lmul) { |
958 | assert((*index)->type() == longType, "invalid input type" ); |
959 | LongConstant* val = con->type()->as_LongConstant(); |
960 | assert(val != NULL, "expecting a long constant" ); |
961 | const_value = val->value(); |
962 | } else { |
963 | #ifndef _LP64 |
964 | if (arith->op() == Bytecodes::_imul) { |
965 | assert((*index)->type() == intType, "invalid input type" ); |
966 | IntConstant* val = con->type()->as_IntConstant(); |
967 | assert(val != NULL, "expecting an int constant" ); |
968 | const_value = val->value(); |
969 | } else { |
970 | return false; |
971 | } |
972 | #else |
973 | return false; |
974 | #endif |
975 | } |
976 | switch (const_value) { |
977 | case 1: *log2_scale = 0; return true; |
978 | case 2: *log2_scale = 1; return true; |
979 | case 4: *log2_scale = 2; return true; |
980 | case 8: *log2_scale = 3; return true; |
981 | default: return false; |
982 | } |
983 | } |
984 | |
985 | // Unknown instruction sequence; don't touch it |
986 | return false; |
987 | } |
988 | |
989 | |
990 | static bool match(UnsafeRawOp* x, |
991 | Instruction** base, |
992 | Instruction** index, |
993 | int* log2_scale) { |
994 | ArithmeticOp* root = x->base()->as_ArithmeticOp(); |
995 | if (root == NULL) return false; |
996 | // Limit ourselves to addition for now |
997 | if (root->op() != Bytecodes::_ladd) return false; |
998 | |
999 | bool match_found = false; |
1000 | // Try to find shift or scale op |
1001 | if (match_index_and_scale(root->y(), index, log2_scale)) { |
1002 | *base = root->x(); |
1003 | match_found = true; |
1004 | } else if (match_index_and_scale(root->x(), index, log2_scale)) { |
1005 | *base = root->y(); |
1006 | match_found = true; |
1007 | } else if (NOT_LP64(root->y()->as_Convert() != NULL) LP64_ONLY(false)) { |
1008 | // Skipping i2l works only on 32bit because of the implicit l2i that the unsafe performs. |
1009 | // 64bit needs a real sign-extending conversion. |
1010 | Convert* convert = root->y()->as_Convert(); |
1011 | if (convert->op() == Bytecodes::_i2l) { |
1012 | assert(convert->value()->type() == intType, "should be an int" ); |
1013 | // pick base and index, setting scale at 1 |
1014 | *base = root->x(); |
1015 | *index = convert->value(); |
1016 | *log2_scale = 0; |
1017 | match_found = true; |
1018 | } |
1019 | } |
1020 | // The default solution |
1021 | if (!match_found) { |
1022 | *base = root->x(); |
1023 | *index = root->y(); |
1024 | *log2_scale = 0; |
1025 | } |
1026 | |
1027 | // If the value is pinned then it will be always be computed so |
1028 | // there's no profit to reshaping the expression. |
1029 | return !root->is_pinned(); |
1030 | } |
1031 | |
1032 | |
1033 | void Canonicalizer::do_UnsafeRawOp(UnsafeRawOp* x) { |
1034 | Instruction* base = NULL; |
1035 | Instruction* index = NULL; |
1036 | int log2_scale; |
1037 | |
1038 | if (match(x, &base, &index, &log2_scale)) { |
1039 | x->set_base(base); |
1040 | x->set_index(index); |
1041 | x->set_log2_scale(log2_scale); |
1042 | if (PrintUnsafeOptimization) { |
1043 | tty->print_cr("Canonicalizer: UnsafeRawOp id %d: base = id %d, index = id %d, log2_scale = %d" , |
1044 | x->id(), x->base()->id(), x->index()->id(), x->log2_scale()); |
1045 | } |
1046 | } |
1047 | } |
1048 | |
1049 | void Canonicalizer::do_RoundFP(RoundFP* x) {} |
1050 | void Canonicalizer::do_UnsafeGetRaw(UnsafeGetRaw* x) { if (OptimizeUnsafes) do_UnsafeRawOp(x); } |
1051 | void Canonicalizer::do_UnsafePutRaw(UnsafePutRaw* x) { if (OptimizeUnsafes) do_UnsafeRawOp(x); } |
1052 | void Canonicalizer::do_UnsafeGetObject(UnsafeGetObject* x) {} |
1053 | void Canonicalizer::do_UnsafePutObject(UnsafePutObject* x) {} |
1054 | void Canonicalizer::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {} |
1055 | void Canonicalizer::do_ProfileCall(ProfileCall* x) {} |
1056 | void Canonicalizer::do_ProfileReturnType(ProfileReturnType* x) {} |
1057 | void Canonicalizer::do_ProfileInvoke(ProfileInvoke* x) {} |
1058 | void Canonicalizer::do_RuntimeCall(RuntimeCall* x) {} |
1059 | void Canonicalizer::do_RangeCheckPredicate(RangeCheckPredicate* x) {} |
1060 | #ifdef ASSERT |
1061 | void Canonicalizer::do_Assert(Assert* x) {} |
1062 | #endif |
1063 | void Canonicalizer::do_MemBar(MemBar* x) {} |
1064 | |