1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/memory/resourceArea.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,226 @@ 1.4 +/* 1.5 + * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// The resource area holds temporary data structures in the VM. 1.29 +// The actual allocation areas are thread local. Typical usage: 1.30 +// 1.31 +// ... 1.32 +// { 1.33 +// ResourceMark rm; 1.34 +// int foo[] = NEW_RESOURCE_ARRAY(int, 64); 1.35 +// ... 1.36 +// } 1.37 +// ... 1.38 + 1.39 +//------------------------------ResourceArea----------------------------------- 1.40 +// A ResourceArea is an Arena that supports safe usage of ResourceMark. 1.41 +class ResourceArea: public Arena { 1.42 + friend class ResourceMark; 1.43 + friend class DeoptResourceMark; 1.44 + debug_only(int _nesting;) // current # of nested ResourceMarks 1.45 + debug_only(static int _warned;) // to suppress multiple warnings 1.46 + 1.47 +public: 1.48 + ResourceArea() { 1.49 + debug_only(_nesting = 0;) 1.50 + } 1.51 + 1.52 + ResourceArea(size_t init_size) : Arena(init_size) { 1.53 + debug_only(_nesting = 0;); 1.54 + } 1.55 + 1.56 + char* allocate_bytes(size_t size) { 1.57 +#ifdef ASSERT 1.58 + if (_nesting < 1 && !_warned++) 1.59 + fatal("memory leak: allocating without ResourceMark"); 1.60 + if (UseMallocOnly) { 1.61 + // use malloc, but save pointer in res. area for later freeing 1.62 + char** save = (char**)internal_malloc_4(sizeof(char*)); 1.63 + return (*save = (char*)os::malloc(size)); 1.64 + } 1.65 +#endif 1.66 + return (char*)Amalloc(size); 1.67 + } 1.68 + 1.69 + debug_only(int nesting() const { return _nesting; }); 1.70 +}; 1.71 + 1.72 + 1.73 +//------------------------------ResourceMark----------------------------------- 1.74 +// A resource mark releases all resources allocated after it was constructed 1.75 +// when the destructor is called. Typically used as a local variable. 1.76 +class ResourceMark: public StackObj { 1.77 +protected: 1.78 + ResourceArea *_area; // Resource area to stack allocate 1.79 + Chunk *_chunk; // saved arena chunk 1.80 + char *_hwm, *_max; 1.81 + NOT_PRODUCT(size_t _size_in_bytes;) 1.82 + 1.83 + void initialize(Thread *thread) { 1.84 + _area = thread->resource_area(); 1.85 + _chunk = _area->_chunk; 1.86 + _hwm = _area->_hwm; 1.87 + _max= _area->_max; 1.88 + NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 1.89 + debug_only(_area->_nesting++;) 1.90 + assert( _area->_nesting > 0, "must stack allocate RMs" ); 1.91 + } 1.92 + 1.93 + public: 1.94 + 1.95 +#ifndef ASSERT 1.96 + ResourceMark(Thread *thread) { 1.97 + assert(thread == Thread::current(), "not the current thread"); 1.98 + initialize(thread); 1.99 + } 1.100 +#else 1.101 + ResourceMark(Thread *thread); 1.102 +#endif // ASSERT 1.103 + 1.104 + ResourceMark() { initialize(Thread::current()); } 1.105 + 1.106 + ResourceMark( ResourceArea *r ) : 1.107 + _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) { 1.108 + NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 1.109 + debug_only(_area->_nesting++;) 1.110 + assert( _area->_nesting > 0, "must stack allocate RMs" ); 1.111 + } 1.112 + 1.113 + void reset_to_mark() { 1.114 + if (UseMallocOnly) free_malloced_objects(); 1.115 + 1.116 + if( _chunk->next() ) // Delete later chunks 1.117 + _chunk->next_chop(); 1.118 + _area->_chunk = _chunk; // Roll back arena to saved chunk 1.119 + _area->_hwm = _hwm; 1.120 + _area->_max = _max; 1.121 + 1.122 + // clear out this chunk (to detect allocation bugs) 1.123 + if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm); 1.124 + _area->set_size_in_bytes(size_in_bytes()); 1.125 + } 1.126 + 1.127 + ~ResourceMark() { 1.128 + assert( _area->_nesting > 0, "must stack allocate RMs" ); 1.129 + debug_only(_area->_nesting--;) 1.130 + reset_to_mark(); 1.131 + } 1.132 + 1.133 + 1.134 + private: 1.135 + void free_malloced_objects() PRODUCT_RETURN; 1.136 + size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; 1.137 +}; 1.138 + 1.139 +//------------------------------DeoptResourceMark----------------------------------- 1.140 +// A deopt resource mark releases all resources allocated after it was constructed 1.141 +// when the destructor is called. Typically used as a local variable. It differs 1.142 +// from a typical resource more in that it is C-Heap allocated so that deoptimization 1.143 +// can use data structures that are arena based but are not amenable to vanilla 1.144 +// ResourceMarks because deoptimization can not use a stack allocated mark. During 1.145 +// deoptimization we go thru the following steps: 1.146 +// 1.147 +// 0: start in assembly stub and call either uncommon_trap/fetch_unroll_info 1.148 +// 1: create the vframeArray (contains pointers to Resource allocated structures) 1.149 +// This allocates the DeoptResourceMark. 1.150 +// 2: return to assembly stub and remove stub frame and deoptee frame and create 1.151 +// the new skeletal frames. 1.152 +// 3: push new stub frame and call unpack_frames 1.153 +// 4: retrieve information from the vframeArray to populate the skeletal frames 1.154 +// 5: release the DeoptResourceMark 1.155 +// 6: return to stub and eventually to interpreter 1.156 +// 1.157 +// With old style eager deoptimization the vframeArray was created by the vmThread there 1.158 +// was no way for the vframeArray to contain resource allocated objects and so 1.159 +// a complex set of data structures to simulate an array of vframes in CHeap memory 1.160 +// was used. With new style lazy deoptimization the vframeArray is created in the 1.161 +// the thread that will use it and we can use a much simpler scheme for the vframeArray 1.162 +// leveraging existing data structures if we simply create a way to manage this one 1.163 +// special need for a ResourceMark. If ResourceMark simply inherited from CHeapObj 1.164 +// then existing ResourceMarks would work fine since no one use new to allocate them 1.165 +// and they would be stack allocated. This leaves open the possibilty of accidental 1.166 +// misuse so we simple duplicate the ResourceMark functionality here. 1.167 + 1.168 +class DeoptResourceMark: public CHeapObj { 1.169 +protected: 1.170 + ResourceArea *_area; // Resource area to stack allocate 1.171 + Chunk *_chunk; // saved arena chunk 1.172 + char *_hwm, *_max; 1.173 + NOT_PRODUCT(size_t _size_in_bytes;) 1.174 + 1.175 + void initialize(Thread *thread) { 1.176 + _area = thread->resource_area(); 1.177 + _chunk = _area->_chunk; 1.178 + _hwm = _area->_hwm; 1.179 + _max= _area->_max; 1.180 + NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 1.181 + debug_only(_area->_nesting++;) 1.182 + assert( _area->_nesting > 0, "must stack allocate RMs" ); 1.183 + } 1.184 + 1.185 + public: 1.186 + 1.187 +#ifndef ASSERT 1.188 + DeoptResourceMark(Thread *thread) { 1.189 + assert(thread == Thread::current(), "not the current thread"); 1.190 + initialize(thread); 1.191 + } 1.192 +#else 1.193 + DeoptResourceMark(Thread *thread); 1.194 +#endif // ASSERT 1.195 + 1.196 + DeoptResourceMark() { initialize(Thread::current()); } 1.197 + 1.198 + DeoptResourceMark( ResourceArea *r ) : 1.199 + _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) { 1.200 + NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 1.201 + debug_only(_area->_nesting++;) 1.202 + assert( _area->_nesting > 0, "must stack allocate RMs" ); 1.203 + } 1.204 + 1.205 + void reset_to_mark() { 1.206 + if (UseMallocOnly) free_malloced_objects(); 1.207 + 1.208 + if( _chunk->next() ) // Delete later chunks 1.209 + _chunk->next_chop(); 1.210 + _area->_chunk = _chunk; // Roll back arena to saved chunk 1.211 + _area->_hwm = _hwm; 1.212 + _area->_max = _max; 1.213 + 1.214 + // clear out this chunk (to detect allocation bugs) 1.215 + if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm); 1.216 + _area->set_size_in_bytes(size_in_bytes()); 1.217 + } 1.218 + 1.219 + ~DeoptResourceMark() { 1.220 + assert( _area->_nesting > 0, "must stack allocate RMs" ); 1.221 + debug_only(_area->_nesting--;) 1.222 + reset_to_mark(); 1.223 + } 1.224 + 1.225 + 1.226 + private: 1.227 + void free_malloced_objects() PRODUCT_RETURN; 1.228 + size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; 1.229 +};