1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is SpiderMonkey global object code.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * the Mozilla Foundation.
21 : * Portions created by the Initial Developer are Copyright (C) 2012
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef jsgc_root_h__
41 : #define jsgc_root_h__
42 :
43 : #include "jsapi.h"
44 : #include "jsprvtd.h"
45 :
46 : namespace js {
47 :
48 : /*
49 : * Moving GC Stack Rooting
50 : *
51 : * A moving GC may change the physical location of GC allocated things, even
52 : * when they are rooted, updating all pointers to the thing to refer to its new
53 : * location. The GC must therefore know about all live pointers to a thing,
54 : * not just one of them, in order to behave correctly.
55 : *
56 : * The classes below are used to root stack locations whose value may be held
57 : * live across a call that can trigger GC (i.e. a call which might allocate any
58 : * GC things). For a code fragment such as:
59 : *
60 : * Foo();
61 : * ... = obj->lastProperty();
62 : *
63 : * If Foo() can trigger a GC, the stack location of obj must be rooted to
64 : * ensure that the GC does not move the JSObject referred to by obj without
65 : * updating obj's location itself. This rooting must happen regardless of
66 : * whether there are other roots which ensure that the object itself will not
67 : * be collected.
68 : *
69 : * If Foo() cannot trigger a GC, and the same holds for all other calls made
70 : * between obj's definitions and its last uses, then no rooting is required.
71 : *
72 : * Several classes are available for rooting stack locations. All are templated
73 : * on the type T of the value being rooted, for which RootMethods<T> must
74 : * have an instantiation.
75 : *
76 : * - Root<T> roots an existing stack allocated variable or other location of
77 : * type T. This is typically used either when a variable only needs to be
78 : * rooted on certain rare paths, or when a function takes a bare GC thing
79 : * pointer as an argument and needs to root it. In the latter case a
80 : * Handle<T> is generally preferred, see below.
81 : *
82 : * - RootedVar<T> declares a variable of type T, whose value is always rooted.
83 : *
84 : * - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
85 : * coerced automatically from such a Root<T> or RootedVar<T>. Functions which
86 : * take GC things or values as arguments and need to root those arguments
87 : * should generally replace those arguments with handles and avoid any
88 : * explicit rooting. This has two benefits. First, when several such
89 : * functions call each other then redundant rooting of multiple copies of the
90 : * GC thing can be avoided. Second, if the caller does not pass a rooted
91 : * value a compile error will be generated, which is quicker and easier to
92 : * fix than when relying on a separate rooting analysis.
93 : */
94 :
95 : template <> struct RootMethods<const jsid>
96 : {
97 : static jsid initial() { return JSID_VOID; }
98 : static ThingRootKind kind() { return THING_ROOT_ID; }
99 23896995 : static bool poisoned(jsid id) { return IsPoisonedId(id); }
100 : };
101 :
102 : template <> struct RootMethods<jsid>
103 : {
104 19822880 : static jsid initial() { return JSID_VOID; }
105 : static ThingRootKind kind() { return THING_ROOT_ID; }
106 221951837 : static bool poisoned(jsid id) { return IsPoisonedId(id); }
107 : };
108 :
109 : template <> struct RootMethods<const Value>
110 : {
111 : static Value initial() { return UndefinedValue(); }
112 : static ThingRootKind kind() { return THING_ROOT_VALUE; }
113 : static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
114 : };
115 :
116 : template <> struct RootMethods<Value>
117 : {
118 36788638 : static Value initial() { return UndefinedValue(); }
119 : static ThingRootKind kind() { return THING_ROOT_VALUE; }
120 90771287 : static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
121 : };
122 :
123 : template <typename T>
124 : struct RootMethods<T *>
125 : {
126 113588604 : static T *initial() { return NULL; }
127 : static ThingRootKind kind() { return T::rootKind(); }
128 478938253 : static bool poisoned(T *v) { return IsPoisonedPtr(v); }
129 : };
130 :
131 : /*
132 : * Root a stack location holding a GC thing. This takes a stack pointer
133 : * and ensures that throughout its lifetime the referenced variable
134 : * will remain pinned against a moving GC.
135 : *
136 : * It is important to ensure that the location referenced by a Root is
137 : * initialized, as otherwise the GC may try to use the the uninitialized value.
138 : * It is generally preferable to use either RootedVar for local variables, or
139 : * Handle for arguments.
140 : */
141 : template <typename T>
142 : class Root
143 : {
144 : public:
145 728322273 : Root(JSContext *cx, const T *ptr
146 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
147 728322273 : {
148 : #ifdef JSGC_ROOT_ANALYSIS
149 : ThingRootKind kind = RootMethods<T>::kind();
150 : this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
151 : this->prev = *stack;
152 : *stack = this;
153 : #endif
154 :
155 728322273 : JS_ASSERT(!RootMethods<T>::poisoned(*ptr));
156 :
157 728322273 : this->ptr = ptr;
158 :
159 728322273 : JS_GUARD_OBJECT_NOTIFIER_INIT;
160 728322273 : }
161 :
162 728322273 : ~Root()
163 : {
164 : #ifdef JSGC_ROOT_ANALYSIS
165 : JS_ASSERT(*stack == this);
166 : *stack = prev;
167 : #endif
168 728322273 : }
169 :
170 : #ifdef JSGC_ROOT_ANALYSIS
171 : Root<T> *previous() { return prev; }
172 : #endif
173 :
174 45688419 : const T *address() const { return ptr; }
175 :
176 : private:
177 :
178 : #ifdef JSGC_ROOT_ANALYSIS
179 : Root<T> **stack, *prev;
180 : #endif
181 : const T *ptr;
182 :
183 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
184 : };
185 :
186 : template<typename T> template <typename S>
187 : inline
188 45688419 : Handle<T>::Handle(const Root<S> &root)
189 : {
190 45688419 : testAssign<S>();
191 45688419 : ptr = reinterpret_cast<const T *>(root.address());
192 45688419 : }
193 :
194 : typedef Root<JSObject*> RootObject;
195 : typedef Root<JSFunction*> RootFunction;
196 : typedef Root<Shape*> RootShape;
197 : typedef Root<BaseShape*> RootBaseShape;
198 : typedef Root<types::TypeObject*> RootTypeObject;
199 : typedef Root<JSString*> RootString;
200 : typedef Root<JSAtom*> RootAtom;
201 : typedef Root<jsid> RootId;
202 : typedef Root<Value> RootValue;
203 :
204 : /* Mark a stack location as a root for a rooting analysis. */
205 : class CheckRoot
206 626052 : {
207 : #if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS)
208 :
209 : CheckRoot **stack, *prev;
210 : const uint8_t *ptr;
211 :
212 : public:
213 : template <typename T>
214 : CheckRoot(JSContext *cx, const T *ptr
215 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
216 : {
217 : this->stack = &cx->checkGCRooters;
218 : this->prev = *stack;
219 : *stack = this;
220 : this->ptr = static_cast<const uint8_t*>(ptr);
221 : JS_GUARD_OBJECT_NOTIFIER_INIT;
222 : }
223 :
224 : ~CheckRoot()
225 : {
226 : JS_ASSERT(*stack == this);
227 : *stack = prev;
228 : }
229 :
230 : CheckRoot *previous() { return prev; }
231 :
232 : bool contains(const uint8_t *v, size_t len) {
233 : return ptr >= v && ptr < v + len;
234 : }
235 :
236 : #else /* DEBUG && JSGC_ROOT_ANALYSIS */
237 :
238 : public:
239 : template <typename T>
240 626052 : CheckRoot(JSContext *cx, const T *ptr
241 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
242 626052 : {
243 626052 : JS_GUARD_OBJECT_NOTIFIER_INIT;
244 626052 : }
245 :
246 : #endif /* DEBUG && JSGC_ROOT_ANALYSIS */
247 :
248 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
249 : };
250 :
251 : /* Make a local variable which stays rooted throughout its lifetime. */
252 : template <typename T>
253 : class RootedVar
254 210038395 : {
255 : public:
256 78823284 : RootedVar(JSContext *cx)
257 78823284 : : ptr(RootMethods<T>::initial()), root(cx, &ptr)
258 78823284 : {}
259 :
260 131215111 : RootedVar(JSContext *cx, T initial)
261 131215111 : : ptr(initial), root(cx, &ptr)
262 131215111 : {}
263 :
264 198936797 : operator T () { return ptr; }
265 525264022 : T operator ->() { return ptr; }
266 43576412 : T * address() { return &ptr; }
267 18013354 : const T * address() const { return &ptr; }
268 0 : T raw() { return ptr; }
269 :
270 87236099 : T & operator =(T value)
271 : {
272 87236099 : JS_ASSERT(!RootMethods<T>::poisoned(value));
273 87236099 : ptr = value;
274 87236099 : return ptr;
275 : }
276 :
277 : private:
278 : T ptr;
279 : Root<T> root;
280 : };
281 :
282 : template <typename T> template <typename S>
283 : inline
284 18013354 : Handle<T>::Handle(const RootedVar<S> &root)
285 : {
286 18013354 : ptr = reinterpret_cast<const T *>(root.address());
287 18013354 : }
288 :
289 : typedef RootedVar<JSObject*> RootedVarObject;
290 : typedef RootedVar<JSFunction*> RootedVarFunction;
291 : typedef RootedVar<Shape*> RootedVarShape;
292 : typedef RootedVar<BaseShape*> RootedVarBaseShape;
293 : typedef RootedVar<types::TypeObject*> RootedVarTypeObject;
294 : typedef RootedVar<JSString*> RootedVarString;
295 : typedef RootedVar<JSAtom*> RootedVarAtom;
296 : typedef RootedVar<jsid> RootedVarId;
297 : typedef RootedVar<Value> RootedVarValue;
298 :
299 : } /* namespace js */
300 : #endif /* jsgc_root_h___ */
|