Mercurial > hg > graal-compiler
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 } |