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 |