comparison src/share/vm/opto/callnode.cpp @ 66:6dbf1a175d6b

6672848: (Escape Analysis) improve lock elimination with EA Summary: Remove lock/unlock MemBar nodes and specify locks in debug info for deoptimization. Reviewed-by: never
author kvn
date Fri, 14 Mar 2008 16:40:42 -0700
parents 99269dbf4ba8
children 2a9af0b9cb1c
comparison
equal deleted inserted replaced
65:99269dbf4ba8 66:6dbf1a175d6b
1362 } 1362 }
1363 1363
1364 //============================================================================= 1364 //=============================================================================
1365 Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { 1365 Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
1366 1366
1367 // perform any generic optimizations first 1367 // perform any generic optimizations first (returns 'this' or NULL)
1368 Node *result = SafePointNode::Ideal(phase, can_reshape); 1368 Node *result = SafePointNode::Ideal(phase, can_reshape);
1369 1369
1370 // Now see if we can optimize away this lock. We don't actually 1370 // Now see if we can optimize away this lock. We don't actually
1371 // remove the locking here, we simply set the _eliminate flag which 1371 // remove the locking here, we simply set the _eliminate flag which
1372 // prevents macro expansion from expanding the lock. Since we don't 1372 // prevents macro expansion from expanding the lock. Since we don't
1373 // modify the graph, the value returned from this function is the 1373 // modify the graph, the value returned from this function is the
1374 // one computed above. 1374 // one computed above.
1375 if (EliminateLocks && !is_eliminated()) { 1375 if (result == NULL && can_reshape && EliminateLocks && !is_eliminated()) {
1376 //
1377 // If we are locking an unescaped object, the lock/unlock is unnecessary
1378 //
1379 ConnectionGraph *cgr = Compile::current()->congraph();
1380 PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
1381 if (cgr != NULL)
1382 es = cgr->escape_state(obj_node(), phase);
1383 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
1384 // Mark it eliminated to update any counters
1385 this->set_eliminated();
1386 return result;
1387 }
1388
1376 // 1389 //
1377 // Try lock coarsening 1390 // Try lock coarsening
1378 // 1391 //
1379 PhaseIterGVN* iter = phase->is_IterGVN(); 1392 PhaseIterGVN* iter = phase->is_IterGVN();
1380 if (iter != NULL) { 1393 if (iter != NULL) {
1410 if (PrintEliminateLocks) { 1423 if (PrintEliminateLocks) {
1411 int locks = 0; 1424 int locks = 0;
1412 int unlocks = 0; 1425 int unlocks = 0;
1413 for (int i = 0; i < lock_ops.length(); i++) { 1426 for (int i = 0; i < lock_ops.length(); i++) {
1414 AbstractLockNode* lock = lock_ops.at(i); 1427 AbstractLockNode* lock = lock_ops.at(i);
1415 if (lock->Opcode() == Op_Lock) locks++; 1428 if (lock->Opcode() == Op_Lock)
1416 else unlocks++; 1429 locks++;
1430 else
1431 unlocks++;
1417 if (Verbose) { 1432 if (Verbose) {
1418 lock->dump(1); 1433 lock->dump(1);
1419 } 1434 }
1420 } 1435 }
1421 tty->print_cr("***Eliminated %d unlocks and %d locks", unlocks, locks); 1436 tty->print_cr("***Eliminated %d unlocks and %d locks", unlocks, locks);
1448 uint UnlockNode::size_of() const { return sizeof(*this); } 1463 uint UnlockNode::size_of() const { return sizeof(*this); }
1449 1464
1450 //============================================================================= 1465 //=============================================================================
1451 Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { 1466 Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
1452 1467
1453 // perform any generic optimizations first 1468 // perform any generic optimizations first (returns 'this' or NULL)
1454 Node * result = SafePointNode::Ideal(phase, can_reshape); 1469 Node * result = SafePointNode::Ideal(phase, can_reshape);
1455 1470
1456 // Now see if we can optimize away this unlock. We don't actually 1471 // Now see if we can optimize away this unlock. We don't actually
1457 // remove the unlocking here, we simply set the _eliminate flag which 1472 // remove the unlocking here, we simply set the _eliminate flag which
1458 // prevents macro expansion from expanding the unlock. Since we don't 1473 // prevents macro expansion from expanding the unlock. Since we don't
1459 // modify the graph, the value returned from this function is the 1474 // modify the graph, the value returned from this function is the
1460 // one computed above. 1475 // one computed above.
1461 if (EliminateLocks && !is_eliminated()) { 1476 // Escape state is defined after Parse phase.
1477 if (result == NULL && can_reshape && EliminateLocks && !is_eliminated()) {
1462 // 1478 //
1463 // If we are unlocking an unescaped object, the lock/unlock is unnecessary 1479 // If we are unlocking an unescaped object, the lock/unlock is unnecessary.
1464 // We can eliminate them if there are no safepoints in the locked region.
1465 // 1480 //
1466 ConnectionGraph *cgr = Compile::current()->congraph(); 1481 ConnectionGraph *cgr = Compile::current()->congraph();
1467 if (cgr != NULL && cgr->escape_state(obj_node(), phase) == PointsToNode::NoEscape) { 1482 PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
1468 GrowableArray<AbstractLockNode*> lock_ops; 1483 if (cgr != NULL)
1469 LockNode *lock = find_matching_lock(this); 1484 es = cgr->escape_state(obj_node(), phase);
1470 if (lock != NULL) { 1485 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
1471 lock_ops.append(this); 1486 // Mark it eliminated to update any counters
1472 lock_ops.append(lock); 1487 this->set_eliminated();
1473 // find other unlocks which pair with the lock we found and add them
1474 // to the list
1475 Node * box = box_node();
1476
1477 for (DUIterator_Fast imax, i = box->fast_outs(imax); i < imax; i++) {
1478 Node *use = box->fast_out(i);
1479 if (use->is_Unlock() && use != this) {
1480 UnlockNode *unlock1 = use->as_Unlock();
1481 if (!unlock1->is_eliminated()) {
1482 LockNode *lock1 = find_matching_lock(unlock1);
1483 if (lock == lock1)
1484 lock_ops.append(unlock1);
1485 else if (lock1 == NULL) {
1486 // we can't find a matching lock, we must assume the worst
1487 lock_ops.trunc_to(0);
1488 break;
1489 }
1490 }
1491 }
1492 }
1493 if (lock_ops.length() > 0) {
1494
1495 #ifndef PRODUCT
1496 if (PrintEliminateLocks) {
1497 int locks = 0;
1498 int unlocks = 0;
1499 for (int i = 0; i < lock_ops.length(); i++) {
1500 AbstractLockNode* lock = lock_ops.at(i);
1501 if (lock->Opcode() == Op_Lock) locks++;
1502 else unlocks++;
1503 if (Verbose) {
1504 lock->dump(1);
1505 }
1506 }
1507 tty->print_cr("***Eliminated %d unescaped unlocks and %d unescaped locks", unlocks, locks);
1508 }
1509 #endif
1510
1511 // for each of the identified locks, mark them
1512 // as eliminatable
1513 for (int i = 0; i < lock_ops.length(); i++) {
1514 AbstractLockNode* lock = lock_ops.at(i);
1515
1516 // Mark it eliminated to update any counters
1517 lock->set_eliminated();
1518 }
1519 }
1520 }
1521 } 1488 }
1522 } 1489 }
1523 return result; 1490 return result;
1524 } 1491 }