< prev index next >

src/share/vm/oops/methodData.cpp

Print this page
rev 8340 : 8038636: speculative traps break when classes are redefined
Summary: remove speculative traps that point to methods that are redefined
Reviewed-by: kvn, twisti


1542   if (shift == 0) {
1543     return;
1544   }
1545   if (!reset) {
1546     // Move all cells of trap entry at dp left by "shift" cells
1547     intptr_t* start = (intptr_t*)dp;
1548     intptr_t* end = (intptr_t*)next_extra(dp);
1549     for (intptr_t* ptr = start; ptr < end; ptr++) {
1550       *(ptr-shift) = *ptr;
1551     }
1552   } else {
1553     // Reset "shift" cells stopping at dp
1554     intptr_t* start = ((intptr_t*)dp) - shift;
1555     intptr_t* end = (intptr_t*)dp;
1556     for (intptr_t* ptr = start; ptr < end; ptr++) {
1557       *ptr = 0;
1558     }
1559   }
1560 }
1561 
1562 // Remove SpeculativeTrapData entries that reference an unloaded
1563 // method
1564 void MethodData::clean_extra_data(BoolObjectClosure* is_alive) {


























1565   DataLayout* dp  = extra_data_base();
1566   DataLayout* end = extra_data_limit();
1567 
1568   int shift = 0;
1569   for (; dp < end; dp = next_extra(dp)) {
1570     switch(dp->tag()) {
1571     case DataLayout::speculative_trap_data_tag: {
1572       SpeculativeTrapData* data = new SpeculativeTrapData(dp);
1573       Method* m = data->method();
1574       assert(m != NULL, "should have a method");
1575       if (!m->method_holder()->is_loader_alive(is_alive)) {
1576         // "shift" accumulates the number of cells for dead
1577         // SpeculativeTrapData entries that have been seen so
1578         // far. Following entries must be shifted left by that many
1579         // cells to remove the dead SpeculativeTrapData entries.
1580         shift += (int)((intptr_t*)next_extra(dp) - (intptr_t*)dp);
1581       } else {
1582         // Shift this entry left if it follows dead
1583         // SpeculativeTrapData entries
1584         clean_extra_data_helper(dp, shift);
1585       }
1586       break;
1587     }
1588     case DataLayout::bit_data_tag:
1589       // Shift this entry left if it follows dead SpeculativeTrapData
1590       // entries
1591       clean_extra_data_helper(dp, shift);
1592       continue;
1593     case DataLayout::no_tag:
1594     case DataLayout::arg_info_data_tag:
1595       // We are at end of the live trap entries. The previous "shift"
1596       // cells contain entries that are either dead or were shifted
1597       // left. They need to be reset to no_tag
1598       clean_extra_data_helper(dp, shift, true);
1599       return;
1600     default:
1601       fatal(err_msg("unexpected tag %d", dp->tag()));
1602     }
1603   }
1604 }
1605 
1606 // Verify there's no unloaded method referenced by a
1607 // SpeculativeTrapData entry
1608 void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) {
1609 #ifdef ASSERT
1610   DataLayout* dp  = extra_data_base();
1611   DataLayout* end = extra_data_limit();
1612 
1613   for (; dp < end; dp = next_extra(dp)) {
1614     switch(dp->tag()) {
1615     case DataLayout::speculative_trap_data_tag: {
1616       SpeculativeTrapData* data = new SpeculativeTrapData(dp);
1617       Method* m = data->method();
1618       assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist");
1619       break;
1620     }
1621     case DataLayout::bit_data_tag:
1622       continue;
1623     case DataLayout::no_tag:
1624     case DataLayout::arg_info_data_tag:
1625       return;
1626     default:
1627       fatal(err_msg("unexpected tag %d", dp->tag()));
1628     }
1629   }
1630 #endif
1631 }
1632 
1633 void MethodData::clean_method_data(BoolObjectClosure* is_alive) {
1634   for (ProfileData* data = first_data();
1635        is_valid(data);
1636        data = next_data(data)) {
1637     data->clean_weak_klass_links(is_alive);
1638   }
1639   ParametersTypeData* parameters = parameters_type_data();
1640   if (parameters != NULL) {
1641     parameters->clean_weak_klass_links(is_alive);
1642   }
1643 
1644   clean_extra_data(is_alive);
1645   verify_extra_data_clean(is_alive);













1646 }


