-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
8335409: Can't allocate and retain memory from resource area in frame::oops_interpreted_do oop closure after 8329665 #20012
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,9 +66,6 @@ class OopMapCacheEntry: private InterpreterOopMap { | |
public: | ||
OopMapCacheEntry() : InterpreterOopMap() { | ||
_next = nullptr; | ||
#ifdef ASSERT | ||
_resource_allocate_bit_mask = false; | ||
#endif | ||
} | ||
}; | ||
|
||
|
@@ -178,10 +175,18 @@ class VerifyClosure : public OffsetClosure { | |
InterpreterOopMap::InterpreterOopMap() { | ||
initialize(); | ||
#ifdef ASSERT | ||
_resource_allocate_bit_mask = true; | ||
_used = false; | ||
#endif | ||
} | ||
|
||
InterpreterOopMap::~InterpreterOopMap() { | ||
if (mask_size() > small_mask_limit) { | ||
assert(!Thread::current()->resource_area()->contains((void*)_bit_mask[0]), | ||
"The bit mask should be allocated from the C heap"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Arguably, this assert is not needed. In debug builds, we have NMT enabled, and that does a check on os::free. However, an assert that _bit_mask[0] != 0 would make sense, since the free quielty swallows null pointers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. We could had such case if the mask was never filled due to invalid bci, so I also improved the conditional. |
||
FREE_C_HEAP_ARRAY(uintptr_t, _bit_mask[0]); | ||
} | ||
} | ||
|
||
bool InterpreterOopMap::is_empty() const { | ||
bool result = _method == nullptr; | ||
assert(_method != nullptr || (_bci == 0 && | ||
|
@@ -400,10 +405,10 @@ void OopMapCacheEntry::deallocate(OopMapCacheEntry* const entry) { | |
// Implementation of OopMapCache | ||
|
||
void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) { | ||
assert(_resource_allocate_bit_mask, | ||
"Should not resource allocate the _bit_mask"); | ||
assert(from->has_valid_mask(), | ||
"Cannot copy entry with an invalid mask"); | ||
// The expectation is that this InterpreterOopMap is a recently created | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/is a recently/is recently/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
// and empty. It is used to get a copy of a cached entry. | ||
assert(!_used, "InterpreterOopMap object can only be filled once"); | ||
assert(from->has_valid_mask(), "Cannot copy entry with an invalid mask"); | ||
|
||
set_method(from->method()); | ||
set_bci(from->bci()); | ||
|
@@ -416,21 +421,11 @@ void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) { | |
memcpy((void *)_bit_mask, (void *)from->_bit_mask, | ||
mask_word_size() * BytesPerWord); | ||
} else { | ||
// The expectation is that this InterpreterOopMap is a recently created | ||
// and empty. It is used to get a copy of a cached entry. | ||
// If the bit mask has a value, it should be in the | ||
// resource area. | ||
assert(_bit_mask[0] == 0 || | ||
Thread::current()->resource_area()->contains((void*)_bit_mask[0]), | ||
"The bit mask should have been allocated from a resource area"); | ||
// Allocate the bit_mask from a Resource area for performance. Allocating | ||
// from the C heap as is done for OopMapCache has a significant | ||
// performance impact. | ||
_bit_mask[0] = (uintptr_t) NEW_RESOURCE_ARRAY(uintptr_t, mask_word_size()); | ||
_bit_mask[0] = (uintptr_t) NEW_C_HEAP_ARRAY(uintptr_t, mask_word_size(), mtClass); | ||
assert(_bit_mask[0] != 0, "bit mask was not allocated"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The assert can be removed, no? NEW_C_HEAP_ARRAY does a null check by default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, removed. |
||
memcpy((void*) _bit_mask[0], (void*) from->_bit_mask[0], | ||
mask_word_size() * BytesPerWord); | ||
memcpy((void*) _bit_mask[0], (void*) from->_bit_mask[0], mask_word_size() * BytesPerWord); | ||
} | ||
DEBUG_ONLY(_used = true); | ||
} | ||
|
||
inline unsigned int OopMapCache::hash_value_for(const methodHandle& method, int bci) const { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,12 +36,13 @@ | |
// OopMapCache's are allocated lazily per InstanceKlass. | ||
|
||
// The oopMap (InterpreterOopMap) is stored as a bit mask. If the | ||
// bit_mask can fit into two words it is stored in | ||
// bit_mask can fit into four words it is stored in | ||
// the _bit_mask array, otherwise it is allocated on the heap. | ||
// For OopMapCacheEntry the bit_mask is allocated in the C heap | ||
// because these entries persist between garbage collections. | ||
// For InterpreterOopMap the bit_mask is allocated in | ||
// a resource area for better performance. InterpreterOopMap | ||
// For InterpreterOopMap the bit_mask is allocated in the C heap | ||
// to avoid issues with allocations from the resource area that have | ||
// to live accross the oop closure (see 8335409). InterpreterOopMap | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't usually put bug numbers in the code and after this change nobody will want to move this back to resource area, so putting the bug number as a caution shouldn't be needed. If one wants to know the details, they can git blame this file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
// should only be created and deleted during same garbage collection. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add 'the' to "during the same garbage collection." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
// | ||
// If ENABBLE_ZAP_DEAD_LOCALS is defined, two bits are used | ||
|
@@ -89,7 +90,7 @@ class InterpreterOopMap: ResourceObj { | |
|
||
protected: | ||
#ifdef ASSERT | ||
bool _resource_allocate_bit_mask; | ||
bool _used; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you make this a DEBUG_ONLY() too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
#endif | ||
int _num_oops; | ||
intptr_t _bit_mask[N]; // the bit mask if | ||
|
@@ -128,11 +129,12 @@ class InterpreterOopMap: ResourceObj { | |
|
||
public: | ||
InterpreterOopMap(); | ||
~InterpreterOopMap(); | ||
|
||
// Copy the OopMapCacheEntry in parameter "from" into this | ||
// InterpreterOopMap. If the _bit_mask[0] in "from" points to | ||
// allocated space (i.e., the bit mask was to large to hold | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit pre-existing: s/to/too/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
// in-line), allocate the space from a Resource area. | ||
// in-line), allocate the space from the C heap. | ||
void resource_copy(OopMapCacheEntry* from); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, this should probably be copy_from, and rename the parameter src. Or something like that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also thought about renaming it but ended up leaving it as is in v1. I changed it to Coleen's suggestion. |
||
|
||
void iterate_oop(OffsetClosure* oop_closure) const; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pre-existing: use of DEBUG_ONLY would be more consistent with later setting of
_used
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.