LCOV - code coverage report
Current view: directory - js/src/gc - Root.h (source / functions) Found Hit Coverage
Test: app.info Lines: 44 43 97.7 %
Date: 2012-06-02 Functions: 115 114 99.1 %

       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___ */

Generated by: LCOV version 1.7