229 } |
229 } |
230 mem = mem->in(MemNode::Memory); |
230 mem = mem->in(MemNode::Memory); |
231 } else { |
231 } else { |
232 return mem; |
232 return mem; |
233 } |
233 } |
234 if (mem == orig_mem) |
234 assert(mem != orig_mem, "dead memory loop"); |
235 return mem; |
|
236 } |
235 } |
237 } |
236 } |
238 |
237 |
239 // |
238 // |
240 // Given a Memory Phi, compute a value Phi containing the values from stores |
239 // Given a Memory Phi, compute a value Phi containing the values from stores |
241 // on the input paths. |
240 // on the input paths. |
242 // Note: this function is recursive, its depth is limied by the "level" argument |
241 // Note: this function is recursive, its depth is limied by the "level" argument |
243 // Returns the computed Phi, or NULL if it cannot compute it. |
242 // Returns the computed Phi, or NULL if it cannot compute it. |
244 Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, int level) { |
243 Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) { |
245 |
244 assert(mem->is_Phi(), "sanity"); |
246 if (level <= 0) { |
|
247 return NULL; |
|
248 } |
|
249 int alias_idx = C->get_alias_index(adr_t); |
245 int alias_idx = C->get_alias_index(adr_t); |
250 int offset = adr_t->offset(); |
246 int offset = adr_t->offset(); |
251 int instance_id = adr_t->instance_id(); |
247 int instance_id = adr_t->instance_id(); |
252 |
248 |
|
249 // Check if an appropriate value phi already exists. |
|
250 Node* region = mem->in(0); |
|
251 for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { |
|
252 Node* phi = region->fast_out(k); |
|
253 if (phi->is_Phi() && phi != mem && |
|
254 phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { |
|
255 return phi; |
|
256 } |
|
257 } |
|
258 // Check if an appropriate new value phi already exists. |
|
259 Node* new_phi = NULL; |
|
260 uint size = value_phis->size(); |
|
261 for (uint i=0; i < size; i++) { |
|
262 if ( mem->_idx == value_phis->index_at(i) ) { |
|
263 return value_phis->node_at(i); |
|
264 } |
|
265 } |
|
266 |
|
267 if (level <= 0) { |
|
268 return NULL; |
|
269 } |
253 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
270 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
254 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
271 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
255 |
272 |
256 uint length = mem->req(); |
273 uint length = mem->req(); |
257 GrowableArray <Node *> values(length, length, NULL); |
274 GrowableArray <Node *> values(length, length, NULL); |
|
275 |
|
276 // create a new Phi for the value |
|
277 PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); |
|
278 transform_later(phi); |
|
279 value_phis->push(phi, mem->_idx); |
258 |
280 |
259 for (uint j = 1; j < length; j++) { |
281 for (uint j = 1; j < length; j++) { |
260 Node *in = mem->in(j); |
282 Node *in = mem->in(j); |
261 if (in == NULL || in->is_top()) { |
283 if (in == NULL || in->is_top()) { |
262 values.at_put(j, in); |
284 values.at_put(j, in); |
278 } else if (val->is_Store()) { |
300 } else if (val->is_Store()) { |
279 values.at_put(j, val->in(MemNode::ValueIn)); |
301 values.at_put(j, val->in(MemNode::ValueIn)); |
280 } else if(val->is_Proj() && val->in(0) == alloc) { |
302 } else if(val->is_Proj() && val->in(0) == alloc) { |
281 values.at_put(j, _igvn.zerocon(ft)); |
303 values.at_put(j, _igvn.zerocon(ft)); |
282 } else if (val->is_Phi()) { |
304 } else if (val->is_Phi()) { |
283 // Check if an appropriate node already exists. |
305 val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1); |
284 Node* region = val->in(0); |
306 if (val == NULL) { |
285 Node* old_phi = NULL; |
307 return NULL; |
286 for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { |
308 } |
287 Node* phi = region->fast_out(k); |
309 values.at_put(j, val); |
288 if (phi->is_Phi() && phi != val && |
|
289 phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { |
|
290 old_phi = phi; |
|
291 break; |
|
292 } |
|
293 } |
|
294 if (old_phi == NULL) { |
|
295 val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, level-1); |
|
296 if (val == NULL) { |
|
297 return NULL; |
|
298 } |
|
299 values.at_put(j, val); |
|
300 } else { |
|
301 values.at_put(j, old_phi); |
|
302 } |
|
303 } else { |
310 } else { |
304 return NULL; // unknown node on this path |
311 return NULL; // unknown node on this path |
305 } |
312 } |
306 } |
313 } |
307 } |
314 } |
308 // create a new Phi for the value |
315 // Set Phi's inputs |
309 PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); |
|
310 for (uint j = 1; j < length; j++) { |
316 for (uint j = 1; j < length; j++) { |
311 if (values.at(j) == mem) { |
317 if (values.at(j) == mem) { |
312 phi->init_req(j, phi); |
318 phi->init_req(j, phi); |
313 } else { |
319 } else { |
314 phi->init_req(j, values.at(j)); |
320 phi->init_req(j, values.at(j)); |
315 } |
321 } |
316 } |
322 } |
317 transform_later(phi); |
|
318 return phi; |
323 return phi; |
319 } |
324 } |
320 |
325 |
321 // Search the last value stored into the object's field. |
326 // Search the last value stored into the object's field. |
322 Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc) { |
327 Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc) { |
327 int alias_idx = C->get_alias_index(adr_t); |
332 int alias_idx = C->get_alias_index(adr_t); |
328 int offset = adr_t->offset(); |
333 int offset = adr_t->offset(); |
329 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
334 Node *start_mem = C->start()->proj_out(TypeFunc::Memory); |
330 Node *alloc_ctrl = alloc->in(TypeFunc::Control); |
335 Node *alloc_ctrl = alloc->in(TypeFunc::Control); |
331 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
336 Node *alloc_mem = alloc->in(TypeFunc::Memory); |
332 VectorSet visited(Thread::current()->resource_area()); |
337 Arena *a = Thread::current()->resource_area(); |
|
338 VectorSet visited(a); |
333 |
339 |
334 |
340 |
335 bool done = sfpt_mem == alloc_mem; |
341 bool done = sfpt_mem == alloc_mem; |
336 Node *mem = sfpt_mem; |
342 Node *mem = sfpt_mem; |
337 while (!done) { |
343 while (!done) { |
387 return _igvn.zerocon(ft); |
393 return _igvn.zerocon(ft); |
388 } else if (mem->is_Store()) { |
394 } else if (mem->is_Store()) { |
389 return mem->in(MemNode::ValueIn); |
395 return mem->in(MemNode::ValueIn); |
390 } else if (mem->is_Phi()) { |
396 } else if (mem->is_Phi()) { |
391 // attempt to produce a Phi reflecting the values on the input paths of the Phi |
397 // attempt to produce a Phi reflecting the values on the input paths of the Phi |
392 Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, 8); |
398 Node_Stack value_phis(a, 8); |
|
399 Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, 8); |
393 if (phi != NULL) { |
400 if (phi != NULL) { |
394 return phi; |
401 return phi; |
|
402 } else { |
|
403 // Kill all new Phis |
|
404 while(value_phis.is_nonempty()) { |
|
405 Node* n = value_phis.node(); |
|
406 _igvn.hash_delete(n); |
|
407 _igvn.subsume_node(n, C->top()); |
|
408 value_phis.pop(); |
|
409 } |
395 } |
410 } |
396 } |
411 } |
397 } |
412 } |
398 // Something go wrong. |
413 // Something go wrong. |
399 return NULL; |
414 return NULL; |