1 /* 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_MEMORY_RESOURCEAREA_HPP 26 #define SHARE_VM_MEMORY_RESOURCEAREA_HPP 27 28 #include "memory/allocation.hpp" 29 #ifdef TARGET_OS_FAMILY_linux 30 # include "thread_linux.inline.hpp" 31 #endif 32 #ifdef TARGET_OS_FAMILY_solaris 33 # include "thread_solaris.inline.hpp" 34 #endif 35 #ifdef TARGET_OS_FAMILY_windows 36 # include "thread_windows.inline.hpp" 37 #endif 38 #ifdef TARGET_OS_FAMILY_bsd 39 # include "thread_bsd.inline.hpp" 40 #endif 41 42 // The resource area holds temporary data structures in the VM. 43 // The actual allocation areas are thread local. Typical usage: 44 // 45 // ... 46 // { 47 // ResourceMark rm; 48 // int foo[] = NEW_RESOURCE_ARRAY(int, 64); 49 // ... 50 // } 51 // ... 52 53 //------------------------------ResourceArea----------------------------------- 54 // A ResourceArea is an Arena that supports safe usage of ResourceMark. 55 class ResourceArea: public Arena { 56 friend class ResourceMark; 57 friend class DeoptResourceMark; 58 friend class VMStructs; 59 debug_only(int _nesting;) // current # of nested ResourceMarks 60 debug_only(static int _warned;) // to suppress multiple warnings 61 62 public: 63 ResourceArea() { 64 debug_only(_nesting = 0;) 65 } 66 67 ResourceArea(size_t init_size) : Arena(init_size) { 68 debug_only(_nesting = 0;); 69 } 70 71 char* allocate_bytes(size_t size) { 72 #ifdef ASSERT 73 if (_nesting < 1 && !_warned++) 74 fatal("memory leak: allocating without ResourceMark"); 75 if (UseMallocOnly) { 76 // use malloc, but save pointer in res. area for later freeing 77 char** save = (char**)internal_malloc_4(sizeof(char*)); 78 return (*save = (char*)os::malloc(size)); 79 } 80 #endif 81 return (char*)Amalloc(size); 82 } 83 84 debug_only(int nesting() const { return _nesting; }); 85 }; 86 87 88 //------------------------------ResourceMark----------------------------------- 89 // A resource mark releases all resources allocated after it was constructed 90 // when the destructor is called. Typically used as a local variable. 91 class ResourceMark: public StackObj { 92 protected: 93 ResourceArea *_area; // Resource area to stack allocate 94 Chunk *_chunk; // saved arena chunk 95 char *_hwm, *_max; 96 NOT_PRODUCT(size_t _size_in_bytes;) 97 98 void initialize(Thread *thread) { 99 _area = thread->resource_area(); 100 _chunk = _area->_chunk; 101 _hwm = _area->_hwm; 102 _max= _area->_max; 103 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 104 debug_only(_area->_nesting++;) 105 assert( _area->_nesting > 0, "must stack allocate RMs" ); 106 } 107 108 public: 109 110 #ifndef ASSERT 111 ResourceMark(Thread *thread) { 112 assert(thread == Thread::current(), "not the current thread"); 113 initialize(thread); 114 } 115 #else 116 ResourceMark(Thread *thread); 117 #endif // ASSERT 118 119 ResourceMark() { initialize(Thread::current()); } 120 121 ResourceMark( ResourceArea *r ) : 122 _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) { 123 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 124 debug_only(_area->_nesting++;) 125 assert( _area->_nesting > 0, "must stack allocate RMs" ); 126 } 127 128 void reset_to_mark() { 129 if (UseMallocOnly) free_malloced_objects(); 130 131 if( _chunk->next() ) // Delete later chunks 132 _chunk->next_chop(); 133 _area->_chunk = _chunk; // Roll back arena to saved chunk 134 _area->_hwm = _hwm; 135 _area->_max = _max; 136 137 // clear out this chunk (to detect allocation bugs) 138 if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm); 139 _area->set_size_in_bytes(size_in_bytes()); 140 } 141 142 ~ResourceMark() { 143 assert( _area->_nesting > 0, "must stack allocate RMs" ); 144 debug_only(_area->_nesting--;) 145 reset_to_mark(); 146 } 147 148 149 private: 150 void free_malloced_objects() PRODUCT_RETURN; 151 size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; 152 }; 153 154 //------------------------------DeoptResourceMark----------------------------------- 155 // A deopt resource mark releases all resources allocated after it was constructed 156 // when the destructor is called. Typically used as a local variable. It differs 157 // from a typical resource more in that it is C-Heap allocated so that deoptimization 158 // can use data structures that are arena based but are not amenable to vanilla 159 // ResourceMarks because deoptimization can not use a stack allocated mark. During 160 // deoptimization we go thru the following steps: 161 // 162 // 0: start in assembly stub and call either uncommon_trap/fetch_unroll_info 163 // 1: create the vframeArray (contains pointers to Resource allocated structures) 164 // This allocates the DeoptResourceMark. 165 // 2: return to assembly stub and remove stub frame and deoptee frame and create 166 // the new skeletal frames. 167 // 3: push new stub frame and call unpack_frames 168 // 4: retrieve information from the vframeArray to populate the skeletal frames 169 // 5: release the DeoptResourceMark 170 // 6: return to stub and eventually to interpreter 171 // 172 // With old style eager deoptimization the vframeArray was created by the vmThread there 173 // was no way for the vframeArray to contain resource allocated objects and so 174 // a complex set of data structures to simulate an array of vframes in CHeap memory 175 // was used. With new style lazy deoptimization the vframeArray is created in the 176 // the thread that will use it and we can use a much simpler scheme for the vframeArray 177 // leveraging existing data structures if we simply create a way to manage this one 178 // special need for a ResourceMark. If ResourceMark simply inherited from CHeapObj 179 // then existing ResourceMarks would work fine since no one use new to allocate them 180 // and they would be stack allocated. This leaves open the possibilty of accidental 181 // misuse so we simple duplicate the ResourceMark functionality here. 182 183 class DeoptResourceMark: public CHeapObj { 184 protected: 185 ResourceArea *_area; // Resource area to stack allocate 186 Chunk *_chunk; // saved arena chunk 187 char *_hwm, *_max; 188 NOT_PRODUCT(size_t _size_in_bytes;) 189 190 void initialize(Thread *thread) { 191 _area = thread->resource_area(); 192 _chunk = _area->_chunk; 193 _hwm = _area->_hwm; 194 _max= _area->_max; 195 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 196 debug_only(_area->_nesting++;) 197 assert( _area->_nesting > 0, "must stack allocate RMs" ); 198 } 199 200 public: 201 202 #ifndef ASSERT 203 DeoptResourceMark(Thread *thread) { 204 assert(thread == Thread::current(), "not the current thread"); 205 initialize(thread); 206 } 207 #else 208 DeoptResourceMark(Thread *thread); 209 #endif // ASSERT 210 211 DeoptResourceMark() { initialize(Thread::current()); } 212 213 DeoptResourceMark( ResourceArea *r ) : 214 _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) { 215 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();) 216 debug_only(_area->_nesting++;) 217 assert( _area->_nesting > 0, "must stack allocate RMs" ); 218 } 219 220 void reset_to_mark() { 221 if (UseMallocOnly) free_malloced_objects(); 222 223 if( _chunk->next() ) // Delete later chunks 224 _chunk->next_chop(); 225 _area->_chunk = _chunk; // Roll back arena to saved chunk 226 _area->_hwm = _hwm; 227 _area->_max = _max; 228 229 // clear out this chunk (to detect allocation bugs) 230 if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm); 231 _area->set_size_in_bytes(size_in_bytes()); 232 } 233 234 ~DeoptResourceMark() { 235 assert( _area->_nesting > 0, "must stack allocate RMs" ); 236 debug_only(_area->_nesting--;) 237 reset_to_mark(); 238 } 239 240 241 private: 242 void free_malloced_objects() PRODUCT_RETURN; 243 size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; 244 }; 245 246 #endif // SHARE_VM_MEMORY_RESOURCEAREA_HPP