Back to index

lightning-sunbird  0.9+nobinonly
jsatom.h
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1998
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifndef jsatom_h___
00041 #define jsatom_h___
00042 /*
00043  * JS atom table.
00044  */
00045 #include <stddef.h>
00046 #include "jstypes.h"
00047 #include "jshash.h" /* Added by JSIFY */
00048 #include "jsapi.h"
00049 #include "jsprvtd.h"
00050 #include "jspubtd.h"
00051 
00052 #ifdef JS_THREADSAFE
00053 #include "jslock.h"
00054 #endif
00055 
00056 JS_BEGIN_EXTERN_C
00057 
00058 #define ATOM_PINNED     0x01            /* atom is pinned against GC */
00059 #define ATOM_INTERNED   0x02            /* pinned variant for JS_Intern* API */
00060 #define ATOM_MARK       0x04            /* atom is reachable via GC */
00061 #define ATOM_HIDDEN     0x08            /* atom is in special hidden subspace */
00062 #define ATOM_NOCOPY     0x40            /* don't copy atom string bytes */
00063 #define ATOM_TMPSTR     0x80            /* internal, to avoid extra string */
00064 
00065 struct JSAtom {
00066     JSHashEntry         entry;          /* key is jsval or unhidden atom
00067                                            if ATOM_HIDDEN */
00068     uint32              flags;          /* pinned, interned, and mark flags */
00069     jsatomid            number;         /* atom serial number and hash code */
00070 };
00071 
00072 #define ATOM_KEY(atom)            ((jsval)(atom)->entry.key)
00073 #define ATOM_IS_OBJECT(atom)      JSVAL_IS_OBJECT(ATOM_KEY(atom))
00074 #define ATOM_TO_OBJECT(atom)      JSVAL_TO_OBJECT(ATOM_KEY(atom))
00075 #define ATOM_IS_INT(atom)         JSVAL_IS_INT(ATOM_KEY(atom))
00076 #define ATOM_TO_INT(atom)         JSVAL_TO_INT(ATOM_KEY(atom))
00077 #define ATOM_IS_DOUBLE(atom)      JSVAL_IS_DOUBLE(ATOM_KEY(atom))
00078 #define ATOM_TO_DOUBLE(atom)      JSVAL_TO_DOUBLE(ATOM_KEY(atom))
00079 #define ATOM_IS_STRING(atom)      JSVAL_IS_STRING(ATOM_KEY(atom))
00080 #define ATOM_TO_STRING(atom)      JSVAL_TO_STRING(ATOM_KEY(atom))
00081 #define ATOM_IS_BOOLEAN(atom)     JSVAL_IS_BOOLEAN(ATOM_KEY(atom))
00082 #define ATOM_TO_BOOLEAN(atom)     JSVAL_TO_BOOLEAN(ATOM_KEY(atom))
00083 
00084 /*
00085  * Return a printable, lossless char[] representation of a string-type atom.
00086  * The lifetime of the result extends at least until the next GC activation,
00087  * longer if cx's string newborn root is not overwritten.
00088  */
00089 extern JS_FRIEND_API(const char *)
00090 js_AtomToPrintableString(JSContext *cx, JSAtom *atom);
00091 
00092 struct JSAtomListElement {
00093     JSHashEntry         entry;
00094 };
00095 
00096 #define ALE_ATOM(ale)   ((JSAtom *) (ale)->entry.key)
00097 #define ALE_INDEX(ale)  ((jsatomid) JS_PTR_TO_UINT32((ale)->entry.value))
00098 #define ALE_JSOP(ale)   ((JSOp) (ale)->entry.value)
00099 #define ALE_VALUE(ale)  ((jsval) (ale)->entry.value)
00100 #define ALE_NEXT(ale)   ((JSAtomListElement *) (ale)->entry.next)
00101 
00102 #define ALE_SET_ATOM(ale,atom)  ((ale)->entry.key = (const void *)(atom))
00103 #define ALE_SET_INDEX(ale,index)((ale)->entry.value = JS_UINT32_TO_PTR(index))
00104 #define ALE_SET_JSOP(ale,op)    ((ale)->entry.value = JS_UINT32_TO_PTR(op))
00105 #define ALE_SET_VALUE(ale,val)  ((ale)->entry.value = (JSHashEntry *)(val))
00106 #define ALE_SET_NEXT(ale,link)  ((ale)->entry.next = (JSHashEntry *)(link))
00107 
00108 struct JSAtomList {
00109     JSAtomListElement   *list;          /* literals indexed for mapping */
00110     JSHashTable         *table;         /* hash table if list gets too long */
00111     jsuint              count;          /* count of indexed literals */
00112 };
00113 
00114 #define ATOM_LIST_INIT(al)  ((al)->list = NULL, (al)->table = NULL,           \
00115                              (al)->count = 0)
00116 
00117 #define ATOM_LIST_SEARCH(_ale,_al,_atom)                                      \
00118     JS_BEGIN_MACRO                                                            \
00119         JSHashEntry **_hep;                                                   \
00120         ATOM_LIST_LOOKUP(_ale, _hep, _al, _atom);                             \
00121     JS_END_MACRO
00122 
00123 #define ATOM_LIST_LOOKUP(_ale,_hep,_al,_atom)                                 \
00124     JS_BEGIN_MACRO                                                            \
00125         if ((_al)->table) {                                                   \
00126             _hep = JS_HashTableRawLookup((_al)->table, _atom->number, _atom); \
00127             _ale = *_hep ? (JSAtomListElement *) *_hep : NULL;                \
00128         } else {                                                              \
00129             JSAtomListElement **_alep = &(_al)->list;                         \
00130             _hep = NULL;                                                      \
00131             while ((_ale = *_alep) != NULL) {                                 \
00132                 if (ALE_ATOM(_ale) == (_atom)) {                              \
00133                     /* Hit, move atom's element to the front of the list. */  \
00134                     *_alep = ALE_NEXT(_ale);                                  \
00135                     ALE_SET_NEXT(_ale, (_al)->list);                          \
00136                     (_al)->list = _ale;                                       \
00137                     break;                                                    \
00138                 }                                                             \
00139                 _alep = (JSAtomListElement **)&_ale->entry.next;              \
00140             }                                                                 \
00141         }                                                                     \
00142     JS_END_MACRO
00143 
00144 struct JSAtomMap {
00145     JSAtom              **vector;       /* array of ptrs to indexed atoms */
00146     jsatomid            length;         /* count of (to-be-)indexed atoms */
00147 };
00148 
00149 struct JSAtomState {
00150     JSRuntime           *runtime;       /* runtime that owns us */
00151     JSHashTable         *table;         /* hash table containing all atoms */
00152     jsatomid            number;         /* one beyond greatest atom number */
00153     jsatomid            liveAtoms;      /* number of live atoms after last GC */
00154 
00155     /* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */
00156     JSAtom              *emptyAtom;
00157 
00158     /* Type names and value literals. */
00159     JSAtom              *typeAtoms[JSTYPE_LIMIT];
00160     JSAtom              *booleanAtoms[2];
00161     JSAtom              *nullAtom;
00162 
00163     /* Standard class constructor or prototype names. */
00164     JSAtom              *classAtoms[JSProto_LIMIT];
00165 
00166     /* Various built-in or commonly-used atoms, pinned on first context. */
00167     JSAtom              *anonymousAtom;
00168     JSAtom              *argumentsAtom;
00169     JSAtom              *arityAtom;
00170     JSAtom              *calleeAtom;
00171     JSAtom              *callerAtom;
00172     JSAtom              *classPrototypeAtom;
00173     JSAtom              *closeAtom;
00174     JSAtom              *constructorAtom;
00175     JSAtom              *countAtom;
00176     JSAtom              *eachAtom;
00177     JSAtom              *etagoAtom;
00178     JSAtom              *evalAtom;
00179     JSAtom              *fileNameAtom;
00180     JSAtom              *getAtom;
00181     JSAtom              *getterAtom;
00182     JSAtom              *indexAtom;
00183     JSAtom              *inputAtom;
00184     JSAtom              *iteratorAtom;
00185     JSAtom              *lengthAtom;
00186     JSAtom              *lineNumberAtom;
00187     JSAtom              *messageAtom;
00188     JSAtom              *nameAtom;
00189     JSAtom              *namespaceAtom;
00190     JSAtom              *nextAtom;
00191     JSAtom              *noSuchMethodAtom;
00192     JSAtom              *parentAtom;
00193     JSAtom              *protoAtom;
00194     JSAtom              *ptagcAtom;
00195     JSAtom              *qualifierAtom;
00196     JSAtom              *setAtom;
00197     JSAtom              *setterAtom;
00198     JSAtom              *spaceAtom;
00199     JSAtom              *stackAtom;
00200     JSAtom              *stagoAtom;
00201     JSAtom              *starAtom;
00202     JSAtom              *starQualifierAtom;
00203     JSAtom              *tagcAtom;
00204     JSAtom              *toLocaleStringAtom;
00205     JSAtom              *toSourceAtom;
00206     JSAtom              *toStringAtom;
00207     JSAtom              *valueOfAtom;
00208     JSAtom              *xmlAtom;
00209 
00210     /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
00211     struct {
00212         JSAtom          *InfinityAtom;
00213         JSAtom          *NaNAtom;
00214         JSAtom          *XMLListAtom;
00215         JSAtom          *decodeURIAtom;
00216         JSAtom          *decodeURIComponentAtom;
00217         JSAtom          *defineGetterAtom;
00218         JSAtom          *defineSetterAtom;
00219         JSAtom          *encodeURIAtom;
00220         JSAtom          *encodeURIComponentAtom;
00221         JSAtom          *escapeAtom;
00222         JSAtom          *functionNamespaceURIAtom;
00223         JSAtom          *hasOwnPropertyAtom;
00224         JSAtom          *isFiniteAtom;
00225         JSAtom          *isNaNAtom;
00226         JSAtom          *isPrototypeOfAtom;
00227         JSAtom          *isXMLNameAtom;
00228         JSAtom          *lookupGetterAtom;
00229         JSAtom          *lookupSetterAtom;
00230         JSAtom          *parseFloatAtom;
00231         JSAtom          *parseIntAtom;
00232         JSAtom          *propertyIsEnumerableAtom;
00233         JSAtom          *unescapeAtom;
00234         JSAtom          *unevalAtom;
00235         JSAtom          *unwatchAtom;
00236         JSAtom          *watchAtom;
00237     } lazy;
00238 
00239 #ifdef JS_THREADSAFE
00240     JSThinLock          lock;
00241     volatile uint32     tablegen;
00242 #endif
00243 #ifdef NARCISSUS
00244     JSAtom              *callAtom;
00245     JSAtom              *constructAtom;
00246     JSAtom              *hasInstanceAtom;
00247     JSAtom              *ExecutionContextAtom;
00248     JSAtom              *currentAtom;
00249 #endif
00250 };
00251 
00252 #define CLASS_ATOM(cx,name) \
00253     ((cx)->runtime->atomState.classAtoms[JSProto_##name])
00254 
00255 /* Well-known predefined strings and their atoms. */
00256 extern const char   *js_type_strs[];
00257 extern const char   *js_boolean_strs[];
00258 extern const char   *js_proto_strs[];
00259 
00260 #define JS_PROTO(name,code,init) extern const char js_##name##_str[];
00261 #include "jsproto.tbl"
00262 #undef JS_PROTO
00263 
00264 extern const char   js_anonymous_str[];
00265 extern const char   js_arguments_str[];
00266 extern const char   js_arity_str[];
00267 extern const char   js_callee_str[];
00268 extern const char   js_caller_str[];
00269 extern const char   js_class_prototype_str[];
00270 extern const char   js_close_str[];
00271 extern const char   js_constructor_str[];
00272 extern const char   js_count_str[];
00273 extern const char   js_etago_str[];
00274 extern const char   js_each_str[];
00275 extern const char   js_eval_str[];
00276 extern const char   js_fileName_str[];
00277 extern const char   js_get_str[];
00278 extern const char   js_getter_str[];
00279 extern const char   js_index_str[];
00280 extern const char   js_input_str[];
00281 extern const char   js_iterator_str[];
00282 extern const char   js_length_str[];
00283 extern const char   js_lineNumber_str[];
00284 extern const char   js_message_str[];
00285 extern const char   js_name_str[];
00286 extern const char   js_namespace_str[];
00287 extern const char   js_next_str[];
00288 extern const char   js_noSuchMethod_str[];
00289 extern const char   js_object_str[];
00290 extern const char   js_parent_str[];
00291 extern const char   js_private_str[];
00292 extern const char   js_proto_str[];
00293 extern const char   js_ptagc_str[];
00294 extern const char   js_qualifier_str[];
00295 extern const char   js_send_str[];
00296 extern const char   js_setter_str[];
00297 extern const char   js_set_str[];
00298 extern const char   js_space_str[];
00299 extern const char   js_stack_str[];
00300 extern const char   js_stago_str[];
00301 extern const char   js_star_str[];
00302 extern const char   js_starQualifier_str[];
00303 extern const char   js_tagc_str[];
00304 extern const char   js_toSource_str[];
00305 extern const char   js_toString_str[];
00306 extern const char   js_toLocaleString_str[];
00307 extern const char   js_valueOf_str[];
00308 extern const char   js_xml_str[];
00309 
00310 #ifdef NARCISSUS
00311 extern const char   js_call_str[];
00312 extern const char   js_construct_str[];
00313 extern const char   js_hasInstance_str[];
00314 extern const char   js_ExecutionContext_str[];
00315 extern const char   js_current_str[];
00316 #endif
00317 
00318 /*
00319  * Initialize atom state.  Return true on success, false with an out of
00320  * memory error report on failure.
00321  */
00322 extern JSBool
00323 js_InitAtomState(JSContext *cx, JSAtomState *state);
00324 
00325 /*
00326  * Free and clear atom state (except for any interned string atoms).
00327  */
00328 extern void
00329 js_FreeAtomState(JSContext *cx, JSAtomState *state);
00330 
00331 /*
00332  * Interned strings are atoms that live until state's runtime is destroyed.
00333  * This function frees all interned string atoms, and then frees and clears
00334  * state's members (just as js_FreeAtomState does), unless there aren't any
00335  * interned strings in state -- in which case state must be "free" already.
00336  *
00337  * NB: js_FreeAtomState is called for each "last" context being destroyed in
00338  * a runtime, where there may yet be another context created in the runtime;
00339  * whereas js_FinishAtomState is called from JS_DestroyRuntime, when we know
00340  * that no more contexts will be created.  Thus we minimize garbage during
00341  * context-free episodes on a runtime, while preserving atoms created by the
00342  * JS_Intern*String APIs for the life of the runtime.
00343  */
00344 extern void
00345 js_FinishAtomState(JSAtomState *state);
00346 
00347 /*
00348  * Atom garbage collection hooks.
00349  */
00350 typedef void
00351 (*JSGCThingMarker)(void *thing, void *data);
00352 
00353 extern void
00354 js_MarkAtomState(JSAtomState *state, JSBool keepAtoms, JSGCThingMarker mark,
00355                  void *data);
00356 
00357 extern void
00358 js_SweepAtomState(JSAtomState *state);
00359 
00360 extern JSBool
00361 js_InitPinnedAtoms(JSContext *cx, JSAtomState *state);
00362 
00363 extern void
00364 js_UnpinPinnedAtoms(JSAtomState *state);
00365 
00366 /*
00367  * Find or create the atom for an object.  If we create a new atom, give it the
00368  * type indicated in flags.  Return 0 on failure to allocate memory.
00369  */
00370 extern JSAtom *
00371 js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags);
00372 
00373 /*
00374  * Find or create the atom for a Boolean value.  If we create a new atom, give
00375  * it the type indicated in flags.  Return 0 on failure to allocate memory.
00376  */
00377 extern JSAtom *
00378 js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags);
00379 
00380 /*
00381  * Find or create the atom for an integer value.  If we create a new atom, give
00382  * it the type indicated in flags.  Return 0 on failure to allocate memory.
00383  */
00384 extern JSAtom *
00385 js_AtomizeInt(JSContext *cx, jsint i, uintN flags);
00386 
00387 /*
00388  * Find or create the atom for a double value.  If we create a new atom, give
00389  * it the type indicated in flags.  Return 0 on failure to allocate memory.
00390  */
00391 extern JSAtom *
00392 js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags);
00393 
00394 /*
00395  * Find or create the atom for a string.  If we create a new atom, give it the
00396  * type indicated in flags.  Return 0 on failure to allocate memory.
00397  */
00398 extern JSAtom *
00399 js_AtomizeString(JSContext *cx, JSString *str, uintN flags);
00400 
00401 extern JS_FRIEND_API(JSAtom *)
00402 js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags);
00403 
00404 extern JS_FRIEND_API(JSAtom *)
00405 js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags);
00406 
00407 /*
00408  * Return an existing atom for the given char array or null if the char
00409  * sequence is currently not atomized.
00410  */
00411 extern JSAtom *
00412 js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
00413 
00414 /*
00415  * This variant handles all value tag types.
00416  */
00417 extern JSAtom *
00418 js_AtomizeValue(JSContext *cx, jsval value, uintN flags);
00419 
00420 /*
00421  * Convert v to an atomized string.
00422  */
00423 extern JSAtom *
00424 js_ValueToStringAtom(JSContext *cx, jsval v);
00425 
00426 /*
00427  * Assign atom an index and insert it on al.
00428  */
00429 extern JSAtomListElement *
00430 js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al);
00431 
00432 /*
00433  * Get the atom with index i from map.
00434  */
00435 extern JS_FRIEND_API(JSAtom *)
00436 js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i);
00437 
00438 /*
00439  * For all unmapped atoms recorded in al, add a mapping from the atom's index
00440  * to its address.  The GC must not run until all indexed atoms in atomLists
00441  * have been mapped by scripts connected to live objects (Function and Script
00442  * class objects have scripts as/in their private data -- the GC knows about
00443  * these two classes).
00444  */
00445 extern JS_FRIEND_API(JSBool)
00446 js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
00447 
00448 /*
00449  * Free map->vector and clear map.
00450  */
00451 extern JS_FRIEND_API(void)
00452 js_FreeAtomMap(JSContext *cx, JSAtomMap *map);
00453 
00454 JS_END_EXTERN_C
00455 
00456 #endif /* jsatom_h___ */