Skip to content

Commit db914b7

Browse files
committed
8335409: Can't allocate and retain memory from resource area in frame::oops_interpreted_do oop closure after 8329665
Reviewed-by: phh, stuefe Backport-of: 7ab96c74e2c39f430a5c2f65a981da7314a2385b
1 parent 345b417 commit db914b7

File tree

3 files changed

+40
-45
lines changed

3 files changed

+40
-45
lines changed

src/hotspot/share/interpreter/oopMapCache.cpp

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,6 @@ class OopMapCacheEntry: private InterpreterOopMap {
6464
public:
6565
OopMapCacheEntry() : InterpreterOopMap() {
6666
_next = nullptr;
67-
#ifdef ASSERT
68-
_resource_allocate_bit_mask = false;
69-
#endif
7067
}
7168
};
7269

@@ -175,9 +172,13 @@ class VerifyClosure : public OffsetClosure {
175172

176173
InterpreterOopMap::InterpreterOopMap() {
177174
initialize();
178-
#ifdef ASSERT
179-
_resource_allocate_bit_mask = true;
180-
#endif
175+
}
176+
177+
InterpreterOopMap::~InterpreterOopMap() {
178+
if (has_valid_mask() && mask_size() > small_mask_limit) {
179+
assert(_bit_mask[0] != 0, "should have pointer to C heap");
180+
FREE_C_HEAP_ARRAY(uintptr_t, _bit_mask[0]);
181+
}
181182
}
182183

183184
bool InterpreterOopMap::is_empty() const {
@@ -397,35 +398,24 @@ void OopMapCacheEntry::deallocate(OopMapCacheEntry* const entry) {
397398

398399
// Implementation of OopMapCache
399400

400-
void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) {
401-
assert(_resource_allocate_bit_mask,
402-
"Should not resource allocate the _bit_mask");
401+
void InterpreterOopMap::copy_from(const OopMapCacheEntry* src) {
402+
// The expectation is that this InterpreterOopMap is recently created
403+
// and empty. It is used to get a copy of a cached entry.
404+
assert(!has_valid_mask(), "InterpreterOopMap object can only be filled once");
405+
assert(src->has_valid_mask(), "Cannot copy entry with an invalid mask");
403406

404-
set_method(from->method());
405-
set_bci(from->bci());
406-
set_mask_size(from->mask_size());
407-
set_expression_stack_size(from->expression_stack_size());
408-
_num_oops = from->num_oops();
407+
set_method(src->method());
408+
set_bci(src->bci());
409+
set_mask_size(src->mask_size());
410+
set_expression_stack_size(src->expression_stack_size());
411+
_num_oops = src->num_oops();
409412

410413
// Is the bit mask contained in the entry?
411-
if (from->mask_size() <= small_mask_limit) {
412-
memcpy((void *)_bit_mask, (void *)from->_bit_mask,
413-
mask_word_size() * BytesPerWord);
414+
if (src->mask_size() <= small_mask_limit) {
415+
memcpy(_bit_mask, src->_bit_mask, mask_word_size() * BytesPerWord);
414416
} else {
415-
// The expectation is that this InterpreterOopMap is a recently created
416-
// and empty. It is used to get a copy of a cached entry.
417-
// If the bit mask has a value, it should be in the
418-
// resource area.
419-
assert(_bit_mask[0] == 0 ||
420-
Thread::current()->resource_area()->contains((void*)_bit_mask[0]),
421-
"The bit mask should have been allocated from a resource area");
422-
// Allocate the bit_mask from a Resource area for performance. Allocating
423-
// from the C heap as is done for OopMapCache has a significant
424-
// performance impact.
425-
_bit_mask[0] = (uintptr_t) NEW_RESOURCE_ARRAY(uintptr_t, mask_word_size());
426-
assert(_bit_mask[0] != 0, "bit mask was not allocated");
427-
memcpy((void*) _bit_mask[0], (void*) from->_bit_mask[0],
428-
mask_word_size() * BytesPerWord);
417+
_bit_mask[0] = (uintptr_t) NEW_C_HEAP_ARRAY(uintptr_t, mask_word_size(), mtClass);
418+
memcpy((void*) _bit_mask[0], (void*) src->_bit_mask[0], mask_word_size() * BytesPerWord);
429419
}
430420
}
431421

@@ -508,7 +498,7 @@ void OopMapCache::lookup(const methodHandle& method,
508498
for (int i = 0; i < probe_depth; i++) {
509499
OopMapCacheEntry *entry = entry_at(probe + i);
510500
if (entry != nullptr && !entry->is_empty() && entry->match(method, bci)) {
511-
entry_for->resource_copy(entry);
501+
entry_for->copy_from(entry);
512502
assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
513503
log_debug(interpreter, oopmap)("- found at hash %d", probe + i);
514504
return;
@@ -522,7 +512,7 @@ void OopMapCache::lookup(const methodHandle& method,
522512
OopMapCacheEntry* tmp = NEW_C_HEAP_OBJ(OopMapCacheEntry, mtClass);
523513
tmp->initialize();
524514
tmp->fill(method, bci);
525-
entry_for->resource_copy(tmp);
515+
entry_for->copy_from(tmp);
526516

527517
if (method->should_not_be_cached()) {
528518
// It is either not safe or not a good idea to cache this Method*
@@ -622,6 +612,8 @@ void OopMapCache::compute_one_oop_map(const methodHandle& method, int bci, Inter
622612
OopMapCacheEntry* tmp = NEW_C_HEAP_OBJ(OopMapCacheEntry, mtClass);
623613
tmp->initialize();
624614
tmp->fill(method, bci);
625-
entry->resource_copy(tmp);
615+
if (tmp->has_valid_mask()) {
616+
entry->copy_from(tmp);
617+
}
626618
OopMapCacheEntry::deallocate(tmp);
627619
}

src/hotspot/share/interpreter/oopMapCache.hpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@
3535
// OopMapCache's are allocated lazily per InstanceKlass.
3636

3737
// The oopMap (InterpreterOopMap) is stored as a bit mask. If the
38-
// bit_mask can fit into two words it is stored in
38+
// bit_mask can fit into four words it is stored in
3939
// the _bit_mask array, otherwise it is allocated on the heap.
4040
// For OopMapCacheEntry the bit_mask is allocated in the C heap
4141
// because these entries persist between garbage collections.
42-
// For InterpreterOopMap the bit_mask is allocated in
43-
// a resource area for better performance. InterpreterOopMap
44-
// should only be created and deleted during same garbage collection.
42+
// For InterpreterOopMap the bit_mask is allocated in the C heap
43+
// to avoid issues with allocations from the resource area that have
44+
// to live accross the oop closure. InterpreterOopMap should only be
45+
// created and deleted during the same garbage collection.
4546
//
4647
// If ENABBLE_ZAP_DEAD_LOCALS is defined, two bits are used
4748
// per entry instead of one. In all cases,
@@ -82,7 +83,7 @@ class InterpreterOopMap: ResourceObj {
8283
private:
8384
Method* _method; // the method for which the mask is valid
8485
unsigned short _bci; // the bci for which the mask is valid
85-
int _mask_size; // the mask size in bits
86+
int _mask_size; // the mask size in bits (USHRT_MAX if invalid)
8687
int _expression_stack_size; // the size of the expression stack in slots
8788

8889
protected:
@@ -126,12 +127,13 @@ class InterpreterOopMap: ResourceObj {
126127

127128
public:
128129
InterpreterOopMap();
130+
~InterpreterOopMap();
129131

130-
// Copy the OopMapCacheEntry in parameter "from" into this
131-
// InterpreterOopMap. If the _bit_mask[0] in "from" points to
132-
// allocated space (i.e., the bit mask was to large to hold
133-
// in-line), allocate the space from a Resource area.
134-
void resource_copy(OopMapCacheEntry* from);
132+
// Copy the OopMapCacheEntry in parameter "src" into this
133+
// InterpreterOopMap. If the _bit_mask[0] in "src" points to
134+
// allocated space (i.e., the bit mask was too large to hold
135+
// in-line), allocate the space from the C heap.
136+
void copy_from(const OopMapCacheEntry* src);
135137

136138
void iterate_oop(OffsetClosure* oop_closure) const;
137139
void print() const;
@@ -143,6 +145,8 @@ class InterpreterOopMap: ResourceObj {
143145

144146
int expression_stack_size() const { return _expression_stack_size; }
145147

148+
// Determines if a valid mask has been computed
149+
bool has_valid_mask() const { return _mask_size != USHRT_MAX; }
146150
};
147151

148152
class OopMapCache : public CHeapObj<mtClass> {

src/hotspot/share/runtime/frame.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,6 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer
952952
InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f);
953953

954954
// process locals & expression stack
955-
ResourceMark rm(thread);
956955
InterpreterOopMap mask;
957956
if (query_oop_map_cache) {
958957
m->mask_for(m, bci, &mask);

0 commit comments

Comments
 (0)