hotspot/src/share/vm/oops/method.cpp
changeset 27478 0eedae0228ac
parent 27461 90e9e0f9c0c5
child 27480 51e6396f8a98
equal deleted inserted replaced
27474:2b061fd571eb 27478:0eedae0228ac
  1725 }
  1725 }
  1726 
  1726 
  1727 // jmethodID handling
  1727 // jmethodID handling
  1728 
  1728 
  1729 // This is a block allocating object, sort of like JNIHandleBlock, only a
  1729 // This is a block allocating object, sort of like JNIHandleBlock, only a
  1730 // lot simpler.  There aren't many of these, they aren't long, they are rarely
  1730 // lot simpler.
  1731 // deleted and so we can do some suboptimal things.
       
  1732 // It's allocated on the CHeap because once we allocate a jmethodID, we can
  1731 // It's allocated on the CHeap because once we allocate a jmethodID, we can
  1733 // never get rid of it.
  1732 // never get rid of it.
  1734 // It would be nice to be able to parameterize the number of methods for
  1733 
  1735 // the null_class_loader but then we'd have to turn this and ClassLoaderData
  1734 static const int min_block_size = 8;
  1736 // into templates.
  1735 
  1737 
  1736 class JNIMethodBlockNode : public CHeapObj<mtClass> {
  1738 // I feel like this brain dead class should exist somewhere in the STL
  1737   friend class JNIMethodBlock;
       
  1738   Method**        _methods;
       
  1739   int             _number_of_methods;
       
  1740   int             _top;
       
  1741   JNIMethodBlockNode* _next;
       
  1742 
       
  1743  public:
       
  1744 
       
  1745   JNIMethodBlockNode(int num_methods = min_block_size);
       
  1746 
       
  1747   ~JNIMethodBlockNode() { FREE_C_HEAP_ARRAY(Method*, _methods, mtInternal); }
       
  1748 
       
  1749   void ensure_methods(int num_addl_methods) {
       
  1750     if (_top < _number_of_methods) {
       
  1751       num_addl_methods -= _number_of_methods - _top;
       
  1752       if (num_addl_methods <= 0) {
       
  1753         return;
       
  1754       }
       
  1755     }
       
  1756     if (_next == NULL) {
       
  1757       _next = new JNIMethodBlockNode(MAX2(num_addl_methods, min_block_size));
       
  1758     } else {
       
  1759       _next->ensure_methods(num_addl_methods);
       
  1760     }
       
  1761   }
       
  1762 };
  1739 
  1763 
  1740 class JNIMethodBlock : public CHeapObj<mtClass> {
  1764 class JNIMethodBlock : public CHeapObj<mtClass> {
  1741   enum { number_of_methods = 8 };
  1765   JNIMethodBlockNode _head;
  1742 
  1766   JNIMethodBlockNode *_last_free;
  1743   Method*         _methods[number_of_methods];
       
  1744   int             _top;
       
  1745   JNIMethodBlock* _next;
       
  1746  public:
  1767  public:
  1747   static Method* const _free_method;
  1768   static Method* const _free_method;
  1748 
  1769 
  1749   JNIMethodBlock() : _next(NULL), _top(0) {
  1770   JNIMethodBlock(int initial_capacity = min_block_size)
  1750     for (int i = 0; i< number_of_methods; i++) _methods[i] = _free_method;
  1771       : _head(initial_capacity), _last_free(&_head) {}
       
  1772 
       
  1773   void ensure_methods(int num_addl_methods) {
       
  1774     _last_free->ensure_methods(num_addl_methods);
  1751   }
  1775   }
  1752 
  1776 
  1753   Method** add_method(Method* m) {
  1777   Method** add_method(Method* m) {
  1754     if (_top < number_of_methods) {
  1778     for (JNIMethodBlockNode* b = _last_free; b != NULL; b = b->_next) {
  1755       // top points to the next free entry.
  1779       if (b->_top < b->_number_of_methods) {
  1756       int i = _top;
  1780         // top points to the next free entry.
  1757       _methods[i] = m;
  1781         int i = b->_top;
  1758       _top++;
  1782         b->_methods[i] = m;
  1759       return &_methods[i];
  1783         b->_top++;
  1760     } else if (_top == number_of_methods) {
  1784         _last_free = b;
  1761       // if the next free entry ran off the block see if there's a free entry
  1785         return &(b->_methods[i]);
  1762       for (int i = 0; i< number_of_methods; i++) {
  1786       } else if (b->_top == b->_number_of_methods) {
  1763         if (_methods[i] == _free_method) {
  1787         // if the next free entry ran off the block see if there's a free entry
  1764           _methods[i] = m;
  1788         for (int i = 0; i < b->_number_of_methods; i++) {
  1765           return &_methods[i];
  1789           if (b->_methods[i] == _free_method) {
       
  1790             b->_methods[i] = m;
       
  1791             _last_free = b;
       
  1792             return &(b->_methods[i]);
       
  1793           }
  1766         }
  1794         }
       
  1795         // Only check each block once for frees.  They're very unlikely.
       
  1796         // Increment top past the end of the block.
       
  1797         b->_top++;
  1767       }
  1798       }
  1768       // Only check each block once for frees.  They're very unlikely.
  1799       // need to allocate a next block.
  1769       // Increment top past the end of the block.
  1800       if (b->_next == NULL) {
  1770       _top++;
  1801         b->_next = _last_free = new JNIMethodBlockNode();
  1771     }
  1802       }
  1772     // need to allocate a next block.
  1803     }
  1773     if (_next == NULL) {
  1804     guarantee(false, "Should always allocate a free block");
  1774       _next = new JNIMethodBlock();
  1805     return NULL;
  1775     }
       
  1776     return _next->add_method(m);
       
  1777   }
  1806   }
  1778 
  1807 
  1779   bool contains(Method** m) {
  1808   bool contains(Method** m) {
  1780     for (JNIMethodBlock* b = this; b != NULL; b = b->_next) {
  1809     if (m == NULL) return false;
  1781       for (int i = 0; i< number_of_methods; i++) {
  1810     for (JNIMethodBlockNode* b = &_head; b != NULL; b = b->_next) {
  1782         if (&(b->_methods[i]) == m) {
  1811       if (b->_methods <= m && m < b->_methods + b->_number_of_methods) {
       
  1812         // This is a bit of extra checking, for two reasons.  One is
       
  1813         // that contains() deals with pointers that are passed in by
       
  1814         // JNI code, so making sure that the pointer is aligned
       
  1815         // correctly is valuable.  The other is that <= and > are
       
  1816         // technically not defined on pointers, so the if guard can
       
  1817         // pass spuriously; no modern compiler is likely to make that
       
  1818         // a problem, though (and if one did, the guard could also
       
  1819         // fail spuriously, which would be bad).
       
  1820         ptrdiff_t idx = m - b->_methods;
       
  1821         if (b->_methods + idx == m) {
  1783           return true;
  1822           return true;
  1784         }
  1823         }
  1785       }
  1824       }
  1786     }
  1825     }
  1787     return false;  // not found
  1826     return false;  // not found
  1796   }
  1835   }
  1797 
  1836 
  1798   // During class unloading the methods are cleared, which is different
  1837   // During class unloading the methods are cleared, which is different
  1799   // than freed.
  1838   // than freed.
  1800   void clear_all_methods() {
  1839   void clear_all_methods() {
  1801     for (JNIMethodBlock* b = this; b != NULL; b = b->_next) {
  1840     for (JNIMethodBlockNode* b = &_head; b != NULL; b = b->_next) {
  1802       for (int i = 0; i< number_of_methods; i++) {
  1841       for (int i = 0; i< b->_number_of_methods; i++) {
  1803         _methods[i] = NULL;
  1842         b->_methods[i] = NULL;
  1804       }
  1843       }
  1805     }
  1844     }
  1806   }
  1845   }
  1807 #ifndef PRODUCT
  1846 #ifndef PRODUCT
  1808   int count_methods() {
  1847   int count_methods() {
  1809     // count all allocated methods
  1848     // count all allocated methods
  1810     int count = 0;
  1849     int count = 0;
  1811     for (JNIMethodBlock* b = this; b != NULL; b = b->_next) {
  1850     for (JNIMethodBlockNode* b = &_head; b != NULL; b = b->_next) {
  1812       for (int i = 0; i< number_of_methods; i++) {
  1851       for (int i = 0; i< b->_number_of_methods; i++) {
  1813         if (_methods[i] != _free_method) count++;
  1852         if (b->_methods[i] != _free_method) count++;
  1814       }
  1853       }
  1815     }
  1854     }
  1816     return count;
  1855     return count;
  1817   }
  1856   }
  1818 #endif // PRODUCT
  1857 #endif // PRODUCT
  1819 };
  1858 };
  1820 
  1859 
  1821 // Something that can't be mistaken for an address or a markOop
  1860 // Something that can't be mistaken for an address or a markOop
  1822 Method* const JNIMethodBlock::_free_method = (Method*)55;
  1861 Method* const JNIMethodBlock::_free_method = (Method*)55;
       
  1862 
       
  1863 JNIMethodBlockNode::JNIMethodBlockNode(int num_methods) : _next(NULL), _top(0) {
       
  1864   _number_of_methods = MAX2(num_methods, min_block_size);
       
  1865   _methods = NEW_C_HEAP_ARRAY(Method*, _number_of_methods, mtInternal);
       
  1866   for (int i = 0; i < _number_of_methods; i++) {
       
  1867     _methods[i] = JNIMethodBlock::_free_method;
       
  1868   }
       
  1869 }
       
  1870 
       
  1871 void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) {
       
  1872   ClassLoaderData* cld = loader_data;
       
  1873   if (!SafepointSynchronize::is_at_safepoint()) {
       
  1874     // Have to add jmethod_ids() to class loader data thread-safely.
       
  1875     // Also have to add the method to the list safely, which the cld lock
       
  1876     // protects as well.
       
  1877     MutexLockerEx ml(cld->metaspace_lock(),  Mutex::_no_safepoint_check_flag);
       
  1878     if (cld->jmethod_ids() == NULL) {
       
  1879       cld->set_jmethod_ids(new JNIMethodBlock(capacity));
       
  1880     } else {
       
  1881       cld->jmethod_ids()->ensure_methods(capacity);
       
  1882     }
       
  1883   } else {
       
  1884     // At safepoint, we are single threaded and can set this.
       
  1885     if (cld->jmethod_ids() == NULL) {
       
  1886       cld->set_jmethod_ids(new JNIMethodBlock(capacity));
       
  1887     } else {
       
  1888       cld->jmethod_ids()->ensure_methods(capacity);
       
  1889     }
       
  1890   }
       
  1891 }
  1823 
  1892 
  1824 // Add a method id to the jmethod_ids
  1893 // Add a method id to the jmethod_ids
  1825 jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) {
  1894 jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) {
  1826   ClassLoaderData* cld = loader_data;
  1895   ClassLoaderData* cld = loader_data;
  1827 
  1896