1542   if (shift == 0) {
1543     return;
1544   }
1545   if (!reset) {
1546     // Move all cells of trap entry at dp left by "shift" cells
1547     intptr_t* start = (intptr_t*)dp;
1548     intptr_t* end = (intptr_t*)next_extra(dp);
1549     for (intptr_t* ptr = start; ptr < end; ptr++) {
1550       *(ptr-shift) = *ptr;
1551     }
1552   } else {
1553     // Reset "shift" cells stopping at dp
1554     intptr_t* start = ((intptr_t*)dp) - shift;
1555     intptr_t* end = (intptr_t*)dp;
1556     for (intptr_t* ptr = start; ptr < end; ptr++) {
1557       *ptr = 0;
1558     }
1559   }
1560 }
1561 
1562 class CleanExtraDataClosure : public StackObj {
1563 public:
1564   virtual bool is_live(Method* m) = 0;
1565 };
1566 
1567 // Check for entries that reference an unloaded method
1568 class CleanExtraDataKlassClosure : public CleanExtraDataClosure {
1569 private:
1570   BoolObjectClosure* _is_alive;
1571 public:
1572   CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {}
1573   bool is_live(Method* m) {
1574     return m->method_holder()->is_loader_alive(_is_alive);
1575   }
1576 };
1577 
1578 // Check for entries that reference a redefined method
1579 class CleanExtraDataMethodClosure : public CleanExtraDataClosure {
1580 public:
1581   CleanExtraDataMethodClosure() {}
1582   bool is_live(Method* m) {
1583     return m->on_stack();
1584   }
1585 };
1586 
1587 
1588 // Remove SpeculativeTrapData entries that reference an unloaded or
1589 // redefined method
1590 void MethodData::clean_extra_data(CleanExtraDataClosure* cl) {
1591   DataLayout* dp  = extra_data_base();
1592   DataLayout* end = extra_data_limit();
1593 
1594   int shift = 0;
1595   for (; dp < end; dp = next_extra(dp)) {
1596     switch(dp->tag()) {
1597     case DataLayout::speculative_trap_data_tag: {
1598       SpeculativeTrapData* data = new SpeculativeTrapData(dp);
1599       Method* m = data->method();
1600       assert(m != NULL, "should have a method");
1601       if (!cl->is_live(m)) {
1602         // "shift" accumulates the number of cells for dead
1603         // SpeculativeTrapData entries that have been seen so
1604         // far. Following entries must be shifted left by that many
1605         // cells to remove the dead SpeculativeTrapData entries.
1606         shift += (int)((intptr_t*)next_extra(dp) - (intptr_t*)dp);
1607       } else {
1608         // Shift this entry left if it follows dead
1609         // SpeculativeTrapData entries
1610         clean_extra_data_helper(dp, shift);
1611       }
1612       break;
1613     }
1614     case DataLayout::bit_data_tag:
1615       // Shift this entry left if it follows dead SpeculativeTrapData
1616       // entries
1617       clean_extra_data_helper(dp, shift);
1618       continue;
1619     case DataLayout::no_tag:
1620     case DataLayout::arg_info_data_tag:
1621       // We are at end of the live trap entries. The previous "shift"
1622       // cells contain entries that are either dead or were shifted
1623       // left. They need to be reset to no_tag
1624       clean_extra_data_helper(dp, shift, true);
1625       return;
1626     default:
1627       fatal(err_msg("unexpected tag %d", dp->tag()));
1628     }
1629   }
1630 }
1631 
1632 // Verify there's no unloaded or redefined method referenced by a
1633 // SpeculativeTrapData entry
1634 void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) {
1635 #ifdef ASSERT
1636   DataLayout* dp  = extra_data_base();
1637   DataLayout* end = extra_data_limit();
1638 
1639   for (; dp < end; dp = next_extra(dp)) {
1640     switch(dp->tag()) {
1641     case DataLayout::speculative_trap_data_tag: {
1642       SpeculativeTrapData* data = new SpeculativeTrapData(dp);
1643       Method* m = data->method();
1644       assert(m != NULL && cl->is_live(m), "Method should exist");
1645       break;
1646     }
1647     case DataLayout::bit_data_tag:
1648       continue;
1649     case DataLayout::no_tag:
1650     case DataLayout::arg_info_data_tag:
1651       return;
1652     default:
1653       fatal(err_msg("unexpected tag %d", dp->tag()));
1654     }
1655   }
1656 #endif
1657 }
1658 
1659 void MethodData::clean_method_data(BoolObjectClosure* is_alive) {
1660   for (ProfileData* data = first_data();
1661        is_valid(data);
1662        data = next_data(data)) {
1663     data->clean_weak_klass_links(is_alive);
1664   }
1665   ParametersTypeData* parameters = parameters_type_data();
1666   if (parameters != NULL) {
1667     parameters->clean_weak_klass_links(is_alive);
1668   }
1669 
1670   CleanExtraDataKlassClosure cl(is_alive);
1671   clean_extra_data(&cl);
1672   verify_extra_data_clean(&cl);
1673 }
1674 
1675 void MethodData::clean_weak_method_links() {
1676   for (ProfileData* data = first_data();
1677        is_valid(data);
1678        data = next_data(data)) {
1679     data->clean_weak_method_links();
1680   }
1681 
1682   CleanExtraDataMethodClosure cl;
1683   clean_extra_data(&cl);
1684   verify_extra_data_clean(&cl);
1685 }
< prev index next >