comparison src/share/vm/opto/macro.cpp @ 4767:d12a66fa3820

7123954: Some CTW test crash with SIGSEGV Summary: Correct Allocate expansion code to preserve i_o when only slow call is generated. Reviewed-by: iveresov
author kvn
date Tue, 27 Dec 2011 15:08:43 -0800
parents 1dc233a8c7fe
children 9c87bcb3b4dd
comparison
equal deleted inserted replaced
4766:40c2484c09e1 4767:d12a66fa3820
1386 result_phi_rawoop->init_req(fast_result_path, fast_oop); 1386 result_phi_rawoop->init_req(fast_result_path, fast_oop);
1387 result_phi_i_o ->init_req(fast_result_path, i_o); 1387 result_phi_i_o ->init_req(fast_result_path, i_o);
1388 result_phi_rawmem->init_req(fast_result_path, fast_oop_rawmem); 1388 result_phi_rawmem->init_req(fast_result_path, fast_oop_rawmem);
1389 } else { 1389 } else {
1390 slow_region = ctrl; 1390 slow_region = ctrl;
1391 result_phi_i_o = i_o; // Rename it to use in the following code.
1391 } 1392 }
1392 1393
1393 // Generate slow-path call 1394 // Generate slow-path call
1394 CallNode *call = new (C, slow_call_type->domain()->cnt()) 1395 CallNode *call = new (C, slow_call_type->domain()->cnt())
1395 CallStaticJavaNode(slow_call_type, slow_call_address, 1396 CallStaticJavaNode(slow_call_type, slow_call_address,
1410 // Copy debug information and adjust JVMState information, then replace 1411 // Copy debug information and adjust JVMState information, then replace
1411 // allocate node with the call 1412 // allocate node with the call
1412 copy_call_debug_info((CallNode *) alloc, call); 1413 copy_call_debug_info((CallNode *) alloc, call);
1413 if (!always_slow) { 1414 if (!always_slow) {
1414 call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. 1415 call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
1416 } else {
1417 // Hook i_o projection to avoid its elimination during allocation
1418 // replacement (when only a slow call is generated).
1419 call->set_req(TypeFunc::I_O, result_phi_i_o);
1415 } 1420 }
1416 _igvn.replace_node(alloc, call); 1421 _igvn.replace_node(alloc, call);
1417 transform_later(call); 1422 transform_later(call);
1418 1423
1419 // Identify the output projections from the allocate node and 1424 // Identify the output projections from the allocate node and
1426 // 1431 //
1427 // We are interested in the CatchProj nodes. 1432 // We are interested in the CatchProj nodes.
1428 // 1433 //
1429 extract_call_projections(call); 1434 extract_call_projections(call);
1430 1435
1431 // An allocate node has separate memory projections for the uses on the control and i_o paths 1436 // An allocate node has separate memory projections for the uses on
1432 // Replace uses of the control memory projection with result_phi_rawmem (unless we are only generating a slow call) 1437 // the control and i_o paths. Replace the control memory projection with
1438 // result_phi_rawmem (unless we are only generating a slow call when
1439 // both memory projections are combined)
1433 if (!always_slow && _memproj_fallthrough != NULL) { 1440 if (!always_slow && _memproj_fallthrough != NULL) {
1434 for (DUIterator_Fast imax, i = _memproj_fallthrough->fast_outs(imax); i < imax; i++) { 1441 for (DUIterator_Fast imax, i = _memproj_fallthrough->fast_outs(imax); i < imax; i++) {
1435 Node *use = _memproj_fallthrough->fast_out(i); 1442 Node *use = _memproj_fallthrough->fast_out(i);
1436 _igvn.hash_delete(use); 1443 _igvn.hash_delete(use);
1437 imax -= replace_input(use, _memproj_fallthrough, result_phi_rawmem); 1444 imax -= replace_input(use, _memproj_fallthrough, result_phi_rawmem);
1438 _igvn._worklist.push(use); 1445 _igvn._worklist.push(use);
1439 // back up iterator 1446 // back up iterator
1440 --i; 1447 --i;
1441 } 1448 }
1442 } 1449 }
1443 // Now change uses of _memproj_catchall to use _memproj_fallthrough and delete _memproj_catchall so 1450 // Now change uses of _memproj_catchall to use _memproj_fallthrough and delete
1444 // we end up with a call that has only 1 memory projection 1451 // _memproj_catchall so we end up with a call that has only 1 memory projection.
1445 if (_memproj_catchall != NULL ) { 1452 if (_memproj_catchall != NULL ) {
1446 if (_memproj_fallthrough == NULL) { 1453 if (_memproj_fallthrough == NULL) {
1447 _memproj_fallthrough = new (C, 1) ProjNode(call, TypeFunc::Memory); 1454 _memproj_fallthrough = new (C, 1) ProjNode(call, TypeFunc::Memory);
1448 transform_later(_memproj_fallthrough); 1455 transform_later(_memproj_fallthrough);
1449 } 1456 }
1453 imax -= replace_input(use, _memproj_catchall, _memproj_fallthrough); 1460 imax -= replace_input(use, _memproj_catchall, _memproj_fallthrough);
1454 _igvn._worklist.push(use); 1461 _igvn._worklist.push(use);
1455 // back up iterator 1462 // back up iterator
1456 --i; 1463 --i;
1457 } 1464 }
1458 } 1465 assert(_memproj_catchall->outcnt() == 0, "all uses must be deleted");
1459 1466 _igvn.remove_dead_node(_memproj_catchall);
1460 // An allocate node has separate i_o projections for the uses on the control and i_o paths 1467 }
1461 // Replace uses of the control i_o projection with result_phi_i_o (unless we are only generating a slow call) 1468
1462 if (_ioproj_fallthrough == NULL) { 1469 // An allocate node has separate i_o projections for the uses on the control
1463 _ioproj_fallthrough = new (C, 1) ProjNode(call, TypeFunc::I_O); 1470 // and i_o paths. Always replace the control i_o projection with result i_o
1464 transform_later(_ioproj_fallthrough); 1471 // otherwise incoming i_o become dead when only a slow call is generated
1465 } else if (!always_slow) { 1472 // (it is different from memory projections where both projections are
1473 // combined in such case).
1474 if (_ioproj_fallthrough != NULL) {
1466 for (DUIterator_Fast imax, i = _ioproj_fallthrough->fast_outs(imax); i < imax; i++) { 1475 for (DUIterator_Fast imax, i = _ioproj_fallthrough->fast_outs(imax); i < imax; i++) {
1467 Node *use = _ioproj_fallthrough->fast_out(i); 1476 Node *use = _ioproj_fallthrough->fast_out(i);
1468
1469 _igvn.hash_delete(use); 1477 _igvn.hash_delete(use);
1470 imax -= replace_input(use, _ioproj_fallthrough, result_phi_i_o); 1478 imax -= replace_input(use, _ioproj_fallthrough, result_phi_i_o);
1471 _igvn._worklist.push(use); 1479 _igvn._worklist.push(use);
1472 // back up iterator 1480 // back up iterator
1473 --i; 1481 --i;
1474 } 1482 }
1475 } 1483 }
1476 // Now change uses of _ioproj_catchall to use _ioproj_fallthrough and delete _ioproj_catchall so 1484 // Now change uses of _ioproj_catchall to use _ioproj_fallthrough and delete
1477 // we end up with a call that has only 1 control projection 1485 // _ioproj_catchall so we end up with a call that has only 1 i_o projection.
1478 if (_ioproj_catchall != NULL ) { 1486 if (_ioproj_catchall != NULL ) {
1487 if (_ioproj_fallthrough == NULL) {
1488 _ioproj_fallthrough = new (C, 1) ProjNode(call, TypeFunc::I_O);
1489 transform_later(_ioproj_fallthrough);
1490 }
1479 for (DUIterator_Fast imax, i = _ioproj_catchall->fast_outs(imax); i < imax; i++) { 1491 for (DUIterator_Fast imax, i = _ioproj_catchall->fast_outs(imax); i < imax; i++) {
1480 Node *use = _ioproj_catchall->fast_out(i); 1492 Node *use = _ioproj_catchall->fast_out(i);
1481 _igvn.hash_delete(use); 1493 _igvn.hash_delete(use);
1482 imax -= replace_input(use, _ioproj_catchall, _ioproj_fallthrough); 1494 imax -= replace_input(use, _ioproj_catchall, _ioproj_fallthrough);
1483 _igvn._worklist.push(use); 1495 _igvn._worklist.push(use);
1484 // back up iterator 1496 // back up iterator
1485 --i; 1497 --i;
1486 } 1498 }
1499 assert(_ioproj_catchall->outcnt() == 0, "all uses must be deleted");
1500 _igvn.remove_dead_node(_ioproj_catchall);
1487 } 1501 }
1488 1502
1489 // if we generated only a slow call, we are done 1503 // if we generated only a slow call, we are done
1490 if (always_slow) 1504 if (always_slow) {
1505 // Now we can unhook i_o.
1506 call->set_req(TypeFunc::I_O, top());
1507 if (result_phi_i_o->outcnt() == 0)
1508 _igvn.remove_dead_node(result_phi_i_o);
1491 return; 1509 return;
1510 }
1492 1511
1493 1512
1494 if (_fallthroughcatchproj != NULL) { 1513 if (_fallthroughcatchproj != NULL) {
1495 ctrl = _fallthroughcatchproj->clone(); 1514 ctrl = _fallthroughcatchproj->clone();
1496 transform_later(ctrl); 1515 transform_later(ctrl);