annotate src/share/vm/memory/resourceArea.hpp @ 452:00b023ae2d78

6722113: CMS: Incorrect overflow handling during precleaning of Reference lists Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery. Reviewed-by: apetrusenko, jcoomes
author ysr
date Thu, 20 Nov 2008 12:27:41 -0800
parents a61af66fc99e
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 // The resource area holds temporary data structures in the VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
26 // The actual allocation areas are thread local. Typical usage:
a61af66fc99e Initial load
duke
parents:
diff changeset
27 //
a61af66fc99e Initial load
duke
parents:
diff changeset
28 // ...
a61af66fc99e Initial load
duke
parents:
diff changeset
29 // {
a61af66fc99e Initial load
duke
parents:
diff changeset
30 // ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
31 // int foo[] = NEW_RESOURCE_ARRAY(int, 64);
a61af66fc99e Initial load
duke
parents:
diff changeset
32 // ...
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // }
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // ...
a61af66fc99e Initial load
duke
parents:
diff changeset
35
a61af66fc99e Initial load
duke
parents:
diff changeset
36 //------------------------------ResourceArea-----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // A ResourceArea is an Arena that supports safe usage of ResourceMark.
a61af66fc99e Initial load
duke
parents:
diff changeset
38 class ResourceArea: public Arena {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 friend class ResourceMark;
a61af66fc99e Initial load
duke
parents:
diff changeset
40 friend class DeoptResourceMark;
a61af66fc99e Initial load
duke
parents:
diff changeset
41 debug_only(int _nesting;) // current # of nested ResourceMarks
a61af66fc99e Initial load
duke
parents:
diff changeset
42 debug_only(static int _warned;) // to suppress multiple warnings
a61af66fc99e Initial load
duke
parents:
diff changeset
43
a61af66fc99e Initial load
duke
parents:
diff changeset
44 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
45 ResourceArea() {
a61af66fc99e Initial load
duke
parents:
diff changeset
46 debug_only(_nesting = 0;)
a61af66fc99e Initial load
duke
parents:
diff changeset
47 }
a61af66fc99e Initial load
duke
parents:
diff changeset
48
a61af66fc99e Initial load
duke
parents:
diff changeset
49 ResourceArea(size_t init_size) : Arena(init_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
50 debug_only(_nesting = 0;);
a61af66fc99e Initial load
duke
parents:
diff changeset
51 }
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 char* allocate_bytes(size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
54 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
55 if (_nesting < 1 && !_warned++)
a61af66fc99e Initial load
duke
parents:
diff changeset
56 fatal("memory leak: allocating without ResourceMark");
a61af66fc99e Initial load
duke
parents:
diff changeset
57 if (UseMallocOnly) {
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // use malloc, but save pointer in res. area for later freeing
a61af66fc99e Initial load
duke
parents:
diff changeset
59 char** save = (char**)internal_malloc_4(sizeof(char*));
a61af66fc99e Initial load
duke
parents:
diff changeset
60 return (*save = (char*)os::malloc(size));
a61af66fc99e Initial load
duke
parents:
diff changeset
61 }
a61af66fc99e Initial load
duke
parents:
diff changeset
62 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
63 return (char*)Amalloc(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
64 }
a61af66fc99e Initial load
duke
parents:
diff changeset
65
a61af66fc99e Initial load
duke
parents:
diff changeset
66 debug_only(int nesting() const { return _nesting; });
a61af66fc99e Initial load
duke
parents:
diff changeset
67 };
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 //------------------------------ResourceMark-----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
71 // A resource mark releases all resources allocated after it was constructed
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // when the destructor is called. Typically used as a local variable.
a61af66fc99e Initial load
duke
parents:
diff changeset
73 class ResourceMark: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
74 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
75 ResourceArea *_area; // Resource area to stack allocate
a61af66fc99e Initial load
duke
parents:
diff changeset
76 Chunk *_chunk; // saved arena chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
77 char *_hwm, *_max;
a61af66fc99e Initial load
duke
parents:
diff changeset
78 NOT_PRODUCT(size_t _size_in_bytes;)
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 void initialize(Thread *thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
81 _area = thread->resource_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
82 _chunk = _area->_chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
83 _hwm = _area->_hwm;
a61af66fc99e Initial load
duke
parents:
diff changeset
84 _max= _area->_max;
a61af66fc99e Initial load
duke
parents:
diff changeset
85 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
a61af66fc99e Initial load
duke
parents:
diff changeset
86 debug_only(_area->_nesting++;)
a61af66fc99e Initial load
duke
parents:
diff changeset
87 assert( _area->_nesting > 0, "must stack allocate RMs" );
a61af66fc99e Initial load
duke
parents:
diff changeset
88 }
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
91
a61af66fc99e Initial load
duke
parents:
diff changeset
92 #ifndef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
93 ResourceMark(Thread *thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
94 assert(thread == Thread::current(), "not the current thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
95 initialize(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
96 }
a61af66fc99e Initial load
duke
parents:
diff changeset
97 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
98 ResourceMark(Thread *thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
99 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
100
a61af66fc99e Initial load
duke
parents:
diff changeset
101 ResourceMark() { initialize(Thread::current()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
102
a61af66fc99e Initial load
duke
parents:
diff changeset
103 ResourceMark( ResourceArea *r ) :
a61af66fc99e Initial load
duke
parents:
diff changeset
104 _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
a61af66fc99e Initial load
duke
parents:
diff changeset
106 debug_only(_area->_nesting++;)
a61af66fc99e Initial load
duke
parents:
diff changeset
107 assert( _area->_nesting > 0, "must stack allocate RMs" );
a61af66fc99e Initial load
duke
parents:
diff changeset
108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
109
a61af66fc99e Initial load
duke
parents:
diff changeset
110 void reset_to_mark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 if (UseMallocOnly) free_malloced_objects();
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 if( _chunk->next() ) // Delete later chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
114 _chunk->next_chop();
a61af66fc99e Initial load
duke
parents:
diff changeset
115 _area->_chunk = _chunk; // Roll back arena to saved chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
116 _area->_hwm = _hwm;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 _area->_max = _max;
a61af66fc99e Initial load
duke
parents:
diff changeset
118
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // clear out this chunk (to detect allocation bugs)
a61af66fc99e Initial load
duke
parents:
diff changeset
120 if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm);
a61af66fc99e Initial load
duke
parents:
diff changeset
121 _area->set_size_in_bytes(size_in_bytes());
a61af66fc99e Initial load
duke
parents:
diff changeset
122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 ~ResourceMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 assert( _area->_nesting > 0, "must stack allocate RMs" );
a61af66fc99e Initial load
duke
parents:
diff changeset
126 debug_only(_area->_nesting--;)
a61af66fc99e Initial load
duke
parents:
diff changeset
127 reset_to_mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
129
a61af66fc99e Initial load
duke
parents:
diff changeset
130
a61af66fc99e Initial load
duke
parents:
diff changeset
131 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
132 void free_malloced_objects() PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
133 size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0;
a61af66fc99e Initial load
duke
parents:
diff changeset
134 };
a61af66fc99e Initial load
duke
parents:
diff changeset
135
a61af66fc99e Initial load
duke
parents:
diff changeset
136 //------------------------------DeoptResourceMark-----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // A deopt resource mark releases all resources allocated after it was constructed
a61af66fc99e Initial load
duke
parents:
diff changeset
138 // when the destructor is called. Typically used as a local variable. It differs
a61af66fc99e Initial load
duke
parents:
diff changeset
139 // from a typical resource more in that it is C-Heap allocated so that deoptimization
a61af66fc99e Initial load
duke
parents:
diff changeset
140 // can use data structures that are arena based but are not amenable to vanilla
a61af66fc99e Initial load
duke
parents:
diff changeset
141 // ResourceMarks because deoptimization can not use a stack allocated mark. During
a61af66fc99e Initial load
duke
parents:
diff changeset
142 // deoptimization we go thru the following steps:
a61af66fc99e Initial load
duke
parents:
diff changeset
143 //
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // 0: start in assembly stub and call either uncommon_trap/fetch_unroll_info
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // 1: create the vframeArray (contains pointers to Resource allocated structures)
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // This allocates the DeoptResourceMark.
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // 2: return to assembly stub and remove stub frame and deoptee frame and create
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // the new skeletal frames.
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // 3: push new stub frame and call unpack_frames
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // 4: retrieve information from the vframeArray to populate the skeletal frames
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // 5: release the DeoptResourceMark
a61af66fc99e Initial load
duke
parents:
diff changeset
152 // 6: return to stub and eventually to interpreter
a61af66fc99e Initial load
duke
parents:
diff changeset
153 //
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // With old style eager deoptimization the vframeArray was created by the vmThread there
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // was no way for the vframeArray to contain resource allocated objects and so
a61af66fc99e Initial load
duke
parents:
diff changeset
156 // a complex set of data structures to simulate an array of vframes in CHeap memory
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // was used. With new style lazy deoptimization the vframeArray is created in the
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // the thread that will use it and we can use a much simpler scheme for the vframeArray
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // leveraging existing data structures if we simply create a way to manage this one
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // special need for a ResourceMark. If ResourceMark simply inherited from CHeapObj
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // then existing ResourceMarks would work fine since no one use new to allocate them
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // and they would be stack allocated. This leaves open the possibilty of accidental
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // misuse so we simple duplicate the ResourceMark functionality here.
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165 class DeoptResourceMark: public CHeapObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
167 ResourceArea *_area; // Resource area to stack allocate
a61af66fc99e Initial load
duke
parents:
diff changeset
168 Chunk *_chunk; // saved arena chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
169 char *_hwm, *_max;
a61af66fc99e Initial load
duke
parents:
diff changeset
170 NOT_PRODUCT(size_t _size_in_bytes;)
a61af66fc99e Initial load
duke
parents:
diff changeset
171
a61af66fc99e Initial load
duke
parents:
diff changeset
172 void initialize(Thread *thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 _area = thread->resource_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
174 _chunk = _area->_chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
175 _hwm = _area->_hwm;
a61af66fc99e Initial load
duke
parents:
diff changeset
176 _max= _area->_max;
a61af66fc99e Initial load
duke
parents:
diff changeset
177 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
a61af66fc99e Initial load
duke
parents:
diff changeset
178 debug_only(_area->_nesting++;)
a61af66fc99e Initial load
duke
parents:
diff changeset
179 assert( _area->_nesting > 0, "must stack allocate RMs" );
a61af66fc99e Initial load
duke
parents:
diff changeset
180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
181
a61af66fc99e Initial load
duke
parents:
diff changeset
182 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184 #ifndef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
185 DeoptResourceMark(Thread *thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 assert(thread == Thread::current(), "not the current thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
187 initialize(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
190 DeoptResourceMark(Thread *thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
191 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
192
a61af66fc99e Initial load
duke
parents:
diff changeset
193 DeoptResourceMark() { initialize(Thread::current()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 DeoptResourceMark( ResourceArea *r ) :
a61af66fc99e Initial load
duke
parents:
diff changeset
196 _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) {
a61af66fc99e Initial load
duke
parents:
diff changeset
197 NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
a61af66fc99e Initial load
duke
parents:
diff changeset
198 debug_only(_area->_nesting++;)
a61af66fc99e Initial load
duke
parents:
diff changeset
199 assert( _area->_nesting > 0, "must stack allocate RMs" );
a61af66fc99e Initial load
duke
parents:
diff changeset
200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 void reset_to_mark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
203 if (UseMallocOnly) free_malloced_objects();
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 if( _chunk->next() ) // Delete later chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
206 _chunk->next_chop();
a61af66fc99e Initial load
duke
parents:
diff changeset
207 _area->_chunk = _chunk; // Roll back arena to saved chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
208 _area->_hwm = _hwm;
a61af66fc99e Initial load
duke
parents:
diff changeset
209 _area->_max = _max;
a61af66fc99e Initial load
duke
parents:
diff changeset
210
a61af66fc99e Initial load
duke
parents:
diff changeset
211 // clear out this chunk (to detect allocation bugs)
a61af66fc99e Initial load
duke
parents:
diff changeset
212 if (ZapResourceArea) memset(_hwm, badResourceValue, _max - _hwm);
a61af66fc99e Initial load
duke
parents:
diff changeset
213 _area->set_size_in_bytes(size_in_bytes());
a61af66fc99e Initial load
duke
parents:
diff changeset
214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
215
a61af66fc99e Initial load
duke
parents:
diff changeset
216 ~DeoptResourceMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
217 assert( _area->_nesting > 0, "must stack allocate RMs" );
a61af66fc99e Initial load
duke
parents:
diff changeset
218 debug_only(_area->_nesting--;)
a61af66fc99e Initial load
duke
parents:
diff changeset
219 reset_to_mark();
a61af66fc99e Initial load
duke
parents:
diff changeset
220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222
a61af66fc99e Initial load
duke
parents:
diff changeset
223 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
224 void free_malloced_objects() PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
225 size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 };