Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jscntxt.h
1 /* -*- 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 jscntxt_h___
42 #define jscntxt_h___
43 /*
44  * JS execution context.
45  */
46 #include <string.h>
47
48 /* Gross special case for Gecko, which defines malloc/calloc/free. */
49 #ifdef mozilla_mozalloc_macro_wrappers_h
50 #  define JS_CNTXT_UNDEFD_MOZALLOC_WRAPPERS
51 /* The "anti-header" */
52 #  include "mozilla/mozalloc_undef_macro_wrappers.h"
53 #endif
54
55 #include "jsprvtd.h"
56 #include "jsarena.h"
57 #include "jsclist.h"
58 #include "jslong.h"
59 #include "jsatom.h"
60 #include "jsdhash.h"
61 #include "jsdtoa.h"
62 #include "jsfun.h"
63 #include "jsgc.h"
64 #include "jsgcchunk.h"
65 #include "jshashtable.h"
66 #include "jsinterp.h"
67 #include "jsmath.h"
68 #include "jsobj.h"
69 #include "jspropertycache.h"
70 #include "jspropertytree.h"
71 #include "jsstaticcheck.h"
72 #include "jsutil.h"
73 #include "jsarray.h"
74 #include "jsvector.h"
75 #include "prmjtime.h"
76
77 #ifdef _MSC_VER
78 #pragma warning(push)
79 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
80 #pragma warning(push)
81 #pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */
82 #endif
83
84 /*
85  * js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
86  * given pc in a script. We use the script->code pointer to tag the cache,
87  * instead of the script address itself, so that source notes are always found
88  * by offset from the bytecode with which they were generated.
89  */
90 typedef struct JSGSNCache {
91     jsbytecode      *code;
92     JSDHashTable    table;
93 #ifdef JS_GSNMETER
94     uint32          hits;
95     uint32          misses;
96     uint32          fills;
97     uint32          purges;
98 # define GSN_CACHE_METER(cache,cnt) (++(cache)->cnt)
99 #else
100 # define GSN_CACHE_METER(cache,cnt) /* nothing */
101 #endif
102 } JSGSNCache;
103
104 #define js_FinishGSNCache(cache) js_PurgeGSNCache(cache)
105
106 extern void
107 js_PurgeGSNCache(JSGSNCache *cache);
108
109 /* These helper macros take a cx as parameter and operate on its GSN cache. */
110 #define JS_PURGE_GSN_CACHE(cx)      js_PurgeGSNCache(&JS_GSN_CACHE(cx))
111 #define JS_METER_GSN_CACHE(cx,cnt)  GSN_CACHE_METER(&JS_GSN_CACHE(cx), cnt)
112
113 /* Forward declarations of nanojit types. */
114 namespace nanojit {
115
116 class Assembler;
117 class CodeAlloc;
118 class Fragment;
119 template<typename K> struct DefaultHash;
120 template<typename K, typename V, typename H> class HashMap;
121 template<typename T> class Seq;
122
123 }  /* namespace nanojit */
124
125 namespace js {
126
127 /* Tracer constants. */
128 static const size_t MONITOR_N_GLOBAL_STATES = 4;
129 static const size_t FRAGMENT_TABLE_SIZE = 512;
130 static const size_t MAX_NATIVE_STACK_SLOTS = 4096;
131 static const size_t MAX_CALL_STACK_ENTRIES = 500;
132 static const size_t MAX_GLOBAL_SLOTS = 4096;
133 static const size_t GLOBAL_SLOTS_BUFFER_SIZE = MAX_GLOBAL_SLOTS + 1;
134 static const size_t MAX_SLOW_NATIVE_EXTRA_SLOTS = 16;
135
136 /* Forward declarations of tracer types. */
137 class VMAllocator;
138 class FrameInfoCache;
139 struct FrameInfo;
140 struct VMSideExit;
141 struct TreeFragment;
142 struct TracerState;
143 template<typename T> class Queue;
144 typedef Queue<uint16> SlotList;
145 class TypeMap;
146 class LoopProfile;
147
148 #if defined(JS_JIT_SPEW) || defined(DEBUG)
149 struct FragPI;
150 typedef nanojit::HashMap<uint32, FragPI, nanojit::DefaultHash<uint32> > FragStatsMap;
151 #endif
152
153 namespace mjit {
154 class JaegerCompartment;
155 }
156
157 /*
158  * Allocation policy that calls JSContext memory functions and reports errors
159  * to the context. Since the JSContext given on construction is stored for
160  * the lifetime of the container, this policy may only be used for containers
161  * whose lifetime is a shorter than the given JSContext.
162  */
163 class ContextAllocPolicy
164 {
165     JSContext *cx;
166
167   public:
168     ContextAllocPolicy(JSContext *cx) : cx(cx) {}
169     JSContext *context() const { return cx; }
170
171     /* Inline definitions below. */
172     void *malloc(size_t bytes);
173     void free(void *p);
174     void *realloc(void *p, size_t bytes);
175     void reportAllocOverflow() const;
176 };
177
178 /*
179  * A StackSegment (referred to as just a 'segment') contains a prev-linked set
180  * of stack frames and the slots associated with each frame. A segment and its
181  * contained frames/slots also have a precise memory layout that is described
182  * in the js::StackSpace comment. A key layout invariant for segments is that
183  * prev-linked frames are adjacent in memory, separated only by the values that
184  * constitute the locals and expression stack of the prev-frame.
185  *
186  * The set of stack frames in a non-empty segment start at the segment's
187  * "current frame", which is the most recently pushed frame, and ends at the
188  * segment's "initial frame". Note that, while all stack frames in a segment
189  * are prev-linked, not all prev-linked frames are in the same segment. Hence,
190  * for a segment |ss|, |ss->getInitialFrame()->prev| may be non-null and in a
191  * different segment. This occurs when the VM reenters itself (via Invoke or
192  * Execute). In full generality, a single context may contain a forest of trees
193  * of stack frames. With respect to this forest, a segment contains a linear
194  * path along a single tree, not necessarily to the root.
195  *
196  * The frames of a non-empty segment must all be in the same context and thus
197  * each non-empty segment is referred to as being "in" a context. Segments in a
198  * context have an additional state of being either "active" or "suspended". A
199  * suspended segment |ss| has a "suspended frame" which is snapshot of |cx->regs|
200  * when the segment was suspended and serves as the current frame of |ss|.
201  * There is at most one active segment in a given context. Segments in a
202  * context execute LIFO and are maintained in a stack.  The top of this stack
203  * is the context's "current segment". If a context |cx| has an active segment
204  * |ss|, then:
205  *   1. |ss| is |cx|'s current segment,
206  *   2. |cx->regs != NULL|, and
207  *   3. |ss|'s current frame is |cx->regs->fp|.
208  * Moreover, |cx->regs != NULL| iff |cx| has an active segment.
209  *
210  * An empty segment is not associated with any context. Empty segments are
211  * created when there is not an active segment for a context at the top of the
212  * stack and claim space for the arguments of an Invoke before the Invoke's
213  * stack frame is pushed. During the intervals when the arguments have been
214  * pushed, but not the stack frame, the segment cannot be pushed onto the
215  * context, since that would require some hack to deal with cx->fp not being
216  * the current frame of cx->currentSegment.
217  *
218  * Finally, (to support JS_SaveFrameChain/JS_RestoreFrameChain) a suspended
219  * segment may or may not be "saved". Normally, when the active segment is
220  * popped, the previous segment (which is necessarily suspended) becomes
221  * active. If the previous segment was saved, however, then it stays suspended
222  * until it is made active by a call to JS_RestoreFrameChain. This is why a
223  * context may have a current segment, but not an active segment.
224  */
225 class StackSegment
226 {
227     /* The context to which this segment belongs. */
228     JSContext           *cx;
229
230     /* Link for JSContext segment stack mentioned in big comment above. */
231     StackSegment        *previousInContext;
232
233     /* Link for StackSpace segment stack mentioned in StackSpace comment. */
234     StackSegment        *previousInMemory;
235
236     /* The first frame executed in this segment. null iff cx is null */
237     JSStackFrame        *initialFrame;
238
239     /* If this segment is suspended, |cx->regs| when it was suspended. */
240     JSFrameRegs         *suspendedRegs;
241
242     /* The varobj on entry to initialFrame. */
243     JSObject            *initialVarObj;
244
245     /* Whether this segment was suspended by JS_SaveFrameChain. */
246     bool                saved;
247
248     /* Align at 8 bytes on all platforms. */
249 #if JS_BITS_PER_WORD == 32
250     void                *padding;
251 #endif
252
253     /*
254      * To make isActive a single null-ness check, this non-null constant is
255      * assigned to suspendedRegs when !inContext.
256      */
257 #define NON_NULL_SUSPENDED_REGS ((JSFrameRegs *)0x1)
258
259   public:
260     StackSegment()
261       : cx(NULL), previousInContext(NULL), previousInMemory(NULL),
262         initialFrame(NULL), suspendedRegs(NON_NULL_SUSPENDED_REGS),
263         initialVarObj(NULL), saved(false)
264     {
265         JS_ASSERT(!inContext());
266     }
267
268     /* Safe casts guaranteed by the contiguous-stack layout. */
269
270     Value *valueRangeBegin() const {
271         return (Value *)(this + 1);
272     }
273
274     /*
275      * As described in the comment at the beginning of the class, a segment
276      * is in one of three states:
277      *
278      *  !inContext:  the segment has been created to root arguments for a
279      *               future call to Invoke.
280      *  isActive:    the segment describes a set of stack frames in a context,
281      *               where the top frame currently executing.
282      *  isSuspended: like isActive, but the top frame has been suspended.
283      */
284
285     bool inContext() const {
286         JS_ASSERT(!!cx == !!initialFrame);
287         JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS && !saved);
288         return cx;
289     }
290
291     bool isActive() const {
292         JS_ASSERT_IF(!suspendedRegs, cx && !saved);
293         JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS);
294         return !suspendedRegs;
295     }
296
297     bool isSuspended() const {
298         JS_ASSERT_IF(!cx || !suspendedRegs, !saved);
299         JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS);
300         return cx && suspendedRegs;
301     }
302
303     /* Substate of suspended, queryable in any state. */
304
305     bool isSaved() const {
306         JS_ASSERT_IF(saved, isSuspended());
307         return saved;
308     }
309
310     /* Transitioning between inContext <--> isActive */
311
312     void joinContext(JSContext *cx, JSStackFrame *f) {
313         JS_ASSERT(!inContext());
314         this->cx = cx;
315         initialFrame = f;
316         suspendedRegs = NULL;
317         JS_ASSERT(isActive());
318     }
319
320     void leaveContext() {
321         JS_ASSERT(isActive());
322         this->cx = NULL;
323         initialFrame = NULL;
324         suspendedRegs = NON_NULL_SUSPENDED_REGS;
325         JS_ASSERT(!inContext());
326     }
327
328     JSContext *maybeContext() const {
329         return cx;
330     }
331
332 #undef NON_NULL_SUSPENDED_REGS
333
334     /* Transitioning between isActive <--> isSuspended */
335
336     void suspend(JSFrameRegs *regs) {
337         JS_ASSERT(isActive());
338         JS_ASSERT(regs && regs->fp && contains(regs->fp));
339         suspendedRegs = regs;
340         JS_ASSERT(isSuspended());
341     }
342
343     void resume() {
344         JS_ASSERT(isSuspended());
345         suspendedRegs = NULL;
346         JS_ASSERT(isActive());
347     }
348
349     /* When isSuspended, transitioning isSaved <--> !isSaved */
350
351     void save(JSFrameRegs *regs) {
352         JS_ASSERT(!isSuspended());
353         suspend(regs);
354         saved = true;
355         JS_ASSERT(isSaved());
356     }
357
358     void restore() {
359         JS_ASSERT(isSaved());
360         saved = false;
361         resume();
362         JS_ASSERT(!isSuspended());
363     }
364
365     /* Data available when inContext */
366
367     JSStackFrame *getInitialFrame() const {
368         JS_ASSERT(inContext());
369         return initialFrame;
370     }
371
372     inline JSFrameRegs *getCurrentRegs() const;
373     inline JSStackFrame *getCurrentFrame() const;
374
375     /* Data available when isSuspended. */
376
377     JSFrameRegs *getSuspendedRegs() const {
378         JS_ASSERT(isSuspended());
379         return suspendedRegs;
380     }
381
382     JSStackFrame *getSuspendedFrame() const {
383         return suspendedRegs->fp;
384     }
385
386     /* JSContext / js::StackSpace bookkeeping. */
387
388     void setPreviousInContext(StackSegment *seg) {
389         previousInContext = seg;
390     }
391
392     StackSegment *getPreviousInContext() const  {
393         return previousInContext;
394     }
395
396     void setPreviousInMemory(StackSegment *seg) {
397         previousInMemory = seg;
398     }
399
400     StackSegment *getPreviousInMemory() const  {
401         return previousInMemory;
402     }
403
404     void setInitialVarObj(JSObject *obj) {
405         JS_ASSERT(inContext());
406         initialVarObj = obj;
407     }
408
409     bool hasInitialVarObj() {
410         JS_ASSERT(inContext());
411         return initialVarObj != NULL;
412     }
413
414     JSObject &getInitialVarObj() const {
415         JS_ASSERT(inContext() && initialVarObj);
416         return *initialVarObj;
417     }
418
419 #ifdef DEBUG
420     JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
421 #endif
422 };
423
424 static const size_t VALUES_PER_STACK_SEGMENT = sizeof(StackSegment) / sizeof(Value);
425 JS_STATIC_ASSERT(sizeof(StackSegment) % sizeof(Value) == 0);
426
427 /* See StackSpace::pushInvokeArgs. */
428 class InvokeArgsGuard : public CallArgs
429 {
430     friend class StackSpace;
431     JSContext        *cx;  /* null implies nothing pushed */
432     StackSegment     *seg;
433     Value            *prevInvokeArgEnd;
434 #ifdef DEBUG
435     StackSegment     *prevInvokeSegment;
436     JSStackFrame     *prevInvokeFrame;
437 #endif
438   public:
439     InvokeArgsGuard() : cx(NULL), seg(NULL) {}
440     ~InvokeArgsGuard();
441     bool pushed() const { return cx != NULL; }
442 };
443
444 /*
445  * This type can be used to call Invoke when the arguments have already been
446  * pushed onto the stack as part of normal execution.
447  */
448 struct InvokeArgsAlreadyOnTheStack : CallArgs
449 {
450     InvokeArgsAlreadyOnTheStack(Value *vp, uintN argc) : CallArgs(vp + 2, argc) {}
451 };
452
453 /* See StackSpace::pushInvokeFrame. */
454 class InvokeFrameGuard
455 {
456     friend class StackSpace;
457     JSContext        *cx_;  /* null implies nothing pushed */
458     JSFrameRegs      regs_;
459     JSFrameRegs      *prevRegs_;
460   public:
461     InvokeFrameGuard() : cx_(NULL) {}
462     ~InvokeFrameGuard() { if (pushed()) pop(); }
463     bool pushed() const { return cx_ != NULL; }
464     JSContext *pushedFrameContext() const { JS_ASSERT(pushed()); return cx_; }
465     void pop();
466     JSStackFrame *fp() const { return regs_.fp; }
467 };
468
469 /* Reusable base; not for direct use. */
470 class FrameGuard
471 {
472     friend class StackSpace;
473     JSContext        *cx_;  /* null implies nothing pushed */
474     StackSegment     *seg_;
475     Value            *vp_;
476     JSStackFrame     *fp_;
477   public:
478     FrameGuard() : cx_(NULL), vp_(NULL), fp_(NULL) {}
479     JS_REQUIRES_STACK ~FrameGuard();
480     bool pushed() const { return cx_ != NULL; }
481     StackSegment *segment() const { return seg_; }
482     Value *vp() const { return vp_; }
483     JSStackFrame *fp() const { return fp_; }
484 };
485
486 /* See StackSpace::pushExecuteFrame. */
487 class ExecuteFrameGuard : public FrameGuard
488 {
489     friend class StackSpace;
490     JSFrameRegs      regs_;
491 };
492
493 /* See StackSpace::pushDummyFrame. */
494 class DummyFrameGuard : public FrameGuard
495 {
496     friend class StackSpace;
497     JSFrameRegs      regs_;
498 };
499
500 /* See StackSpace::pushGeneratorFrame. */
501 class GeneratorFrameGuard : public FrameGuard
502 {};
503
504 /*
505  * Stack layout
506  *
507  * Each JSThreadData has one associated StackSpace object which allocates all
508  * segments for the thread. StackSpace performs all such allocations in a
509  * single, fixed-size buffer using a specific layout scheme that allows some
510  * associations between segments, frames, and slots to be implicit, rather
511  * than explicitly stored as pointers. To maintain useful invariants, stack
512  * space is not given out arbitrarily, but rather allocated/deallocated for
513  * specific purposes. The use cases currently supported are: calling a function
514  * with arguments (e.g. Invoke), executing a script (e.g. Execute), inline
515  * interpreter calls, and pushing "dummy" frames for bookkeeping purposes. See
516  * associated member functions below.
517  *
518  * First, we consider the layout of individual segments. (See the
519  * js::StackSegment comment for terminology.) A non-empty segment (i.e., a
520  * segment in a context) has the following layout:
521  *
522  *           initial frame                 current frame ------.  if regs,
523  *          .------------.                           |         |  regs->sp
524  *          |            V                           V         V
525  *   |segment| slots |frame| slots |frame| slots |frame| slots |
526  *                       |  ^          |  ^          |
527  *          ? <----------'  `----------'  `----------'
528  *                prev          prev          prev
529  *
530  * Moreover, the bytes in the following ranges form a contiguous array of
531  * Values that are marked during GC:
532  *   1. between a segment and its first frame
533  *   2. between two adjacent frames in a segment
534  *   3. between a segment's current frame and (if fp->regs) fp->regs->sp
535  * Thus, the VM must ensure that all such Values are safe to be marked.
536  *
537  * An empty segment is followed by arguments that are rooted by the
538  * StackSpace::invokeArgEnd pointer:
539  *
540  *              invokeArgEnd
541  *                   |
542  *                   V
543  *   |segment| slots |
544  *
545  * Above the level of segments, a StackSpace is simply a contiguous sequence
546  * of segments kept in a linked list:
547  *
548  *   base                       currentSegment  firstUnused            end
549  *    |                               |             |                   |
550  *    V                               V             V                   V
551  *    |segment| --- |segment| --- |segment| ------- |                   |
552  *         | ^           | ^           |
553  *   0 <---' `-----------' `-----------'
554  *   previous    previous       previous
555  *
556  * Both js::StackSpace and JSContext maintain a stack of segments, the top of
557  * which is the "current segment" for that thread or context, respectively.
558  * Since different contexts can arbitrarily interleave execution in a single
559  * thread, these stacks are different enough that a segment needs both
560  * "previousInMemory" and "previousInContext".
561  *
562  * For example, in a single thread, a function in segment S1 in a context CX1
563  * may call out into C++ code that reenters the VM in a context CX2, which
564  * creates a new segment S2 in CX2, and CX1 may or may not equal CX2.
565  *
566  * Note that there is some structure to this interleaving of segments:
567  *   1. the inclusion from segments in a context to segments in a thread
568  *      preserves order (in terms of previousInContext and previousInMemory,
569  *      respectively).
570  *   2. the mapping from stack frames to their containing segment preserves
571  *      order (in terms of prev and previousInContext, respectively).
572  */
573 class StackSpace
574 {
575     Value *base;
576 #ifdef XP_WIN
577     mutable Value *commitEnd;
578 #endif
579     Value *end;
580     StackSegment *currentSegment;
581 #ifdef DEBUG
582     /*
583      * Keep track of which segment/frame bumped invokeArgEnd so that
584      * firstUnused() can assert that, when invokeArgEnd is used as the top of
585      * the stack, it is being used appropriately.
586      */
587     StackSegment *invokeSegment;
588     JSStackFrame *invokeFrame;
589 #endif
590     Value        *invokeArgEnd;
591
592     friend class InvokeArgsGuard;
593     friend class InvokeFrameGuard;
594     friend class FrameGuard;
595
596     bool pushSegmentForInvoke(JSContext *cx, uintN argc, InvokeArgsGuard *ag);
597     void popSegmentForInvoke(const InvokeArgsGuard &ag);
598
599     bool pushInvokeFrameSlow(JSContext *cx, const InvokeArgsGuard &ag,
600                              InvokeFrameGuard *fg);
601     void popInvokeFrameSlow(const CallArgs &args);
602
603     bool getSegmentAndFrame(JSContext *cx, uintN vplen, uintN nslots,
604                             FrameGuard *fg) const;
605     void pushSegmentAndFrame(JSContext *cx, JSFrameRegs *regs, FrameGuard *fg);
606     void popSegmentAndFrame(JSContext *cx);
607
608     struct EnsureSpaceCheck {
609         inline bool operator()(const StackSpace &, JSContext *, Value *, uintN);
610     };
611
612     struct LimitCheck {
613         JSStackFrame *base;
614         Value **limit;
615         LimitCheck(JSStackFrame *base, Value **limit) : base(base), limit(limit) {}
616         inline bool operator()(const StackSpace &, JSContext *, Value *, uintN);
617     };
618
619     template <class Check>
620     inline JSStackFrame *getCallFrame(JSContext *cx, Value *sp, uintN nactual,
621                                       JSFunction *fun, JSScript *script,
622                                       uint32 *pflags, Check check) const;
623
624     inline void popInvokeArgs(const InvokeArgsGuard &args);
625     inline void popInvokeFrame(const InvokeFrameGuard &ag);
626
627     inline Value *firstUnused() const;
628
629     inline bool isCurrentAndActive(JSContext *cx) const;
630     friend class AllFramesIter;
631     StackSegment *getCurrentSegment() const { return currentSegment; }
632
633 #ifdef XP_WIN
634     /* Commit more memory from the reserved stack space. */
635     JS_FRIEND_API(bool) bumpCommit(Value *from, ptrdiff_t nvals) const;
636 #endif
637
638   public:
639     static const size_t CAPACITY_VALS   = 512 * 1024;
640     static const size_t CAPACITY_BYTES  = CAPACITY_VALS * sizeof(Value);
641     static const size_t COMMIT_VALS     = 16 * 1024;
642     static const size_t COMMIT_BYTES    = COMMIT_VALS * sizeof(Value);
643
644     /*
645      * SunSpider and v8bench have roughly an average of 9 slots per script.
646      * Our heuristic for a quick over-recursion check uses a generous slot
647      * count based on this estimate. We take this frame size and multiply it
648      * by the old recursion limit from the interpreter.
649      *
650      * Worst case, if an average size script (<=9 slots) over recurses, it'll
651      * effectively be the same as having increased the old inline call count
652      * to <= 5,000.
653      */
654     static const size_t STACK_QUOTA    = (VALUES_PER_STACK_FRAME + 18) *
655                                          JS_MAX_INLINE_CALL_COUNT;
656
657     /* Kept as a member of JSThreadData; cannot use constructor/destructor. */
658     bool init();
659     void finish();
660
661 #ifdef DEBUG
662     template <class T>
663     bool contains(T *t) const {
664         char *v = (char *)t;
665         JS_ASSERT(size_t(-1) - uintptr_t(t) >= sizeof(T));
666         return v >= (char *)base && v + sizeof(T) <= (char *)end;
667     }
668 #endif
669
670     /*
671      * When we LeaveTree, we need to rebuild the stack, which requires stack
672      * allocation. There is no good way to handle an OOM for these allocations,
673      * so this function checks that they cannot occur using the size of the
674      * TraceNativeStorage as a conservative upper bound.
675      */
676     inline bool ensureEnoughSpaceToEnterTrace();
677
678     /* +1 for slow native's stack frame. */
679     static const ptrdiff_t MAX_TRACE_SPACE_VALS =
680       MAX_NATIVE_STACK_SLOTS + MAX_CALL_STACK_ENTRIES * VALUES_PER_STACK_FRAME +
681       (VALUES_PER_STACK_SEGMENT + VALUES_PER_STACK_FRAME /* synthesized slow native */);
682
683     /* Mark all segments, frames, and slots on the stack. */
684     JS_REQUIRES_STACK void mark(JSTracer *trc);
685
686     /*
687      * For all five use cases below:
688      *  - The boolean-valued functions call js_ReportOutOfScriptQuota on OOM.
689      *  - The "get*Frame" functions do not change any global state, they just
690      *    check OOM and return pointers to an uninitialized frame with the
691      *    requested missing arguments/slots. Only once the "push*Frame"
692      *    function has been called is global state updated. Thus, between
693      *    "get*Frame" and "push*Frame", the frame and slots are unrooted.
694      *  - The "push*Frame" functions will set fp->prev; the caller needn't.
695      *  - Functions taking "*Guard" arguments will use the guard's destructor
696      *    to pop the allocation. The caller must ensure the guard has the
697      *    appropriate lifetime.
698      *  - The get*Frame functions put the 'nmissing' slots contiguously after
699      *    the arguments.
700      */
701
702     /*
703      * pushInvokeArgs allocates |argc + 2| rooted values that will be passed as
704      * the arguments to Invoke. A single allocation can be used for multiple
705      * Invoke calls. The InvokeArgumentsGuard passed to Invoke must come from
706      * an immediately-enclosing (stack-wise) call to pushInvokeArgs.
707      */
708     bool pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *ag);
709
710     /* These functions are called inside Invoke, not Invoke clients. */
711     bool getInvokeFrame(JSContext *cx, const CallArgs &args, JSFunction *fun,
712                         JSScript *script, uint32 *flags, InvokeFrameGuard *fg) const;
713
714     void pushInvokeFrame(JSContext *cx, const CallArgs &args, InvokeFrameGuard *fg);
715
716     /* These functions are called inside Execute, not Execute clients. */
717     bool getExecuteFrame(JSContext *cx, JSScript *script, ExecuteFrameGuard *fg) const;
718     void pushExecuteFrame(JSContext *cx, JSObject *initialVarObj, ExecuteFrameGuard *fg);
719
720     /*
721      * Since RAII cannot be used for inline frames, callers must manually
722      * call pushInlineFrame/popInlineFrame.
723      */
724     inline JSStackFrame *getInlineFrame(JSContext *cx, Value *sp, uintN nactual,
725                                         JSFunction *fun, JSScript *script,
726                                         uint32 *flags) const;
727     inline void pushInlineFrame(JSContext *cx, JSScript *script, JSStackFrame *fp,
728                                 JSFrameRegs *regs);
729     inline void popInlineFrame(JSContext *cx, JSStackFrame *prev, js::Value *newsp);
730
731     /* These functions are called inside SendToGenerator. */
732     bool getGeneratorFrame(JSContext *cx, uintN vplen, uintN nslots,
733                            GeneratorFrameGuard *fg);
734     void pushGeneratorFrame(JSContext *cx, JSFrameRegs *regs, GeneratorFrameGuard *fg);
735
736     /* Pushes a JSStackFrame::isDummyFrame. */
737     bool pushDummyFrame(JSContext *cx, JSObject &scopeChain, DummyFrameGuard *fg);
738
739     /* Check and bump the given stack limit. */
740     inline JSStackFrame *getInlineFrameWithinLimit(JSContext *cx, Value *sp, uintN nactual,
741                                                    JSFunction *fun, JSScript *script, uint32 *flags,
742                                                    JSStackFrame *base, Value **limit) const;
743
744     /*
745      * Compute a stack limit for entering method jit code which allows the
746      * method jit to check for end-of-stack and over-recursion with a single
747      * comparison. See STACK_QUOTA above.
748      */
749     inline Value *getStackLimit(JSContext *cx);
750
751     /*
752      * Try to bump the given 'limit' by bumping the commit limit. Return false
753      * if fully committed or if 'limit' exceeds 'base' + STACK_QUOTA.
754      */
755     bool bumpCommitAndLimit(JSStackFrame *base, Value *from, uintN nvals, Value **limit) const;
756
757     /*
758      * Allocate nvals on the top of the stack, report error on failure.
759      * N.B. the caller must ensure |from >= firstUnused()|.
760      */
761     inline bool ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const;
762 };
763
764 JS_STATIC_ASSERT(StackSpace::CAPACITY_VALS % StackSpace::COMMIT_VALS == 0);
765
766 /*
767  * While |cx->fp|'s pc/sp are available in |cx->regs|, to compute the saved
768  * value of pc/sp for any other frame, it is necessary to know about that
769  * frame's next-frame. This iterator maintains this information when walking
770  * a chain of stack frames starting at |cx->fp|.
771  *
772  * Usage:
773  *   for (FrameRegsIter i(cx); !i.done(); ++i)
774  *     ... i.fp() ... i.sp() ... i.pc()
775  */
776 class FrameRegsIter
777 {
778     JSContext         *cx;
779     StackSegment      *curseg;
780     JSStackFrame      *curfp;
781     Value             *cursp;
782     jsbytecode        *curpc;
783
784     void initSlow();
785     void incSlow(JSStackFrame *fp, JSStackFrame *prev);
786
787   public:
788     JS_REQUIRES_STACK inline FrameRegsIter(JSContext *cx);
789
790     bool done() const { return curfp == NULL; }
791     inline FrameRegsIter &operator++();
792
793     JSStackFrame *fp() const { return curfp; }
794     Value *sp() const { return cursp; }
795     jsbytecode *pc() const { return curpc; }
796 };
797
798 /*
799  * Utility class for iteration over all active stack frames.
800  */
801 class AllFramesIter
802 {
803 public:
804     AllFramesIter(JSContext *cx);
805
806     bool done() const { return curfp == NULL; }
807     AllFramesIter& operator++();
808
809     JSStackFrame *fp() const { return curfp; }
810
811 private:
812     StackSegment *curcs;
813     JSStackFrame *curfp;
814 };
815
816 } /* namespace js */
817
818 #ifdef DEBUG
819 # define FUNCTION_KIND_METER_LIST(_)                                          \
820                         _(allfun), _(heavy), _(nofreeupvar), _(onlyfreevar),  \
821                         _(flat), _(badfunarg),                                \
822                         _(joinedsetmethod), _(joinedinitmethod),              \
823                         _(joinedreplace), _(joinedsort), _(joinedmodulepat),  \
824                         _(mreadbarrier), _(mwritebarrier), _(mwslotbarrier),  \
825                         _(unjoined), _(indynamicscope)
826 # define identity(x)    x
827
828 struct JSFunctionMeter {
829     int32 FUNCTION_KIND_METER_LIST(identity);
830 };
831
832 # undef identity
833
834 # define JS_FUNCTION_METER(cx,x) JS_RUNTIME_METER((cx)->runtime, functionMeter.x)
835 #else
836 # define JS_FUNCTION_METER(cx,x) ((void)0)
837 #endif
838
839
840 struct JSPendingProxyOperation {
841     JSPendingProxyOperation *next;
842     JSObject *object;
843 };
844
845 struct JSThreadData {
846 #ifdef JS_THREADSAFE
847     /* The request depth for this thread. */
848     unsigned            requestDepth;
849 #endif
850
851 #ifdef JS_TRACER
852     /*
853      * During trace execution (or during trace recording or
854      * profiling), these fields point to the compartment doing the
855      * execution on this thread. At other times, they are NULL.  If a
856      * thread tries to execute/record/profile one trace while another
857      * is still running, the initial one will abort. Therefore, we
858      * only need to track one at a time.
859      */
860     JSCompartment       *onTraceCompartment;
861     JSCompartment       *recordingCompartment;
862     JSCompartment       *profilingCompartment;
863  #endif
864
865     /*
866      * If non-zero, we were been asked to call the operation callback as soon
867      * as possible.  If the thread has an active request, this contributes
868      * towards rt->interruptCounter.
869      */
870     volatile int32      interruptFlags;
871
872     /* Keeper of the contiguous stack used by all contexts in this thread. */
873     js::StackSpace      stackSpace;
874
875     /*
876      * Flag indicating that we are waiving any soft limits on the GC heap
877      * because we want allocations to be infallible (except when we hit OOM).
878      */
879     bool                waiveGCQuota;
880
881     /*
882      * The GSN cache is per thread since even multi-cx-per-thread embeddings
883      * do not interleave js_GetSrcNote calls.
884      */
885     JSGSNCache          gsnCache;
886
887     /* Property cache for faster call/get/set invocation. */
888     js::PropertyCache   propertyCache;
889
890 #ifdef JS_TRACER
891     /* Maximum size of the tracer's code cache before we start flushing. */
892     uint32              maxCodeCacheBytes;
893 #endif
894
895     /* State used by dtoa.c. */
896     DtoaState           *dtoaState;
897
898     /* Base address of the native stack for the current thread. */
899     jsuword             *nativeStackBase;
900
901     /* List of currently pending operations on proxies. */
902     JSPendingProxyOperation *pendingProxyOperation;
903
904     js::ConservativeGCThreadData conservativeGC;
905
906     bool init();
907     void finish();
908     void mark(JSTracer *trc);
909     void purge(JSContext *cx);
910
911     /* This must be called with the GC lock held. */
912     inline void triggerOperationCallback(JSRuntime *rt);
913 };
914
915 #ifdef JS_THREADSAFE
916
917 /*
918  * Structure uniquely representing a thread.  It holds thread-private data
919  * that can be accessed without a global lock.
920  */
921 struct JSThread {
922     typedef js::HashMap<void *,
923                         JSThread *,
924                         js::DefaultHasher<void *>,
925                         js::SystemAllocPolicy> Map;
926
927     /* Linked list of all contexts in use on this thread. */
928     JSCList             contextList;
929
930     /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
931     void                *id;
932
933     /* Number of JS_SuspendRequest calls withot JS_ResumeRequest. */
934     unsigned            suspendCount;
935
936 # ifdef DEBUG
937     unsigned            checkRequestDepth;
938 # endif
939
940     /* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */
941     JSThreadData        data;
942 };
943
944 #define JS_THREAD_DATA(cx)      (&(cx)->thread->data)
945
946 extern JSThread *
947 js_CurrentThread(JSRuntime *rt);
948
949 /*
950  * The function takes the GC lock and does not release in successful return.
951  * On error (out of memory) the function releases the lock but delegates
952  * the error reporting to the caller.
953  */
954 extern JSBool
955 js_InitContextThread(JSContext *cx);
956
957 /*
958  * On entrance the GC lock must be held and it will be held on exit.
959  */
960 extern void
961 js_ClearContextThread(JSContext *cx);
962
963 #endif /* JS_THREADSAFE */
964
965 typedef enum JSDestroyContextMode {
966     JSDCM_NO_GC,
967     JSDCM_MAYBE_GC,
968     JSDCM_FORCE_GC,
969     JSDCM_NEW_FAILED
970 } JSDestroyContextMode;
971
972 typedef enum JSRuntimeState {
973     JSRTS_DOWN,
974     JSRTS_LAUNCHING,
975     JSRTS_UP,
976     JSRTS_LANDING
977 } JSRuntimeState;
978
979 typedef struct JSPropertyTreeEntry {
980     JSDHashEntryHdr     hdr;
981     js::Shape           *child;
982 } JSPropertyTreeEntry;
983
984 typedef void
985 (* JSActivityCallback)(void *arg, JSBool active);
986
987 namespace js {
988
989 typedef js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> WrapperVector;
990
991 }
992
993 struct JSRuntime {
994     /* Default compartment. */
995     JSCompartment       *atomsCompartment;
996 #ifdef JS_THREADSAFE
997     bool                atomsCompartmentIsLocked;
998 #endif
999
1000     /* List of compartments (protected by the GC lock). */
1001     js::WrapperVector compartments;
1002
1003     /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
1004     JSRuntimeState      state;
1005
1006     /* Context create/destroy callback. */
1007     JSContextCallback   cxCallback;
1008
1009     /* Compartment create/destroy callback. */
1010     JSCompartmentCallback compartmentCallback;
1011
1012     /*
1013      * Sets a callback that is run whenever the runtime goes idle - the
1014      * last active request ceases - and begins activity - when it was
1015      * idle and a request begins. Note: The callback is called under the
1016      * GC lock.
1017      */
1018     void setActivityCallback(JSActivityCallback cb, void *arg) {
1019         activityCallback = cb;
1020         activityCallbackArg = arg;
1021     }
1022
1023     JSActivityCallback    activityCallback;
1024     void                 *activityCallbackArg;
1025
1026     /*
1027      * Shape regenerated whenever a prototype implicated by an "add property"
1028      * property cache fill and induced trace guard has a readonly property or a
1029      * setter defined on it. This number proxies for the shapes of all objects
1030      * along the prototype chain of all objects in the runtime on which such an
1031      * add-property result has been cached/traced.
1032      *
1033      * See bug 492355 for more details.
1034      *
1035      * This comes early in JSRuntime to minimize the immediate format used by
1036      * trace-JITted code that reads it.
1037      */
1038     uint32              protoHazardShape;
1039
1040     /* Garbage collector state, used by jsgc.c. */
1041     js::GCChunkSet      gcChunkSet;
1042
1043     js::RootedValueMap  gcRootsHash;
1044     js::GCLocks         gcLocksHash;
1045     jsrefcount          gcKeepAtoms;
1046     size_t              gcBytes;
1047     size_t              gcTriggerBytes;
1048     size_t              gcLastBytes;
1049     size_t              gcMaxBytes;
1050     size_t              gcMaxMallocBytes;
1051     size_t              gcChunksWaitingToExpire;
1052     uint32              gcEmptyArenaPoolLifespan;
1053     uint32              gcNumber;
1054     js::GCMarker        *gcMarkingTracer;
1055     uint32              gcTriggerFactor;
1056     int64               gcJitReleaseTime;
1057     JSGCMode            gcMode;
1058     volatile bool       gcIsNeeded;
1059
1060     /*
1061      * Compartment that triggered GC. If more than one Compatment need GC,
1062      * gcTriggerCompartment is reset to NULL and a global GC is performed.
1063      */
1064     JSCompartment       *gcTriggerCompartment;
1065
1066     /* Compartment that is currently involved in per-compartment GC */
1067     JSCompartment       *gcCurrentCompartment;
1068
1069     /*
1070      * We can pack these flags as only the GC thread writes to them. Atomic
1071      * updates to packed bytes are not guaranteed, so stores issued by one
1072      * thread may be lost due to unsynchronized read-modify-write cycles on
1073      * other threads.
1074      */
1075     bool                gcPoke;
1076     bool                gcMarkAndSweep;
1077     bool                gcRunning;
1078     bool                gcRegenShapes;
1079
1080 #ifdef JS_GC_ZEAL
1081     jsrefcount          gcZeal;
1082 #endif
1083
1084     JSGCCallback        gcCallback;
1085
1086   private:
1087     /*
1088      * Malloc counter to measure memory pressure for GC scheduling. It runs
1089      * from gcMaxMallocBytes down to zero.
1090      */
1091     volatile ptrdiff_t  gcMallocBytes;
1092
1093   public:
1094     js::GCChunkAllocator    *gcChunkAllocator;
1095
1096     void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) {
1097         JS_ASSERT(allocator);
1098         JS_ASSERT(state == JSRTS_DOWN);
1099         gcChunkAllocator = allocator;
1100     }
1101
1102     /*
1103      * The trace operation and its data argument to trace embedding-specific
1104      * GC roots.
1105      */
1106     JSTraceDataOp       gcExtraRootsTraceOp;
1107     void                *gcExtraRootsData;
1108
1109     /* Well-known numbers held for use by this runtime's contexts. */
1110     js::Value           NaNValue;
1111     js::Value           negativeInfinityValue;
1112     js::Value           positiveInfinityValue;
1113
1114     JSFlatString        *emptyString;
1115
1116     /* List of active contexts sharing this runtime; protected by gcLock. */
1117     JSCList             contextList;
1118
1119     /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
1120     JSDebugHooks        globalDebugHooks;
1121
1122     /*
1123      * Right now, we only support runtime-wide debugging.
1124      */
1125     JSBool              debugMode;
1126
1127 #ifdef JS_TRACER
1128     /* True if any debug hooks not supported by the JIT are enabled. */
1129     bool debuggerInhibitsJIT() const {
1130         return (globalDebugHooks.interruptHook ||
1131                 globalDebugHooks.callHook);
1132     }
1133 #endif
1134
1135     /* More debugging state, see jsdbgapi.c. */
1136     JSCList             trapList;
1137     JSCList             watchPointList;
1138
1139     /* Client opaque pointers */
1140     void                *data;
1141
1142 #ifdef JS_THREADSAFE
1143     /* These combine to interlock the GC and new requests. */
1144     PRLock              *gcLock;
1145     PRCondVar           *gcDone;
1146     PRCondVar           *requestDone;
1147     uint32              requestCount;
1148     JSThread            *gcThread;
1149
1150     js::GCHelperThread  gcHelperThread;
1151
1152     /* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
1153     PRLock              *rtLock;
1154 #ifdef DEBUG
1155     void *              rtLockOwner;
1156 #endif
1157
1158     /* Used to synchronize down/up state change; protected by gcLock. */
1159     PRCondVar           *stateChange;
1160
1161     /*
1162      * Lock serializing trapList and watchPointList accesses, and count of all
1163      * mutations to trapList and watchPointList made by debugger threads.  To
1164      * keep the code simple, we define debuggerMutations for the thread-unsafe
1165      * case too.
1166      */
1167     PRLock              *debuggerLock;
1168
1169     JSThread::Map       threads;
1170 #endif /* JS_THREADSAFE */
1171     uint32              debuggerMutations;
1172
1173     /*
1174      * Security callbacks set on the runtime are used by each context unless
1175      * an override is set on the context.
1176      */
1177     JSSecurityCallbacks *securityCallbacks;
1178
1179     /* Structured data callbacks are runtime-wide. */
1180     const JSStructuredCloneCallbacks *structuredCloneCallbacks;
1181
1182     /*
1183      * The propertyRemovals counter is incremented for every JSObject::clear,
1184      * and for each JSObject::remove method call that frees a slot in the given
1185      * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
1186      */
1187     int32               propertyRemovals;
1188
1189     /* Script filename table. */
1190     struct JSHashTable  *scriptFilenameTable;
1191     JSCList             scriptFilenamePrefixes;
1192 #ifdef JS_THREADSAFE
1193     PRLock              *scriptFilenameTableLock;
1194 #endif
1195
1196     /* Number localization, used by jsnum.c */
1197     const char          *thousandsSeparator;
1198     const char          *decimalSeparator;
1199     const char          *numGrouping;
1200
1201     /*
1202      * Weak references to lazily-created, well-known XML singletons.
1203      *
1204      * NB: Singleton objects must be carefully disconnected from the rest of
1205      * the object graph usually associated with a JSContext's global object,
1206      * including the set of standard class objects.  See jsxml.c for details.
1207      */
1208     JSObject            *anynameObject;
1209     JSObject            *functionNamespaceObject;
1210
1211 #ifdef JS_THREADSAFE
1212     /* Number of threads with active requests and unhandled interrupts. */
1213     volatile int32      interruptCounter;
1214 #else
1215     JSThreadData        threadData;
1216
1217 #define JS_THREAD_DATA(cx)      (&(cx)->runtime->threadData)
1218 #endif
1219
1220     /*
1221      * Object shape (property cache structural type) identifier generator.
1222      *
1223      * Type 0 stands for the empty scope, and must not be regenerated due to
1224      * uint32 wrap-around. Since js_GenerateShape (in jsinterp.cpp) uses
1225      * atomic pre-increment, the initial value for the first typed non-empty
1226      * scope will be 1.
1227      *
1228      * If this counter overflows into SHAPE_OVERFLOW_BIT (in jsinterp.h), the
1229      * cache is disabled, to avoid aliasing two different types. It stays
1230      * disabled until a triggered GC at some later moment compresses live
1231      * types, minimizing rt->shapeGen in the process.
1232      */
1233     volatile uint32     shapeGen;
1234
1235     /* Literal table maintained by jsatom.c functions. */
1236     JSAtomState         atomState;
1237
1238     /*
1239      * Various metering fields are defined at the end of JSRuntime. In this
1240      * way there is no need to recompile all the code that refers to other
1241      * fields of JSRuntime after enabling the corresponding metering macro.
1242      */
1243 #ifdef JS_DUMP_ENUM_CACHE_STATS
1244     int32               nativeEnumProbes;
1245     int32               nativeEnumMisses;
1246 # define ENUM_CACHE_METER(name)     JS_ATOMIC_INCREMENT(&cx->runtime->name)
1247 #else
1248 # define ENUM_CACHE_METER(name)     ((void) 0)
1249 #endif
1250
1251 #ifdef JS_DUMP_LOOP_STATS
1252     /* Loop statistics, to trigger trace recording and compiling. */
1253     JSBasicStats        loopStats;
1254 #endif
1255
1256 #ifdef DEBUG
1257     /* Function invocation metering. */
1258     jsrefcount          inlineCalls;
1259     jsrefcount          nativeCalls;
1260     jsrefcount          nonInlineCalls;
1261     jsrefcount          constructs;
1262
1263     jsrefcount          liveObjectProps;
1264     jsrefcount          liveObjectPropsPreSweep;
1265
1266     /*
1267      * NB: emptyShapes (in JSCompartment) is init'ed iff at least one
1268      * of these envars is set:
1269      *
1270      *  JS_PROPTREE_STATFILE  statistics on the property tree forest
1271      *  JS_PROPTREE_DUMPFILE  all paths in the property tree forest
1272      */
1273     const char          *propTreeStatFilename;
1274     const char          *propTreeDumpFilename;
1275
1276     bool meterEmptyShapes() const { return propTreeStatFilename || propTreeDumpFilename; }
1277
1278     /* String instrumentation. */
1279     jsrefcount          liveStrings;
1280     jsrefcount          totalStrings;
1281     jsrefcount          liveDependentStrings;
1282     jsrefcount          totalDependentStrings;
1283     jsrefcount          badUndependStrings;
1284     double              lengthSum;
1285     double              lengthSquaredSum;
1286     double              strdepLengthSum;
1287     double              strdepLengthSquaredSum;
1288
1289     /* Script instrumentation. */
1290     jsrefcount          liveScripts;
1291     jsrefcount          totalScripts;
1292     jsrefcount          liveEmptyScripts;
1293     jsrefcount          totalEmptyScripts;
1294     jsrefcount          highWaterLiveScripts;
1295 #endif /* DEBUG */
1296
1297 #ifdef JS_SCOPE_DEPTH_METER
1298     /*
1299      * Stats on runtime prototype chain lookups and scope chain depths, i.e.,
1300      * counts of objects traversed on a chain until the wanted id is found.
1301      */
1302     JSBasicStats        protoLookupDepthStats;
1303     JSBasicStats        scopeSearchDepthStats;
1304
1305     /*
1306      * Stats on compile-time host environment and lexical scope chain lengths
1307      * (maximum depths).
1308      */
1309     JSBasicStats        hostenvScopeDepthStats;
1310     JSBasicStats        lexicalScopeDepthStats;
1311 #endif
1312
1313 #ifdef JS_GCMETER
1314     js::gc::JSGCStats           gcStats;
1315     js::gc::JSGCArenaStats      globalArenaStats[js::gc::FINALIZE_LIMIT];
1316 #endif
1317
1318 #ifdef DEBUG
1319     /*
1320      * If functionMeterFilename, set from an envariable in JSRuntime's ctor, is
1321      * null, the remaining members in this ifdef'ed group are not initialized.
1322      */
1323     const char          *functionMeterFilename;
1324     JSFunctionMeter     functionMeter;
1325     char                lastScriptFilename[1024];
1326
1327     typedef js::HashMap<JSFunction *,
1328                         int32,
1329                         js::DefaultHasher<JSFunction *>,
1330                         js::SystemAllocPolicy> FunctionCountMap;
1331
1332     FunctionCountMap    methodReadBarrierCountMap;
1333     FunctionCountMap    unjoinedFunctionCountMap;
1334 #endif
1335
1336     JSWrapObjectCallback wrapObjectCallback;
1337     JSPreWrapCallback    preWrapObjectCallback;
1338
1339 #ifdef JS_METHODJIT
1340     uint32               mjitMemoryUsed;
1341 #endif
1342     uint32               stringMemoryUsed;
1343
1344     JSRuntime();
1345     ~JSRuntime();
1346
1347     bool init(uint32 maxbytes);
1348
1349     void setGCTriggerFactor(uint32 factor);
1350     void setGCLastBytes(size_t lastBytes);
1351
1352     /*
1353      * Call the system malloc while checking for GC memory pressure and
1354      * reporting OOM error when cx is not null.
1355      */
1356     void* malloc(size_t bytes, JSContext *cx = NULL) {
1357         updateMallocCounter(bytes);
1358         void *p = ::js_malloc(bytes);
1359         return JS_LIKELY(!!p) ? p : onOutOfMemory(NULL, bytes, cx);
1360     }
1361
1362     /*
1363      * Call the system calloc while checking for GC memory pressure and
1364      * reporting OOM error when cx is not null.
1365      */
1366     void* calloc(size_t bytes, JSContext *cx = NULL) {
1367         updateMallocCounter(bytes);
1368         void *p = ::js_calloc(bytes);
1369         return JS_LIKELY(!!p) ? p : onOutOfMemory(reinterpret_cast<void *>(1), bytes, cx);
1370     }
1371
1372     void* realloc(void* p, size_t oldBytes, size_t newBytes, JSContext *cx = NULL) {
1373         JS_ASSERT(oldBytes < newBytes);
1374         updateMallocCounter(newBytes - oldBytes);
1375         void *p2 = ::js_realloc(p, newBytes);
1376         return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, newBytes, cx);
1377     }
1378
1379     void* realloc(void* p, size_t bytes, JSContext *cx = NULL) {
1380         /*
1381          * For compatibility we do not account for realloc that increases
1382          * previously allocated memory.
1383          */
1384         if (!p)
1385             updateMallocCounter(bytes);
1386         void *p2 = ::js_realloc(p, bytes);
1387         return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
1388     }
1389
1390     void free(void* p) { ::js_free(p); }
1391
1392     bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
1393
1394     void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
1395
1396     void setGCMaxMallocBytes(size_t value) {
1397         /*
1398          * For compatibility treat any value that exceeds PTRDIFF_T_MAX to
1399          * mean that value.
1400          */
1401         gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
1402         resetGCMallocBytes();
1403     }
1404
1405     /*
1406      * Call this after allocating memory held by GC things, to update memory
1407      * pressure counters or report the OOM error if necessary. If oomError and
1408      * cx is not null the function also reports OOM error.
1409      *
1410      * The function must be called outside the GC lock and in case of OOM error
1411      * the caller must ensure that no deadlock possible during OOM reporting.
1412      */
1413     void updateMallocCounter(size_t nbytes) {
1414         /* We tolerate any thread races when updating gcMallocBytes. */
1415         ptrdiff_t newCount = gcMallocBytes - ptrdiff_t(nbytes);
1416         gcMallocBytes = newCount;
1417         if (JS_UNLIKELY(newCount <= 0))
1418             onTooMuchMalloc();
1419     }
1420
1421   private:
1422     /*
1423      * The function must be called outside the GC lock.
1424      */
1425     JS_FRIEND_API(void) onTooMuchMalloc();
1426
1427     /*
1428      * This should be called after system malloc/realloc returns NULL to try
1429      * to recove some memory or to report an error. Failures in malloc and
1430      * calloc are signaled by p == null and p == reinterpret_cast<void *>(1).
1431      * Other values of p mean a realloc failure.
1432      *
1433      * The function must be called outside the GC lock.
1434      */
1435     JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes, JSContext *cx);
1436 };
1437
1438 /* Common macros to access thread-local caches in JSThread or JSRuntime. */
1439 #define JS_GSN_CACHE(cx)        (JS_THREAD_DATA(cx)->gsnCache)
1440 #define JS_PROPERTY_CACHE(cx)   (JS_THREAD_DATA(cx)->propertyCache)
1441
1442 #ifdef DEBUG
1443 # define JS_RUNTIME_METER(rt, which)    JS_ATOMIC_INCREMENT(&(rt)->which)
1444 # define JS_RUNTIME_UNMETER(rt, which)  JS_ATOMIC_DECREMENT(&(rt)->which)
1445 #else
1446 # define JS_RUNTIME_METER(rt, which)    /* nothing */
1447 # define JS_RUNTIME_UNMETER(rt, which)  /* nothing */
1448 #endif
1449
1450 #define JS_KEEP_ATOMS(rt)   JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms);
1451 #define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms);
1452
1453 #ifdef JS_ARGUMENT_FORMATTER_DEFINED
1454 /*
1455  * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to
1456  * formatter functions.  Elements are sorted in non-increasing format string
1457  * length order.
1458  */
1459 struct JSArgumentFormatMap {
1460     const char          *format;
1461     size_t              length;
1462     JSArgumentFormatter formatter;
1463     JSArgumentFormatMap *next;
1464 };
1465 #endif
1466
1467 /*
1468  * Key and entry types for the JSContext.resolvingTable hash table, typedef'd
1469  * here because all consumers need to see these declarations (and not just the
1470  * typedef names, as would be the case for an opaque pointer-to-typedef'd-type
1471  * declaration), along with cx->resolvingTable.
1472  */
1473 typedef struct JSResolvingKey {
1474     JSObject            *obj;
1475     jsid                id;
1476 } JSResolvingKey;
1477
1478 typedef struct JSResolvingEntry {
1479     JSDHashEntryHdr     hdr;
1480     JSResolvingKey      key;
1481     uint32              flags;
1482 } JSResolvingEntry;
1483
1484 #define JSRESFLAG_LOOKUP        0x1     /* resolving id from lookup */
1485 #define JSRESFLAG_WATCH         0x2     /* resolving id from watch */
1486 #define JSRESOLVE_INFER         0xffff  /* infer bits from current bytecode */
1487
1488 extern const JSDebugHooks js_NullDebugHooks;  /* defined in jsdbgapi.cpp */
1489
1490 namespace js {
1491
1492 class AutoGCRooter;
1493
1494 static inline bool
1495 OptionsHasXML(uint32 options)
1496 {
1497     return !!(options & JSOPTION_XML);
1498 }
1499
1500 static inline bool
1501 OptionsHasAnonFunFix(uint32 options)
1502 {
1503     return !!(options & JSOPTION_ANONFUNFIX);
1504 }
1505
1506 static inline bool
1507 OptionsSameVersionFlags(uint32 self, uint32 other)
1508 {
1509     static const uint32 mask = JSOPTION_XML | JSOPTION_ANONFUNFIX;
1510     return !((self & mask) ^ (other & mask));
1511 }
1512
1513 /*
1514  * Flags accompany script version data so that a) dynamically created scripts
1515  * can inherit their caller's compile-time properties and b) scripts can be
1516  * appropriately compared in the eval cache across global option changes. An
1517  * example of the latter is enabling the top-level-anonymous-function-is-error
1518  * option: subsequent evals of the same, previously-valid script text may have
1519  * become invalid.
1520  */
1521 namespace VersionFlags {
1522 static const uintN MASK         = 0x0FFF; /* see JSVersion in jspubtd.h */
1523 static const uintN HAS_XML      = 0x1000; /* flag induced by XML option */
1524 static const uintN ANONFUNFIX   = 0x2000; /* see jsapi.h comment on JSOPTION_ANONFUNFIX */
1525 static const uintN FULL_MASK    = 0x3FFF;
1526 }
1527
1528 static inline JSVersion
1529 VersionNumber(JSVersion version)
1530 {
1531     return JSVersion(uint32(version) & VersionFlags::MASK);
1532 }
1533
1534 static inline bool
1535 VersionHasXML(JSVersion version)
1536 {
1537     return !!(version & VersionFlags::HAS_XML);
1538 }
1539
1540 /* @warning This is a distinct condition from having the XML flag set. */
1541 static inline bool
1542 VersionShouldParseXML(JSVersion version)
1543 {
1544     return VersionHasXML(version) || VersionNumber(version) >= JSVERSION_1_6;
1545 }
1546
1547 static inline bool
1548 VersionHasAnonFunFix(JSVersion version)
1549 {
1550     return !!(version & VersionFlags::ANONFUNFIX);
1551 }
1552
1553 static inline void
1554 VersionSetXML(JSVersion *version, bool enable)
1555 {
1556     if (enable)
1557         *version = JSVersion(uint32(*version) | VersionFlags::HAS_XML);
1558     else
1559         *version = JSVersion(uint32(*version) & ~VersionFlags::HAS_XML);
1560 }
1561
1562 static inline void
1563 VersionSetAnonFunFix(JSVersion *version, bool enable)
1564 {
1565     if (enable)
1566         *version = JSVersion(uint32(*version) | VersionFlags::ANONFUNFIX);
1567     else
1568         *version = JSVersion(uint32(*version) & ~VersionFlags::ANONFUNFIX);
1569 }
1570
1571 static inline JSVersion
1572 VersionExtractFlags(JSVersion version)
1573 {
1574     return JSVersion(uint32(version) & ~VersionFlags::MASK);
1575 }
1576
1577 static inline void
1578 VersionCopyFlags(JSVersion *version, JSVersion from)
1579 {
1580     *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
1581 }
1582
1583 static inline bool
1584 VersionHasFlags(JSVersion version)
1585 {
1586     return !!VersionExtractFlags(version);
1587 }
1588
1589 static inline uintN
1590 VersionFlagsToOptions(JSVersion version)
1591 {
1592     uintN copts = (VersionHasXML(version) ? JSOPTION_XML : 0) |
1593                   (VersionHasAnonFunFix(version) ? JSOPTION_ANONFUNFIX : 0);
1594     JS_ASSERT((copts & JSCOMPILEOPTION_MASK) == copts);
1595     return copts;
1596 }
1597
1598 static inline JSVersion
1599 OptionFlagsToVersion(uintN options, JSVersion version)
1600 {
1601     VersionSetXML(&version, OptionsHasXML(options));
1602     VersionSetAnonFunFix(&version, OptionsHasAnonFunFix(options));
1603     return version;
1604 }
1605
1606 static inline bool
1607 VersionIsKnown(JSVersion version)
1608 {
1609     return VersionNumber(version) != JSVERSION_UNKNOWN;
1610 }
1611
1612 typedef js::HashSet<JSObject *,
1613                     js::DefaultHasher<JSObject *>,
1614                     js::SystemAllocPolicy> BusyArraysMap;
1615
1616 } /* namespace js */
1617
1618 struct JSContext
1619 {
1620     explicit JSContext(JSRuntime *rt);
1621
1622     /* JSRuntime contextList linkage. */
1623     JSCList             link;
1624
1625   private:
1626     /* See JSContext::findVersion. */
1627     JSVersion           defaultVersion;      /* script compilation version */
1628     JSVersion           versionOverride;     /* supercedes defaultVersion when valid */
1629     bool                hasVersionOverride;
1630
1631     /* Exception state -- the exception member is a GC root by definition. */
1632     JSBool              throwing;           /* is there a pending exception? */
1633     js::Value           exception;          /* most-recently-thrown exception */
1634
1635     /* Per-context run options. */
1636     uintN               runOptions;            /* see jsapi.h for JSOPTION_* */
1637
1638   public:
1639     /* Locale specific callbacks for string conversion. */
1640     JSLocaleCallbacks   *localeCallbacks;
1641
1642     /*
1643      * cx->resolvingTable is non-null and non-empty if we are initializing
1644      * standard classes lazily, or if we are otherwise recursing indirectly
1645      * from js_LookupProperty through a Class.resolve hook.  It is used to
1646      * limit runaway recursion (see jsapi.c and jsobj.c).
1647      */
1648     JSDHashTable        *resolvingTable;
1649
1650     /*
1651      * True if generating an error, to prevent runaway recursion.
1652      * NB: generatingError packs with throwing below.
1653      */
1654     JSPackedBool        generatingError;
1655
1656     /* Limit pointer for checking native stack consumption during recursion. */
1657     jsuword             stackLimit;
1658
1659     /* Quota on the size of arenas used to compile and execute scripts. */
1660     size_t              scriptStackQuota;
1661
1662     /* Data shared by threads in an address space. */
1663     JSRuntime *const    runtime;
1664
1665     /* GC heap compartment. */
1666     JSCompartment       *compartment;
1667
1668     /* Currently executing frame and regs, set by stack operations. */
1669     JS_REQUIRES_STACK
1670     JSFrameRegs         *regs;
1671
1672     /* Current frame accessors. */
1673
1674     JSStackFrame* fp() {
1675         JS_ASSERT(regs && regs->fp);
1676         return regs->fp;
1677     }
1678
1679     JSStackFrame* maybefp() {
1680         JS_ASSERT_IF(regs, regs->fp);
1681         return regs ? regs->fp : NULL;
1682     }
1683
1684     bool hasfp() {
1685         JS_ASSERT_IF(regs, regs->fp);
1686         return !!regs;
1687     }
1688
1689   public:
1690     friend class js::StackSpace;
1691     friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, JSInterpMode);
1692
1693     void resetCompartment();
1694     void wrapPendingException();
1695
1696     /* For grep-ability, changes to 'regs' should call this function. */
1697     void setCurrentRegs(JSFrameRegs *regs) {
1698         JS_ASSERT_IF(regs, regs->fp);
1699         this->regs = regs;
1700     }
1701
1702     /* Temporary arena pool used while compiling and decompiling. */
1703     JSArenaPool         tempPool;
1704
1705     /* Temporary arena pool used while evaluate regular expressions. */
1706     JSArenaPool         regExpPool;
1707
1708     /* Top-level object and pointer to top stack frame's scope chain. */
1709     JSObject            *globalObject;
1710
1711     /* State for object and array toSource conversion. */
1712     JSSharpObjectMap    sharpObjectMap;
1713     js::BusyArraysMap   busyArrays;
1714
1715     /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
1716     JSArgumentFormatMap *argumentFormatMap;
1717
1718     /* Last message string and log file for debugging. */
1719     char                *lastMessage;
1720 #ifdef DEBUG
1721     void                *logfp;
1722     jsbytecode          *logPrevPc;
1723 #endif
1724
1725     /* Per-context optional error reporter. */
1726     JSErrorReporter     errorReporter;
1727
1728     /* Branch callback. */
1729     JSOperationCallback operationCallback;
1730
1731     /* Interpreter activation count. */
1732     uintN               interpLevel;
1733
1734     /* Client opaque pointers. */
1735     void                *data;
1736     void                *data2;
1737
1738   private:
1739     /* Linked list of segments. See StackSegment. */
1740     js::StackSegment *currentSegment;
1741
1742   public:
1743     void assertSegmentsInSync() const {
1744 #ifdef DEBUG
1745         if (regs) {
1746             JS_ASSERT(currentSegment->isActive());
1747             if (js::StackSegment *prev = currentSegment->getPreviousInContext())
1748                 JS_ASSERT(!prev->isActive());
1749         } else {
1750             JS_ASSERT_IF(currentSegment, !currentSegment->isActive());
1751         }
1752 #endif
1753     }
1754
1755     /* Return whether this context has an active segment. */
1756     bool hasActiveSegment() const {
1757         assertSegmentsInSync();
1758         return !!regs;
1759     }
1760
1761     /* Assuming there is an active segment, return it. */
1762     js::StackSegment *activeSegment() const {
1763         JS_ASSERT(hasActiveSegment());
1764         return currentSegment;
1765     }
1766
1767     /* Return the current segment, which may or may not be active. */
1768     js::StackSegment *getCurrentSegment() const {
1769         assertSegmentsInSync();
1770         return currentSegment;
1771     }
1772
1773     inline js::RegExpStatics *regExpStatics();
1774
1775     /* Add the given segment to the list as the new active segment. */
1776     void pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs &regs);
1777
1778     /* Remove the active segment and make the next segment active. */
1779     void popSegmentAndFrame();
1780
1781     /* Mark the top segment as suspended, without pushing a new one. */
1782     void saveActiveSegment();
1783
1784     /* Undoes calls to suspendActiveSegment. */
1785     void restoreSegment();
1786
1787     /* Get the frame whose prev() is fp, which may be in any segment. */
1788     inline JSStackFrame *computeNextFrame(JSStackFrame *fp);
1789
1790     /*
1791      * Perform a linear search of all frames in all segments in the given context
1792      * for the given frame, returning the segment, if found, and null otherwise.
1793      */
1794     js::StackSegment *containingSegment(const JSStackFrame *target);
1795
1796     /* Search the call stack for the nearest frame with static level targetLevel. */
1797     JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
1798         JSStackFrame *fp = regs->fp;
1799         while (true) {
1800             JS_ASSERT(fp && fp->isScriptFrame());
1801             if (fp->script()->staticLevel == targetLevel)
1802                 break;
1803             fp = fp->prev();
1804         }
1805         return fp;
1806     }
1807
1808   public:
1809     /*
1810      * The default script compilation version can be set iff there is no code running.
1811      * This typically occurs via the JSAPI right after a context is constructed.
1812      */
1813     bool canSetDefaultVersion() const {
1814         return !regs && !hasVersionOverride;
1815     }
1816
1817     /* Force a version for future script compilation. */
1818     void overrideVersion(JSVersion newVersion) {
1819         JS_ASSERT(!canSetDefaultVersion());
1820         versionOverride = newVersion;
1821         hasVersionOverride = true;
1822     }
1823
1824     /* Set the default script compilation version. */
1825     void setDefaultVersion(JSVersion version) {
1826         defaultVersion = version;
1827     }
1828
1829     void clearVersionOverride() { hasVersionOverride = false; }
1830     JSVersion getDefaultVersion() const { return defaultVersion; }
1831     bool isVersionOverridden() const { return hasVersionOverride; }
1832
1833     JSVersion getVersionOverride() const {
1834         JS_ASSERT(isVersionOverridden());
1835         return versionOverride;
1836     }
1837
1838     /*
1839      * Set the default version if possible; otherwise, force the version.
1840      * Return whether an override occurred.
1841      */
1842     bool maybeOverrideVersion(JSVersion newVersion) {
1843         if (canSetDefaultVersion()) {
1844             setDefaultVersion(newVersion);
1845             return false;
1846         }
1847         overrideVersion(newVersion);
1848         return true;
1849     }
1850
1851   private:
1852     /*
1853      * If there is no code currently executing, turn the override version into
1854      * the default version.
1855      *
1856      * NB: the only time the version is potentially capable of migrating is
1857      * on return from the Execute or ExternalInvoke paths as they call through
1858      * JSContext::popSegmentAndFrame.
1859      */
1860     void maybeMigrateVersionOverride() {
1861         if (JS_LIKELY(!isVersionOverridden() || currentSegment))
1862             return;
1863         defaultVersion = versionOverride;
1864         clearVersionOverride();
1865     }
1866
1867   public:
1868     /*
1869      * Return:
1870      * - The override version, if there is an override version.
1871      * - The newest scripted frame's version, if there is such a frame.
1872      * - The default verion.
1873      *
1874      * Note: if this ever shows up in a profile, just add caching!
1875      */
1876     JSVersion findVersion() const {
1877         if (hasVersionOverride)
1878             return versionOverride;
1879
1880         if (regs) {
1881             /* There may be a scripted function somewhere on the stack! */
1882             JSStackFrame *fp = regs->fp;
1883             while (fp && !fp->isScriptFrame())
1884                 fp = fp->prev();
1885             if (fp)
1886                 return fp->script()->getVersion();
1887         }
1888
1889         return defaultVersion;
1890     }
1891
1892     void setRunOptions(uintN ropts) {
1893         JS_ASSERT((ropts & JSRUNOPTION_MASK) == ropts);
1894         runOptions = ropts;
1895     }
1896
1897     /* Note: may override the version. */
1898     void setCompileOptions(uintN newcopts) {
1899         JS_ASSERT((newcopts & JSCOMPILEOPTION_MASK) == newcopts);
1900         if (JS_LIKELY(getCompileOptions() == newcopts))
1901             return;
1902         JSVersion version = findVersion();
1903         JSVersion newVersion = js::OptionFlagsToVersion(newcopts, version);
1904         maybeOverrideVersion(newVersion);
1905     }
1906
1907     uintN getRunOptions() const { return runOptions; }
1908     uintN getCompileOptions() const { return js::VersionFlagsToOptions(findVersion()); }
1909     uintN allOptions() const { return getRunOptions() | getCompileOptions(); }
1910
1911     bool hasRunOption(uintN ropt) const {
1912         JS_ASSERT((ropt & JSRUNOPTION_MASK) == ropt);
1913         return !!(runOptions & ropt);
1914     }
1915
1916     bool hasStrictOption() const { return hasRunOption(JSOPTION_STRICT); }
1917     bool hasWErrorOption() const { return hasRunOption(JSOPTION_WERROR); }
1918     bool hasAtLineOption() const { return hasRunOption(JSOPTION_ATLINE); }
1919
1920 #ifdef JS_THREADSAFE
1921     JSThread            *thread;
1922     unsigned            outstandingRequests;/* number of JS_BeginRequest calls
1923                                                without the corresponding
1924                                                JS_EndRequest. */
1925     JSCList             threadLinks;        /* JSThread contextList linkage */
1926
1927 #define CX_FROM_THREAD_LINKS(tl) \
1928     ((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks)))
1929 #endif
1930
1931     /* Stack of thread-stack-allocated GC roots. */
1932     js::AutoGCRooter   *autoGCRooters;
1933
1934     /* Debug hooks associated with the current context. */
1935     const JSDebugHooks  *debugHooks;
1936
1937     /* Security callbacks that override any defined on the runtime. */
1938     JSSecurityCallbacks *securityCallbacks;
1939
1940     /* Stored here to avoid passing it around as a parameter. */
1941     uintN               resolveFlags;
1942
1943     /* Random number generator state, used by jsmath.cpp. */
1944     int64               rngSeed;
1945
1946     /* Location to stash the iteration value between JSOP_MOREITER and JSOP_FOR*. */
1947     js::Value           iterValue;
1948
1949 #ifdef JS_TRACER
1950     /*
1951      * True if traces may be executed. Invariant: The value of traceJitenabled
1952      * is always equal to the expression in updateJITEnabled below.
1953      *
1954      * This flag and the fields accessed by updateJITEnabled are written only
1955      * in runtime->gcLock, to avoid race conditions that would leave the wrong
1956      * value in traceJitEnabled. (But the interpreter reads this without
1957      * locking. That can race against another thread setting debug hooks, but
1958      * we always read cx->debugHooks without locking anyway.)
1959      */
1960     bool                 traceJitEnabled;
1961 #endif
1962
1963 #ifdef JS_METHODJIT
1964     bool                 methodJitEnabled;
1965     bool                 profilingEnabled;
1966 #endif
1967
1968     /* Caller must be holding runtime->gcLock. */
1969     void updateJITEnabled();
1970
1971 #ifdef MOZ_TRACE_JSCALLS
1972     /* Function entry/exit debugging callback. */
1973     JSFunctionCallback    functionCallback;
1974
1975     void doFunctionCallback(const JSFunction *fun,
1976                             const JSScript *scr,
1977                             int entering) const
1978     {
1979         if (functionCallback)
1980             functionCallback(fun, scr, this, entering);
1981     }
1982 #endif
1983
1984     DSTOffsetCache dstOffsetCache;
1985
1986     /* List of currently active non-escaping enumerators (for-in). */
1987     JSObject *enumerators;
1988
1989   private:
1990     /*
1991      * To go from a live generator frame (on the stack) to its generator object
1992      * (see comment js_FloatingFrameIfGenerator), we maintain a stack of active
1993      * generators, pushing and popping when entering and leaving generator
1994      * frames, respectively.
1995      */
1996     js::Vector<JSGenerator *, 2, js::SystemAllocPolicy> genStack;
1997
1998   public:
1999 #ifdef JS_METHODJIT
2000     inline js::mjit::JaegerCompartment *jaegerCompartment();
2001 #endif
2002
2003     /* Return the generator object for the given generator frame. */
2004     JSGenerator *generatorFor(JSStackFrame *fp) const;
2005
2006     /* Early OOM-check. */
2007     inline bool ensureGeneratorStackSpace();
2008
2009     bool enterGenerator(JSGenerator *gen) {
2010         return genStack.append(gen);
2011     }
2012
2013     void leaveGenerator(JSGenerator *gen) {
2014         JS_ASSERT(genStack.back() == gen);
2015         genStack.popBack();
2016     }
2017
2018 #ifdef JS_THREADSAFE
2019     /*
2020      * When non-null JSContext::free delegates the job to the background
2021      * thread.
2022      */
2023     js::GCHelperThread *gcBackgroundFree;
2024 #endif
2025
2026     inline void* malloc(size_t bytes) {
2027         return runtime->malloc(bytes, this);
2028     }
2029
2030     inline void* mallocNoReport(size_t bytes) {
2031         JS_ASSERT(bytes != 0);
2032         return runtime->malloc(bytes, NULL);
2033     }
2034
2035     inline void* calloc(size_t bytes) {
2036         JS_ASSERT(bytes != 0);
2037         return runtime->calloc(bytes, this);
2038     }
2039
2040     inline void* realloc(void* p, size_t bytes) {
2041         return runtime->realloc(p, bytes, this);
2042     }
2043
2044     inline void* realloc(void* p, size_t oldBytes, size_t newBytes) {
2045         return runtime->realloc(p, oldBytes, newBytes, this);
2046     }
2047
2048     inline void free(void* p) {
2049 #ifdef JS_THREADSAFE
2050         if (gcBackgroundFree) {
2051             gcBackgroundFree->freeLater(p);
2052             return;
2053         }
2054 #endif
2055         runtime->free(p);
2056     }
2057
2058     /*
2059      * In the common case that we'd like to allocate the memory for an object
2060      * with cx->malloc/free, we cannot use overloaded C++ operators (no
2061      * placement delete).  Factor the common workaround into one place.
2062      */
2063 #define CREATE_BODY(parms)                                                    \
2064     void *memory = this->malloc(sizeof(T));                                   \
2065     if (!memory)                                                              \
2066         return NULL;                                                          \
2067     return new(memory) T parms;
2068
2069     template <class T>
2070     JS_ALWAYS_INLINE T *create() {
2071         CREATE_BODY(())
2072     }
2073
2074     template <class T, class P1>
2075     JS_ALWAYS_INLINE T *create(const P1 &p1) {
2076         CREATE_BODY((p1))
2077     }
2078
2079     template <class T, class P1, class P2>
2080     JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2) {
2081         CREATE_BODY((p1, p2))
2082     }
2083
2084     template <class T, class P1, class P2, class P3>
2085     JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2, const P3 &p3) {
2086         CREATE_BODY((p1, p2, p3))
2087     }
2088 #undef CREATE_BODY
2089
2090     template <class T>
2091     JS_ALWAYS_INLINE void destroy(T *p) {
2092         p->~T();
2093         this->free(p);
2094     }
2095
2096     void purge();
2097
2098     js::StackSpace &stack() const {
2099         return JS_THREAD_DATA(this)->stackSpace;
2100     }
2101
2102 #ifdef DEBUG
2103     void assertValidStackDepth(uintN depth) {
2104         JS_ASSERT(0 <= regs->sp - regs->fp->base());
2105         JS_ASSERT(depth <= uintptr_t(regs->sp - regs->fp->base()));
2106     }
2107 #else
2108     void assertValidStackDepth(uintN /*depth*/) {}
2109 #endif
2110
2111     bool isExceptionPending() {
2112         return throwing;
2113     }
2114
2115     js::Value getPendingException() {
2116         JS_ASSERT(throwing);
2117         return exception;
2118     }
2119
2120     void setPendingException(js::Value v);
2121
2122     void clearPendingException() {
2123         this->throwing = false;
2124         this->exception.setUndefined();
2125     }
2126
2127   private:
2128     /*
2129      * The allocation code calls the function to indicate either OOM failure
2130      * when p is null or that a memory pressure counter has reached some
2131      * threshold when p is not null. The function takes the pointer and not
2132      * a boolean flag to minimize the amount of code in its inlined callers.
2133      */
2134     JS_FRIEND_API(void) checkMallocGCPressure(void *p);
2135 }; /* struct JSContext */
2136
2137 #ifdef JS_THREADSAFE
2138 # define JS_THREAD_ID(cx)       ((cx)->thread ? (cx)->thread->id : 0)
2139 #endif
2140
2141 #if defined JS_THREADSAFE && defined DEBUG
2142
2143 namespace js {
2144
2145 class AutoCheckRequestDepth {
2146     JSContext *cx;
2147   public:
2148     AutoCheckRequestDepth(JSContext *cx) : cx(cx) { cx->thread->checkRequestDepth++; }
2149
2150     ~AutoCheckRequestDepth() {
2151         JS_ASSERT(cx->thread->checkRequestDepth != 0);
2152         cx->thread->checkRequestDepth--;
2153     }
2154 };
2155
2156 }
2157
2158 # define CHECK_REQUEST(cx)                                                    \
2159     JS_ASSERT((cx)->thread);                                                  \
2160     JS_ASSERT((cx)->thread->data.requestDepth || (cx)->thread == (cx)->runtime->gcThread); \
2161     AutoCheckRequestDepth _autoCheckRequestDepth(cx);
2162
2163 #else
2164 # define CHECK_REQUEST(cx)          ((void) 0)
2165 # define CHECK_REQUEST_THREAD(cx)   ((void) 0)
2166 #endif
2167
2168 static inline uintN
2169 FramePCOffset(JSContext *cx, JSStackFrame* fp)
2170 {
2171     jsbytecode *pc = fp->hasImacropc() ? fp->imacropc() : fp->pc(cx);
2172     return uintN(pc - fp->script()->code);
2173 }
2174
2175 static inline JSAtom **
2176 FrameAtomBase(JSContext *cx, JSStackFrame *fp)
2177 {
2178     return fp->hasImacropc()
2179            ? COMMON_ATOMS_START(&cx->runtime->atomState)
2180            : fp->script()->atomMap.vector;
2181 }
2182
2183 namespace js {
2184
2185 class AutoGCRooter {
2186   public:
2187     AutoGCRooter(JSContext *cx, ptrdiff_t tag)
2188       : down(cx->autoGCRooters), tag(tag), context(cx)
2189     {
2190         JS_ASSERT(this != cx->autoGCRooters);
2191         CHECK_REQUEST(cx);
2192         cx->autoGCRooters = this;
2193     }
2194
2195     ~AutoGCRooter() {
2196         JS_ASSERT(this == context->autoGCRooters);
2197         CHECK_REQUEST(context);
2198         context->autoGCRooters = down;
2199     }
2200
2201     /* Implemented in jsgc.cpp. */
2202     inline void trace(JSTracer *trc);
2203
2204 #ifdef __GNUC__
2205 # pragma GCC visibility push(default)
2206 #endif
2207     friend JS_FRIEND_API(void) MarkContext(JSTracer *trc, JSContext *acx);
2208     friend void MarkRuntime(JSTracer *trc);
2209 #ifdef __GNUC__
2210 # pragma GCC visibility pop
2211 #endif
2212
2213   protected:
2214     AutoGCRooter * const down;
2215
2216     /*
2217      * Discriminates actual subclass of this being used.  If non-negative, the
2218      * subclass roots an array of values of the length stored in this field.
2219      * If negative, meaning is indicated by the corresponding value in the enum
2220      * below.  Any other negative value indicates some deeper problem such as
2221      * memory corruption.
2222      */
2223     ptrdiff_t tag;
2224
2225     JSContext * const context;
2226
2227     enum {
2228         JSVAL =        -1, /* js::AutoValueRooter */
2229         SHAPE =        -2, /* js::AutoShapeRooter */
2230         PARSER =       -3, /* js::Parser */
2231         SCRIPT =       -4, /* js::AutoScriptRooter */
2232         ENUMERATOR =   -5, /* js::AutoEnumStateRooter */
2233         IDARRAY =      -6, /* js::AutoIdArray */
2234         DESCRIPTORS =  -7, /* js::AutoPropDescArrayRooter */
2235         NAMESPACES =   -8, /* js::AutoNamespaceArray */
2236         XML =          -9, /* js::AutoXMLRooter */
2237         OBJECT =      -10, /* js::AutoObjectRooter */
2238         ID =          -11, /* js::AutoIdRooter */
2239         VALVECTOR =   -12, /* js::AutoValueVector */
2240         DESCRIPTOR =  -13, /* js::AutoPropertyDescriptorRooter */
2241         STRING =      -14, /* js::AutoStringRooter */
2242         IDVECTOR =    -15, /* js::AutoIdVector */
2243         BINDINGS =    -16, /* js::Bindings */
2244         SHAPEVECTOR = -17  /* js::AutoShapeVector */
2245     };
2246
2247     private:
2248     /* No copy or assignment semantics. */
2249     AutoGCRooter(AutoGCRooter &ida);
2250     void operator=(AutoGCRooter &ida);
2251 };
2252
2253 /* FIXME(bug 332648): Move this into a public header. */
2254 class AutoValueRooter : private AutoGCRooter
2255 {
2256   public:
2257     explicit AutoValueRooter(JSContext *cx
2258                              JS_GUARD_OBJECT_NOTIFIER_PARAM)
2259       : AutoGCRooter(cx, JSVAL), val(js::NullValue())
2260     {
2261         JS_GUARD_OBJECT_NOTIFIER_INIT;
2262     }
2263
2264     AutoValueRooter(JSContext *cx, const Value &v
2265                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
2266       : AutoGCRooter(cx, JSVAL), val(v)
2267     {
2268         JS_GUARD_OBJECT_NOTIFIER_INIT;
2269     }
2270
2271     AutoValueRooter(JSContext *cx, jsval v
2272                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
2273       : AutoGCRooter(cx, JSVAL), val(js::Valueify(v))
2274     {
2275         JS_GUARD_OBJECT_NOTIFIER_INIT;
2276     }
2277
2278     /*
2279      * If you are looking for Object* overloads, use AutoObjectRooter instead;
2280      * rooting Object*s as a js::Value requires discerning whether or not it is
2281      * a function object. Also, AutoObjectRooter is smaller.
2282      */
2283
2284     void set(Value v) {
2285         JS_ASSERT(tag == JSVAL);
2286         val = v;
2287     }
2288
2289     void set(jsval v) {
2290         JS_ASSERT(tag == JSVAL);
2291         val = js::Valueify(v);
2292     }
2293
2294     const Value &value() const {
2295         JS_ASSERT(tag == JSVAL);
2296         return val;
2297     }
2298
2299     Value *addr() {
2300         JS_ASSERT(tag == JSVAL);
2301         return &val;
2302     }
2303
2304     const jsval &jsval_value() const {
2305         JS_ASSERT(tag == JSVAL);
2306         return Jsvalify(val);
2307     }
2308
2309     jsval *jsval_addr() {
2310         JS_ASSERT(tag == JSVAL);
2311         return Jsvalify(&val);
2312     }
2313
2314     friend void AutoGCRooter::trace(JSTracer *trc);
2315     friend void MarkRuntime(JSTracer *trc);
2316
2317   private:
2318     Value val;
2319     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2320 };
2321
2322 class AutoObjectRooter : private AutoGCRooter {
2323   public:
2324     AutoObjectRooter(JSContext *cx, JSObject *obj = NULL
2325                      JS_GUARD_OBJECT_NOTIFIER_PARAM)
2326       : AutoGCRooter(cx, OBJECT), obj(obj)
2327     {
2328         JS_GUARD_OBJECT_NOTIFIER_INIT;
2329     }
2330
2331     void setObject(JSObject *obj) {
2332         this->obj = obj;
2333     }
2334
2335     JSObject * object() const {
2336         return obj;
2337     }
2338
2339     JSObject ** addr() {
2340         return &obj;
2341     }
2342
2343     friend void AutoGCRooter::trace(JSTracer *trc);
2344     friend void MarkRuntime(JSTracer *trc);
2345
2346   private:
2347     JSObject *obj;
2348     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2349 };
2350
2351 class AutoStringRooter : private AutoGCRooter {
2352   public:
2353     AutoStringRooter(JSContext *cx, JSString *str = NULL
2354                      JS_GUARD_OBJECT_NOTIFIER_PARAM)
2355       : AutoGCRooter(cx, STRING), str(str)
2356     {
2357         JS_GUARD_OBJECT_NOTIFIER_INIT;
2358     }
2359
2360     void setString(JSString *str) {
2361         this->str = str;
2362     }
2363
2364     JSString * string() const {
2365         return str;
2366     }
2367
2368     JSString ** addr() {
2369         return &str;
2370     }
2371
2372     friend void AutoGCRooter::trace(JSTracer *trc);
2373
2374   private:
2375     JSString *str;
2376     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2377 };
2378
2379 class AutoArrayRooter : private AutoGCRooter {
2380   public:
2381     AutoArrayRooter(JSContext *cx, size_t len, Value *vec
2382                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
2383       : AutoGCRooter(cx, len), array(vec)
2384     {
2385         JS_GUARD_OBJECT_NOTIFIER_INIT;
2386         JS_ASSERT(tag >= 0);
2387     }
2388
2389     AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
2390                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
2391       : AutoGCRooter(cx, len), array(Valueify(vec))
2392     {
2393         JS_GUARD_OBJECT_NOTIFIER_INIT;
2394         JS_ASSERT(tag >= 0);
2395     }
2396
2397     void changeLength(size_t newLength) {
2398         tag = ptrdiff_t(newLength);
2399         JS_ASSERT(tag >= 0);
2400     }
2401
2402     void changeArray(Value *newArray, size_t newLength) {
2403         changeLength(newLength);
2404         array = newArray;
2405     }
2406
2407     Value *array;
2408
2409     friend void AutoGCRooter::trace(JSTracer *trc);
2410
2411   private:
2412     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2413 };
2414
2415 class AutoShapeRooter : private AutoGCRooter {
2416   public:
2417     AutoShapeRooter(JSContext *cx, const js::Shape *shape
2418                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
2419       : AutoGCRooter(cx, SHAPE), shape(shape)
2420     {
2421         JS_GUARD_OBJECT_NOTIFIER_INIT;
2422     }
2423
2424     friend void AutoGCRooter::trace(JSTracer *trc);
2425     friend void MarkRuntime(JSTracer *trc);
2426
2427   private:
2428     const js::Shape * const shape;
2429     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2430 };
2431
2432 class AutoScriptRooter : private AutoGCRooter {
2433   public:
2434     AutoScriptRooter(JSContext *cx, JSScript *script
2435                      JS_GUARD_OBJECT_NOTIFIER_PARAM)
2436       : AutoGCRooter(cx, SCRIPT), script(script)
2437     {
2438         JS_GUARD_OBJECT_NOTIFIER_INIT;
2439     }
2440
2441     void setScript(JSScript *script) {
2442         this->script = script;
2443     }
2444
2445     friend void AutoGCRooter::trace(JSTracer *trc);
2446
2447   private:
2448     JSScript *script;
2449     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2450 };
2451
2452 class AutoIdRooter : private AutoGCRooter
2453 {
2454   public:
2455     explicit AutoIdRooter(JSContext *cx, jsid id = INT_TO_JSID(0)
2456                           JS_GUARD_OBJECT_NOTIFIER_PARAM)
2457       : AutoGCRooter(cx, ID), id_(id)
2458     {
2459         JS_GUARD_OBJECT_NOTIFIER_INIT;
2460     }
2461
2462     jsid id() {
2463         return id_;
2464     }
2465
2466     jsid * addr() {
2467         return &id_;
2468     }
2469
2470     friend void AutoGCRooter::trace(JSTracer *trc);
2471     friend void MarkRuntime(JSTracer *trc);
2472
2473   private:
2474     jsid id_;
2475     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2476 };
2477
2478 class AutoIdArray : private AutoGCRooter {
2479   public:
2480     AutoIdArray(JSContext *cx, JSIdArray *ida JS_GUARD_OBJECT_NOTIFIER_PARAM)
2481       : AutoGCRooter(cx, IDARRAY), idArray(ida)
2482     {
2483         JS_GUARD_OBJECT_NOTIFIER_INIT;
2484     }
2485     ~AutoIdArray() {
2486         if (idArray)
2487             JS_DestroyIdArray(context, idArray);
2488     }
2489     bool operator!() {
2490         return idArray == NULL;
2491     }
2492     jsid operator[](size_t i) const {
2493         JS_ASSERT(idArray);
2494         JS_ASSERT(i < size_t(idArray->length));
2495         return idArray->vector[i];
2496     }
2497     size_t length() const {
2498          return idArray->length;
2499     }
2500
2501     friend void AutoGCRooter::trace(JSTracer *trc);
2502
2503     JSIdArray *steal() {
2504         JSIdArray *copy = idArray;
2505         idArray = NULL;
2506         return copy;
2507     }
2508
2509   protected:
2510     inline void trace(JSTracer *trc);
2511
2512   private:
2513     JSIdArray * idArray;
2514     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2515
2516     /* No copy or assignment semantics. */
2517     AutoIdArray(AutoIdArray &ida);
2518     void operator=(AutoIdArray &ida);
2519 };
2520
2521 /* The auto-root for enumeration object and its state. */
2522 class AutoEnumStateRooter : private AutoGCRooter
2523 {
2524   public:
2525     AutoEnumStateRooter(JSContext *cx, JSObject *obj
2526                         JS_GUARD_OBJECT_NOTIFIER_PARAM)
2527       : AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue()
2528     {
2529         JS_GUARD_OBJECT_NOTIFIER_INIT;
2530         JS_ASSERT(obj);
2531     }
2532
2533     ~AutoEnumStateRooter() {
2534         if (!stateValue.isNull()) {
2535 #ifdef DEBUG
2536             JSBool ok =
2537 #endif
2538             obj->enumerate(context, JSENUMERATE_DESTROY, &stateValue, 0);
2539             JS_ASSERT(ok);
2540         }
2541     }
2542
2543     friend void AutoGCRooter::trace(JSTracer *trc);
2544
2545     const Value &state() const { return stateValue; }
2546     Value *addr() { return &stateValue; }
2547
2548   protected:
2549     void trace(JSTracer *trc);
2550
2551     JSObject * const obj;
2552
2553   private:
2554     Value stateValue;
2555     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2556 };
2557
2558 #ifdef JS_HAS_XML_SUPPORT
2559 class AutoXMLRooter : private AutoGCRooter {
2560   public:
2561     AutoXMLRooter(JSContext *cx, JSXML *xml
2562                   JS_GUARD_OBJECT_NOTIFIER_PARAM)
2563       : AutoGCRooter(cx, XML), xml(xml)
2564     {
2565         JS_GUARD_OBJECT_NOTIFIER_INIT;
2566         JS_ASSERT(xml);
2567     }
2568
2569     friend void AutoGCRooter::trace(JSTracer *trc);
2570     friend void MarkRuntime(JSTracer *trc);
2571
2572   private:
2573     JSXML * const xml;
2574     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2575 };
2576 #endif /* JS_HAS_XML_SUPPORT */
2577
2578 class AutoBindingsRooter : private AutoGCRooter {
2579   public:
2580     AutoBindingsRooter(JSContext *cx, Bindings &bindings
2581                        JS_GUARD_OBJECT_NOTIFIER_PARAM)
2582       : AutoGCRooter(cx, BINDINGS), bindings(bindings)
2583     {
2584         JS_GUARD_OBJECT_NOTIFIER_INIT;
2585     }
2586
2587     friend void AutoGCRooter::trace(JSTracer *trc);
2588
2589   private:
2590     Bindings &bindings;
2591     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2592 };
2593
2594 class AutoLockGC {
2595   public:
2596     explicit AutoLockGC(JSRuntime *rt
2597                         JS_GUARD_OBJECT_NOTIFIER_PARAM)
2598       : rt(rt)
2599     {
2600         JS_GUARD_OBJECT_NOTIFIER_INIT;
2601         JS_LOCK_GC(rt);
2602     }
2603     ~AutoLockGC() { JS_UNLOCK_GC(rt); }
2604
2605   private:
2606     JSRuntime *rt;
2607     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2608 };
2609
2610 class AutoUnlockGC {
2611   private:
2612     JSRuntime *rt;
2613     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2614
2615   public:
2616     explicit AutoUnlockGC(JSRuntime *rt
2617                           JS_GUARD_OBJECT_NOTIFIER_PARAM)
2618       : rt(rt)
2619     {
2620         JS_GUARD_OBJECT_NOTIFIER_INIT;
2621         JS_UNLOCK_GC(rt);
2622     }
2623     ~AutoUnlockGC() { JS_LOCK_GC(rt); }
2624 };
2625
2626 class AutoLockAtomsCompartment {
2627   private:
2628     JSContext *cx;
2629     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2630
2631   public:
2632     AutoLockAtomsCompartment(JSContext *cx
2633                                JS_GUARD_OBJECT_NOTIFIER_PARAM)
2634       : cx(cx)
2635     {
2636         JS_GUARD_OBJECT_NOTIFIER_INIT;
2637         JS_LOCK(cx, &cx->runtime->atomState.lock);
2638 #ifdef JS_THREADSAFE
2639         cx->runtime->atomsCompartmentIsLocked = true;
2640 #endif
2641     }
2642     ~AutoLockAtomsCompartment() {
2643 #ifdef JS_THREADSAFE
2644         cx->runtime->atomsCompartmentIsLocked = false;
2645 #endif
2646         JS_UNLOCK(cx, &cx->runtime->atomState.lock);
2647     }
2648 };
2649
2650 class AutoUnlockAtomsCompartment {
2651     JSContext *cx;
2652     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2653
2654   public:
2655     AutoUnlockAtomsCompartment(JSContext *cx
2656                                  JS_GUARD_OBJECT_NOTIFIER_PARAM)
2657       : cx(cx)
2658     {
2659         JS_GUARD_OBJECT_NOTIFIER_INIT;
2660 #ifdef JS_THREADSAFE
2661         cx->runtime->atomsCompartmentIsLocked = false;
2662 #endif
2663         JS_UNLOCK(cx, &cx->runtime->atomState.lock);
2664     }
2665     ~AutoUnlockAtomsCompartment() {
2666         JS_LOCK(cx, &cx->runtime->atomState.lock);
2667 #ifdef JS_THREADSAFE
2668         cx->runtime->atomsCompartmentIsLocked = true;
2669 #endif
2670     }
2671 };
2672
2673 class AutoKeepAtoms {
2674     JSRuntime *rt;
2675     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2676
2677   public:
2678     explicit AutoKeepAtoms(JSRuntime *rt
2679                            JS_GUARD_OBJECT_NOTIFIER_PARAM)
2680       : rt(rt)
2681     {
2682         JS_GUARD_OBJECT_NOTIFIER_INIT;
2683         JS_KEEP_ATOMS(rt);
2684     }
2685     ~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
2686 };
2687
2688 class AutoArenaAllocator {
2689     JSArenaPool *pool;
2690     void        *mark;
2691     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2692
2693   public:
2694     explicit AutoArenaAllocator(JSArenaPool *pool
2695                                 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2696       : pool(pool), mark(JS_ARENA_MARK(pool))
2697     {
2698         JS_GUARD_OBJECT_NOTIFIER_INIT;
2699     }
2700     ~AutoArenaAllocator() { JS_ARENA_RELEASE(pool, mark); }
2701
2702     template <typename T>
2703     T *alloc(size_t elems) {
2704         void *ptr;
2705         JS_ARENA_ALLOCATE(ptr, pool, elems * sizeof(T));
2706         return static_cast<T *>(ptr);
2707     }
2708 };
2709
2710 class AutoReleasePtr {
2711     JSContext   *cx;
2712     void        *ptr;
2713     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2714
2715     AutoReleasePtr operator=(const AutoReleasePtr &other);
2716
2717   public:
2718     explicit AutoReleasePtr(JSContext *cx, void *ptr
2719                             JS_GUARD_OBJECT_NOTIFIER_PARAM)
2720       : cx(cx), ptr(ptr)
2721     {
2722         JS_GUARD_OBJECT_NOTIFIER_INIT;
2723     }
2724     ~AutoReleasePtr() { cx->free(ptr); }
2725 };
2726
2727 /*
2728  * FIXME: bug 602774: cleaner API for AutoReleaseNullablePtr
2729  */
2730 class AutoReleaseNullablePtr {
2731     JSContext   *cx;
2732     void        *ptr;
2733     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2734
2735     AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other);
2736
2737   public:
2738     explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr
2739                                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
2740       : cx(cx), ptr(ptr)
2741     {
2742         JS_GUARD_OBJECT_NOTIFIER_INIT;
2743     }
2744     void reset(void *ptr2) {
2745         if (ptr)
2746             cx->free(ptr);
2747         ptr = ptr2;
2748     }
2749     ~AutoReleaseNullablePtr() { if (ptr) cx->free(ptr); }
2750 };
2751
2752 class AutoLocalNameArray {
2753   public:
2754     explicit AutoLocalNameArray(JSContext *cx, JSFunction *fun
2755                                 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2756       : context(cx),
2757         mark(JS_ARENA_MARK(&cx->tempPool)),
2758         names(fun->script()->bindings.getLocalNameArray(cx, &cx->tempPool)),
2759         count(fun->script()->bindings.countLocalNames())
2760     {
2761         JS_GUARD_OBJECT_NOTIFIER_INIT;
2762     }
2763
2764     ~AutoLocalNameArray() {
2765         JS_ARENA_RELEASE(&context->tempPool, mark);
2766     }
2767
2768     operator bool() const { return !!names; }
2769
2770     uint32 length() const { return count; }
2771
2772     const jsuword &operator [](unsigned i) const { return names[i]; }
2773
2774   private:
2775     JSContext   *context;
2776     void        *mark;
2777     jsuword     *names;
2778     uint32      count;
2779
2780     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2781 };
2782
2783 template <class RefCountable>
2784 class AlreadyIncRefed
2785 {
2786     typedef RefCountable *****ConvertibleToBool;
2787
2788     RefCountable *obj;
2789
2790   public:
2791     explicit AlreadyIncRefed(RefCountable *obj) : obj(obj) {}
2792
2793     bool null() const { return obj == NULL; }
2794     operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2795
2796     RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2797     RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2798     RefCountable *get() const { return obj; }
2799 };
2800
2801 template <class RefCountable>
2802 class NeedsIncRef
2803 {
2804     typedef RefCountable *****ConvertibleToBool;
2805
2806     RefCountable *obj;
2807
2808   public:
2809     explicit NeedsIncRef(RefCountable *obj) : obj(obj) {}
2810
2811     bool null() const { return obj == NULL; }
2812     operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2813
2814     RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2815     RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2816     RefCountable *get() const { return obj; }
2817 };
2818
2819 template <class RefCountable>
2820 class AutoRefCount
2821 {
2822     typedef RefCountable *****ConvertibleToBool;
2823
2824     JSContext *const cx;
2825     RefCountable *obj;
2826
2827     AutoRefCount(const AutoRefCount &);
2828     void operator=(const AutoRefCount &);
2829
2830   public:
2831     explicit AutoRefCount(JSContext *cx)
2832       : cx(cx), obj(NULL)
2833     {}
2834
2835     AutoRefCount(JSContext *cx, NeedsIncRef<RefCountable> aobj)
2836       : cx(cx), obj(aobj.get())
2837     {
2838         if (obj)
2839             obj->incref(cx);
2840     }
2841
2842     AutoRefCount(JSContext *cx, AlreadyIncRefed<RefCountable> aobj)
2843       : cx(cx), obj(aobj.get())
2844     {}
2845
2846     ~AutoRefCount() {
2847         if (obj)
2848             obj->decref(cx);
2849     }
2850
2851     void reset(NeedsIncRef<RefCountable> aobj) {
2852         if (obj)
2853             obj->decref(cx);
2854         obj = aobj.get();
2855         if (obj)
2856             obj->incref(cx);
2857     }
2858
2859     void reset(AlreadyIncRefed<RefCountable> aobj) {
2860         if (obj)
2861             obj->decref(cx);
2862         obj = aobj.get();
2863     }
2864
2865     bool null() const { return obj == NULL; }
2866     operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2867
2868     RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2869     RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2870     RefCountable *get() const { return obj; }
2871 };
2872
2873 } /* namespace js */
2874
2875 class JSAutoResolveFlags
2876 {
2877   public:
2878     JSAutoResolveFlags(JSContext *cx, uintN flags
2879                        JS_GUARD_OBJECT_NOTIFIER_PARAM)
2880       : mContext(cx), mSaved(cx->resolveFlags)
2881     {
2882         JS_GUARD_OBJECT_NOTIFIER_INIT;
2883         cx->resolveFlags = flags;
2884     }
2885
2886     ~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; }
2887
2888   private:
2889     JSContext *mContext;
2890     uintN mSaved;
2891     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2892 };
2893
2894 extern JSThreadData *
2895 js_CurrentThreadData(JSRuntime *rt);
2896
2897 extern JSBool
2898 js_InitThreads(JSRuntime *rt);
2899
2900 extern void
2901 js_FinishThreads(JSRuntime *rt);
2902
2903 extern void
2904 js_PurgeThreads(JSContext *cx);
2905
2906 namespace js {
2907
2908 #ifdef JS_THREADSAFE
2909
2910 /* Iterator over JSThreadData from all JSThread instances. */
2911 class ThreadDataIter : public JSThread::Map::Range
2912 {
2913   public:
2914     ThreadDataIter(JSRuntime *rt) : JSThread::Map::Range(rt->threads.all()) {}
2915
2916     JSThreadData *threadData() const {
2917         return &front().value->data;
2918     }
2919 };
2920
2921 #else /* !JS_THREADSAFE */
2922
2923 class ThreadDataIter
2924 {
2925     JSRuntime *runtime;
2926     bool done;
2927   public:
2928     ThreadDataIter(JSRuntime *rt) : runtime(rt), done(false) {}
2929
2930     bool empty() const {
2931         return done;
2932     }
2933
2934     void popFront() {
2935         JS_ASSERT(!done);
2936         done = true;
2937     }
2938
2939     JSThreadData *threadData() const {
2940         JS_ASSERT(!done);
2941         return &runtime->threadData;
2942     }
2943 };
2944
2945 #endif  /* !JS_THREADSAFE */
2946
2947 } /* namespace js */
2948
2949 /*
2950  * Create and destroy functions for JSContext, which is manually allocated
2951  * and exclusively owned.
2952  */
2953 extern JSContext *
2954 js_NewContext(JSRuntime *rt, size_t stackChunkSize);
2955
2956 extern void
2957 js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
2958
2959 static JS_INLINE JSContext *
2960 js_ContextFromLinkField(JSCList *link)
2961 {
2962     JS_ASSERT(link);
2963     return (JSContext *) ((uint8 *) link - offsetof(JSContext, link));
2964 }
2965
2966 /*
2967  * If unlocked, acquire and release rt->gcLock around *iterp update; otherwise
2968  * the caller must be holding rt->gcLock.
2969  */
2970 extern JSContext *
2971 js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
2972
2973 /*
2974  * Iterate through contexts with active requests. The caller must be holding
2975  * rt->gcLock in case of a thread-safe build, or otherwise guarantee that the
2976  * context list is not alternated asynchroniously.
2977  */
2978 extern JS_FRIEND_API(JSContext *)
2979 js_NextActiveContext(JSRuntime *, JSContext *);
2980
2981 /*
2982  * Class.resolve and watchpoint recursion damping machinery.
2983  */
2984 extern JSBool
2985 js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
2986                   JSResolvingEntry **entryp);
2987
2988 extern void
2989 js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
2990                  JSResolvingEntry *entry, uint32 generation);
2991
2992 /*
2993  * Report an exception, which is currently realized as a printf-style format
2994  * string and its arguments.
2995  */
2996 typedef enum JSErrNum {
2997 #define MSG_DEF(name, number, count, exception, format) \
2998     name = number,
2999 #include "js.msg"
3000 #undef MSG_DEF
3001     JSErr_Limit
3002 } JSErrNum;
3003
3004 extern JS_FRIEND_API(const JSErrorFormatString *)
3005 js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
3006
3007 #ifdef va_start
3008 extern JSBool
3009 js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
3010
3011 extern JSBool
3012 js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
3013                        void *userRef, const uintN errorNumber,
3014                        JSBool charArgs, va_list ap);
3015
3016 extern JSBool
3017 js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
3018                         void *userRef, const uintN errorNumber,
3019                         char **message, JSErrorReport *reportp,
3020                         bool charArgs, va_list ap);
3021 #endif
3022
3023 extern void
3024 js_ReportOutOfMemory(JSContext *cx);
3025
3026 /*
3027  * Report that cx->scriptStackQuota is exhausted.
3028  */
3029 void
3030 js_ReportOutOfScriptQuota(JSContext *cx);
3031
3032 extern JS_FRIEND_API(void)
3033 js_ReportOverRecursed(JSContext *cx);
3034
3035 extern JS_FRIEND_API(void)
3036 js_ReportAllocationOverflow(JSContext *cx);
3037
3038 #define JS_CHECK_RECURSION(cx, onerror)                                       \
3039     JS_BEGIN_MACRO                                                            \
3040         int stackDummy_;                                                      \
3041                                                                               \
3042         if (!JS_CHECK_STACK_SIZE(cx->stackLimit, &stackDummy_)) {             \
3043             js_ReportOverRecursed(cx);                                        \
3044             onerror;                                                          \
3045         }                                                                     \
3046     JS_END_MACRO
3047
3048 /*
3049  * Report an exception using a previously composed JSErrorReport.
3050  * XXXbe remove from "friend" API
3051  */
3052 extern JS_FRIEND_API(void)
3053 js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
3054
3055 extern void
3056 js_ReportIsNotDefined(JSContext *cx, const char *name);
3057
3058 /*
3059  * Report an attempt to access the property of a null or undefined value (v).
3060  */
3061 extern JSBool
3062 js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const js::Value &v,
3063                            JSString *fallback);
3064
3065 extern void
3066 js_ReportMissingArg(JSContext *cx, const js::Value &v, uintN arg);
3067
3068 /*
3069  * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
3070  * the first argument for the error message. If the error message has less
3071  * then 3 arguments, use null for arg1 or arg2.
3072  */
3073 extern JSBool
3074 js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
3075                          intN spindex, const js::Value &v, JSString *fallback,
3076                          const char *arg1, const char *arg2);
3077
3078 #define js_ReportValueError(cx,errorNumber,spindex,v,fallback)                \
3079     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
3080                                     spindex, v, fallback, NULL, NULL))
3081
3082 #define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1)          \
3083     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
3084                                     spindex, v, fallback, arg1, NULL))
3085
3086 #define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2)     \
3087     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
3088                                     spindex, v, fallback, arg1, arg2))
3089
3090 extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
3091
3092 #ifdef JS_THREADSAFE
3093 # define JS_ASSERT_REQUEST_DEPTH(cx)  (JS_ASSERT((cx)->thread),               \
3094                                        JS_ASSERT((cx)->thread->data.requestDepth >= 1))
3095 #else
3096 # define JS_ASSERT_REQUEST_DEPTH(cx)  ((void) 0)
3097 #endif
3098
3099 /*
3100  * If the operation callback flag was set, call the operation callback.
3101  * This macro can run the full GC. Return true if it is OK to continue and
3102  * false otherwise.
3103  */
3104 #define JS_CHECK_OPERATION_LIMIT(cx)                                          \
3105     (JS_ASSERT_REQUEST_DEPTH(cx),                                             \
3106      (!JS_THREAD_DATA(cx)->interruptFlags || js_InvokeOperationCallback(cx)))
3107
3108 JS_ALWAYS_INLINE void
3109 JSThreadData::triggerOperationCallback(JSRuntime *rt)
3110 {
3111     /*
3112      * Use JS_ATOMIC_SET and JS_ATOMIC_INCREMENT in the hope that it ensures
3113      * the write will become immediately visible to other processors polling
3114      * the flag.  Note that we only care about visibility here, not read/write
3115      * ordering: this field can only be written with the GC lock held.
3116      */
3117     if (interruptFlags)
3118         return;
3119     JS_ATOMIC_SET(&interruptFlags, 1);
3120
3121 #ifdef JS_THREADSAFE
3122     /* rt->interruptCounter does not reflect suspended threads. */
3123     if (requestDepth != 0)
3124         JS_ATOMIC_INCREMENT(&rt->interruptCounter);
3125 #endif
3126 }
3127
3128 /*
3129  * Invoke the operation callback and return false if the current execution
3130  * is to be terminated.
3131  */
3132 extern JSBool
3133 js_InvokeOperationCallback(JSContext *cx);
3134
3135 extern JSBool
3136 js_HandleExecutionInterrupt(JSContext *cx);
3137
3138 namespace js {
3139
3140 /* These must be called with GC lock taken. */
3141
3142 JS_FRIEND_API(void)
3143 TriggerOperationCallback(JSContext *cx);
3144
3145 void
3146 TriggerAllOperationCallbacks(JSRuntime *rt);
3147
3148 } /* namespace js */
3149
3150 extern JSStackFrame *
3151 js_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
3152
3153 extern jsbytecode*
3154 js_GetCurrentBytecodePC(JSContext* cx);
3155
3156 extern bool
3157 js_CurrentPCIsInImacro(JSContext *cx);
3158
3159 namespace js {
3160
3161 class RegExpStatics;
3162
3163 extern JS_FORCES_STACK JS_FRIEND_API(void)
3164 LeaveTrace(JSContext *cx);
3165
3166 } /* namespace js */
3167
3168 /*
3169  * Get the current frame, first lazily instantiating stack frames if needed.
3170  * (Do not access cx->fp() directly except in JS_REQUIRES_STACK code.)
3171  *
3172  * Defined in jstracer.cpp if JS_TRACER is defined.
3173  */
3174 static JS_FORCES_STACK JS_INLINE JSStackFrame *
3175 js_GetTopStackFrame(JSContext *cx)
3176 {
3177     js::LeaveTrace(cx);
3178     return cx->maybefp();
3179 }
3180
3181 static JS_INLINE JSBool
3182 js_IsPropertyCacheDisabled(JSContext *cx)
3183 {
3184     return cx->runtime->shapeGen >= js::SHAPE_OVERFLOW_BIT;
3185 }
3186
3187 static JS_INLINE uint32
3188 js_RegenerateShapeForGC(JSRuntime *rt)
3189 {
3190     JS_ASSERT(rt->gcRunning);
3191     JS_ASSERT(rt->gcRegenShapes);
3192
3193     /*
3194      * Under the GC, compared with js_GenerateShape, we don't need to use
3195      * atomic increments but we still must make sure that after an overflow
3196      * the shape stays such.
3197      */
3198     uint32 shape = rt->shapeGen;
3199     shape = (shape + 1) | (shape & js::SHAPE_OVERFLOW_BIT);
3200     rt->shapeGen = shape;
3201     return shape;
3202 }
3203
3204 namespace js {
3205
3206 inline void *
3207 ContextAllocPolicy::malloc(size_t bytes)
3208 {
3209     return cx->malloc(bytes);
3210 }
3211
3212 inline void
3213 ContextAllocPolicy::free(void *p)
3214 {
3215     cx->free(p);
3216 }
3217
3218 inline void *
3219 ContextAllocPolicy::realloc(void *p, size_t bytes)
3220 {
3221     return cx->realloc(p, bytes);
3222 }
3223
3224 inline void
3225 ContextAllocPolicy::reportAllocOverflow() const
3226 {
3227     js_ReportAllocationOverflow(cx);
3228 }
3229
3230 template<class T>
3231 class AutoVectorRooter : protected AutoGCRooter
3232 {
3233   public:
3234     explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
3235                               JS_GUARD_OBJECT_NOTIFIER_PARAM)
3236         : AutoGCRooter(cx, tag), vector(cx)
3237     {
3238         JS_GUARD_OBJECT_NOTIFIER_INIT;
3239     }
3240
3241     size_t length() const { return vector.length(); }
3242
3243     bool append(const T &v) { return vector.append(v); }
3244
3245     void popBack() { vector.popBack(); }
3246
3247     bool growBy(size_t inc) {
3248         size_t oldLength = vector.length();
3249         if (!vector.growByUninitialized(inc))
3250             return false;
3251         MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
3252         return true;
3253     }
3254
3255     bool resize(size_t newLength) {
3256         size_t oldLength = vector.length();
3257         if (newLength <= oldLength) {
3258             vector.shrinkBy(oldLength - newLength);
3259             return true;
3260         }
3261         if (!vector.growByUninitialized(newLength - oldLength))
3262             return false;
3263         MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
3264         return true;
3265     }
3266
3267     bool reserve(size_t newLength) {
3268         return vector.reserve(newLength);
3269     }
3270
3271     T &operator[](size_t i) { return vector[i]; }
3272     const T &operator[](size_t i) const { return vector[i]; }
3273
3274     const T *begin() const { return vector.begin(); }
3275     T *begin() { return vector.begin(); }
3276
3277     const T *end() const { return vector.end(); }
3278     T *end() { return vector.end(); }
3279
3280     const T &back() const { return vector.back(); }
3281
3282     friend void AutoGCRooter::trace(JSTracer *trc);
3283
3284   private:
3285     Vector<T, 8> vector;
3286     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3287 };
3288
3289 class AutoValueVector : public AutoVectorRooter<Value>
3290 {
3291   public:
3292     explicit AutoValueVector(JSContext *cx
3293                              JS_GUARD_OBJECT_NOTIFIER_PARAM)
3294         : AutoVectorRooter<Value>(cx, VALVECTOR)
3295     {
3296         JS_GUARD_OBJECT_NOTIFIER_INIT;
3297     }
3298
3299     const jsval *jsval_begin() const { return Jsvalify(begin()); }
3300     jsval *jsval_begin() { return Jsvalify(begin()); }
3301
3302     const jsval *jsval_end() const { return Jsvalify(end()); }
3303     jsval *jsval_end() { return Jsvalify(end()); }
3304
3305     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3306 };
3307
3308 class AutoIdVector : public AutoVectorRooter<jsid>
3309 {
3310   public:
3311     explicit AutoIdVector(JSContext *cx
3312                           JS_GUARD_OBJECT_NOTIFIER_PARAM)
3313         : AutoVectorRooter<jsid>(cx, IDVECTOR)
3314     {
3315         JS_GUARD_OBJECT_NOTIFIER_INIT;
3316     }
3317
3318     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3319 };
3320
3321 class AutoShapeVector : public AutoVectorRooter<const Shape *>
3322 {
3323   public:
3324     explicit AutoShapeVector(JSContext *cx
3325                              JS_GUARD_OBJECT_NOTIFIER_PARAM)
3326         : AutoVectorRooter<const Shape *>(cx, SHAPEVECTOR)
3327     {
3328         JS_GUARD_OBJECT_NOTIFIER_INIT;
3329     }
3330
3331     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3332 };
3333
3334 JSIdArray *
3335 NewIdArray(JSContext *cx, jsint length);
3336
3337 } /* namespace js */
3338
3339 #ifdef _MSC_VER
3340 #pragma warning(pop)
3341 #pragma warning(pop)
3342 #endif
3343
3344 #ifdef JS_CNTXT_UNDEFD_MOZALLOC_WRAPPERS
3345 #  include "mozilla/mozalloc_macro_wrappers.h"
3346 #endif
3347
3348 #endif /* jscntxt_h___ */