diff --git a/src/share/vm/asm/codeBuffer.cpp b/src/share/vm/asm/codeBuffer.cpp index e0978a78e6232aaa4270b591deb0cd5bdef4eee4..f2d9bbc9087b94dc66264498d78812b4087519af 100644 --- a/src/share/vm/asm/codeBuffer.cpp +++ b/src/share/vm/asm/codeBuffer.cpp @@ -131,6 +131,7 @@ CodeBuffer::~CodeBuffer() { #ifdef ASSERT // Save allocation type to execute assert in ~ResourceObj() // 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(); Copy::fill_to_bytes(this, sizeof(*this), badResourceValue); ResourceObj::set_allocation_type((address)(&_default_oop_recorder), at); diff --git a/src/share/vm/memory/allocation.cpp b/src/share/vm/memory/allocation.cpp index 69f5d9269153f1eebf66d339c3a5ff6a2b42b98a..d334d4d8785778d4a50f6f703f1599377018878d 100644 --- a/src/share/vm/memory/allocation.cpp +++ b/src/share/vm/memory/allocation.cpp @@ -73,7 +73,7 @@ void* ResourceObj::operator new(size_t size, allocation_type type) { void ResourceObj::operator delete(void* p) { assert(((ResourceObj *)p)->allocated_on_C_heap(), "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); } @@ -83,43 +83,73 @@ void ResourceObj::set_allocation_type(address res, allocation_type type) { uintptr_t allocation = (uintptr_t)res; assert((allocation & allocation_mask) == 0, "address should be aligned to 4 bytes at least"); 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 { - assert(~(_allocation | allocation_mask) == (uintptr_t)this, "lost resource object"); - return (allocation_type)((~_allocation) & allocation_mask); + assert(~(_allocation_t[0] | allocation_mask) == (uintptr_t)this, "lost resource object"); + 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 - 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); - } else if (allocated_on_stack()) { - // For some reason we got a value which looks like an allocation on stack. - // Pass if it is really allocated on stack. - assert(Thread::current()->on_local_stack((address)this),"should be on stack"); + } else if (allocated_on_stack()) { // STACK_OR_EMBEDDED + // For some reason we got a value which resembles + // an embedded or stack object (operator new() does not + // 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 { - assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena(), - "allocation_type should be set by operator new()"); + // Operator new() was not called. + // 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 // 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); + _allocation_t[1] = 0; // Zap verification value } ResourceObj& ResourceObj::operator=(const ResourceObj& r) { // default copy assignment // Used in InlineTree::ok_to_inline() for WarmCallInfo. - assert(allocated_on_stack(), "copy only into local"); - // Keep current _allocation value; + assert(allocated_on_stack(), + 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; } ResourceObj::~ResourceObj() { // allocated_on_C_heap() also checks that encoded (in _allocation) address == this. - if (!allocated_on_C_heap()) { // ResourceObj::delete() zaps _allocation for C_heap. - _allocation = (uintptr_t)badHeapOopVal; // zap type + if (!allocated_on_C_heap()) { // ResourceObj::delete() will zap _allocation for C_heap. + _allocation_t[0] = (uintptr_t)badHeapOopVal; // zap type } } #endif // ASSERT diff --git a/src/share/vm/memory/allocation.hpp b/src/share/vm/memory/allocation.hpp index 529b8bb44a509dafc79e03b25e27b9a42097f66a..c3eb1a5c49dbd15a89f31b79c21264f93314c1f6 100644 --- a/src/share/vm/memory/allocation.hpp +++ b/src/share/vm/memory/allocation.hpp @@ -337,7 +337,9 @@ class ResourceObj ALLOCATION_SUPER_CLASS_SPEC { // When this object is allocated on stack the new() operator is not // called but garbage on stack may look like a valid allocation_type. // 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: allocation_type get_allocation_type() const; bool allocated_on_stack() const { return get_allocation_type() == STACK_OR_EMBEDDED; }