65 |
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom)) |
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom)) |
66 |
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom)) |
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom)) |
67 |
|
|
|
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4); |
|
|
JS_STATIC_ASSERT(sizeof(JSAtom *) == JS_BYTES_PER_WORD); |
|
|
|
|
68 |
#if JS_BYTES_PER_WORD == 4 |
#if JS_BYTES_PER_WORD == 4 |
69 |
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2) |
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2) |
70 |
#elif JS_BYTES_PER_WORD == 8 |
#elif JS_BYTES_PER_WORD == 8 |
88 |
|
|
89 |
#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key) |
#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key) |
90 |
#define ALE_INDEX(ale) ((jsatomid) JS_PTR_TO_UINT32((ale)->entry.value)) |
#define ALE_INDEX(ale) ((jsatomid) JS_PTR_TO_UINT32((ale)->entry.value)) |
|
#define ALE_JSOP(ale) ((JSOp) JS_PTR_TO_UINT32((ale)->entry.value)) |
|
91 |
#define ALE_VALUE(ale) ((jsval) (ale)->entry.value) |
#define ALE_VALUE(ale) ((jsval) (ale)->entry.value) |
92 |
#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next) |
#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next) |
93 |
|
|
94 |
|
/* |
95 |
|
* In an upvars list, ALE_DEFN(ale)->resolve() is the outermost definition the |
96 |
|
* name may reference. If a with block or a function that calls eval encloses |
97 |
|
* the use, the name may end up referring to something else at runtime. |
98 |
|
*/ |
99 |
|
#define ALE_DEFN(ale) ((JSDefinition *) (ale)->entry.value) |
100 |
|
|
101 |
#define ALE_SET_ATOM(ale,atom) ((ale)->entry.key = (const void *)(atom)) |
#define ALE_SET_ATOM(ale,atom) ((ale)->entry.key = (const void *)(atom)) |
102 |
#define ALE_SET_INDEX(ale,index)((ale)->entry.value = JS_UINT32_TO_PTR(index)) |
#define ALE_SET_INDEX(ale,index)((ale)->entry.value = JS_UINT32_TO_PTR(index)) |
103 |
#define ALE_SET_JSOP(ale,op) ((ale)->entry.value = JS_UINT32_TO_PTR(op)) |
#define ALE_SET_DEFN(ale, dn) ((ale)->entry.value = (void *)(dn)) |
104 |
#define ALE_SET_VALUE(ale, v) ((ale)->entry.value = (void *)(v)) |
#define ALE_SET_VALUE(ale, v) ((ale)->entry.value = (void *)(v)) |
105 |
|
#define ALE_SET_NEXT(ale,nxt) ((ale)->entry.next = (JSHashEntry *)(nxt)) |
106 |
|
|
107 |
struct JSAtomList { |
/* |
108 |
|
* NB: JSAtomSet must be plain-old-data as it is embedded in the pn_u union in |
109 |
|
* JSParseNode. JSAtomList encapsulates all operational uses of a JSAtomSet. |
110 |
|
* |
111 |
|
* The JSAtomList name is traditional, even though the implementation is a map |
112 |
|
* (not to be confused with JSAtomMap). In particular the "ALE" and "ale" short |
113 |
|
* names for JSAtomListElement variables roll off the fingers, compared to ASE |
114 |
|
* or AME alternatives. |
115 |
|
*/ |
116 |
|
struct JSAtomSet { |
117 |
JSHashEntry *list; /* literals indexed for mapping */ |
JSHashEntry *list; /* literals indexed for mapping */ |
118 |
JSHashTable *table; /* hash table if list gets too long */ |
JSHashTable *table; /* hash table if list gets too long */ |
119 |
jsuint count; /* count of indexed literals */ |
jsuint count; /* count of indexed literals */ |
120 |
}; |
}; |
121 |
|
|
122 |
#define ATOM_LIST_INIT(al) ((al)->list = NULL, (al)->table = NULL, \ |
#ifdef __cplusplus |
123 |
(al)->count = 0) |
|
124 |
|
struct JSAtomList : public JSAtomSet |
125 |
|
{ |
126 |
|
#ifdef DEBUG |
127 |
|
const JSAtomSet* set; /* asserted null in mutating methods */ |
128 |
|
#endif |
129 |
|
|
130 |
|
JSAtomList() { |
131 |
|
list = NULL; table = NULL; count = 0; |
132 |
|
#ifdef DEBUG |
133 |
|
set = NULL; |
134 |
|
#endif |
135 |
|
} |
136 |
|
|
137 |
|
JSAtomList(const JSAtomSet& as) { |
138 |
|
list = as.list; table = as.table; count = as.count; |
139 |
|
#ifdef DEBUG |
140 |
|
set = &as; |
141 |
|
#endif |
142 |
|
} |
143 |
|
|
144 |
|
void clear() { JS_ASSERT(!set); list = NULL; table = NULL; count = 0; } |
145 |
|
|
146 |
|
JSAtomListElement *lookup(JSAtom *atom) { |
147 |
|
JSHashEntry **hep; |
148 |
|
return rawLookup(atom, hep); |
149 |
|
} |
150 |
|
|
151 |
|
JSAtomListElement *rawLookup(JSAtom *atom, JSHashEntry **&hep); |
152 |
|
|
153 |
|
enum AddHow { UNIQUE, SHADOW, HOIST }; |
154 |
|
|
155 |
|
JSAtomListElement *add(JSCompiler *jsc, JSAtom *atom, AddHow how = UNIQUE); |
156 |
|
|
157 |
|
void remove(JSCompiler *jsc, JSAtom *atom) { |
158 |
|
JSHashEntry **hep; |
159 |
|
JSAtomListElement *ale = rawLookup(atom, hep); |
160 |
|
if (ale) |
161 |
|
rawRemove(jsc, ale, hep); |
162 |
|
} |
163 |
|
|
164 |
|
void rawRemove(JSCompiler *jsc, JSAtomListElement *ale, JSHashEntry **hep); |
165 |
|
}; |
166 |
|
|
167 |
|
/* |
168 |
|
* Iterate over an atom list. We define a call operator to minimize the syntax |
169 |
|
* tax for users. We do not use a more standard pattern using ++ and * because |
170 |
|
* (a) it's the wrong pattern for a non-scalar; (b) it's overkill -- one method |
171 |
|
* is enough. (This comment is overkill!) |
172 |
|
*/ |
173 |
|
class JSAtomListIterator { |
174 |
|
JSAtomList* list; |
175 |
|
JSAtomListElement* next; |
176 |
|
uint32 index; |
177 |
|
|
178 |
|
public: |
179 |
|
JSAtomListIterator(JSAtomList* al) : list(al) { reset(); } |
180 |
|
|
181 |
|
void reset() { |
182 |
|
next = (JSAtomListElement *) list->list; |
183 |
|
index = 0; |
184 |
|
} |
185 |
|
|
186 |
|
JSAtomListElement* operator ()(); |
187 |
|
}; |
188 |
|
|
189 |
#define ATOM_LIST_SEARCH(_ale,_al,_atom) \ |
#endif /* __cplusplus */ |
|
JS_BEGIN_MACRO \ |
|
|
JSHashEntry **_hep; \ |
|
|
ATOM_LIST_LOOKUP(_ale, _hep, _al, _atom); \ |
|
|
JS_END_MACRO |
|
|
|
|
|
#define ATOM_LIST_LOOKUP(_ale,_hep,_al,_atom) \ |
|
|
JS_BEGIN_MACRO \ |
|
|
if ((_al)->table) { \ |
|
|
_hep = JS_HashTableRawLookup((_al)->table, ATOM_HASH(_atom), \ |
|
|
_atom); \ |
|
|
_ale = *_hep ? (JSAtomListElement *) *_hep : NULL; \ |
|
|
} else { \ |
|
|
JSHashEntry **_alep = &(_al)->list; \ |
|
|
_hep = NULL; \ |
|
|
while ((_ale = (JSAtomListElement *)*_alep) != NULL) { \ |
|
|
if (ALE_ATOM(_ale) == (_atom)) { \ |
|
|
/* Hit, move atom's element to the front of the list. */ \ |
|
|
*_alep = (_ale)->entry.next; \ |
|
|
(_ale)->entry.next = (_al)->list; \ |
|
|
(_al)->list = &_ale->entry; \ |
|
|
break; \ |
|
|
} \ |
|
|
_alep = &_ale->entry.next; \ |
|
|
} \ |
|
|
} \ |
|
|
JS_END_MACRO |
|
190 |
|
|
191 |
struct JSAtomMap { |
struct JSAtomMap { |
192 |
JSAtom **vector; /* array of ptrs to indexed atoms */ |
JSAtom **vector; /* array of ptrs to indexed atoms */ |
325 |
((offsetof(JSAtomState, typeAtoms[type]) - ATOM_OFFSET_START) \ |
((offsetof(JSAtomState, typeAtoms[type]) - ATOM_OFFSET_START) \ |
326 |
/ sizeof(JSAtom*)) |
/ sizeof(JSAtom*)) |
327 |
|
|
|
/* Start and limit offsets should correspond to atoms. */ |
|
|
JS_STATIC_ASSERT(ATOM_OFFSET_START % sizeof(JSAtom *) == 0); |
|
|
JS_STATIC_ASSERT(ATOM_OFFSET_LIMIT % sizeof(JSAtom *) == 0); |
|
|
|
|
328 |
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom) |
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom) |
329 |
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off))) |
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off))) |
330 |
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState,classAtoms[JSProto_##name]) |
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState,classAtoms[JSProto_##name]) |
336 |
extern const size_t js_common_atom_count; |
extern const size_t js_common_atom_count; |
337 |
|
|
338 |
/* |
/* |
339 |
* Macros to access C strings for JSType and boolean literals together with |
* Macros to access C strings for JSType and boolean literals. |
|
* checks that boolean names start from index 1 and type names from 1+2. |
|
340 |
*/ |
*/ |
341 |
#define JS_BOOLEAN_STR(type) (js_common_atom_names[1 + (type)]) |
#define JS_BOOLEAN_STR(type) (js_common_atom_names[1 + (type)]) |
342 |
#define JS_TYPE_STR(type) (js_common_atom_names[1 + 2 + (type)]) |
#define JS_TYPE_STR(type) (js_common_atom_names[1 + 2 + (type)]) |
343 |
|
|
|
JS_STATIC_ASSERT(1 * sizeof(JSAtom *) == |
|
|
offsetof(JSAtomState, booleanAtoms) - ATOM_OFFSET_START); |
|
|
JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) == |
|
|
offsetof(JSAtomState, typeAtoms) - ATOM_OFFSET_START); |
|
|
|
|
344 |
/* Well-known predefined C strings. */ |
/* Well-known predefined C strings. */ |
345 |
#define JS_PROTO(name,code,init) extern const char js_##name##_str[]; |
#define JS_PROTO(name,code,init) extern const char js_##name##_str[]; |
346 |
#include "jsproto.tbl" |
#include "jsproto.tbl" |
481 |
#endif |
#endif |
482 |
|
|
483 |
/* |
/* |
|
* Assign atom an index and insert it on al. |
|
|
*/ |
|
|
extern JSAtomListElement * |
|
|
js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al); |
|
|
|
|
|
/* |
|
484 |
* For all unmapped atoms recorded in al, add a mapping from the atom's index |
* For all unmapped atoms recorded in al, add a mapping from the atom's index |
485 |
* to its address. map->length must already be set to the number of atoms in |
* to its address. map->length must already be set to the number of atoms in |
486 |
* the list and map->vector must point to pre-allocated memory. |
* the list and map->vector must point to pre-allocated memory. |