LCOV - app.info - js/src/frontend/ParseMaps.h

LCOV - code coverage report
| Current view: | directory - js/src/frontend - ParseMaps.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 131 | 120 | 91.6 %
| Date: | 2012-04-07 | Functions: | 46 | 45 | 97.8 %

           1                 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=4 sw=4 et tw=99 ft=cpp:
           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 JavaScript engine.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Mozilla Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 2011
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *   Chris Leary <cdleary@mozilla.com>
          26                 :  *
          27                 :  * Alternatively, the contents of this file may be used under the terms of
          28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          31                 :  * of those above. If you wish to allow use of your version of this file only
          32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          33                 :  * use your version of this file under the terms of the MPL, indicate your
          34                 :  * decision by deleting the provisions above and replace them with the notice
          35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          36                 :  * the provisions above, a recipient may use your version of this file under
          37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : #ifndef ParseMaps_h__
          42                 : #define ParseMaps_h__
          43                 :
          44                 : #include "mozilla/Attributes.h"
          45                 :
          46                 : #include "ds/InlineMap.h"
          47                 : #include "js/HashTable.h"
          48                 : #include "js/Vector.h"
          49                 :
          50                 : namespace js {
          51                 :
          52                 : struct Definition;
          53                 :
          54                 : /*
          55                 :  * A pool that permits the reuse of the backing storage for the defn, index, or
          56                 :  * defn-or-header (multi) maps.
          57                 :  *
          58                 :  * The pool owns all the maps that are given out, and is responsible for
          59                 :  * relinquishing all resources when |purgeAll| is triggered.
          60                 :  */
          61                 : class ParseMapPool
          62                 : {
          63                 :     typedef Vector<void *, 32, SystemAllocPolicy> RecyclableMaps;
          64                 :
          65                 :     RecyclableMaps      all;
          66                 :     RecyclableMaps      recyclable;
          67                 :     JSContext           *cx;
          68                 :
          69                 :     void checkInvariants();
          70                 :
          71          803626 :     void recycle(void *map) {
          72          803626 :         JS_ASSERT(map);
          73                 : #ifdef DEBUG
          74          803626 :         bool ok = false;
          75                 :         /* Make sure the map is in |all| but not already in |recyclable|. */
          76         3207447 :         for (void **it = all.begin(), **end = all.end(); it != end; ++it) {
          77         3207447 :             if (*it == map) {
          78          803626 :                 ok = true;
          79          803626 :                 break;
          80                 :             }
          81                 :         }
          82          803626 :         JS_ASSERT(ok);
          83         2779419 :         for (void **it = recyclable.begin(), **end = recyclable.end(); it != end; ++it)
          84         1975793 :             JS_ASSERT(*it != map);
          85                 : #endif
          86          803626 :         JS_ASSERT(recyclable.length() < all.length());
          87          803626 :         recyclable.infallibleAppend(map); /* Reserved in allocateFresh. */
          88          803626 :     }
          89                 :
          90                 :     void *allocateFresh();
          91                 :     void *allocate();
          92                 :
          93                 :     /* Arbitrary atom map type, that has keys and values of the same kind. */
          94                 :     typedef AtomIndexMap AtomMapT;
          95                 :
          96          804211 :     static AtomMapT *asAtomMap(void *ptr) {
          97          804211 :         return reinterpret_cast<AtomMapT *>(ptr);
          98                 :     }
          99                 :
         100                 :   public:
         101           19321 :     explicit ParseMapPool(JSContext *cx) : cx(cx) {}
         102                 :
         103           38642 :     ~ParseMapPool() {
         104           19321 :         purgeAll();
         105           19321 :     }
         106                 :
         107                 :     void purgeAll();
         108                 :
         109                 :     bool empty() const {
         110                 :         return all.empty();
         111                 :     }
         112                 :
         113                 :     /* Fallibly aquire one of the supported map types from the pool. */
         114                 :     template <typename T>
         115                 :     T *acquire();
         116                 :
         117                 :     /* Release one of the supported map types back to the pool. */
         118                 :
         119          272267 :     void release(AtomIndexMap *map) {
         120          272267 :         recycle((void *) map);
         121          272267 :     }
         122                 :
         123          265387 :     void release(AtomDefnMap *map) {
         124          265387 :         recycle((void *) map);
         125          265387 :     }
         126                 :
         127          265972 :     void release(AtomDOHMap *map) {
         128          265972 :         recycle((void *) map);
         129          265972 :     }
         130                 : }; /* ParseMapPool */
         131                 :
         132                 : /*
         133                 :  * N.B. This is a POD-type so that it can be included in the ParseNode union.
         134                 :  * If possible, use the corresponding |OwnedAtomThingMapPtr| variant.
         135                 :  */
         136                 : template <class Map>
         137                 : struct AtomThingMapPtr
         138          939320 : {
         139                 :     Map *map_;
         140                 :
         141         1198919 :     void init() { clearMap(); }
         142                 :
         143          549508 :     bool ensureMap(JSContext *cx);
         144         1000056 :     void releaseMap(JSContext *cx);
         145                 :
         146           53084 :     bool hasMap() const { return map_; }
         147          259010 :     Map *getMap() { return map_; }
         148                 :     void setMap(Map *newMap) { JS_ASSERT(!map_); map_ = newMap; }
         149         1320769 :     void clearMap() { map_ = NULL; }
         150                 :
         151         7430909 :     Map *operator->() { return map_; }
         152               0 :     const Map *operator->() const { return map_; }
         153                 :     Map &operator*() const { return *map_; }
         154                 : };
         155                 :
         156                 : struct AtomDefnMapPtr : public AtomThingMapPtr<AtomDefnMap>
         157          420122 : {
         158                 :     JS_ALWAYS_INLINE
         159          829695 :     Definition *lookupDefn(JSAtom *atom) {
         160          829695 :         AtomDefnMap::Ptr p = map_->lookup(atom);
         161          829695 :         return p ? p.value() : NULL;
         162                 :     }
         163                 : };
         164                 :
         165                 : typedef AtomThingMapPtr<AtomIndexMap> AtomIndexMapPtr;
         166                 :
         167                 : /*
         168                 :  * Wrapper around an AtomThingMapPtr (or its derivatives) that automatically
         169                 :  * releases a map on destruction, if one has been acquired.
         170                 :  */
         171                 : template <typename AtomThingMapPtrT>
         172                 : class OwnedAtomThingMapPtr : public AtomThingMapPtrT
         173                 : {
         174                 :     JSContext *cx;
         175                 :
         176                 :   public:
         177          939320 :     explicit OwnedAtomThingMapPtr(JSContext *cx) : cx(cx) {
         178          939320 :         AtomThingMapPtrT::init();
         179          939320 :     }
         180                 :
         181          939320 :     ~OwnedAtomThingMapPtr() {
         182          939320 :         AtomThingMapPtrT::releaseMap(cx);
         183          939320 :     }
         184                 : };
         185                 :
         186                 : typedef OwnedAtomThingMapPtr<AtomDefnMapPtr> OwnedAtomDefnMapPtr;
         187                 : typedef OwnedAtomThingMapPtr<AtomIndexMapPtr> OwnedAtomIndexMapPtr;
         188                 :
         189                 : /* Node structure for chaining in AtomDecls. */
         190                 : struct AtomDeclNode
         191                 : {
         192                 :     Definition *defn;
         193                 :     AtomDeclNode *next;
         194                 :
         195          325424 :     explicit AtomDeclNode(Definition *defn)
         196          325424 :       : defn(defn), next(NULL)
         197          325424 :     {}
         198                 : };
         199                 :
         200                 : /*
         201                 :  * Tagged union of a Definition and an AtomDeclNode, for use in AtomDecl's
         202                 :  * internal map.
         203                 :  */
         204                 : class DefnOrHeader
         205                 : {
         206                 :     union {
         207                 :         Definition    *defn;
         208                 :         AtomDeclNode    *head;
         209                 :         uintptr_t       bits;
         210                 :     } u;
         211                 :
         212                 :   public:
         213         1664478 :     DefnOrHeader() {
         214         1664478 :         u.bits = 0;
         215         1664478 :     }
         216                 :
         217          481509 :     explicit DefnOrHeader(Definition *defn) {
         218          481509 :         u.defn = defn;
         219          481509 :         JS_ASSERT(!isHeader());
         220          481509 :     }
         221                 :
         222          325928 :     explicit DefnOrHeader(AtomDeclNode *node) {
         223          325928 :         u.head = node;
         224          325928 :         u.bits |= 0x1;
         225          325928 :         JS_ASSERT(isHeader());
         226          325928 :     }
         227                 :
         228         2930147 :     bool isHeader() const {
         229         2930147 :         return u.bits & 0x1;
         230                 :     }
         231                 :
         232          711895 :     Definition *defn() const {
         233          711895 :         JS_ASSERT(!isHeader());
         234          711895 :         return u.defn;
         235                 :     }
         236                 :
         237          349424 :     AtomDeclNode *header() const {
         238          349424 :         JS_ASSERT(isHeader());
         239          349424 :         return (AtomDeclNode *) (u.bits & ~0x1);
         240                 :     }
         241                 :
         242                 : #ifdef DEBUG
         243                 :     void dump();
         244                 : #endif
         245                 : };
         246                 :
         247                 : namespace tl {
         248                 :
         249                 : template <> struct IsPodType<DefnOrHeader> {
         250                 :     static const bool result = true;
         251                 : };
         252                 :
         253                 : } /* namespace tl */
         254                 :
         255                 : /*
         256                 :  * Multimap for function-scope atom declarations.
         257                 :  *
         258                 :  * Wraps an internal DeclOrHeader map with multi-map functionality.
         259                 :  *
         260                 :  * In the common case, no block scoping is used, and atoms have a single
         261                 :  * associated definition. In the uncommon (block scoping) case, we map the atom
         262                 :  * to a chain of definition nodes.
         263                 :  */
         264                 : class AtomDecls
         265                 : {
         266                 :     /* AtomDeclsIter needs to get at the DOHMap directly. */
         267                 :     friend class AtomDeclsIter;
         268                 :
         269                 :     JSContext   *cx;
         270                 :     AtomDOHMap  *map;
         271                 :
         272                 :     AtomDecls(const AtomDecls &other) MOZ_DELETE;
         273                 :     void operator=(const AtomDecls &other) MOZ_DELETE;
         274                 :
         275                 :     AtomDeclNode *allocNode(Definition *defn);
         276                 :
         277                 :     /*
         278                 :      * Fallibly return the value in |doh| as a node.
         279                 :      * Update the defn currently occupying |doh| to a node if necessary.
         280                 :      */
         281                 :     AtomDeclNode *lastAsNode(DefnOrHeader *doh);
         282                 :
         283                 :   public:
         284          420122 :     explicit AtomDecls(JSContext *cx)
         285          420122 :       : cx(cx), map(NULL)
         286          420122 :     {}
         287                 :
         288                 :     ~AtomDecls();
         289                 :
         290                 :     bool init();
         291                 :
         292                 :     void clear() {
         293                 :         map->clear();
         294                 :     }
         295                 :
         296                 :     /* Return the definition at the head of the chain for |atom|. */
         297                 :     inline Definition *lookupFirst(JSAtom *atom);
         298                 :
         299                 :     /* Perform a lookup that can iterate over the definitions associated with |atom|. */
         300                 :     inline MultiDeclRange lookupMulti(JSAtom *atom);
         301                 :
         302                 :     /* Add-or-update a known-unique definition for |atom|. */
         303                 :     inline bool addUnique(JSAtom *atom, Definition *defn);
         304                 :     bool addShadow(JSAtom *atom, Definition *defn);
         305                 :     bool addHoist(JSAtom *atom, Definition *defn);
         306                 :
         307                 :     /* Updating the definition for an entry that is known to exist is infallible. */
         308              72 :     void updateFirst(JSAtom *atom, Definition *defn) {
         309              72 :         JS_ASSERT(map);
         310              72 :         AtomDOHMap::Ptr p = map->lookup(atom);
         311              72 :         JS_ASSERT(p);
         312              72 :         if (p.value().isHeader())
         313              18 :             p.value().header()->defn = defn;
         314                 :         else
         315              54 :             p.value() = DefnOrHeader(defn);
         316              72 :     }
         317                 :
         318                 :     /* Remove the node at the head of the chain for |atom|. */
         319          322949 :     void remove(JSAtom *atom) {
         320          322949 :         JS_ASSERT(map);
         321          322949 :         AtomDOHMap::Ptr p = map->lookup(atom);
         322          322949 :         if (!p)
         323               0 :             return;
         324                 :
         325          322949 :         DefnOrHeader &doh = p.value();
         326          322949 :         if (!doh.isHeader()) {
         327               0 :             map->remove(p);
         328               0 :             return;
         329                 :         }
         330                 :
         331          322949 :         AtomDeclNode *node = doh.header();
         332          322949 :         AtomDeclNode *newHead = node->next;
         333          322949 :         if (newHead)
         334            2943 :             p.value() = DefnOrHeader(newHead);
         335                 :         else
         336          320006 :             map->remove(p);
         337                 :     }
         338                 :
         339             360 :     AtomDOHMap::Range all() {
         340             360 :         JS_ASSERT(map);
         341             360 :         return map->all();
         342                 :     }
         343                 :
         344                 : #ifdef DEBUG
         345                 :     void dump();
         346                 : #endif
         347                 : };
         348                 :
         349                 : /*
         350                 :  * Lookup state tracker for those situations where the caller wants to traverse
         351                 :  * multiple definitions associated with a single atom. This occurs due to block
         352                 :  * scoping.
         353                 :  */
         354                 : class MultiDeclRange
         355                 : {
         356                 :     friend class AtomDecls;
         357                 :
         358                 :     AtomDeclNode *node;
         359                 :     Definition *defn;
         360                 :
         361         2690496 :     explicit MultiDeclRange(Definition *defn) : node(NULL), defn(defn) {}
         362           24764 :     explicit MultiDeclRange(AtomDeclNode *node) : node(node), defn(node->defn) {}
         363                 :
         364                 :   public:
         365               9 :     void popFront() {
         366               9 :         JS_ASSERT(!empty());
         367               9 :         if (!node) {
         368               0 :             defn = NULL;
         369               0 :             return;
         370                 :         }
         371               9 :         node = node->next;
         372               9 :         defn = node ? node->defn : NULL;
         373                 :     }
         374                 :
         375          703234 :     Definition *front() {
         376          703234 :         JS_ASSERT(!empty());
         377          703234 :         return defn;
         378                 :     }
         379                 :
         380         3650822 :     bool empty() const {
         381         3650822 :         JS_ASSERT_IF(!defn, !node);
         382         3650822 :         return !defn;
         383                 :     }
         384                 : };
         385                 :
         386                 : /* Iterates over all the definitions in an AtomDecls. */
         387                 : class AtomDeclsIter
         388                 : {
         389                 :     AtomDOHMap::Range   r;     /* Range over the map. */
         390                 :     AtomDeclNode        *link; /* Optional next node in the current atom's chain. */
         391                 :
         392                 :   public:
         393             360 :     explicit AtomDeclsIter(AtomDecls *decls) : r(decls->all()), link(NULL) {}
         394                 :
         395             981 :     Definition *operator()() {
         396             981 :         if (link) {
         397               0 :             JS_ASSERT(link != link->next);
         398               0 :             Definition *result = link->defn;
         399               0 :             link = link->next;
         400               0 :             JS_ASSERT(result);
         401               0 :             return result;
         402                 :         }
         403                 :
         404             981 :         if (r.empty())
         405             306 :             return NULL;
         406                 :
         407             675 :         const DefnOrHeader &doh = r.front().value();
         408             675 :         r.popFront();
         409                 :
         410             675 :         if (!doh.isHeader())
         411             666 :             return doh.defn();
         412                 :
         413               9 :         JS_ASSERT(!link);
         414               9 :         AtomDeclNode *node = doh.header();
         415               9 :         link = node->next;
         416               9 :         return node->defn;
         417                 :     }
         418                 : };
         419                 :
         420                 : typedef AtomDefnMap::Range      AtomDefnRange;
         421                 : typedef AtomDefnMap::AddPtr     AtomDefnAddPtr;
         422                 : typedef AtomDefnMap::Ptr        AtomDefnPtr;
         423                 : typedef AtomIndexMap::AddPtr    AtomIndexAddPtr;
         424                 : typedef AtomIndexMap::Ptr       AtomIndexPtr;
         425                 : typedef AtomDOHMap::Ptr         AtomDOHPtr;
         426                 : typedef AtomDOHMap::AddPtr      AtomDOHAddPtr;
         427                 : typedef AtomDOHMap::Range       AtomDOHRange;
         428                 :
         429                 : } /* namepsace js */
         430                 :
         431                 : #endif

Generated by: LCOV version 1.7