6993125: runThese crashes with assert(Thread::current()->on_local_stack((address)this))
Add another ResourceObj debug field to distinguish garbage Reviewed-by: dholmes, coleenp
This commit is contained in:
parent
a9bee9ec34
commit
19a01fed97
@ -131,6 +131,7 @@ CodeBuffer::~CodeBuffer() {
|
|||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// Save allocation type to execute assert in ~ResourceObj()
|
// Save allocation type to execute assert in ~ResourceObj()
|
||||||
// which is called after this destructor.
|
// which is called after this destructor.
|
||||||
|
assert(_default_oop_recorder.allocated_on_stack(), "should be embedded object");
|
||||||
ResourceObj::allocation_type at = _default_oop_recorder.get_allocation_type();
|
ResourceObj::allocation_type at = _default_oop_recorder.get_allocation_type();
|
||||||
Copy::fill_to_bytes(this, sizeof(*this), badResourceValue);
|
Copy::fill_to_bytes(this, sizeof(*this), badResourceValue);
|
||||||
ResourceObj::set_allocation_type((address)(&_default_oop_recorder), at);
|
ResourceObj::set_allocation_type((address)(&_default_oop_recorder), at);
|
||||||
|
@ -73,7 +73,7 @@ void* ResourceObj::operator new(size_t size, allocation_type type) {
|
|||||||
void ResourceObj::operator delete(void* p) {
|
void ResourceObj::operator delete(void* p) {
|
||||||
assert(((ResourceObj *)p)->allocated_on_C_heap(),
|
assert(((ResourceObj *)p)->allocated_on_C_heap(),
|
||||||
"delete only allowed for C_HEAP objects");
|
"delete only allowed for C_HEAP objects");
|
||||||
DEBUG_ONLY(((ResourceObj *)p)->_allocation = (uintptr_t)badHeapOopVal;)
|
DEBUG_ONLY(((ResourceObj *)p)->_allocation_t[0] = (uintptr_t)badHeapOopVal;)
|
||||||
FreeHeap(p);
|
FreeHeap(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,43 +83,73 @@ void ResourceObj::set_allocation_type(address res, allocation_type type) {
|
|||||||
uintptr_t allocation = (uintptr_t)res;
|
uintptr_t allocation = (uintptr_t)res;
|
||||||
assert((allocation & allocation_mask) == 0, "address should be aligned to 4 bytes at least");
|
assert((allocation & allocation_mask) == 0, "address should be aligned to 4 bytes at least");
|
||||||
assert(type <= allocation_mask, "incorrect allocation type");
|
assert(type <= allocation_mask, "incorrect allocation type");
|
||||||
((ResourceObj *)res)->_allocation = ~(allocation + type);
|
ResourceObj* resobj = (ResourceObj *)res;
|
||||||
|
resobj->_allocation_t[0] = ~(allocation + type);
|
||||||
|
if (type != STACK_OR_EMBEDDED) {
|
||||||
|
// Called from operator new() and CollectionSetChooser(),
|
||||||
|
// set verification value.
|
||||||
|
resobj->_allocation_t[1] = (uintptr_t)&(resobj->_allocation_t[1]) + type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceObj::allocation_type ResourceObj::get_allocation_type() const {
|
ResourceObj::allocation_type ResourceObj::get_allocation_type() const {
|
||||||
assert(~(_allocation | allocation_mask) == (uintptr_t)this, "lost resource object");
|
assert(~(_allocation_t[0] | allocation_mask) == (uintptr_t)this, "lost resource object");
|
||||||
return (allocation_type)((~_allocation) & allocation_mask);
|
return (allocation_type)((~_allocation_t[0]) & allocation_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceObj::is_type_set() const {
|
||||||
|
allocation_type type = (allocation_type)(_allocation_t[1] & allocation_mask);
|
||||||
|
return get_allocation_type() == type &&
|
||||||
|
(_allocation_t[1] - type) == (uintptr_t)(&_allocation_t[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceObj::ResourceObj() { // default constructor
|
ResourceObj::ResourceObj() { // default constructor
|
||||||
if (~(_allocation | allocation_mask) != (uintptr_t)this) {
|
if (~(_allocation_t[0] | allocation_mask) != (uintptr_t)this) {
|
||||||
|
// Operator new() is not called for allocations
|
||||||
|
// on stack and for embedded objects.
|
||||||
set_allocation_type((address)this, STACK_OR_EMBEDDED);
|
set_allocation_type((address)this, STACK_OR_EMBEDDED);
|
||||||
} else if (allocated_on_stack()) {
|
} else if (allocated_on_stack()) { // STACK_OR_EMBEDDED
|
||||||
// For some reason we got a value which looks like an allocation on stack.
|
// For some reason we got a value which resembles
|
||||||
// Pass if it is really allocated on stack.
|
// an embedded or stack object (operator new() does not
|
||||||
assert(Thread::current()->on_local_stack((address)this),"should be on stack");
|
// set such type). Keep it since it is valid value
|
||||||
|
// (even if it was garbage).
|
||||||
|
// Ignore garbage in other fields.
|
||||||
|
} else if (is_type_set()) {
|
||||||
|
// Operator new() was called and type was set.
|
||||||
|
assert(!allocated_on_stack(),
|
||||||
|
err_msg("not embedded or stack, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",
|
||||||
|
this, get_allocation_type(), _allocation_t[0], _allocation_t[1]));
|
||||||
} else {
|
} else {
|
||||||
assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena(),
|
// Operator new() was not called.
|
||||||
"allocation_type should be set by operator new()");
|
// Assume that it is embedded or stack object.
|
||||||
|
set_allocation_type((address)this, STACK_OR_EMBEDDED);
|
||||||
}
|
}
|
||||||
|
_allocation_t[1] = 0; // Zap verification value
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceObj::ResourceObj(const ResourceObj& r) { // default copy constructor
|
ResourceObj::ResourceObj(const ResourceObj& r) { // default copy constructor
|
||||||
// Used in ClassFileParser::parse_constant_pool_entries() for ClassFileStream.
|
// Used in ClassFileParser::parse_constant_pool_entries() for ClassFileStream.
|
||||||
|
// Note: garbage may resembles valid value.
|
||||||
|
assert(~(_allocation_t[0] | allocation_mask) != (uintptr_t)this || !is_type_set(),
|
||||||
|
err_msg("embedded or stack only, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",
|
||||||
|
this, get_allocation_type(), _allocation_t[0], _allocation_t[1]));
|
||||||
set_allocation_type((address)this, STACK_OR_EMBEDDED);
|
set_allocation_type((address)this, STACK_OR_EMBEDDED);
|
||||||
|
_allocation_t[1] = 0; // Zap verification value
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceObj& ResourceObj::operator=(const ResourceObj& r) { // default copy assignment
|
ResourceObj& ResourceObj::operator=(const ResourceObj& r) { // default copy assignment
|
||||||
// Used in InlineTree::ok_to_inline() for WarmCallInfo.
|
// Used in InlineTree::ok_to_inline() for WarmCallInfo.
|
||||||
assert(allocated_on_stack(), "copy only into local");
|
assert(allocated_on_stack(),
|
||||||
// Keep current _allocation value;
|
err_msg("copy only into local, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",
|
||||||
|
this, get_allocation_type(), _allocation_t[0], _allocation_t[1]));
|
||||||
|
// Keep current _allocation_t value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceObj::~ResourceObj() {
|
ResourceObj::~ResourceObj() {
|
||||||
// allocated_on_C_heap() also checks that encoded (in _allocation) address == this.
|
// allocated_on_C_heap() also checks that encoded (in _allocation) address == this.
|
||||||
if (!allocated_on_C_heap()) { // ResourceObj::delete() zaps _allocation for C_heap.
|
if (!allocated_on_C_heap()) { // ResourceObj::delete() will zap _allocation for C_heap.
|
||||||
_allocation = (uintptr_t)badHeapOopVal; // zap type
|
_allocation_t[0] = (uintptr_t)badHeapOopVal; // zap type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
@ -337,7 +337,9 @@ class ResourceObj ALLOCATION_SUPER_CLASS_SPEC {
|
|||||||
// When this object is allocated on stack the new() operator is not
|
// When this object is allocated on stack the new() operator is not
|
||||||
// called but garbage on stack may look like a valid allocation_type.
|
// called but garbage on stack may look like a valid allocation_type.
|
||||||
// Store negated 'this' pointer when new() is called to distinguish cases.
|
// Store negated 'this' pointer when new() is called to distinguish cases.
|
||||||
uintptr_t _allocation;
|
// Use second array's element for verification value to distinguish garbage.
|
||||||
|
uintptr_t _allocation_t[2];
|
||||||
|
bool is_type_set() const;
|
||||||
public:
|
public:
|
||||||
allocation_type get_allocation_type() const;
|
allocation_type get_allocation_type() const;
|
||||||
bool allocated_on_stack() const { return get_allocation_type() == STACK_OR_EMBEDDED; }
|
bool allocated_on_stack() const { return get_allocation_type() == STACK_OR_EMBEDDED; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user