resourceArea.hpp revision 1472:c18cbe5936b8
1238104Sdes/* 2238104Sdes * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. 3238104Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4238104Sdes * 5238104Sdes * This code is free software; you can redistribute it and/or modify it 6238104Sdes * under the terms of the GNU General Public License version 2 only, as 7238104Sdes * published by the Free Software Foundation. 8238104Sdes * 9238104Sdes * This code is distributed in the hope that it will be useful, but WITHOUT 10238104Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11238104Sdes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12238104Sdes * version 2 for more details (a copy is included in the LICENSE file that 13238104Sdes * accompanied this code). 14238104Sdes * 15238104Sdes * You should have received a copy of the GNU General Public License version 16238104Sdes * 2 along with this work; if not, write to the Free Software Foundation, 17238104Sdes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18238104Sdes * 19238104Sdes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20238104Sdes * or visit www.oracle.com if you need additional information or have any 21238104Sdes * questions. 22238104Sdes * 23238104Sdes */ 24238104Sdes 25238104Sdes// The resource area holds temporary data structures in the VM. 26238104Sdes// The actual allocation areas are thread local. Typical usage: 27238104Sdes// 28238104Sdes// ... 29238104Sdes// { 30238104Sdes// ResourceMark rm; 31238104Sdes// int foo[] = NEW_RESOURCE_ARRAY(int, 64); 32238104Sdes// ... 33238104Sdes// } 34238104Sdes// ... 35238104Sdes 36238104Sdes//------------------------------ResourceArea----------------------------------- 37238104Sdes// A ResourceArea is an Arena that supports safe usage of ResourceMark. 38238104Sdesclass ResourceArea: public Arena { 39238104Sdes friend class ResourceMark; 40238104Sdes friend class DeoptResourceMark; 41238104Sdes debug_only(int _nesting;) // current # of nested ResourceMarks 42238104Sdes debug_only(static int _warned;) // to suppress multiple warnings 43238104Sdes 44238104Sdespublic: 45238104Sdes ResourceArea() { 46238104Sdes debug_only(_nesting = 0;) 47238104Sdes } 48238104Sdes 49238104Sdes ResourceArea(size_t init_size) : Arena(init_size) { 50238104Sdes debug_only(_nesting = 0;); 51238104Sdes } 52238104Sdes 53238104Sdes char* allocate_bytes(size_t size) { 54238104Sdes#ifdef ASSERT 55238104Sdes if (_nesting < 1 && !_warned++) 56238104Sdes fatal("memory leak: allocating without ResourceMark"); 57238104Sdes if (UseMallocOnly) { 58238104Sdes // use malloc, but save pointer in res. area for later freeing 59238104Sdes char** save = (char**)internal_malloc_4(sizeof(char*)); 60238104Sdes return (*save = (char*)os::malloc(size)); 61238104Sdes } 62238104Sdes#endif 63238104Sdes return (char*)Amalloc(size); 64238104Sdes } 65238104Sdes 66238104Sdes debug_only(int nesting() const { return _nesting; }); 67238104Sdes}; 68238104Sdes 69238104Sdes 70238104Sdes//------------------------------ResourceMark----------------------------------- 71238104Sdes// A resource mark releases all resources allocated after it was constructed 72238104Sdes// when the destructor is called. Typically used as a local variable. 73238104Sdesclass ResourceMark: public StackObj { 74238104Sdesprotected: 75238104Sdes ResourceArea *_area; // Resource area to stack allocate 76238104Sdes Chunk *_chunk; // saved arena chunk 77238104Sdes char *_hwm, *_max; 78238104Sdes NOT_PRODUCT(size_t _size_in_bytes;) 79238104Sdes 80238104Sdes void initialize(Thread *thread) { 81238104Sdes _area = thread->resource_area(); 82238104Sdes _chunk = _area->_chunk; 83238104Sdes _hwm = _area->_hwm; 84238104Sdes _max= _area->_max; 85238104Sdes NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 86238104Sdes debug_only(_area->_nesting++;) 87238104Sdes assert( _area->_nesting > 0, "must stack allocate RMs" ); 88238104Sdes } 89238104Sdes 90238104Sdes public: 91238104Sdes 92238104Sdes#ifndef ASSERT 93238104Sdes ResourceMark(Thread *thread) { 94238104Sdes assert(thread == Thread::current(), "not the current thread"); 95238104Sdes initialize(thread); 96238104Sdes } 97238104Sdes#else 98238104Sdes ResourceMark(Thread *thread); 99238104Sdes#endif // ASSERT 100238104Sdes 101238104Sdes ResourceMark() { initialize(Thread::current()); } 102238104Sdes 103238104Sdes ResourceMark( ResourceArea *r ) : 104238104Sdes _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) { 105238104Sdes NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 106238104Sdes debug_only(_area->_nesting++;) 107238104Sdes assert( _area->_nesting > 0, "must stack allocate RMs" ); 108238104Sdes } 109238104Sdes 110238104Sdes void reset_to_mark() { 111238104Sdes if (UseMallocOnly) free_malloced_objects(); 112238104Sdes 113238104Sdes if( _chunk->next() ) // Delete later chunks 114238104Sdes _chunk->next_chop(); 115238104Sdes _area->_chunk = _chunk; // Roll back arena to saved chunk 116238104Sdes _area->_hwm = _hwm; 117238104Sdes _area->_max = _max; 118238104Sdes 119238104Sdes // clear out this chunk (to detect allocation bugs) 120238104Sdes if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm); 121238104Sdes _area->set_size_in_bytes(size_in_bytes()); 122238104Sdes } 123238104Sdes 124238104Sdes ~ResourceMark() { 125238104Sdes assert( _area->_nesting > 0, "must stack allocate RMs" ); 126238104Sdes debug_only(_area->_nesting--;) 127238104Sdes reset_to_mark(); 128238104Sdes } 129238104Sdes 130238104Sdes 131238104Sdes private: 132238104Sdes void free_malloced_objects() PRODUCT_RETURN; 133238104Sdes size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; 134238104Sdes}; 135238104Sdes 136238104Sdes//------------------------------DeoptResourceMark----------------------------------- 137238104Sdes// A deopt resource mark releases all resources allocated after it was constructed 138238104Sdes// when the destructor is called. Typically used as a local variable. It differs 139238104Sdes// from a typical resource more in that it is C-Heap allocated so that deoptimization 140238104Sdes// can use data structures that are arena based but are not amenable to vanilla 141238104Sdes// ResourceMarks because deoptimization can not use a stack allocated mark. During 142238104Sdes// deoptimization we go thru the following steps: 143238104Sdes// 144238104Sdes// 0: start in assembly stub and call either uncommon_trap/fetch_unroll_info 145238104Sdes// 1: create the vframeArray (contains pointers to Resource allocated structures) 146238104Sdes// This allocates the DeoptResourceMark. 147238104Sdes// 2: return to assembly stub and remove stub frame and deoptee frame and create 148238104Sdes// the new skeletal frames. 149238104Sdes// 3: push new stub frame and call unpack_frames 150238104Sdes// 4: retrieve information from the vframeArray to populate the skeletal frames 151238104Sdes// 5: release the DeoptResourceMark 152238104Sdes// 6: return to stub and eventually to interpreter 153238104Sdes// 154238104Sdes// With old style eager deoptimization the vframeArray was created by the vmThread there 155238104Sdes// was no way for the vframeArray to contain resource allocated objects and so 156238104Sdes// a complex set of data structures to simulate an array of vframes in CHeap memory 157238104Sdes// was used. With new style lazy deoptimization the vframeArray is created in the 158238104Sdes// the thread that will use it and we can use a much simpler scheme for the vframeArray 159238104Sdes// leveraging existing data structures if we simply create a way to manage this one 160238104Sdes// special need for a ResourceMark. If ResourceMark simply inherited from CHeapObj 161238104Sdes// then existing ResourceMarks would work fine since no one use new to allocate them 162238104Sdes// and they would be stack allocated. This leaves open the possibilty of accidental 163238104Sdes// misuse so we simple duplicate the ResourceMark functionality here. 164238104Sdes 165238104Sdesclass DeoptResourceMark: public CHeapObj { 166238104Sdesprotected: 167238104Sdes ResourceArea *_area; // Resource area to stack allocate 168238104Sdes Chunk *_chunk; // saved arena chunk 169238104Sdes char *_hwm, *_max; 170238104Sdes NOT_PRODUCT(size_t _size_in_bytes;) 171238104Sdes 172238104Sdes void initialize(Thread *thread) { 173238104Sdes _area = thread->resource_area(); 174238104Sdes _chunk = _area->_chunk; 175238104Sdes _hwm = _area->_hwm; 176238104Sdes _max= _area->_max; 177238104Sdes NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 178238104Sdes debug_only(_area->_nesting++;) 179238104Sdes assert( _area->_nesting > 0, "must stack allocate RMs" ); 180238104Sdes } 181238104Sdes 182238104Sdes public: 183238104Sdes 184238104Sdes#ifndef ASSERT 185238104Sdes DeoptResourceMark(Thread *thread) { 186238104Sdes assert(thread == Thread::current(), "not the current thread"); 187238104Sdes initialize(thread); 188238104Sdes } 189238104Sdes#else 190238104Sdes DeoptResourceMark(Thread *thread); 191238104Sdes#endif // ASSERT 192238104Sdes 193238104Sdes DeoptResourceMark() { initialize(Thread::current()); } 194238104Sdes 195238104Sdes DeoptResourceMark( ResourceArea *r ) : 196238104Sdes _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) { 197238104Sdes NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 198238104Sdes debug_only(_area->_nesting++;) 199238104Sdes assert( _area->_nesting > 0, "must stack allocate RMs" ); 200238104Sdes } 201238104Sdes 202238104Sdes void reset_to_mark() { 203238104Sdes if (UseMallocOnly) free_malloced_objects(); 204238104Sdes 205238104Sdes if( _chunk->next() ) // Delete later chunks 206238104Sdes _chunk->next_chop(); 207238104Sdes _area->_chunk = _chunk; // Roll back arena to saved chunk 208238104Sdes _area->_hwm = _hwm; 209238104Sdes _area->_max = _max; 210238104Sdes 211238104Sdes // clear out this chunk (to detect allocation bugs) 212238104Sdes if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm); 213238104Sdes _area->set_size_in_bytes(size_in_bytes()); 214238104Sdes } 215238104Sdes 216238104Sdes ~DeoptResourceMark() { 217238104Sdes assert( _area->_nesting > 0, "must stack allocate RMs" ); 218238104Sdes debug_only(_area->_nesting--;) 219238104Sdes reset_to_mark(); 220238104Sdes } 221238104Sdes 222238104Sdes 223238104Sdes private: 224238104Sdes void free_malloced_objects() PRODUCT_RETURN; 225238104Sdes size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; 226238104Sdes}; 227238104Sdes