diff --git a/src/share/vm/memory/resourceArea.hpp b/src/share/vm/memory/resourceArea.hpp index 0699334a5e6fff040d6498be89f18aaf8dd79cde..1357081fd67a8530287696a5e90b522cd13c5248 100644 --- a/src/share/vm/memory/resourceArea.hpp +++ b/src/share/vm/memory/resourceArea.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,10 @@ protected: Chunk *_chunk; // saved arena chunk char *_hwm, *_max; size_t _size_in_bytes; +#ifdef ASSERT + Thread* _thread; + ResourceMark* _previous_resource_mark; +#endif //ASSERT void initialize(Thread *thread) { _area = thread->resource_area(); @@ -92,6 +96,11 @@ protected: _size_in_bytes = _area->size_in_bytes(); debug_only(_area->_nesting++;) assert( _area->_nesting > 0, "must stack allocate RMs" ); +#ifdef ASSERT + _thread = thread; + _previous_resource_mark = thread->current_resource_mark(); + thread->set_current_resource_mark(this); +#endif // ASSERT } public: @@ -111,6 +120,17 @@ protected: _size_in_bytes = r->_size_in_bytes; debug_only(_area->_nesting++;) assert( _area->_nesting > 0, "must stack allocate RMs" ); +#ifdef ASSERT + Thread* thread = ThreadLocalStorage::thread(); + if (thread != NULL) { + _thread = thread; + _previous_resource_mark = thread->current_resource_mark(); + thread->set_current_resource_mark(this); + } else { + _thread = NULL; + _previous_resource_mark = NULL; + } +#endif // ASSERT } void reset_to_mark() { @@ -137,6 +157,11 @@ protected: assert( _area->_nesting > 0, "must stack allocate RMs" ); debug_only(_area->_nesting--;) reset_to_mark(); +#ifdef ASSERT + if (_thread != NULL) { + _thread->set_current_resource_mark(_previous_resource_mark); + } +#endif // ASSERT } diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index ef862012fcc7a80a7301e566f53f7cca09d0d154..a491c4d26b8d868ac388b072769e52f96db6336f 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -218,6 +218,7 @@ Thread::Thread() { // allocated data structures set_osthread(NULL); set_resource_area(new (mtThread)ResourceArea()); + DEBUG_ONLY(_current_resource_mark = NULL;) set_handle_area(new (mtThread) HandleArea(NULL)); set_metadata_handles(new (ResourceObj::C_HEAP, mtClass) GrowableArray(30, true)); set_active_handles(NULL); diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp index 8b8e6dd4e62e4e38237ba9b5b9c953e5f6d54c7f..13950ec169af6af539175f551109916ed33f0e76 100644 --- a/src/share/vm/runtime/thread.hpp +++ b/src/share/vm/runtime/thread.hpp @@ -86,6 +86,8 @@ class GCTaskQueue; class ThreadClosure; class IdealGraphPrinter; +DEBUG_ONLY(class ResourceMark;) + class WorkerThread; // Class hierarchy @@ -531,6 +533,8 @@ public: // Thread local resource area for temporary allocation within the VM ResourceArea* _resource_area; + DEBUG_ONLY(ResourceMark* _current_resource_mark;) + // Thread local handle area for allocation of handles within the VM HandleArea* _handle_area; GrowableArray* _metadata_handles; @@ -585,6 +589,8 @@ public: // Deadlock detection bool allow_allocation() { return _allow_allocation_count == 0; } + ResourceMark* current_resource_mark() { return _current_resource_mark; } + void set_current_resource_mark(ResourceMark* rm) { _current_resource_mark = rm; } #endif void check_for_valid_safepoint_state(bool potential_vm_operation) PRODUCT_RETURN; diff --git a/src/share/vm/utilities/ostream.cpp b/src/share/vm/utilities/ostream.cpp index 1d066ddde4c2a2073e656766924b3d2f12cb80a9..2f04fa0e437dec36ffd187c6146c89deada35f2e 100644 --- a/src/share/vm/utilities/ostream.cpp +++ b/src/share/vm/utilities/ostream.cpp @@ -296,6 +296,7 @@ stringStream::stringStream(size_t initial_size) : outputStream() { buffer = NEW_RESOURCE_ARRAY(char, buffer_length); buffer_pos = 0; buffer_fixed = false; + DEBUG_ONLY(rm = Thread::current()->current_resource_mark();) } // useful for output to fixed chunks of memory, such as performance counters @@ -321,6 +322,8 @@ void stringStream::write(const char* s, size_t len) { end = buffer_length * 2; } char* oldbuf = buffer; + assert(rm == NULL || Thread::current()->current_resource_mark() == rm, + "stringStream is re-allocated with a different ResourceMark"); buffer = NEW_RESOURCE_ARRAY(char, end); strncpy(buffer, oldbuf, buffer_pos); buffer_length = end; diff --git a/src/share/vm/utilities/ostream.hpp b/src/share/vm/utilities/ostream.hpp index 6b154184b013b1a96158d9d70aaa0f7d4758adf5..4d13847663e038b3156cb436991c770d81d88e39 100644 --- a/src/share/vm/utilities/ostream.hpp +++ b/src/share/vm/utilities/ostream.hpp @@ -28,6 +28,8 @@ #include "memory/allocation.hpp" #include "runtime/timer.hpp" +DEBUG_ONLY(class ResourceMark;) + // Output streams for printing // // Printing guidelines: @@ -177,6 +179,7 @@ class stringStream : public outputStream { size_t buffer_pos; size_t buffer_length; bool buffer_fixed; + DEBUG_ONLY(ResourceMark* rm;) public: stringStream(size_t initial_bufsize = 256); stringStream(char* fixed_buffer, size_t fixed_buffer_size);