1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
17 * The Original Code is Mozilla Communicator client code, released
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.
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.
39 * ***** END LICENSE BLOCK ***** */
44 * JS execution context.
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"
64 #include "jsgcchunk.h"
65 #include "jshashtable.h"
69 #include "jspropertycache.h"
70 #include "jspropertytree.h"
71 #include "jsstaticcheck.h"
79 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
81 #pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */
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.
90 typedef struct JSGSNCache {
98 # define GSN_CACHE_METER(cache,cnt) (++(cache)->cnt)
100 # define GSN_CACHE_METER(cache,cnt) /* nothing */
104 #define js_FinishGSNCache(cache) js_PurgeGSNCache(cache)
107 js_PurgeGSNCache(JSGSNCache *cache);
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)
113 /* Forward declarations of nanojit types. */
119 template<typename K> struct DefaultHash;
120 template<typename K, typename V, typename H> class HashMap;
121 template<typename T> class Seq;
123 } /* namespace nanojit */
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;
136 /* Forward declarations of tracer types. */
138 class FrameInfoCache;
143 template<typename T> class Queue;
144 typedef Queue<uint16> SlotList;
148 #if defined(JS_JIT_SPEW) || defined(DEBUG)
150 typedef nanojit::HashMap<uint32, FragPI, nanojit::DefaultHash<uint32> > FragStatsMap;
154 class JaegerCompartment;
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.
163 class ContextAllocPolicy
168 ContextAllocPolicy(JSContext *cx) : cx(cx) {}
169 JSContext *context() const { return cx; }
171 /* Inline definitions below. */
172 void *malloc(size_t bytes);
174 void *realloc(void *p, size_t bytes);
175 void reportAllocOverflow() const;
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.
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.
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
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.
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.
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.
227 /* The context to which this segment belongs. */
230 /* Link for JSContext segment stack mentioned in big comment above. */
231 StackSegment *previousInContext;
233 /* Link for StackSpace segment stack mentioned in StackSpace comment. */
234 StackSegment *previousInMemory;
236 /* The first frame executed in this segment. null iff cx is null */
237 JSStackFrame *initialFrame;
239 /* If this segment is suspended, |cx->regs| when it was suspended. */
240 JSFrameRegs *suspendedRegs;
242 /* The varobj on entry to initialFrame. */
243 JSObject *initialVarObj;
245 /* Whether this segment was suspended by JS_SaveFrameChain. */
248 /* Align at 8 bytes on all platforms. */
249 #if JS_BITS_PER_WORD == 32
254 * To make isActive a single null-ness check, this non-null constant is
255 * assigned to suspendedRegs when !inContext.
257 #define NON_NULL_SUSPENDED_REGS ((JSFrameRegs *)0x1)
261 : cx(NULL), previousInContext(NULL), previousInMemory(NULL),
262 initialFrame(NULL), suspendedRegs(NON_NULL_SUSPENDED_REGS),
263 initialVarObj(NULL), saved(false)
265 JS_ASSERT(!inContext());
268 /* Safe casts guaranteed by the contiguous-stack layout. */
270 Value *valueRangeBegin() const {
271 return (Value *)(this + 1);
275 * As described in the comment at the beginning of the class, a segment
276 * is in one of three states:
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.
285 bool inContext() const {
286 JS_ASSERT(!!cx == !!initialFrame);
287 JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS && !saved);
291 bool isActive() const {
292 JS_ASSERT_IF(!suspendedRegs, cx && !saved);
293 JS_ASSERT_IF(!cx, suspendedRegs == NON_NULL_SUSPENDED_REGS);
294 return !suspendedRegs;
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;
303 /* Substate of suspended, queryable in any state. */
305 bool isSaved() const {
306 JS_ASSERT_IF(saved, isSuspended());
310 /* Transitioning between inContext <--> isActive */
312 void joinContext(JSContext *cx, JSStackFrame *f) {
313 JS_ASSERT(!inContext());
316 suspendedRegs = NULL;
317 JS_ASSERT(isActive());
320 void leaveContext() {
321 JS_ASSERT(isActive());
324 suspendedRegs = NON_NULL_SUSPENDED_REGS;
325 JS_ASSERT(!inContext());
328 JSContext *maybeContext() const {
332 #undef NON_NULL_SUSPENDED_REGS
334 /* Transitioning between isActive <--> isSuspended */
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());
344 JS_ASSERT(isSuspended());
345 suspendedRegs = NULL;
346 JS_ASSERT(isActive());
349 /* When isSuspended, transitioning isSaved <--> !isSaved */
351 void save(JSFrameRegs *regs) {
352 JS_ASSERT(!isSuspended());
355 JS_ASSERT(isSaved());
359 JS_ASSERT(isSaved());
362 JS_ASSERT(!isSuspended());
365 /* Data available when inContext */
367 JSStackFrame *getInitialFrame() const {
368 JS_ASSERT(inContext());
372 inline JSFrameRegs *getCurrentRegs() const;
373 inline JSStackFrame *getCurrentFrame() const;
375 /* Data available when isSuspended. */
377 JSFrameRegs *getSuspendedRegs() const {
378 JS_ASSERT(isSuspended());
379 return suspendedRegs;
382 JSStackFrame *getSuspendedFrame() const {
383 return suspendedRegs->fp;
386 /* JSContext / js::StackSpace bookkeeping. */
388 void setPreviousInContext(StackSegment *seg) {
389 previousInContext = seg;
392 StackSegment *getPreviousInContext() const {
393 return previousInContext;
396 void setPreviousInMemory(StackSegment *seg) {
397 previousInMemory = seg;
400 StackSegment *getPreviousInMemory() const {
401 return previousInMemory;
404 void setInitialVarObj(JSObject *obj) {
405 JS_ASSERT(inContext());
409 bool hasInitialVarObj() {
410 JS_ASSERT(inContext());
411 return initialVarObj != NULL;
414 JSObject &getInitialVarObj() const {
415 JS_ASSERT(inContext() && initialVarObj);
416 return *initialVarObj;
420 JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
424 static const size_t VALUES_PER_STACK_SEGMENT = sizeof(StackSegment) / sizeof(Value);
425 JS_STATIC_ASSERT(sizeof(StackSegment) % sizeof(Value) == 0);
427 /* See StackSpace::pushInvokeArgs. */
428 class InvokeArgsGuard : public CallArgs
430 friend class StackSpace;
431 JSContext *cx; /* null implies nothing pushed */
433 Value *prevInvokeArgEnd;
435 StackSegment *prevInvokeSegment;
436 JSStackFrame *prevInvokeFrame;
439 InvokeArgsGuard() : cx(NULL), seg(NULL) {}
441 bool pushed() const { return cx != NULL; }
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.
448 struct InvokeArgsAlreadyOnTheStack : CallArgs
450 InvokeArgsAlreadyOnTheStack(Value *vp, uintN argc) : CallArgs(vp + 2, argc) {}
453 /* See StackSpace::pushInvokeFrame. */
454 class InvokeFrameGuard
456 friend class StackSpace;
457 JSContext *cx_; /* null implies nothing pushed */
459 JSFrameRegs *prevRegs_;
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_; }
466 JSStackFrame *fp() const { return regs_.fp; }
469 /* Reusable base; not for direct use. */
472 friend class StackSpace;
473 JSContext *cx_; /* null implies nothing pushed */
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_; }
486 /* See StackSpace::pushExecuteFrame. */
487 class ExecuteFrameGuard : public FrameGuard
489 friend class StackSpace;
493 /* See StackSpace::pushDummyFrame. */
494 class DummyFrameGuard : public FrameGuard
496 friend class StackSpace;
500 /* See StackSpace::pushGeneratorFrame. */
501 class GeneratorFrameGuard : public FrameGuard
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.
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:
522 * initial frame current frame ------. if regs,
523 * .------------. | | regs->sp
525 * |segment| slots |frame| slots |frame| slots |frame| slots |
527 * ? <----------' `----------' `----------'
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.
537 * An empty segment is followed by arguments that are rooted by the
538 * StackSpace::invokeArgEnd pointer:
545 * Above the level of segments, a StackSpace is simply a contiguous sequence
546 * of segments kept in a linked list:
548 * base currentSegment firstUnused end
551 * |segment| --- |segment| --- |segment| ------- | |
553 * 0 <---' `-----------' `-----------'
554 * previous previous previous
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".
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.
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,
570 * 2. the mapping from stack frames to their containing segment preserves
571 * order (in terms of prev and previousInContext, respectively).
577 mutable Value *commitEnd;
580 StackSegment *currentSegment;
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.
587 StackSegment *invokeSegment;
588 JSStackFrame *invokeFrame;
592 friend class InvokeArgsGuard;
593 friend class InvokeFrameGuard;
594 friend class FrameGuard;
596 bool pushSegmentForInvoke(JSContext *cx, uintN argc, InvokeArgsGuard *ag);
597 void popSegmentForInvoke(const InvokeArgsGuard &ag);
599 bool pushInvokeFrameSlow(JSContext *cx, const InvokeArgsGuard &ag,
600 InvokeFrameGuard *fg);
601 void popInvokeFrameSlow(const CallArgs &args);
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);
608 struct EnsureSpaceCheck {
609 inline bool operator()(const StackSpace &, JSContext *, Value *, uintN);
615 LimitCheck(JSStackFrame *base, Value **limit) : base(base), limit(limit) {}
616 inline bool operator()(const StackSpace &, JSContext *, Value *, uintN);
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;
624 inline void popInvokeArgs(const InvokeArgsGuard &args);
625 inline void popInvokeFrame(const InvokeFrameGuard &ag);
627 inline Value *firstUnused() const;
629 inline bool isCurrentAndActive(JSContext *cx) const;
630 friend class AllFramesIter;
631 StackSegment *getCurrentSegment() const { return currentSegment; }
634 /* Commit more memory from the reserved stack space. */
635 JS_FRIEND_API(bool) bumpCommit(Value *from, ptrdiff_t nvals) const;
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);
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.
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
654 static const size_t STACK_QUOTA = (VALUES_PER_STACK_FRAME + 18) *
655 JS_MAX_INLINE_CALL_COUNT;
657 /* Kept as a member of JSThreadData; cannot use constructor/destructor. */
663 bool contains(T *t) const {
665 JS_ASSERT(size_t(-1) - uintptr_t(t) >= sizeof(T));
666 return v >= (char *)base && v + sizeof(T) <= (char *)end;
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.
676 inline bool ensureEnoughSpaceToEnterTrace();
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 */);
683 /* Mark all segments, frames, and slots on the stack. */
684 JS_REQUIRES_STACK void mark(JSTracer *trc);
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
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.
708 bool pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *ag);
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;
714 void pushInvokeFrame(JSContext *cx, const CallArgs &args, InvokeFrameGuard *fg);
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);
721 * Since RAII cannot be used for inline frames, callers must manually
722 * call pushInlineFrame/popInlineFrame.
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,
729 inline void popInlineFrame(JSContext *cx, JSStackFrame *prev, js::Value *newsp);
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);
736 /* Pushes a JSStackFrame::isDummyFrame. */
737 bool pushDummyFrame(JSContext *cx, JSObject &scopeChain, DummyFrameGuard *fg);
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;
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.
749 inline Value *getStackLimit(JSContext *cx);
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.
755 bool bumpCommitAndLimit(JSStackFrame *base, Value *from, uintN nvals, Value **limit) const;
758 * Allocate nvals on the top of the stack, report error on failure.
759 * N.B. the caller must ensure |from >= firstUnused()|.
761 inline bool ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const;
764 JS_STATIC_ASSERT(StackSpace::CAPACITY_VALS % StackSpace::COMMIT_VALS == 0);
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|.
773 * for (FrameRegsIter i(cx); !i.done(); ++i)
774 * ... i.fp() ... i.sp() ... i.pc()
779 StackSegment *curseg;
785 void incSlow(JSStackFrame *fp, JSStackFrame *prev);
788 JS_REQUIRES_STACK inline FrameRegsIter(JSContext *cx);
790 bool done() const { return curfp == NULL; }
791 inline FrameRegsIter &operator++();
793 JSStackFrame *fp() const { return curfp; }
794 Value *sp() const { return cursp; }
795 jsbytecode *pc() const { return curpc; }
799 * Utility class for iteration over all active stack frames.
804 AllFramesIter(JSContext *cx);
806 bool done() const { return curfp == NULL; }
807 AllFramesIter& operator++();
809 JSStackFrame *fp() const { return curfp; }
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
828 struct JSFunctionMeter {
829 int32 FUNCTION_KIND_METER_LIST(identity);
834 # define JS_FUNCTION_METER(cx,x) JS_RUNTIME_METER((cx)->runtime, functionMeter.x)
836 # define JS_FUNCTION_METER(cx,x) ((void)0)
840 struct JSPendingProxyOperation {
841 JSPendingProxyOperation *next;
845 struct JSThreadData {
847 /* The request depth for this thread. */
848 unsigned requestDepth;
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.
860 JSCompartment *onTraceCompartment;
861 JSCompartment *recordingCompartment;
862 JSCompartment *profilingCompartment;
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.
870 volatile int32 interruptFlags;
872 /* Keeper of the contiguous stack used by all contexts in this thread. */
873 js::StackSpace stackSpace;
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).
882 * The GSN cache is per thread since even multi-cx-per-thread embeddings
883 * do not interleave js_GetSrcNote calls.
887 /* Property cache for faster call/get/set invocation. */
888 js::PropertyCache propertyCache;
891 /* Maximum size of the tracer's code cache before we start flushing. */
892 uint32 maxCodeCacheBytes;
895 /* State used by dtoa.c. */
896 DtoaState *dtoaState;
898 /* Base address of the native stack for the current thread. */
899 jsuword *nativeStackBase;
901 /* List of currently pending operations on proxies. */
902 JSPendingProxyOperation *pendingProxyOperation;
904 js::ConservativeGCThreadData conservativeGC;
908 void mark(JSTracer *trc);
909 void purge(JSContext *cx);
911 /* This must be called with the GC lock held. */
912 inline void triggerOperationCallback(JSRuntime *rt);
918 * Structure uniquely representing a thread. It holds thread-private data
919 * that can be accessed without a global lock.
922 typedef js::HashMap<void *,
924 js::DefaultHasher<void *>,
925 js::SystemAllocPolicy> Map;
927 /* Linked list of all contexts in use on this thread. */
930 /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
933 /* Number of JS_SuspendRequest calls withot JS_ResumeRequest. */
934 unsigned suspendCount;
937 unsigned checkRequestDepth;
940 /* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */
944 #define JS_THREAD_DATA(cx) (&(cx)->thread->data)
947 js_CurrentThread(JSRuntime *rt);
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.
955 js_InitContextThread(JSContext *cx);
958 * On entrance the GC lock must be held and it will be held on exit.
961 js_ClearContextThread(JSContext *cx);
963 #endif /* JS_THREADSAFE */
965 typedef enum JSDestroyContextMode {
970 } JSDestroyContextMode;
972 typedef enum JSRuntimeState {
979 typedef struct JSPropertyTreeEntry {
982 } JSPropertyTreeEntry;
985 (* JSActivityCallback)(void *arg, JSBool active);
989 typedef js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> WrapperVector;
994 /* Default compartment. */
995 JSCompartment *atomsCompartment;
997 bool atomsCompartmentIsLocked;
1000 /* List of compartments (protected by the GC lock). */
1001 js::WrapperVector compartments;
1003 /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
1004 JSRuntimeState state;
1006 /* Context create/destroy callback. */
1007 JSContextCallback cxCallback;
1009 /* Compartment create/destroy callback. */
1010 JSCompartmentCallback compartmentCallback;
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
1018 void setActivityCallback(JSActivityCallback cb, void *arg) {
1019 activityCallback = cb;
1020 activityCallbackArg = arg;
1023 JSActivityCallback activityCallback;
1024 void *activityCallbackArg;
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.
1033 * See bug 492355 for more details.
1035 * This comes early in JSRuntime to minimize the immediate format used by
1036 * trace-JITted code that reads it.
1038 uint32 protoHazardShape;
1040 /* Garbage collector state, used by jsgc.c. */
1041 js::GCChunkSet gcChunkSet;
1043 js::RootedValueMap gcRootsHash;
1044 js::GCLocks gcLocksHash;
1045 jsrefcount gcKeepAtoms;
1047 size_t gcTriggerBytes;
1050 size_t gcMaxMallocBytes;
1051 size_t gcChunksWaitingToExpire;
1052 uint32 gcEmptyArenaPoolLifespan;
1054 js::GCMarker *gcMarkingTracer;
1055 uint32 gcTriggerFactor;
1056 int64 gcJitReleaseTime;
1058 volatile bool gcIsNeeded;
1061 * Compartment that triggered GC. If more than one Compatment need GC,
1062 * gcTriggerCompartment is reset to NULL and a global GC is performed.
1064 JSCompartment *gcTriggerCompartment;
1066 /* Compartment that is currently involved in per-compartment GC */
1067 JSCompartment *gcCurrentCompartment;
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
1076 bool gcMarkAndSweep;
1084 JSGCCallback gcCallback;
1088 * Malloc counter to measure memory pressure for GC scheduling. It runs
1089 * from gcMaxMallocBytes down to zero.
1091 volatile ptrdiff_t gcMallocBytes;
1094 js::GCChunkAllocator *gcChunkAllocator;
1096 void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) {
1097 JS_ASSERT(allocator);
1098 JS_ASSERT(state == JSRTS_DOWN);
1099 gcChunkAllocator = allocator;
1103 * The trace operation and its data argument to trace embedding-specific
1106 JSTraceDataOp gcExtraRootsTraceOp;
1107 void *gcExtraRootsData;
1109 /* Well-known numbers held for use by this runtime's contexts. */
1111 js::Value negativeInfinityValue;
1112 js::Value positiveInfinityValue;
1114 JSFlatString *emptyString;
1116 /* List of active contexts sharing this runtime; protected by gcLock. */
1117 JSCList contextList;
1119 /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
1120 JSDebugHooks globalDebugHooks;
1123 * Right now, we only support runtime-wide debugging.
1128 /* True if any debug hooks not supported by the JIT are enabled. */
1129 bool debuggerInhibitsJIT() const {
1130 return (globalDebugHooks.interruptHook ||
1131 globalDebugHooks.callHook);
1135 /* More debugging state, see jsdbgapi.c. */
1137 JSCList watchPointList;
1139 /* Client opaque pointers */
1142 #ifdef JS_THREADSAFE
1143 /* These combine to interlock the GC and new requests. */
1146 PRCondVar *requestDone;
1147 uint32 requestCount;
1150 js::GCHelperThread gcHelperThread;
1152 /* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
1158 /* Used to synchronize down/up state change; protected by gcLock. */
1159 PRCondVar *stateChange;
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
1167 PRLock *debuggerLock;
1169 JSThread::Map threads;
1170 #endif /* JS_THREADSAFE */
1171 uint32 debuggerMutations;
1174 * Security callbacks set on the runtime are used by each context unless
1175 * an override is set on the context.
1177 JSSecurityCallbacks *securityCallbacks;
1179 /* Structured data callbacks are runtime-wide. */
1180 const JSStructuredCloneCallbacks *structuredCloneCallbacks;
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.
1187 int32 propertyRemovals;
1189 /* Script filename table. */
1190 struct JSHashTable *scriptFilenameTable;
1191 JSCList scriptFilenamePrefixes;
1192 #ifdef JS_THREADSAFE
1193 PRLock *scriptFilenameTableLock;
1196 /* Number localization, used by jsnum.c */
1197 const char *thousandsSeparator;
1198 const char *decimalSeparator;
1199 const char *numGrouping;
1202 * Weak references to lazily-created, well-known XML singletons.
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.
1208 JSObject *anynameObject;
1209 JSObject *functionNamespaceObject;
1211 #ifdef JS_THREADSAFE
1212 /* Number of threads with active requests and unhandled interrupts. */
1213 volatile int32 interruptCounter;
1215 JSThreadData threadData;
1217 #define JS_THREAD_DATA(cx) (&(cx)->runtime->threadData)
1221 * Object shape (property cache structural type) identifier generator.
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
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.
1233 volatile uint32 shapeGen;
1235 /* Literal table maintained by jsatom.c functions. */
1236 JSAtomState atomState;
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.
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)
1248 # define ENUM_CACHE_METER(name) ((void) 0)
1251 #ifdef JS_DUMP_LOOP_STATS
1252 /* Loop statistics, to trigger trace recording and compiling. */
1253 JSBasicStats loopStats;
1257 /* Function invocation metering. */
1258 jsrefcount inlineCalls;
1259 jsrefcount nativeCalls;
1260 jsrefcount nonInlineCalls;
1261 jsrefcount constructs;
1263 jsrefcount liveObjectProps;
1264 jsrefcount liveObjectPropsPreSweep;
1267 * NB: emptyShapes (in JSCompartment) is init'ed iff at least one
1268 * of these envars is set:
1270 * JS_PROPTREE_STATFILE statistics on the property tree forest
1271 * JS_PROPTREE_DUMPFILE all paths in the property tree forest
1273 const char *propTreeStatFilename;
1274 const char *propTreeDumpFilename;
1276 bool meterEmptyShapes() const { return propTreeStatFilename || propTreeDumpFilename; }
1278 /* String instrumentation. */
1279 jsrefcount liveStrings;
1280 jsrefcount totalStrings;
1281 jsrefcount liveDependentStrings;
1282 jsrefcount totalDependentStrings;
1283 jsrefcount badUndependStrings;
1285 double lengthSquaredSum;
1286 double strdepLengthSum;
1287 double strdepLengthSquaredSum;
1289 /* Script instrumentation. */
1290 jsrefcount liveScripts;
1291 jsrefcount totalScripts;
1292 jsrefcount liveEmptyScripts;
1293 jsrefcount totalEmptyScripts;
1294 jsrefcount highWaterLiveScripts;
1297 #ifdef JS_SCOPE_DEPTH_METER
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.
1302 JSBasicStats protoLookupDepthStats;
1303 JSBasicStats scopeSearchDepthStats;
1306 * Stats on compile-time host environment and lexical scope chain lengths
1309 JSBasicStats hostenvScopeDepthStats;
1310 JSBasicStats lexicalScopeDepthStats;
1314 js::gc::JSGCStats gcStats;
1315 js::gc::JSGCArenaStats globalArenaStats[js::gc::FINALIZE_LIMIT];
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.
1323 const char *functionMeterFilename;
1324 JSFunctionMeter functionMeter;
1325 char lastScriptFilename[1024];
1327 typedef js::HashMap<JSFunction *,
1329 js::DefaultHasher<JSFunction *>,
1330 js::SystemAllocPolicy> FunctionCountMap;
1332 FunctionCountMap methodReadBarrierCountMap;
1333 FunctionCountMap unjoinedFunctionCountMap;
1336 JSWrapObjectCallback wrapObjectCallback;
1337 JSPreWrapCallback preWrapObjectCallback;
1340 uint32 mjitMemoryUsed;
1342 uint32 stringMemoryUsed;
1347 bool init(uint32 maxbytes);
1349 void setGCTriggerFactor(uint32 factor);
1350 void setGCLastBytes(size_t lastBytes);
1353 * Call the system malloc while checking for GC memory pressure and
1354 * reporting OOM error when cx is not null.
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);
1363 * Call the system calloc while checking for GC memory pressure and
1364 * reporting OOM error when cx is not null.
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);
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);
1379 void* realloc(void* p, size_t bytes, JSContext *cx = NULL) {
1381 * For compatibility we do not account for realloc that increases
1382 * previously allocated memory.
1385 updateMallocCounter(bytes);
1386 void *p2 = ::js_realloc(p, bytes);
1387 return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
1390 void free(void* p) { ::js_free(p); }
1392 bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
1394 void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
1396 void setGCMaxMallocBytes(size_t value) {
1398 * For compatibility treat any value that exceeds PTRDIFF_T_MAX to
1401 gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
1402 resetGCMallocBytes();
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.
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.
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))
1423 * The function must be called outside the GC lock.
1425 JS_FRIEND_API(void) onTooMuchMalloc();
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.
1433 * The function must be called outside the GC lock.
1435 JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes, JSContext *cx);
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)
1443 # define JS_RUNTIME_METER(rt, which) JS_ATOMIC_INCREMENT(&(rt)->which)
1444 # define JS_RUNTIME_UNMETER(rt, which) JS_ATOMIC_DECREMENT(&(rt)->which)
1446 # define JS_RUNTIME_METER(rt, which) /* nothing */
1447 # define JS_RUNTIME_UNMETER(rt, which) /* nothing */
1450 #define JS_KEEP_ATOMS(rt) JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms);
1451 #define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms);
1453 #ifdef JS_ARGUMENT_FORMATTER_DEFINED
1455 * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to
1456 * formatter functions. Elements are sorted in non-increasing format string
1459 struct JSArgumentFormatMap {
1462 JSArgumentFormatter formatter;
1463 JSArgumentFormatMap *next;
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.
1473 typedef struct JSResolvingKey {
1478 typedef struct JSResolvingEntry {
1479 JSDHashEntryHdr hdr;
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 */
1488 extern const JSDebugHooks js_NullDebugHooks; /* defined in jsdbgapi.cpp */
1495 OptionsHasXML(uint32 options)
1497 return !!(options & JSOPTION_XML);
1501 OptionsHasAnonFunFix(uint32 options)
1503 return !!(options & JSOPTION_ANONFUNFIX);
1507 OptionsSameVersionFlags(uint32 self, uint32 other)
1509 static const uint32 mask = JSOPTION_XML | JSOPTION_ANONFUNFIX;
1510 return !((self & mask) ^ (other & mask));
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
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;
1528 static inline JSVersion
1529 VersionNumber(JSVersion version)
1531 return JSVersion(uint32(version) & VersionFlags::MASK);
1535 VersionHasXML(JSVersion version)
1537 return !!(version & VersionFlags::HAS_XML);
1540 /* @warning This is a distinct condition from having the XML flag set. */
1542 VersionShouldParseXML(JSVersion version)
1544 return VersionHasXML(version) || VersionNumber(version) >= JSVERSION_1_6;
1548 VersionHasAnonFunFix(JSVersion version)
1550 return !!(version & VersionFlags::ANONFUNFIX);
1554 VersionSetXML(JSVersion *version, bool enable)
1557 *version = JSVersion(uint32(*version) | VersionFlags::HAS_XML);
1559 *version = JSVersion(uint32(*version) & ~VersionFlags::HAS_XML);
1563 VersionSetAnonFunFix(JSVersion *version, bool enable)
1566 *version = JSVersion(uint32(*version) | VersionFlags::ANONFUNFIX);
1568 *version = JSVersion(uint32(*version) & ~VersionFlags::ANONFUNFIX);
1571 static inline JSVersion
1572 VersionExtractFlags(JSVersion version)
1574 return JSVersion(uint32(version) & ~VersionFlags::MASK);
1578 VersionCopyFlags(JSVersion *version, JSVersion from)
1580 *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
1584 VersionHasFlags(JSVersion version)
1586 return !!VersionExtractFlags(version);
1590 VersionFlagsToOptions(JSVersion version)
1592 uintN copts = (VersionHasXML(version) ? JSOPTION_XML : 0) |
1593 (VersionHasAnonFunFix(version) ? JSOPTION_ANONFUNFIX : 0);
1594 JS_ASSERT((copts & JSCOMPILEOPTION_MASK) == copts);
1598 static inline JSVersion
1599 OptionFlagsToVersion(uintN options, JSVersion version)
1601 VersionSetXML(&version, OptionsHasXML(options));
1602 VersionSetAnonFunFix(&version, OptionsHasAnonFunFix(options));
1607 VersionIsKnown(JSVersion version)
1609 return VersionNumber(version) != JSVERSION_UNKNOWN;
1612 typedef js::HashSet<JSObject *,
1613 js::DefaultHasher<JSObject *>,
1614 js::SystemAllocPolicy> BusyArraysMap;
1616 } /* namespace js */
1620 explicit JSContext(JSRuntime *rt);
1622 /* JSRuntime contextList linkage. */
1626 /* See JSContext::findVersion. */
1627 JSVersion defaultVersion; /* script compilation version */
1628 JSVersion versionOverride; /* supercedes defaultVersion when valid */
1629 bool hasVersionOverride;
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 */
1635 /* Per-context run options. */
1636 uintN runOptions; /* see jsapi.h for JSOPTION_* */
1639 /* Locale specific callbacks for string conversion. */
1640 JSLocaleCallbacks *localeCallbacks;
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).
1648 JSDHashTable *resolvingTable;
1651 * True if generating an error, to prevent runaway recursion.
1652 * NB: generatingError packs with throwing below.
1654 JSPackedBool generatingError;
1656 /* Limit pointer for checking native stack consumption during recursion. */
1659 /* Quota on the size of arenas used to compile and execute scripts. */
1660 size_t scriptStackQuota;
1662 /* Data shared by threads in an address space. */
1663 JSRuntime *const runtime;
1665 /* GC heap compartment. */
1666 JSCompartment *compartment;
1668 /* Currently executing frame and regs, set by stack operations. */
1672 /* Current frame accessors. */
1674 JSStackFrame* fp() {
1675 JS_ASSERT(regs && regs->fp);
1679 JSStackFrame* maybefp() {
1680 JS_ASSERT_IF(regs, regs->fp);
1681 return regs ? regs->fp : NULL;
1685 JS_ASSERT_IF(regs, regs->fp);
1690 friend class js::StackSpace;
1691 friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, JSInterpMode);
1693 void resetCompartment();
1694 void wrapPendingException();
1696 /* For grep-ability, changes to 'regs' should call this function. */
1697 void setCurrentRegs(JSFrameRegs *regs) {
1698 JS_ASSERT_IF(regs, regs->fp);
1702 /* Temporary arena pool used while compiling and decompiling. */
1703 JSArenaPool tempPool;
1705 /* Temporary arena pool used while evaluate regular expressions. */
1706 JSArenaPool regExpPool;
1708 /* Top-level object and pointer to top stack frame's scope chain. */
1709 JSObject *globalObject;
1711 /* State for object and array toSource conversion. */
1712 JSSharpObjectMap sharpObjectMap;
1713 js::BusyArraysMap busyArrays;
1715 /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
1716 JSArgumentFormatMap *argumentFormatMap;
1718 /* Last message string and log file for debugging. */
1722 jsbytecode *logPrevPc;
1725 /* Per-context optional error reporter. */
1726 JSErrorReporter errorReporter;
1728 /* Branch callback. */
1729 JSOperationCallback operationCallback;
1731 /* Interpreter activation count. */
1734 /* Client opaque pointers. */
1739 /* Linked list of segments. See StackSegment. */
1740 js::StackSegment *currentSegment;
1743 void assertSegmentsInSync() const {
1746 JS_ASSERT(currentSegment->isActive());
1747 if (js::StackSegment *prev = currentSegment->getPreviousInContext())
1748 JS_ASSERT(!prev->isActive());
1750 JS_ASSERT_IF(currentSegment, !currentSegment->isActive());
1755 /* Return whether this context has an active segment. */
1756 bool hasActiveSegment() const {
1757 assertSegmentsInSync();
1761 /* Assuming there is an active segment, return it. */
1762 js::StackSegment *activeSegment() const {
1763 JS_ASSERT(hasActiveSegment());
1764 return currentSegment;
1767 /* Return the current segment, which may or may not be active. */
1768 js::StackSegment *getCurrentSegment() const {
1769 assertSegmentsInSync();
1770 return currentSegment;
1773 inline js::RegExpStatics *regExpStatics();
1775 /* Add the given segment to the list as the new active segment. */
1776 void pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs ®s);
1778 /* Remove the active segment and make the next segment active. */
1779 void popSegmentAndFrame();
1781 /* Mark the top segment as suspended, without pushing a new one. */
1782 void saveActiveSegment();
1784 /* Undoes calls to suspendActiveSegment. */
1785 void restoreSegment();
1787 /* Get the frame whose prev() is fp, which may be in any segment. */
1788 inline JSStackFrame *computeNextFrame(JSStackFrame *fp);
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.
1794 js::StackSegment *containingSegment(const JSStackFrame *target);
1796 /* Search the call stack for the nearest frame with static level targetLevel. */
1797 JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
1798 JSStackFrame *fp = regs->fp;
1800 JS_ASSERT(fp && fp->isScriptFrame());
1801 if (fp->script()->staticLevel == targetLevel)
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.
1813 bool canSetDefaultVersion() const {
1814 return !regs && !hasVersionOverride;
1817 /* Force a version for future script compilation. */
1818 void overrideVersion(JSVersion newVersion) {
1819 JS_ASSERT(!canSetDefaultVersion());
1820 versionOverride = newVersion;
1821 hasVersionOverride = true;
1824 /* Set the default script compilation version. */
1825 void setDefaultVersion(JSVersion version) {
1826 defaultVersion = version;
1829 void clearVersionOverride() { hasVersionOverride = false; }
1830 JSVersion getDefaultVersion() const { return defaultVersion; }
1831 bool isVersionOverridden() const { return hasVersionOverride; }
1833 JSVersion getVersionOverride() const {
1834 JS_ASSERT(isVersionOverridden());
1835 return versionOverride;
1839 * Set the default version if possible; otherwise, force the version.
1840 * Return whether an override occurred.
1842 bool maybeOverrideVersion(JSVersion newVersion) {
1843 if (canSetDefaultVersion()) {
1844 setDefaultVersion(newVersion);
1847 overrideVersion(newVersion);
1853 * If there is no code currently executing, turn the override version into
1854 * the default version.
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.
1860 void maybeMigrateVersionOverride() {
1861 if (JS_LIKELY(!isVersionOverridden() || currentSegment))
1863 defaultVersion = versionOverride;
1864 clearVersionOverride();
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.
1874 * Note: if this ever shows up in a profile, just add caching!
1876 JSVersion findVersion() const {
1877 if (hasVersionOverride)
1878 return versionOverride;
1881 /* There may be a scripted function somewhere on the stack! */
1882 JSStackFrame *fp = regs->fp;
1883 while (fp && !fp->isScriptFrame())
1886 return fp->script()->getVersion();
1889 return defaultVersion;
1892 void setRunOptions(uintN ropts) {
1893 JS_ASSERT((ropts & JSRUNOPTION_MASK) == ropts);
1897 /* Note: may override the version. */
1898 void setCompileOptions(uintN newcopts) {
1899 JS_ASSERT((newcopts & JSCOMPILEOPTION_MASK) == newcopts);
1900 if (JS_LIKELY(getCompileOptions() == newcopts))
1902 JSVersion version = findVersion();
1903 JSVersion newVersion = js::OptionFlagsToVersion(newcopts, version);
1904 maybeOverrideVersion(newVersion);
1907 uintN getRunOptions() const { return runOptions; }
1908 uintN getCompileOptions() const { return js::VersionFlagsToOptions(findVersion()); }
1909 uintN allOptions() const { return getRunOptions() | getCompileOptions(); }
1911 bool hasRunOption(uintN ropt) const {
1912 JS_ASSERT((ropt & JSRUNOPTION_MASK) == ropt);
1913 return !!(runOptions & ropt);
1916 bool hasStrictOption() const { return hasRunOption(JSOPTION_STRICT); }
1917 bool hasWErrorOption() const { return hasRunOption(JSOPTION_WERROR); }
1918 bool hasAtLineOption() const { return hasRunOption(JSOPTION_ATLINE); }
1920 #ifdef JS_THREADSAFE
1922 unsigned outstandingRequests;/* number of JS_BeginRequest calls
1923 without the corresponding
1925 JSCList threadLinks; /* JSThread contextList linkage */
1927 #define CX_FROM_THREAD_LINKS(tl) \
1928 ((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks)))
1931 /* Stack of thread-stack-allocated GC roots. */
1932 js::AutoGCRooter *autoGCRooters;
1934 /* Debug hooks associated with the current context. */
1935 const JSDebugHooks *debugHooks;
1937 /* Security callbacks that override any defined on the runtime. */
1938 JSSecurityCallbacks *securityCallbacks;
1940 /* Stored here to avoid passing it around as a parameter. */
1943 /* Random number generator state, used by jsmath.cpp. */
1946 /* Location to stash the iteration value between JSOP_MOREITER and JSOP_FOR*. */
1947 js::Value iterValue;
1951 * True if traces may be executed. Invariant: The value of traceJitenabled
1952 * is always equal to the expression in updateJITEnabled below.
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.)
1960 bool traceJitEnabled;
1964 bool methodJitEnabled;
1965 bool profilingEnabled;
1968 /* Caller must be holding runtime->gcLock. */
1969 void updateJITEnabled();
1971 #ifdef MOZ_TRACE_JSCALLS
1972 /* Function entry/exit debugging callback. */
1973 JSFunctionCallback functionCallback;
1975 void doFunctionCallback(const JSFunction *fun,
1976 const JSScript *scr,
1979 if (functionCallback)
1980 functionCallback(fun, scr, this, entering);
1984 DSTOffsetCache dstOffsetCache;
1986 /* List of currently active non-escaping enumerators (for-in). */
1987 JSObject *enumerators;
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.
1996 js::Vector<JSGenerator *, 2, js::SystemAllocPolicy> genStack;
2000 inline js::mjit::JaegerCompartment *jaegerCompartment();
2003 /* Return the generator object for the given generator frame. */
2004 JSGenerator *generatorFor(JSStackFrame *fp) const;
2006 /* Early OOM-check. */
2007 inline bool ensureGeneratorStackSpace();
2009 bool enterGenerator(JSGenerator *gen) {
2010 return genStack.append(gen);
2013 void leaveGenerator(JSGenerator *gen) {
2014 JS_ASSERT(genStack.back() == gen);
2018 #ifdef JS_THREADSAFE
2020 * When non-null JSContext::free delegates the job to the background
2023 js::GCHelperThread *gcBackgroundFree;
2026 inline void* malloc(size_t bytes) {
2027 return runtime->malloc(bytes, this);
2030 inline void* mallocNoReport(size_t bytes) {
2031 JS_ASSERT(bytes != 0);
2032 return runtime->malloc(bytes, NULL);
2035 inline void* calloc(size_t bytes) {
2036 JS_ASSERT(bytes != 0);
2037 return runtime->calloc(bytes, this);
2040 inline void* realloc(void* p, size_t bytes) {
2041 return runtime->realloc(p, bytes, this);
2044 inline void* realloc(void* p, size_t oldBytes, size_t newBytes) {
2045 return runtime->realloc(p, oldBytes, newBytes, this);
2048 inline void free(void* p) {
2049 #ifdef JS_THREADSAFE
2050 if (gcBackgroundFree) {
2051 gcBackgroundFree->freeLater(p);
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.
2063 #define CREATE_BODY(parms) \
2064 void *memory = this->malloc(sizeof(T)); \
2067 return new(memory) T parms;
2070 JS_ALWAYS_INLINE T *create() {
2074 template <class T, class P1>
2075 JS_ALWAYS_INLINE T *create(const P1 &p1) {
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))
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))
2091 JS_ALWAYS_INLINE void destroy(T *p) {
2098 js::StackSpace &stack() const {
2099 return JS_THREAD_DATA(this)->stackSpace;
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()));
2108 void assertValidStackDepth(uintN /*depth*/) {}
2111 bool isExceptionPending() {
2115 js::Value getPendingException() {
2116 JS_ASSERT(throwing);
2120 void setPendingException(js::Value v);
2122 void clearPendingException() {
2123 this->throwing = false;
2124 this->exception.setUndefined();
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.
2134 JS_FRIEND_API(void) checkMallocGCPressure(void *p);
2135 }; /* struct JSContext */
2137 #ifdef JS_THREADSAFE
2138 # define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)
2141 #if defined JS_THREADSAFE && defined DEBUG
2145 class AutoCheckRequestDepth {
2148 AutoCheckRequestDepth(JSContext *cx) : cx(cx) { cx->thread->checkRequestDepth++; }
2150 ~AutoCheckRequestDepth() {
2151 JS_ASSERT(cx->thread->checkRequestDepth != 0);
2152 cx->thread->checkRequestDepth--;
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);
2164 # define CHECK_REQUEST(cx) ((void) 0)
2165 # define CHECK_REQUEST_THREAD(cx) ((void) 0)
2169 FramePCOffset(JSContext *cx, JSStackFrame* fp)
2171 jsbytecode *pc = fp->hasImacropc() ? fp->imacropc() : fp->pc(cx);
2172 return uintN(pc - fp->script()->code);
2175 static inline JSAtom **
2176 FrameAtomBase(JSContext *cx, JSStackFrame *fp)
2178 return fp->hasImacropc()
2179 ? COMMON_ATOMS_START(&cx->runtime->atomState)
2180 : fp->script()->atomMap.vector;
2185 class AutoGCRooter {
2187 AutoGCRooter(JSContext *cx, ptrdiff_t tag)
2188 : down(cx->autoGCRooters), tag(tag), context(cx)
2190 JS_ASSERT(this != cx->autoGCRooters);
2192 cx->autoGCRooters = this;
2196 JS_ASSERT(this == context->autoGCRooters);
2197 CHECK_REQUEST(context);
2198 context->autoGCRooters = down;
2201 /* Implemented in jsgc.cpp. */
2202 inline void trace(JSTracer *trc);
2205 # pragma GCC visibility push(default)
2207 friend JS_FRIEND_API(void) MarkContext(JSTracer *trc, JSContext *acx);
2208 friend void MarkRuntime(JSTracer *trc);
2210 # pragma GCC visibility pop
2214 AutoGCRooter * const down;
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.
2225 JSContext * const context;
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 */
2248 /* No copy or assignment semantics. */
2249 AutoGCRooter(AutoGCRooter &ida);
2250 void operator=(AutoGCRooter &ida);
2253 /* FIXME(bug 332648): Move this into a public header. */
2254 class AutoValueRooter : private AutoGCRooter
2257 explicit AutoValueRooter(JSContext *cx
2258 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2259 : AutoGCRooter(cx, JSVAL), val(js::NullValue())
2261 JS_GUARD_OBJECT_NOTIFIER_INIT;
2264 AutoValueRooter(JSContext *cx, const Value &v
2265 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2266 : AutoGCRooter(cx, JSVAL), val(v)
2268 JS_GUARD_OBJECT_NOTIFIER_INIT;
2271 AutoValueRooter(JSContext *cx, jsval v
2272 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2273 : AutoGCRooter(cx, JSVAL), val(js::Valueify(v))
2275 JS_GUARD_OBJECT_NOTIFIER_INIT;
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.
2285 JS_ASSERT(tag == JSVAL);
2290 JS_ASSERT(tag == JSVAL);
2291 val = js::Valueify(v);
2294 const Value &value() const {
2295 JS_ASSERT(tag == JSVAL);
2300 JS_ASSERT(tag == JSVAL);
2304 const jsval &jsval_value() const {
2305 JS_ASSERT(tag == JSVAL);
2306 return Jsvalify(val);
2309 jsval *jsval_addr() {
2310 JS_ASSERT(tag == JSVAL);
2311 return Jsvalify(&val);
2314 friend void AutoGCRooter::trace(JSTracer *trc);
2315 friend void MarkRuntime(JSTracer *trc);
2319 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2322 class AutoObjectRooter : private AutoGCRooter {
2324 AutoObjectRooter(JSContext *cx, JSObject *obj = NULL
2325 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2326 : AutoGCRooter(cx, OBJECT), obj(obj)
2328 JS_GUARD_OBJECT_NOTIFIER_INIT;
2331 void setObject(JSObject *obj) {
2335 JSObject * object() const {
2339 JSObject ** addr() {
2343 friend void AutoGCRooter::trace(JSTracer *trc);
2344 friend void MarkRuntime(JSTracer *trc);
2348 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2351 class AutoStringRooter : private AutoGCRooter {
2353 AutoStringRooter(JSContext *cx, JSString *str = NULL
2354 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2355 : AutoGCRooter(cx, STRING), str(str)
2357 JS_GUARD_OBJECT_NOTIFIER_INIT;
2360 void setString(JSString *str) {
2364 JSString * string() const {
2368 JSString ** addr() {
2372 friend void AutoGCRooter::trace(JSTracer *trc);
2376 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2379 class AutoArrayRooter : private AutoGCRooter {
2381 AutoArrayRooter(JSContext *cx, size_t len, Value *vec
2382 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2383 : AutoGCRooter(cx, len), array(vec)
2385 JS_GUARD_OBJECT_NOTIFIER_INIT;
2386 JS_ASSERT(tag >= 0);
2389 AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
2390 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2391 : AutoGCRooter(cx, len), array(Valueify(vec))
2393 JS_GUARD_OBJECT_NOTIFIER_INIT;
2394 JS_ASSERT(tag >= 0);
2397 void changeLength(size_t newLength) {
2398 tag = ptrdiff_t(newLength);
2399 JS_ASSERT(tag >= 0);
2402 void changeArray(Value *newArray, size_t newLength) {
2403 changeLength(newLength);
2409 friend void AutoGCRooter::trace(JSTracer *trc);
2412 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2415 class AutoShapeRooter : private AutoGCRooter {
2417 AutoShapeRooter(JSContext *cx, const js::Shape *shape
2418 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2419 : AutoGCRooter(cx, SHAPE), shape(shape)
2421 JS_GUARD_OBJECT_NOTIFIER_INIT;
2424 friend void AutoGCRooter::trace(JSTracer *trc);
2425 friend void MarkRuntime(JSTracer *trc);
2428 const js::Shape * const shape;
2429 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2432 class AutoScriptRooter : private AutoGCRooter {
2434 AutoScriptRooter(JSContext *cx, JSScript *script
2435 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2436 : AutoGCRooter(cx, SCRIPT), script(script)
2438 JS_GUARD_OBJECT_NOTIFIER_INIT;
2441 void setScript(JSScript *script) {
2442 this->script = script;
2445 friend void AutoGCRooter::trace(JSTracer *trc);
2449 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2452 class AutoIdRooter : private AutoGCRooter
2455 explicit AutoIdRooter(JSContext *cx, jsid id = INT_TO_JSID(0)
2456 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2457 : AutoGCRooter(cx, ID), id_(id)
2459 JS_GUARD_OBJECT_NOTIFIER_INIT;
2470 friend void AutoGCRooter::trace(JSTracer *trc);
2471 friend void MarkRuntime(JSTracer *trc);
2475 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2478 class AutoIdArray : private AutoGCRooter {
2480 AutoIdArray(JSContext *cx, JSIdArray *ida JS_GUARD_OBJECT_NOTIFIER_PARAM)
2481 : AutoGCRooter(cx, IDARRAY), idArray(ida)
2483 JS_GUARD_OBJECT_NOTIFIER_INIT;
2487 JS_DestroyIdArray(context, idArray);
2490 return idArray == NULL;
2492 jsid operator[](size_t i) const {
2494 JS_ASSERT(i < size_t(idArray->length));
2495 return idArray->vector[i];
2497 size_t length() const {
2498 return idArray->length;
2501 friend void AutoGCRooter::trace(JSTracer *trc);
2503 JSIdArray *steal() {
2504 JSIdArray *copy = idArray;
2510 inline void trace(JSTracer *trc);
2513 JSIdArray * idArray;
2514 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2516 /* No copy or assignment semantics. */
2517 AutoIdArray(AutoIdArray &ida);
2518 void operator=(AutoIdArray &ida);
2521 /* The auto-root for enumeration object and its state. */
2522 class AutoEnumStateRooter : private AutoGCRooter
2525 AutoEnumStateRooter(JSContext *cx, JSObject *obj
2526 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2527 : AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue()
2529 JS_GUARD_OBJECT_NOTIFIER_INIT;
2533 ~AutoEnumStateRooter() {
2534 if (!stateValue.isNull()) {
2538 obj->enumerate(context, JSENUMERATE_DESTROY, &stateValue, 0);
2543 friend void AutoGCRooter::trace(JSTracer *trc);
2545 const Value &state() const { return stateValue; }
2546 Value *addr() { return &stateValue; }
2549 void trace(JSTracer *trc);
2551 JSObject * const obj;
2555 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2558 #ifdef JS_HAS_XML_SUPPORT
2559 class AutoXMLRooter : private AutoGCRooter {
2561 AutoXMLRooter(JSContext *cx, JSXML *xml
2562 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2563 : AutoGCRooter(cx, XML), xml(xml)
2565 JS_GUARD_OBJECT_NOTIFIER_INIT;
2569 friend void AutoGCRooter::trace(JSTracer *trc);
2570 friend void MarkRuntime(JSTracer *trc);
2574 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2576 #endif /* JS_HAS_XML_SUPPORT */
2578 class AutoBindingsRooter : private AutoGCRooter {
2580 AutoBindingsRooter(JSContext *cx, Bindings &bindings
2581 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2582 : AutoGCRooter(cx, BINDINGS), bindings(bindings)
2584 JS_GUARD_OBJECT_NOTIFIER_INIT;
2587 friend void AutoGCRooter::trace(JSTracer *trc);
2591 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2596 explicit AutoLockGC(JSRuntime *rt
2597 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2600 JS_GUARD_OBJECT_NOTIFIER_INIT;
2603 ~AutoLockGC() { JS_UNLOCK_GC(rt); }
2607 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2610 class AutoUnlockGC {
2613 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2616 explicit AutoUnlockGC(JSRuntime *rt
2617 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2620 JS_GUARD_OBJECT_NOTIFIER_INIT;
2623 ~AutoUnlockGC() { JS_LOCK_GC(rt); }
2626 class AutoLockAtomsCompartment {
2629 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2632 AutoLockAtomsCompartment(JSContext *cx
2633 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2636 JS_GUARD_OBJECT_NOTIFIER_INIT;
2637 JS_LOCK(cx, &cx->runtime->atomState.lock);
2638 #ifdef JS_THREADSAFE
2639 cx->runtime->atomsCompartmentIsLocked = true;
2642 ~AutoLockAtomsCompartment() {
2643 #ifdef JS_THREADSAFE
2644 cx->runtime->atomsCompartmentIsLocked = false;
2646 JS_UNLOCK(cx, &cx->runtime->atomState.lock);
2650 class AutoUnlockAtomsCompartment {
2652 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2655 AutoUnlockAtomsCompartment(JSContext *cx
2656 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2659 JS_GUARD_OBJECT_NOTIFIER_INIT;
2660 #ifdef JS_THREADSAFE
2661 cx->runtime->atomsCompartmentIsLocked = false;
2663 JS_UNLOCK(cx, &cx->runtime->atomState.lock);
2665 ~AutoUnlockAtomsCompartment() {
2666 JS_LOCK(cx, &cx->runtime->atomState.lock);
2667 #ifdef JS_THREADSAFE
2668 cx->runtime->atomsCompartmentIsLocked = true;
2673 class AutoKeepAtoms {
2675 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2678 explicit AutoKeepAtoms(JSRuntime *rt
2679 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2682 JS_GUARD_OBJECT_NOTIFIER_INIT;
2685 ~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
2688 class AutoArenaAllocator {
2691 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2694 explicit AutoArenaAllocator(JSArenaPool *pool
2695 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2696 : pool(pool), mark(JS_ARENA_MARK(pool))
2698 JS_GUARD_OBJECT_NOTIFIER_INIT;
2700 ~AutoArenaAllocator() { JS_ARENA_RELEASE(pool, mark); }
2702 template <typename T>
2703 T *alloc(size_t elems) {
2705 JS_ARENA_ALLOCATE(ptr, pool, elems * sizeof(T));
2706 return static_cast<T *>(ptr);
2710 class AutoReleasePtr {
2713 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2715 AutoReleasePtr operator=(const AutoReleasePtr &other);
2718 explicit AutoReleasePtr(JSContext *cx, void *ptr
2719 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2722 JS_GUARD_OBJECT_NOTIFIER_INIT;
2724 ~AutoReleasePtr() { cx->free(ptr); }
2728 * FIXME: bug 602774: cleaner API for AutoReleaseNullablePtr
2730 class AutoReleaseNullablePtr {
2733 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2735 AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other);
2738 explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr
2739 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2742 JS_GUARD_OBJECT_NOTIFIER_INIT;
2744 void reset(void *ptr2) {
2749 ~AutoReleaseNullablePtr() { if (ptr) cx->free(ptr); }
2752 class AutoLocalNameArray {
2754 explicit AutoLocalNameArray(JSContext *cx, JSFunction *fun
2755 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2757 mark(JS_ARENA_MARK(&cx->tempPool)),
2758 names(fun->script()->bindings.getLocalNameArray(cx, &cx->tempPool)),
2759 count(fun->script()->bindings.countLocalNames())
2761 JS_GUARD_OBJECT_NOTIFIER_INIT;
2764 ~AutoLocalNameArray() {
2765 JS_ARENA_RELEASE(&context->tempPool, mark);
2768 operator bool() const { return !!names; }
2770 uint32 length() const { return count; }
2772 const jsuword &operator [](unsigned i) const { return names[i]; }
2780 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2783 template <class RefCountable>
2784 class AlreadyIncRefed
2786 typedef RefCountable *****ConvertibleToBool;
2791 explicit AlreadyIncRefed(RefCountable *obj) : obj(obj) {}
2793 bool null() const { return obj == NULL; }
2794 operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2796 RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2797 RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2798 RefCountable *get() const { return obj; }
2801 template <class RefCountable>
2804 typedef RefCountable *****ConvertibleToBool;
2809 explicit NeedsIncRef(RefCountable *obj) : obj(obj) {}
2811 bool null() const { return obj == NULL; }
2812 operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2814 RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2815 RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2816 RefCountable *get() const { return obj; }
2819 template <class RefCountable>
2822 typedef RefCountable *****ConvertibleToBool;
2824 JSContext *const cx;
2827 AutoRefCount(const AutoRefCount &);
2828 void operator=(const AutoRefCount &);
2831 explicit AutoRefCount(JSContext *cx)
2835 AutoRefCount(JSContext *cx, NeedsIncRef<RefCountable> aobj)
2836 : cx(cx), obj(aobj.get())
2842 AutoRefCount(JSContext *cx, AlreadyIncRefed<RefCountable> aobj)
2843 : cx(cx), obj(aobj.get())
2851 void reset(NeedsIncRef<RefCountable> aobj) {
2859 void reset(AlreadyIncRefed<RefCountable> aobj) {
2865 bool null() const { return obj == NULL; }
2866 operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2868 RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2869 RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2870 RefCountable *get() const { return obj; }
2873 } /* namespace js */
2875 class JSAutoResolveFlags
2878 JSAutoResolveFlags(JSContext *cx, uintN flags
2879 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2880 : mContext(cx), mSaved(cx->resolveFlags)
2882 JS_GUARD_OBJECT_NOTIFIER_INIT;
2883 cx->resolveFlags = flags;
2886 ~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; }
2889 JSContext *mContext;
2891 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2894 extern JSThreadData *
2895 js_CurrentThreadData(JSRuntime *rt);
2898 js_InitThreads(JSRuntime *rt);
2901 js_FinishThreads(JSRuntime *rt);
2904 js_PurgeThreads(JSContext *cx);
2908 #ifdef JS_THREADSAFE
2910 /* Iterator over JSThreadData from all JSThread instances. */
2911 class ThreadDataIter : public JSThread::Map::Range
2914 ThreadDataIter(JSRuntime *rt) : JSThread::Map::Range(rt->threads.all()) {}
2916 JSThreadData *threadData() const {
2917 return &front().value->data;
2921 #else /* !JS_THREADSAFE */
2923 class ThreadDataIter
2928 ThreadDataIter(JSRuntime *rt) : runtime(rt), done(false) {}
2930 bool empty() const {
2939 JSThreadData *threadData() const {
2941 return &runtime->threadData;
2945 #endif /* !JS_THREADSAFE */
2947 } /* namespace js */
2950 * Create and destroy functions for JSContext, which is manually allocated
2951 * and exclusively owned.
2954 js_NewContext(JSRuntime *rt, size_t stackChunkSize);
2957 js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
2959 static JS_INLINE JSContext *
2960 js_ContextFromLinkField(JSCList *link)
2963 return (JSContext *) ((uint8 *) link - offsetof(JSContext, link));
2967 * If unlocked, acquire and release rt->gcLock around *iterp update; otherwise
2968 * the caller must be holding rt->gcLock.
2971 js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
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.
2978 extern JS_FRIEND_API(JSContext *)
2979 js_NextActiveContext(JSRuntime *, JSContext *);
2982 * Class.resolve and watchpoint recursion damping machinery.
2985 js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
2986 JSResolvingEntry **entryp);
2989 js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
2990 JSResolvingEntry *entry, uint32 generation);
2993 * Report an exception, which is currently realized as a printf-style format
2994 * string and its arguments.
2996 typedef enum JSErrNum {
2997 #define MSG_DEF(name, number, count, exception, format) \
3004 extern JS_FRIEND_API(const JSErrorFormatString *)
3005 js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
3009 js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
3012 js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
3013 void *userRef, const uintN errorNumber,
3014 JSBool charArgs, va_list ap);
3017 js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
3018 void *userRef, const uintN errorNumber,
3019 char **message, JSErrorReport *reportp,
3020 bool charArgs, va_list ap);
3024 js_ReportOutOfMemory(JSContext *cx);
3027 * Report that cx->scriptStackQuota is exhausted.
3030 js_ReportOutOfScriptQuota(JSContext *cx);
3032 extern JS_FRIEND_API(void)
3033 js_ReportOverRecursed(JSContext *cx);
3035 extern JS_FRIEND_API(void)
3036 js_ReportAllocationOverflow(JSContext *cx);
3038 #define JS_CHECK_RECURSION(cx, onerror) \
3042 if (!JS_CHECK_STACK_SIZE(cx->stackLimit, &stackDummy_)) { \
3043 js_ReportOverRecursed(cx); \
3049 * Report an exception using a previously composed JSErrorReport.
3050 * XXXbe remove from "friend" API
3052 extern JS_FRIEND_API(void)
3053 js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
3056 js_ReportIsNotDefined(JSContext *cx, const char *name);
3059 * Report an attempt to access the property of a null or undefined value (v).
3062 js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const js::Value &v,
3063 JSString *fallback);
3066 js_ReportMissingArg(JSContext *cx, const js::Value &v, uintN arg);
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.
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);
3078 #define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
3079 ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
3080 spindex, v, fallback, NULL, NULL))
3082 #define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1) \
3083 ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
3084 spindex, v, fallback, arg1, NULL))
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))
3090 extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
3092 #ifdef JS_THREADSAFE
3093 # define JS_ASSERT_REQUEST_DEPTH(cx) (JS_ASSERT((cx)->thread), \
3094 JS_ASSERT((cx)->thread->data.requestDepth >= 1))
3096 # define JS_ASSERT_REQUEST_DEPTH(cx) ((void) 0)
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
3104 #define JS_CHECK_OPERATION_LIMIT(cx) \
3105 (JS_ASSERT_REQUEST_DEPTH(cx), \
3106 (!JS_THREAD_DATA(cx)->interruptFlags || js_InvokeOperationCallback(cx)))
3108 JS_ALWAYS_INLINE void
3109 JSThreadData::triggerOperationCallback(JSRuntime *rt)
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.
3119 JS_ATOMIC_SET(&interruptFlags, 1);
3121 #ifdef JS_THREADSAFE
3122 /* rt->interruptCounter does not reflect suspended threads. */
3123 if (requestDepth != 0)
3124 JS_ATOMIC_INCREMENT(&rt->interruptCounter);
3129 * Invoke the operation callback and return false if the current execution
3130 * is to be terminated.
3133 js_InvokeOperationCallback(JSContext *cx);
3136 js_HandleExecutionInterrupt(JSContext *cx);
3140 /* These must be called with GC lock taken. */
3143 TriggerOperationCallback(JSContext *cx);
3146 TriggerAllOperationCallbacks(JSRuntime *rt);
3148 } /* namespace js */
3150 extern JSStackFrame *
3151 js_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
3154 js_GetCurrentBytecodePC(JSContext* cx);
3157 js_CurrentPCIsInImacro(JSContext *cx);
3161 class RegExpStatics;
3163 extern JS_FORCES_STACK JS_FRIEND_API(void)
3164 LeaveTrace(JSContext *cx);
3166 } /* namespace js */
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.)
3172 * Defined in jstracer.cpp if JS_TRACER is defined.
3174 static JS_FORCES_STACK JS_INLINE JSStackFrame *
3175 js_GetTopStackFrame(JSContext *cx)
3178 return cx->maybefp();
3181 static JS_INLINE JSBool
3182 js_IsPropertyCacheDisabled(JSContext *cx)
3184 return cx->runtime->shapeGen >= js::SHAPE_OVERFLOW_BIT;
3187 static JS_INLINE uint32
3188 js_RegenerateShapeForGC(JSRuntime *rt)
3190 JS_ASSERT(rt->gcRunning);
3191 JS_ASSERT(rt->gcRegenShapes);
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.
3198 uint32 shape = rt->shapeGen;
3199 shape = (shape + 1) | (shape & js::SHAPE_OVERFLOW_BIT);
3200 rt->shapeGen = shape;
3207 ContextAllocPolicy::malloc(size_t bytes)
3209 return cx->malloc(bytes);
3213 ContextAllocPolicy::free(void *p)
3219 ContextAllocPolicy::realloc(void *p, size_t bytes)
3221 return cx->realloc(p, bytes);
3225 ContextAllocPolicy::reportAllocOverflow() const
3227 js_ReportAllocationOverflow(cx);
3231 class AutoVectorRooter : protected AutoGCRooter
3234 explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
3235 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3236 : AutoGCRooter(cx, tag), vector(cx)
3238 JS_GUARD_OBJECT_NOTIFIER_INIT;
3241 size_t length() const { return vector.length(); }
3243 bool append(const T &v) { return vector.append(v); }
3245 void popBack() { vector.popBack(); }
3247 bool growBy(size_t inc) {
3248 size_t oldLength = vector.length();
3249 if (!vector.growByUninitialized(inc))
3251 MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
3255 bool resize(size_t newLength) {
3256 size_t oldLength = vector.length();
3257 if (newLength <= oldLength) {
3258 vector.shrinkBy(oldLength - newLength);
3261 if (!vector.growByUninitialized(newLength - oldLength))
3263 MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
3267 bool reserve(size_t newLength) {
3268 return vector.reserve(newLength);
3271 T &operator[](size_t i) { return vector[i]; }
3272 const T &operator[](size_t i) const { return vector[i]; }
3274 const T *begin() const { return vector.begin(); }
3275 T *begin() { return vector.begin(); }
3277 const T *end() const { return vector.end(); }
3278 T *end() { return vector.end(); }
3280 const T &back() const { return vector.back(); }
3282 friend void AutoGCRooter::trace(JSTracer *trc);
3285 Vector<T, 8> vector;
3286 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3289 class AutoValueVector : public AutoVectorRooter<Value>
3292 explicit AutoValueVector(JSContext *cx
3293 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3294 : AutoVectorRooter<Value>(cx, VALVECTOR)
3296 JS_GUARD_OBJECT_NOTIFIER_INIT;
3299 const jsval *jsval_begin() const { return Jsvalify(begin()); }
3300 jsval *jsval_begin() { return Jsvalify(begin()); }
3302 const jsval *jsval_end() const { return Jsvalify(end()); }
3303 jsval *jsval_end() { return Jsvalify(end()); }
3305 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3308 class AutoIdVector : public AutoVectorRooter<jsid>
3311 explicit AutoIdVector(JSContext *cx
3312 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3313 : AutoVectorRooter<jsid>(cx, IDVECTOR)
3315 JS_GUARD_OBJECT_NOTIFIER_INIT;
3318 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3321 class AutoShapeVector : public AutoVectorRooter<const Shape *>
3324 explicit AutoShapeVector(JSContext *cx
3325 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3326 : AutoVectorRooter<const Shape *>(cx, SHAPEVECTOR)
3328 JS_GUARD_OBJECT_NOTIFIER_INIT;
3331 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3335 NewIdArray(JSContext *cx, jsint length);
3337 } /* namespace js */
3340 #pragma warning(pop)
3341 #pragma warning(pop)
3344 #ifdef JS_CNTXT_UNDEFD_MOZALLOC_WRAPPERS
3345 # include "mozilla/mozalloc_macro_wrappers.h"
3348 #endif /* jscntxt_h___ */