192 _igvn.replace_node(st, st->in(MemNode::Memory)); |
192 _igvn.replace_node(st, st->in(MemNode::Memory)); |
193 } |
193 } |
194 } |
194 } |
195 |
195 |
196 // Search for a memory operation for the specified memory slice. |
196 // Search for a memory operation for the specified memory slice. |
197 static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc) { |
197 static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) { |
198 Node *orig_mem = mem; |
198 Node *orig_mem = mem; |
199 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
199 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
|
200 const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr(); |
200 while (true) { |
201 while (true) { |
201 if (mem == alloc_mem || mem == start_mem ) { |
202 if (mem == alloc_mem || mem == start_mem ) { |
202 return mem; // hit one of our sentinals |
203 return mem; // hit one of our sentinals |
203 } else if (mem->is_MergeMem()) { |
204 } else if (mem->is_MergeMem()) { |
204 mem = mem->as_MergeMem()->memory_at(alias_idx); |
205 mem = mem->as_MergeMem()->memory_at(alias_idx); |
206 Node *in = mem->in(0); |
207 Node *in = mem->in(0); |
207 // we can safely skip over safepoints, calls, locks and membars because we |
208 // we can safely skip over safepoints, calls, locks and membars because we |
208 // already know that the object is safe to eliminate. |
209 // already know that the object is safe to eliminate. |
209 if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) { |
210 if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) { |
210 return in; |
211 return in; |
211 } else if (in->is_Call() || in->is_MemBar()) { |
212 } else if (in->is_Call()) { |
|
213 CallNode *call = in->as_Call(); |
|
214 if (!call->may_modify(tinst, phase)) { |
|
215 mem = call->in(TypeFunc::Memory); |
|
216 } |
|
217 mem = in->in(TypeFunc::Memory); |
|
218 } else if (in->is_MemBar()) { |
212 mem = in->in(TypeFunc::Memory); |
219 mem = in->in(TypeFunc::Memory); |
213 } else { |
220 } else { |
214 assert(false, "unexpected projection"); |
221 assert(false, "unexpected projection"); |
215 } |
222 } |
216 } else if (mem->is_Store()) { |
223 } else if (mem->is_Store()) { |
281 for (uint j = 1; j < length; j++) { |
288 for (uint j = 1; j < length; j++) { |
282 Node *in = mem->in(j); |
289 Node *in = mem->in(j); |
283 if (in == NULL || in->is_top()) { |
290 if (in == NULL || in->is_top()) { |
284 values.at_put(j, in); |
291 values.at_put(j, in); |
285 } else { |
292 } else { |
286 Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc); |
293 Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc, &_igvn); |
287 if (val == start_mem || val == alloc_mem) { |
294 if (val == start_mem || val == alloc_mem) { |
288 // hit a sentinel, return appropriate 0 value |
295 // hit a sentinel, return appropriate 0 value |
289 values.at_put(j, _igvn.zerocon(ft)); |
296 values.at_put(j, _igvn.zerocon(ft)); |
290 continue; |
297 continue; |
291 } |
298 } |
342 Node *mem = sfpt_mem; |
350 Node *mem = sfpt_mem; |
343 while (!done) { |
351 while (!done) { |
344 if (visited.test_set(mem->_idx)) { |
352 if (visited.test_set(mem->_idx)) { |
345 return NULL; // found a loop, give up |
353 return NULL; // found a loop, give up |
346 } |
354 } |
347 mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc); |
355 mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc, &_igvn); |
348 if (mem == start_mem || mem == alloc_mem) { |
356 if (mem == start_mem || mem == alloc_mem) { |
349 done = true; // hit a sentinel, return appropriate 0 value |
357 done = true; // hit a sentinel, return appropriate 0 value |
350 } else if (mem->is_Initialize()) { |
358 } else if (mem->is_Initialize()) { |
351 mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn); |
359 mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn); |
352 if (mem == NULL) { |
360 if (mem == NULL) { |
366 } else if (mem->is_Phi()) { |
374 } else if (mem->is_Phi()) { |
367 // try to find a phi's unique input |
375 // try to find a phi's unique input |
368 Node *unique_input = NULL; |
376 Node *unique_input = NULL; |
369 Node *top = C->top(); |
377 Node *top = C->top(); |
370 for (uint i = 1; i < mem->req(); i++) { |
378 for (uint i = 1; i < mem->req(); i++) { |
371 Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc); |
379 Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc, &_igvn); |
372 if (n == NULL || n == top || n == mem) { |
380 if (n == NULL || n == top || n == mem) { |
373 continue; |
381 continue; |
374 } else if (unique_input == NULL) { |
382 } else if (unique_input == NULL) { |
375 unique_input = n; |
383 unique_input = n; |
376 } else if (unique_input != n) { |
384 } else if (unique_input != n) { |
394 } else if (mem->is_Store()) { |
402 } else if (mem->is_Store()) { |
395 return mem->in(MemNode::ValueIn); |
403 return mem->in(MemNode::ValueIn); |
396 } else if (mem->is_Phi()) { |
404 } else if (mem->is_Phi()) { |
397 // attempt to produce a Phi reflecting the values on the input paths of the Phi |
405 // attempt to produce a Phi reflecting the values on the input paths of the Phi |
398 Node_Stack value_phis(a, 8); |
406 Node_Stack value_phis(a, 8); |
399 Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, 8); |
407 Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit); |
400 if (phi != NULL) { |
408 if (phi != NULL) { |
401 return phi; |
409 return phi; |
402 } else { |
410 } else { |
403 // Kill all new Phis |
411 // Kill all new Phis |
404 while(value_phis.is_nonempty()) { |
412 while(value_phis.is_nonempty()) { |
461 for (DUIterator_Fast kmax, k = use->fast_outs(kmax); |
469 for (DUIterator_Fast kmax, k = use->fast_outs(kmax); |
462 k < kmax && can_eliminate; k++) { |
470 k < kmax && can_eliminate; k++) { |
463 Node* n = use->fast_out(k); |
471 Node* n = use->fast_out(k); |
464 if (!n->is_Store() && n->Opcode() != Op_CastP2X) { |
472 if (!n->is_Store() && n->Opcode() != Op_CastP2X) { |
465 DEBUG_ONLY(disq_node = n;) |
473 DEBUG_ONLY(disq_node = n;) |
466 if (n->is_Load()) { |
474 if (n->is_Load() || n->is_LoadStore()) { |
467 NOT_PRODUCT(fail_eliminate = "Field load";) |
475 NOT_PRODUCT(fail_eliminate = "Field load";) |
468 } else { |
476 } else { |
469 NOT_PRODUCT(fail_eliminate = "Not store field referrence";) |
477 NOT_PRODUCT(fail_eliminate = "Not store field referrence";) |
470 } |
478 } |
471 can_eliminate = false; |
479 can_eliminate = false; |