/[jscoverage]/trunk/js/jsscope.h
ViewVC logotype

Annotation of /trunk/js/jsscope.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 460 - (hide annotations)
Sat Sep 26 23:15:22 2009 UTC (11 years ago) by siliconforks
File MIME type: text/plain
File size: 22032 byte(s)
Upgrade to SpiderMonkey from Firefox 3.5.3.

1 siliconforks 332 /* -*- 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 Mozilla Communicator client code, released
18     * March 31, 1998.
19     *
20     * The Initial Developer of the Original Code is
21     * Netscape Communications Corporation.
22     * Portions created by the Initial Developer are Copyright (C) 1998
23     * the Initial Developer. All Rights Reserved.
24     *
25     * Contributor(s):
26     *
27     * Alternatively, the contents of this file may be used under the terms of
28     * either of the GNU General Public License Version 2 or later (the "GPL"),
29     * or 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 jsscope_h___
42     #define jsscope_h___
43     /*
44     * JS symbol tables.
45     */
46     #include "jstypes.h"
47     #include "jslock.h"
48     #include "jsobj.h"
49     #include "jsprvtd.h"
50     #include "jspubtd.h"
51    
52     JS_BEGIN_EXTERN_C
53    
54     /*
55     * Given P independent, non-unique properties each of size S words mapped by
56     * all scopes in a runtime, construct a property tree of N nodes each of size
57     * S+L words (L for tree linkage). A nominal L value is 2 for leftmost-child
58     * and right-sibling links. We hope that the N < P by enough that the space
59     * overhead of L, and the overhead of scope entries pointing at property tree
60     * nodes, is worth it.
61     *
62     * The tree construction goes as follows. If any empty scope in the runtime
63     * has a property X added to it, find or create a node under the tree root
64     * labeled X, and set scope->lastProp to point at that node. If any non-empty
65     * scope whose most recently added property is labeled Y has another property
66     * labeled Z added, find or create a node for Z under the node that was added
67     * for Y, and set scope->lastProp to point at that node.
68     *
69     * A property is labeled by its members' values: id, getter, setter, slot,
70     * attributes, tiny or short id, and a field telling for..in order. Note that
71     * labels are not unique in the tree, but they are unique among a node's kids
72     * (barring rare and benign multi-threaded race condition outcomes, see below)
73     * and along any ancestor line from the tree root to a given leaf node (except
74     * for the hard case of duplicate formal parameters to a function).
75     *
76     * Thus the root of the tree represents all empty scopes, and the first ply
77     * of the tree represents all scopes containing one property, etc. Each node
78     * in the tree can stand for any number of scopes having the same ordered set
79     * of properties, where that node was the last added to the scope. (We need
80     * not store the root of the tree as a node, and do not -- all we need are
81     * links to its kids.)
82     *
83     * Sidebar on for..in loop order: ECMA requires no particular order, but this
84     * implementation has promised and delivered property definition order, and
85     * compatibility is king. We could use an order number per property, which
86     * would require a sort in js_Enumerate, and an entry order generation number
87     * per scope. An order number beats a list, which should be doubly-linked for
88     * O(1) delete. An even better scheme is to use a parent link in the property
89     * tree, so that the ancestor line can be iterated from scope->lastProp when
90     * filling in a JSIdArray from back to front. This parent link also helps the
91     * GC to sweep properties iteratively.
92     *
93     * What if a property Y is deleted from a scope? If Y is the last property in
94     * the scope, we simply adjust the scope's lastProp member after we remove the
95     * scope's hash-table entry pointing at that property node. The parent link
96     * mentioned in the for..in sidebar above makes this adjustment O(1). But if
97     * Y comes between X and Z in the scope, then we might have to "fork" the tree
98     * at X, leaving X->Y->Z in case other scopes have those properties added in
99     * that order; and to finish the fork, we'd add a node labeled Z with the path
100     * X->Z, if it doesn't exist. This could lead to lots of extra nodes, and to
101     * O(n^2) growth when deleting lots of properties.
102     *
103     * Rather, for O(1) growth all around, we should share the path X->Y->Z among
104     * scopes having those three properties added in that order, and among scopes
105     * having only X->Z where Y was deleted. All such scopes have a lastProp that
106     * points to the Z child of Y. But a scope in which Y was deleted does not
107     * have a table entry for Y, and when iterating that scope by traversing the
108     * ancestor line from Z, we will have to test for a table entry for each node,
109     * skipping nodes that lack entries.
110     *
111     * What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
112     * Therefore we must fork in such a case, if not earlier. Because delete is
113     * "bursty", we should not fork eagerly. Delaying a fork till we are at risk
114     * of adding Y after it was deleted already requires a flag in the JSScope, to
115     * wit, SCOPE_MIDDLE_DELETE.
116     *
117     * What about thread safety? If the property tree operations done by requests
118     * are find-node and insert-node, then the only hazard is duplicate insertion.
119     * This is harmless except for minor bloat. When all requests have ended or
120     * been suspended, the GC is free to sweep the tree after marking all nodes
121     * reachable from scopes, performing remove-node operations as needed.
122     *
123     * Is the property tree worth it compared to property storage in each table's
124     * entries? To decide, we must find the relation <> between the words used
125     * with a property tree and the words required without a tree.
126     *
127     * Model all scopes as one super-scope of capacity T entries (T a power of 2).
128     * Let alpha be the load factor of this double hash-table. With the property
129     * tree, each entry in the table is a word-sized pointer to a node that can be
130     * shared by many scopes. But all such pointers are overhead compared to the
131     * situation without the property tree, where the table stores property nodes
132     * directly, as entries each of size S words. With the property tree, we need
133     * L=2 extra words per node for siblings and kids pointers. Without the tree,
134     * (1-alpha)*S*T words are wasted on free or removed sentinel-entries required
135     * by double hashing.
136     *
137     * Therefore,
138     *
139     * (property tree) <> (no property tree)
140     * N*(S+L) + T <> S*T
141     * N*(S+L) + T <> P*S + (1-alpha)*S*T
142     * N*(S+L) + alpha*T + (1-alpha)*T <> P*S + (1-alpha)*S*T
143     *
144     * Note that P is alpha*T by definition, so
145     *
146     * N*(S+L) + P + (1-alpha)*T <> P*S + (1-alpha)*S*T
147     * N*(S+L) <> P*S - P + (1-alpha)*S*T - (1-alpha)*T
148     * N*(S+L) <> (P + (1-alpha)*T) * (S-1)
149     * N*(S+L) <> (P + (1-alpha)*P/alpha) * (S-1)
150     * N*(S+L) <> P * (1/alpha) * (S-1)
151     *
152     * Let N = P*beta for a compression ratio beta, beta <= 1:
153     *
154     * P*beta*(S+L) <> P * (1/alpha) * (S-1)
155     * beta*(S+L) <> (S-1)/alpha
156     * beta <> (S-1)/((S+L)*alpha)
157     *
158     * For S = 6 (32-bit architectures) and L = 2, the property tree wins iff
159     *
160     * beta < 5/(8*alpha)
161     *
162     * We ensure that alpha <= .75, so the property tree wins if beta < .83_. An
163     * average beta from recent Mozilla browser startups was around .6.
164     *
165     * Can we reduce L? Observe that the property tree degenerates into a list of
166     * lists if at most one property Y follows X in all scopes. In or near such a
167     * case, we waste a word on the right-sibling link outside of the root ply of
168     * the tree. Note also that the root ply tends to be large, so O(n^2) growth
169     * searching it is likely, indicating the need for hashing (but with increased
170     * thread safety costs).
171     *
172     * If only K out of N nodes in the property tree have more than one child, we
173     * could eliminate the sibling link and overlay a children list or hash-table
174     * pointer on the leftmost-child link (which would then be either null or an
175     * only-child link; the overlay could be tagged in the low bit of the pointer,
176     * or flagged elsewhere in the property tree node, although such a flag must
177     * not be considered when comparing node labels during tree search).
178     *
179     * For such a system, L = 1 + (K * averageChildrenTableSize) / N instead of 2.
180     * If K << N, L approaches 1 and the property tree wins if beta < .95.
181     *
182     * We observe that fan-out below the root ply of the property tree appears to
183     * have extremely low degree (see the MeterPropertyTree code that histograms
184     * child-counts in jsscope.c), so instead of a hash-table we use a linked list
185     * of child node pointer arrays ("kid chunks"). The details are isolated in
186     * jsscope.c; others must treat JSScopeProperty.kids as opaque. We leave it
187     * strongly typed for debug-ability of the common (null or one-kid) cases.
188     *
189     * One final twist (can you stand it?): the mean number of entries per scope
190     * in Mozilla is < 5, with a large standard deviation (~8). Instead of always
191     * allocating scope->table, we leave it null while initializing all the other
192     * scope members as if it were non-null and minimal-length. Until a property
193     * is added that crosses the threshold of 6 or more entries for hashing, or
194     * until a "middle delete" occurs, we use linear search from scope->lastProp
195     * to find a given id, and save on the space overhead of a hash table.
196     */
197    
198     struct JSScope {
199     JSObjectMap map; /* base class state */
200     #ifdef JS_THREADSAFE
201     JSTitle title; /* lock state */
202     #endif
203     JSObject *object; /* object that owns this scope */
204 siliconforks 460 jsrefcount nrefs; /* count of all referencing objects */
205     uint32 freeslot; /* index of next free slot in object */
206 siliconforks 332 uint32 shape; /* property cache shape identifier */
207     uint8 flags; /* flags, see below */
208     int8 hashShift; /* multiplicative hash shift */
209     uint16 spare; /* reserved */
210     uint32 entryCount; /* number of entries in table */
211     uint32 removedCount; /* removed entry sentinels in table */
212     JSScopeProperty **table; /* table of ptrs to shared tree nodes */
213     JSScopeProperty *lastProp; /* pointer to last property added */
214     };
215    
216     #define JS_IS_SCOPE_LOCKED(cx, scope) JS_IS_TITLE_LOCKED(cx, &(scope)->title)
217    
218 siliconforks 460 #define OBJ_SCOPE(obj) (JS_ASSERT(OBJ_IS_NATIVE(obj)), \
219     (JSScope *) (obj)->map)
220 siliconforks 332 #define OBJ_SHAPE(obj) (OBJ_SCOPE(obj)->shape)
221    
222     /* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
223     #define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
224    
225     /* Scope flags and some macros to hide them from other files than jsscope.c. */
226     #define SCOPE_MIDDLE_DELETE 0x0001
227     #define SCOPE_SEALED 0x0002
228     #define SCOPE_BRANDED 0x0004
229 siliconforks 460 #define SCOPE_INDEXED_PROPERTIES 0x0008
230 siliconforks 332
231     #define SCOPE_HAD_MIDDLE_DELETE(scope) ((scope)->flags & SCOPE_MIDDLE_DELETE)
232     #define SCOPE_SET_MIDDLE_DELETE(scope) ((scope)->flags |= SCOPE_MIDDLE_DELETE)
233     #define SCOPE_CLR_MIDDLE_DELETE(scope) ((scope)->flags &= ~SCOPE_MIDDLE_DELETE)
234 siliconforks 460 #define SCOPE_HAS_INDEXED_PROPERTIES(scope) ((scope)->flags & SCOPE_INDEXED_PROPERTIES)
235     #define SCOPE_SET_INDEXED_PROPERTIES(scope) ((scope)->flags |= SCOPE_INDEXED_PROPERTIES)
236 siliconforks 332
237     #define SCOPE_IS_SEALED(scope) ((scope)->flags & SCOPE_SEALED)
238     #define SCOPE_SET_SEALED(scope) ((scope)->flags |= SCOPE_SEALED)
239     #if 0
240     /*
241     * Don't define this, it can't be done safely because JS_LOCK_OBJ will avoid
242     * taking the lock if the object owns its scope and the scope is sealed.
243     */
244     #undef SCOPE_CLR_SEALED(scope) ((scope)->flags &= ~SCOPE_SEALED)
245     #endif
246    
247     /*
248     * A branded scope's object contains plain old methods (function-valued
249     * properties without magic getters and setters), and its scope->shape
250     * evolves whenever a function value changes.
251     */
252     #define SCOPE_IS_BRANDED(scope) ((scope)->flags & SCOPE_BRANDED)
253     #define SCOPE_SET_BRANDED(scope) ((scope)->flags |= SCOPE_BRANDED)
254     #define SCOPE_CLR_BRANDED(scope) ((scope)->flags &= ~SCOPE_BRANDED)
255    
256     /*
257     * A little information hiding for scope->lastProp, in case it ever becomes
258     * a tagged pointer again.
259     */
260     #define SCOPE_LAST_PROP(scope) ((scope)->lastProp)
261     #define SCOPE_REMOVE_LAST_PROP(scope) ((scope)->lastProp = \
262     (scope)->lastProp->parent)
263 siliconforks 460 /*
264     * Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters
265     * and setters.
266     */
267     static inline JSObject *
268     js_CastAsObject(JSPropertyOp op)
269     {
270     return JS_FUNC_TO_DATA_PTR(JSObject *, op);
271     }
272 siliconforks 332
273 siliconforks 460 static inline jsval
274     js_CastAsObjectJSVal(JSPropertyOp op)
275     {
276     return OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, op));
277     }
278    
279     static inline JSPropertyOp
280     js_CastAsPropertyOp(JSObject *object)
281     {
282     return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
283     }
284    
285 siliconforks 332 struct JSScopeProperty {
286     jsid id; /* int-tagged jsval/untagged JSAtom* */
287     JSPropertyOp getter; /* getter and setter hooks or objects */
288     JSPropertyOp setter;
289     uint32 slot; /* abstract index in object slots */
290     uint8 attrs; /* attributes, see jsapi.h JSPROP_* */
291     uint8 flags; /* flags, see below for defines */
292     int16 shortid; /* tinyid, or local arg/var index */
293     JSScopeProperty *parent; /* parent node, reverse for..in order */
294     JSScopeProperty *kids; /* null, single child, or a tagged ptr
295     to many-kids data structure */
296     uint32 shape; /* property cache shape identifier */
297     };
298    
299     /* JSScopeProperty pointer tag bit indicating a collision. */
300     #define SPROP_COLLISION ((jsuword)1)
301     #define SPROP_REMOVED ((JSScopeProperty *) SPROP_COLLISION)
302    
303     /* Macros to get and set sprop pointer values and collision flags. */
304     #define SPROP_IS_FREE(sprop) ((sprop) == NULL)
305     #define SPROP_IS_REMOVED(sprop) ((sprop) == SPROP_REMOVED)
306     #define SPROP_IS_LIVE(sprop) ((sprop) > SPROP_REMOVED)
307     #define SPROP_FLAG_COLLISION(spp,sprop) (*(spp) = (JSScopeProperty *) \
308     ((jsuword)(sprop) | SPROP_COLLISION))
309     #define SPROP_HAD_COLLISION(sprop) ((jsuword)(sprop) & SPROP_COLLISION)
310     #define SPROP_FETCH(spp) SPROP_CLEAR_COLLISION(*(spp))
311    
312     #define SPROP_CLEAR_COLLISION(sprop) \
313     ((JSScopeProperty *) ((jsuword)(sprop) & ~SPROP_COLLISION))
314    
315     #define SPROP_STORE_PRESERVING_COLLISION(spp, sprop) \
316     (*(spp) = (JSScopeProperty *) ((jsuword)(sprop) \
317     | SPROP_HAD_COLLISION(*(spp))))
318    
319     /* Bits stored in sprop->flags. */
320     #define SPROP_MARK 0x01
321     #define SPROP_IS_ALIAS 0x02
322     #define SPROP_HAS_SHORTID 0x04
323     #define SPROP_FLAG_SHAPE_REGEN 0x08
324    
325     /*
326     * If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
327     * than id when calling sprop's getter or setter.
328     */
329     #define SPROP_USERID(sprop) \
330     (((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
331     : ID_TO_VALUE((sprop)->id))
332    
333     #define SPROP_INVALID_SLOT 0xffffffff
334    
335 siliconforks 460 #define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
336 siliconforks 332 #define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
337    
338     #define SPROP_HAS_STUB_GETTER(sprop) (!(sprop)->getter)
339     #define SPROP_HAS_STUB_SETTER(sprop) (!(sprop)->setter)
340    
341 siliconforks 460 static inline void
342     js_MakeScopeShapeUnique(JSContext *cx, JSScope *scope)
343     {
344     js_LeaveTraceIfGlobalObject(cx, scope->object);
345     scope->shape = js_GenerateShape(cx, JS_FALSE);
346     }
347 siliconforks 332
348 siliconforks 460 static inline void
349     js_ExtendScopeShape(JSContext *cx, JSScope *scope, JSScopeProperty *sprop)
350     {
351     js_LeaveTraceIfGlobalObject(cx, scope->object);
352     if (!scope->lastProp ||
353     scope->shape == scope->lastProp->shape) {
354     scope->shape = sprop->shape;
355     } else {
356     scope->shape = js_GenerateShape(cx, JS_FALSE);
357     }
358     }
359    
360     static JS_INLINE JSBool
361     js_GetSprop(JSContext* cx, JSScopeProperty* sprop, JSObject* obj, jsval* vp)
362     {
363     JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
364     if (sprop->attrs & JSPROP_GETTER) {
365     jsval fval = js_CastAsObjectJSVal(sprop->getter);
366     return js_InternalGetOrSet(cx, obj, sprop->id, fval, JSACC_READ,
367     0, 0, vp);
368     }
369    
370     /*
371     * JSObjectOps is private, so we know there are only two implementations
372     * of the thisObject hook: with objects and XPConnect wrapped native
373     * objects. XPConnect objects don't expect the hook to be called here,
374     * but with objects do.
375     */
376     if (STOBJ_GET_CLASS(obj) == &js_WithClass)
377     obj = obj->map->ops->thisObject(cx, obj);
378     return sprop->getter(cx, obj, SPROP_USERID(sprop), vp);
379     }
380    
381     static JS_INLINE JSBool
382     js_SetSprop(JSContext* cx, JSScopeProperty* sprop, JSObject* obj, jsval* vp)
383     {
384     JS_ASSERT(!(SPROP_HAS_STUB_SETTER(sprop) &&
385     !(sprop->attrs & JSPROP_GETTER)));
386    
387     if (sprop->attrs & JSPROP_SETTER) {
388     jsval fval = js_CastAsObjectJSVal(sprop->setter);
389     return js_InternalGetOrSet(cx, obj, (sprop)->id, fval, JSACC_WRITE,
390     1, vp, vp);
391     }
392    
393     if (sprop->attrs & JSPROP_GETTER) {
394     js_ReportGetterOnlyAssignment(cx);
395     return JS_FALSE;
396     }
397    
398     /* See the comment in js_GetSprop as to why we can check for 'with'. */
399     if (STOBJ_GET_CLASS(obj) == &js_WithClass)
400     obj = obj->map->ops->thisObject(cx, obj);
401     return sprop->setter(cx, obj, SPROP_USERID(sprop), vp);
402     }
403    
404 siliconforks 332 /*
405     * NB: SPROP_SET must not be called if (SPROP_HAS_STUB_SETTER(sprop) &&
406     * !(sprop->attrs & JSPROP_GETTER)).
407     */
408     #define SPROP_SET(cx,sprop,obj,obj2,vp) \
409     (((sprop)->attrs & JSPROP_SETTER) \
410     ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
411 siliconforks 460 OBJECT_TO_JSVAL((JSObject *) (sprop)->setter), \
412     JSACC_WRITE, 1, vp, vp) \
413 siliconforks 332 : ((sprop)->attrs & JSPROP_GETTER) \
414     ? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
415     JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
416 siliconforks 460 : (sprop)->setter(cx, obj, SPROP_USERID(sprop), vp))
417 siliconforks 332
418     /* Macro for common expression to test for shared permanent attributes. */
419     #define SPROP_IS_SHARED_PERMANENT(sprop) \
420     ((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
421    
422     extern JSScope *
423     js_GetMutableScope(JSContext *cx, JSObject *obj);
424    
425     extern JSScope *
426 siliconforks 460 js_NewScope(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj);
427 siliconforks 332
428     extern void
429     js_DestroyScope(JSContext *cx, JSScope *scope);
430    
431 siliconforks 460 extern void
432     js_HoldScope(JSScope *scope);
433    
434     extern JSBool
435     js_DropScope(JSContext *cx, JSScope *scope, JSObject *obj);
436    
437 siliconforks 332 extern JS_FRIEND_API(JSScopeProperty **)
438     js_SearchScope(JSScope *scope, jsid id, JSBool adding);
439    
440     #define SCOPE_GET_PROPERTY(scope, id) \
441     SPROP_FETCH(js_SearchScope(scope, id, JS_FALSE))
442    
443     #define SCOPE_HAS_PROPERTY(scope, sprop) \
444     (SCOPE_GET_PROPERTY(scope, (sprop)->id) == (sprop))
445    
446     extern JSScopeProperty *
447     js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
448     JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
449     uintN attrs, uintN flags, intN shortid);
450    
451     extern JSScopeProperty *
452     js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
453     JSScopeProperty *sprop, uintN attrs, uintN mask,
454     JSPropertyOp getter, JSPropertyOp setter);
455    
456     extern JSBool
457     js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id);
458    
459     extern void
460     js_ClearScope(JSContext *cx, JSScope *scope);
461    
462     /*
463     * These macros used to inline short code sequences, but they grew over time.
464     * We retain them for internal backward compatibility, and in case one or both
465     * ever shrink to inline-able size.
466     */
467     #define TRACE_ID(trc, id) js_TraceId(trc, id)
468     #define TRACE_SCOPE_PROPERTY(trc, sprop) js_TraceScopeProperty(trc, sprop)
469    
470     extern void
471     js_TraceId(JSTracer *trc, jsid id);
472    
473     extern void
474     js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop);
475    
476     extern void
477     js_SweepScopeProperties(JSContext *cx);
478    
479     extern JSBool
480     js_InitPropertyTree(JSRuntime *rt);
481    
482     extern void
483     js_FinishPropertyTree(JSRuntime *rt);
484    
485     JS_END_EXTERN_C
486    
487     #endif /* jsscope_h___ */

  ViewVC Help
Powered by ViewVC 1.1.24