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