LCOV - app.info - js/src/jsatom.h

LCOV - code coverage report
| Current view: | directory - js/src - jsatom.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 59 | 57 | 96.6 %
| Date: | 2012-04-07 | Functions: | 23 | 23 | 100.0 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla Communicator client code, released
          17                 :  * March 31, 1998.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Netscape Communications Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          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 jsatom_h___
          41                 : #define jsatom_h___
          42                 :
          43                 : #include <stddef.h>
          44                 : #include "jsversion.h"
          45                 : #include "jsalloc.h"
          46                 : #include "jsapi.h"
          47                 : #include "jsprvtd.h"
          48                 : #include "jshash.h"
          49                 : #include "jspubtd.h"
          50                 : #include "jslock.h"
          51                 :
          52                 : #include "gc/Barrier.h"
          53                 : #include "js/HashTable.h"
          54                 :
          55                 : struct JSIdArray {
          56                 :     int length;
          57                 :     js::HeapId vector[1];    /* actually, length jsid words */
          58                 : };
          59                 :
          60                 : /* Engine-internal extensions of jsid */
          61                 :
          62                 : static JS_ALWAYS_INLINE jsid
          63        99353608 : JSID_FROM_BITS(size_t bits)
          64                 : {
          65                 :     jsid id;
          66        99353608 :     JSID_BITS(id) = bits;
          67                 :     return id;
          68                 : }
          69                 :
          70                 : static JS_ALWAYS_INLINE jsid
          71        99353608 : ATOM_TO_JSID(JSAtom *atom)
          72                 : {
          73        99353608 :     JS_ASSERT(((size_t)atom & 0x7) == 0);
          74        99353608 :     return JSID_FROM_BITS((size_t)atom);
          75                 : }
          76                 :
          77                 : /* All strings stored in jsids are atomized. */
          78                 : static JS_ALWAYS_INLINE JSBool
          79       174392100 : JSID_IS_ATOM(jsid id)
          80                 : {
          81       174392100 :     return JSID_IS_STRING(id);
          82                 : }
          83                 :
          84                 : static JS_ALWAYS_INLINE JSBool
          85        22506104 : JSID_IS_ATOM(jsid id, JSAtom *atom)
          86                 : {
          87        22506104 :     return JSID_BITS(id) == JSID_BITS(ATOM_TO_JSID(atom));
          88                 : }
          89                 :
          90                 : static JS_ALWAYS_INLINE JSAtom *
          91       200620575 : JSID_TO_ATOM(jsid id)
          92                 : {
          93       200620575 :     return (JSAtom *)JSID_TO_STRING(id);
          94                 : }
          95                 :
          96                 : extern jsid
          97                 : js_CheckForStringIndex(jsid id);
          98                 :
          99                 : JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
         100                 : JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
         101                 :
         102                 : namespace js {
         103                 :
         104                 : static JS_ALWAYS_INLINE JSHashNumber
         105        55247233 : HashId(jsid id)
         106                 : {
         107        55247233 :     JS_ASSERT(js_CheckForStringIndex(id) == id);
         108                 :     JSHashNumber n =
         109                 : #if JS_BYTES_PER_WORD == 4
         110        55247233 :         JSHashNumber(JSID_BITS(id));
         111                 : #elif JS_BYTES_PER_WORD == 8
         112                 :         JSHashNumber(JSID_BITS(id)) ^ JSHashNumber(JSID_BITS(id) >> 32);
         113                 : #else
         114                 : # error "Unsupported configuration"
         115                 : #endif
         116        55247233 :     return n * JS_GOLDEN_RATIO;
         117                 : }
         118                 :
         119                 : static JS_ALWAYS_INLINE Value
         120         3000001 : IdToValue(jsid id)
         121                 : {
         122         3000001 :     if (JSID_IS_STRING(id))
         123         2977195 :         return StringValue(JSID_TO_STRING(id));
         124           22806 :     if (JS_LIKELY(JSID_IS_INT(id)))
         125           22752 :         return Int32Value(JSID_TO_INT(id));
         126              54 :     if (JS_LIKELY(JSID_IS_OBJECT(id)))
         127              54 :         return ObjectValue(*JSID_TO_OBJECT(id));
         128               0 :     JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id) || JSID_IS_VOID(id));
         129               0 :     return UndefinedValue();
         130                 : }
         131                 :
         132                 : static JS_ALWAYS_INLINE jsval
         133           11668 : IdToJsval(jsid id)
         134                 : {
         135           11668 :     return IdToValue(id);
         136                 : }
         137                 :
         138                 : template<>
         139                 : struct DefaultHasher<jsid>
         140                 : {
         141                 :     typedef jsid Lookup;
         142              63 :     static HashNumber hash(const Lookup &l) {
         143              63 :         JS_ASSERT(l == js_CheckForStringIndex(l));
         144              63 :         return HashNumber(JSID_BITS(l));
         145                 :     }
         146               9 :     static bool match(const jsid &id, const Lookup &l) {
         147               9 :         JS_ASSERT(l == js_CheckForStringIndex(l));
         148               9 :         return id == l;
         149                 :     }
         150                 : };
         151                 :
         152                 : }
         153                 :
         154                 : #if JS_BYTES_PER_WORD == 4
         155                 : # define ATOM_HASH(atom)          ((JSHashNumber)(atom) >> 2)
         156                 : #elif JS_BYTES_PER_WORD == 8
         157                 : # define ATOM_HASH(atom)          (((JSHashNumber)(uintptr_t)(atom) >> 3) ^   \
         158                 :                                    (JSHashNumber)((uintptr_t)(atom) >> 32))
         159                 : #else
         160                 : # error "Unsupported configuration"
         161                 : #endif
         162                 :
         163                 : /*
         164                 :  * Return a printable, lossless char[] representation of a string-type atom.
         165                 :  * The lifetime of the result matches the lifetime of bytes.
         166                 :  */
         167                 : extern const char *
         168                 : js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes);
         169                 :
         170                 : namespace js {
         171                 :
         172                 : /* Compute a hash function from chars/length. */
         173                 : inline uint32_t
         174        31974399 : HashChars(const jschar *chars, size_t length)
         175                 : {
         176        31974399 :     uint32_t h = 0;
         177       429252977 :     for (; length; chars++, length--)
         178       397278578 :         h = JS_ROTATE_LEFT32(h, 4) ^ *chars;
         179        31974399 :     return h;
         180                 : }
         181                 :
         182                 : class AtomStateEntry
         183                 : {
         184                 :     uintptr_t bits;
         185                 :
         186                 :     static const uintptr_t NO_TAG_MASK = uintptr_t(-1) - 1;
         187                 :
         188                 :   public:
         189        70161698 :     AtomStateEntry() : bits(0) {}
         190        42316465 :     AtomStateEntry(const AtomStateEntry &other) : bits(other.bits) {}
         191        11865225 :     AtomStateEntry(JSAtom *ptr, bool tagged)
         192        11865225 :       : bits(uintptr_t(ptr) | uintptr_t(tagged))
         193                 :     {
         194        11865225 :         JS_ASSERT((uintptr_t(ptr) & 0x1) == 0);
         195        11865225 :     }
         196                 :
         197        42316478 :     bool isTagged() const {
         198        42316478 :         return bits & 0x1;
         199                 :     }
         200                 :
         201                 :     /*
         202                 :      * Non-branching code sequence. Note that the const_cast is safe because
         203                 :      * the hash function doesn't consider the tag to be a portion of the key.
         204                 :      */
         205        20105255 :     void setTagged(bool enabled) const {
         206        20105255 :         const_cast<AtomStateEntry *>(this)->bits |= uintptr_t(enabled);
         207        20105255 :     }
         208                 :
         209                 :     JSAtom *asPtr() const;
         210                 : };
         211                 :
         212                 : struct AtomHasher
         213                 : {
         214                 :     struct Lookup
         215                 :     {
         216                 :         const jschar    *chars;
         217                 :         size_t          length;
         218                 :         const JSAtom    *atom; /* Optional. */
         219                 :
         220        43835704 :         Lookup(const jschar *chars, size_t length) : chars(chars), length(length), atom(NULL) {}
         221                 :         inline Lookup(const JSAtom *atom);
         222                 :     };
         223                 :
         224        31970493 :     static HashNumber hash(const Lookup &l) { return HashChars(l.chars, l.length); }
         225                 :     static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
         226                 : };
         227                 :
         228                 : typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
         229                 :
         230                 : /*
         231                 :  * On encodings:
         232                 :  *
         233                 :  * - Some string functions have an optional FlationCoding argument that allow
         234                 :  *   the caller to force CESU-8 encoding handling.
         235                 :  * - Functions that don't take a FlationCoding base their NormalEncoding
         236                 :  *   behavior on the js_CStringsAreUTF8 value. NormalEncoding is either raw
         237                 :  *   (simple zero-extension) or UTF-8 depending on js_CStringsAreUTF8.
         238                 :  * - Functions that explicitly state their encoding do not use the
         239                 :  *   js_CStringsAreUTF8 value.
         240                 :  *
         241                 :  * CESU-8 (Compatibility Encoding Scheme for UTF-16: 8-bit) is a variant of
         242                 :  * UTF-8 that allows us to store any wide character string as a narrow
         243                 :  * character string. For strings containing mostly ascii, it saves space.
         244                 :  * http://www.unicode.org/reports/tr26/
         245                 :  */
         246                 :
         247                 : enum FlationCoding
         248                 : {
         249                 :     NormalEncoding,
         250                 :     CESU8Encoding
         251                 : };
         252                 :
         253                 : class PropertyName;
         254                 :
         255                 : }  /* namespace js */
         256                 :
         257                 : struct JSAtomState
         258           37522 : {
         259                 :     js::AtomSet         atoms;
         260                 :
         261                 :     /*
         262                 :      * From this point until the end of struct definition the struct must
         263                 :      * contain only js::PropertyName fields. We use this to access the storage
         264                 :      * occupied by the common atoms in js_FinishCommonAtoms.
         265                 :      *
         266                 :      * js_common_atom_names defined in jsatom.cpp contains C strings for atoms
         267                 :      * in the order of atom fields here. Therefore you must update that array
         268                 :      * if you change member order here.
         269                 :      */
         270                 :
         271                 :     /* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */
         272                 :     js::PropertyName    *emptyAtom;
         273                 :
         274                 :     /*
         275                 :      * Literal value and type names.
         276                 :      * NB: booleanAtoms must come right before typeAtoms!
         277                 :      */
         278                 :     js::PropertyName    *booleanAtoms[2];
         279                 :     js::PropertyName    *typeAtoms[JSTYPE_LIMIT];
         280                 :     js::PropertyName    *nullAtom;
         281                 :
         282                 :     /* Standard class constructor or prototype names. */
         283                 :     js::PropertyName    *classAtoms[JSProto_LIMIT];
         284                 :
         285                 :     /* Various built-in or commonly-used atoms, pinned on first context. */
         286                 : #define DEFINE_ATOM(id, text)          js::PropertyName *id##Atom;
         287                 : #define DEFINE_PROTOTYPE_ATOM(id)      js::PropertyName *id##Atom;
         288                 : #define DEFINE_KEYWORD_ATOM(id)        js::PropertyName *id##Atom;
         289                 : #include "jsatom.tbl"
         290                 : #undef DEFINE_ATOM
         291                 : #undef DEFINE_PROTOTYPE_ATOM
         292                 : #undef DEFINE_KEYWORD_ATOM
         293                 :
         294                 :     /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
         295                 :     struct {
         296                 :         js::PropertyName *XMLListAtom;
         297                 :         js::PropertyName *decodeURIAtom;
         298                 :         js::PropertyName *decodeURIComponentAtom;
         299                 :         js::PropertyName *defineGetterAtom;
         300                 :         js::PropertyName *defineSetterAtom;
         301                 :         js::PropertyName *encodeURIAtom;
         302                 :         js::PropertyName *encodeURIComponentAtom;
         303                 :         js::PropertyName *escapeAtom;
         304                 :         js::PropertyName *hasOwnPropertyAtom;
         305                 :         js::PropertyName *isFiniteAtom;
         306                 :         js::PropertyName *isNaNAtom;
         307                 :         js::PropertyName *isPrototypeOfAtom;
         308                 :         js::PropertyName *isXMLNameAtom;
         309                 :         js::PropertyName *lookupGetterAtom;
         310                 :         js::PropertyName *lookupSetterAtom;
         311                 :         js::PropertyName *parseFloatAtom;
         312                 :         js::PropertyName *parseIntAtom;
         313                 :         js::PropertyName *propertyIsEnumerableAtom;
         314                 :         js::PropertyName *unescapeAtom;
         315                 :         js::PropertyName *unevalAtom;
         316                 :         js::PropertyName *unwatchAtom;
         317                 :         js::PropertyName *watchAtom;
         318                 :     } lazy;
         319                 :
         320                 :     static const size_t commonAtomsOffset;
         321                 :     static const size_t lazyAtomsOffset;
         322                 :
         323           18761 :     void clearLazyAtoms() {
         324           18761 :         memset(&lazy, 0, sizeof(lazy));
         325           18761 :     }
         326                 :
         327           18761 :     void junkAtoms() {
         328                 : #ifdef DEBUG
         329           18761 :         memset(commonAtomsStart(), JS_FREE_PATTERN, sizeof(*this) - commonAtomsOffset);
         330                 : #endif
         331           18761 :     }
         332                 :
         333           37522 :     JSAtom **commonAtomsStart() {
         334           37522 :         return reinterpret_cast<JSAtom **>(&emptyAtom);
         335                 :     }
         336                 :
         337                 :     void checkStaticInvariants();
         338                 : };
         339                 :
         340                 : extern bool
         341                 : AtomIsInterned(JSContext *cx, JSAtom *atom);
         342                 :
         343                 : #define ATOM(name) cx->runtime->atomState.name##Atom
         344                 :
         345                 : #define COMMON_ATOM_INDEX(name)                                               \
         346                 :     ((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset)     \
         347                 :      / sizeof(JSAtom*))
         348                 : #define COMMON_TYPE_ATOM_INDEX(type)                                          \
         349                 :     ((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\
         350                 :      / sizeof(JSAtom*))
         351                 :
         352                 : #define ATOM_OFFSET(name)       offsetof(JSAtomState, name##Atom)
         353                 : #define OFFSET_TO_ATOM(rt,off)  (*(JSAtom **)((char*)&(rt)->atomState + (off)))
         354                 : #define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
         355                 : #define CLASS_ATOM(cx,name)     ((cx)->runtime->atomState.classAtoms[JSProto_##name])
         356                 :
         357                 : extern const char *const js_common_atom_names[];
         358                 : extern const size_t      js_common_atom_count;
         359                 :
         360                 : /*
         361                 :  * Macros to access C strings for JSType and boolean literals.
         362                 :  */
         363                 : #define JS_BOOLEAN_STR(type) (js_common_atom_names[1 + (type)])
         364                 : #define JS_TYPE_STR(type)    (js_common_atom_names[1 + 2 + (type)])
         365                 :
         366                 : /* Type names. */
         367                 : extern const char   js_object_str[];
         368                 : extern const char   js_undefined_str[];
         369                 :
         370                 : /* Well-known predefined C strings. */
         371                 : #define JS_PROTO(name,code,init) extern const char js_##name##_str[];
         372                 : #include "jsproto.tbl"
         373                 : #undef JS_PROTO
         374                 :
         375                 : #define DEFINE_ATOM(id, text)  extern const char js_##id##_str[];
         376                 : #define DEFINE_PROTOTYPE_ATOM(id)
         377                 : #define DEFINE_KEYWORD_ATOM(id)
         378                 : #include "jsatom.tbl"
         379                 : #undef DEFINE_ATOM
         380                 : #undef DEFINE_PROTOTYPE_ATOM
         381                 : #undef DEFINE_KEYWORD_ATOM
         382                 :
         383                 : #if JS_HAS_GENERATORS
         384                 : extern const char   js_close_str[];
         385                 : extern const char   js_send_str[];
         386                 : #endif
         387                 :
         388                 : /* Constant strings that are not atomized. */
         389                 : extern const char   js_getter_str[];
         390                 : extern const char   js_setter_str[];
         391                 :
         392                 : /*
         393                 :  * Initialize atom state. Return true on success, false on failure to allocate
         394                 :  * memory. The caller must zero rt->atomState before calling this function and
         395                 :  * only call it after js_InitGC successfully returns.
         396                 :  */
         397                 : extern JSBool
         398                 : js_InitAtomState(JSRuntime *rt);
         399                 :
         400                 : /*
         401                 :  * Free and clear atom state including any interned string atoms. This
         402                 :  * function must be called before js_FinishGC.
         403                 :  */
         404                 : extern void
         405                 : js_FinishAtomState(JSRuntime *rt);
         406                 :
         407                 : /*
         408                 :  * Atom tracing and garbage collection hooks.
         409                 :  */
         410                 :
         411                 : namespace js {
         412                 :
         413                 : extern void
         414                 : MarkAtomState(JSTracer *trc, bool markAll);
         415                 :
         416                 : extern void
         417                 : SweepAtomState(JSRuntime *rt);
         418                 :
         419                 : extern bool
         420                 : InitCommonAtoms(JSContext *cx);
         421                 :
         422                 : extern void
         423                 : FinishCommonAtoms(JSRuntime *rt);
         424                 :
         425                 : /* N.B. must correspond to boolean tagging behavior. */
         426                 : enum InternBehavior
         427                 : {
         428                 :     DoNotInternAtom = false,
         429                 :     InternAtom = true
         430                 : };
         431                 :
         432                 : }  /* namespace js */
         433                 :
         434                 : extern JSAtom *
         435                 : js_Atomize(JSContext *cx, const char *bytes, size_t length,
         436                 :            js::InternBehavior ib = js::DoNotInternAtom,
         437                 :            js::FlationCoding fc = js::NormalEncoding);
         438                 :
         439                 : extern JSAtom *
         440                 : js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length,
         441                 :                 js::InternBehavior ib = js::DoNotInternAtom);
         442                 :
         443                 : extern JSAtom *
         444                 : js_AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
         445                 :
         446                 : /*
         447                 :  * Return an existing atom for the given char array or null if the char
         448                 :  * sequence is currently not atomized.
         449                 :  */
         450                 : extern JSAtom *
         451                 : js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
         452                 :
         453                 : #ifdef DEBUG
         454                 :
         455                 : extern JS_FRIEND_API(void)
         456                 : js_DumpAtoms(JSContext *cx, FILE *fp);
         457                 :
         458                 : #endif
         459                 :
         460                 : inline bool
         461                 : js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp);
         462                 :
         463                 : inline bool
         464                 : js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp);
         465                 :
         466                 : inline bool
         467                 : js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
         468                 :                          jsid *idp);
         469                 : inline bool
         470                 : js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
         471                 :                          jsid *idp, js::Value *vp);
         472                 :
         473                 : /*
         474                 :  * For all unmapped atoms recorded in al, add a mapping from the atom's index
         475                 :  * to its address. map->length must already be set to the number of atoms in
         476                 :  * the list and map->vector must point to pre-allocated memory.
         477                 :  */
         478                 : extern void
         479                 : js_InitAtomMap(JSContext *cx, js::AtomIndexMap *indices, JSAtom **atoms);
         480                 :
         481                 : namespace js {
         482                 :
         483                 : template<XDRMode mode>
         484                 : bool
         485                 : XDRAtom(XDRState<mode> *xdr, JSAtom **atomp);
         486                 :
         487                 : } /* namespace js */
         488                 :
         489                 : #endif /* jsatom_h___ */

Generated by: LCOV version 1.7