CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / js / src / jscntxt.h
blob6dc627e4a1297514ab9634e12ebfda02549e1093
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
15 * License.
17 * The Original Code is Mozilla Communicator client code, released
18 * March 31, 1998.
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.
25 * Contributor(s):
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 ***** */
41 #ifndef jscntxt_h___
42 #define jscntxt_h___
44 * JS execution context.
46 #include <string.h>
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
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"
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
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 {
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;
104 #define js_FinishGSNCache(cache) js_PurgeGSNCache(cache)
106 extern void
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. */
114 namespace nanojit {
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;
123 } /* namespace nanojit */
125 namespace js {
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. */
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;
148 #if defined(JS_JIT_SPEW) || defined(DEBUG)
149 struct FragPI;
150 typedef nanojit::HashMap<uint32, FragPI, nanojit::DefaultHash<uint32> > FragStatsMap;
151 #endif
153 namespace mjit {
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
165 JSContext *cx;
167 public:
168 ContextAllocPolicy(JSContext *cx) : cx(cx) {}
169 JSContext *context() const { return cx; }
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;
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
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.
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.
225 class StackSegment
227 /* The context to which this segment belongs. */
228 JSContext *cx;
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. */
246 bool saved;
248 /* Align at 8 bytes on all platforms. */
249 #if JS_BITS_PER_WORD == 32
250 void *padding;
251 #endif
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)
259 public:
260 StackSegment()
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);
288 return cx;
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());
307 return saved;
310 /* Transitioning between inContext <--> isActive */
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());
320 void leaveContext() {
321 JS_ASSERT(isActive());
322 this->cx = NULL;
323 initialFrame = NULL;
324 suspendedRegs = NON_NULL_SUSPENDED_REGS;
325 JS_ASSERT(!inContext());
328 JSContext *maybeContext() const {
329 return cx;
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());
343 void resume() {
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());
353 suspend(regs);
354 saved = true;
355 JS_ASSERT(isSaved());
358 void restore() {
359 JS_ASSERT(isSaved());
360 saved = false;
361 resume();
362 JS_ASSERT(!isSuspended());
365 /* Data available when inContext */
367 JSStackFrame *getInitialFrame() const {
368 JS_ASSERT(inContext());
369 return initialFrame;
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());
406 initialVarObj = obj;
409 bool hasInitialVarObj() {
410 JS_ASSERT(inContext());
411 return initialVarObj != NULL;
414 JSObject &getInitialVarObj() const {
415 JS_ASSERT(inContext() && initialVarObj);
416 return *initialVarObj;
419 #ifdef DEBUG
420 JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
421 #endif
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 */
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; }
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 */
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 void pop();
465 JSStackFrame *fp() const { return regs_.fp; }
468 /* Reusable base; not for direct use. */
469 class FrameGuard
471 friend class StackSpace;
472 JSContext *cx_; /* null implies nothing pushed */
473 StackSegment *seg_;
474 Value *vp_;
475 JSStackFrame *fp_;
476 public:
477 FrameGuard() : cx_(NULL), vp_(NULL), fp_(NULL) {}
478 JS_REQUIRES_STACK ~FrameGuard();
479 bool pushed() const { return cx_ != NULL; }
480 StackSegment *segment() const { return seg_; }
481 Value *vp() const { return vp_; }
482 JSStackFrame *fp() const { return fp_; }
485 /* See StackSpace::pushExecuteFrame. */
486 class ExecuteFrameGuard : public FrameGuard
488 friend class StackSpace;
489 JSFrameRegs regs_;
492 /* See StackSpace::pushDummyFrame. */
493 class DummyFrameGuard : public FrameGuard
495 friend class StackSpace;
496 JSFrameRegs regs_;
499 /* See StackSpace::pushGeneratorFrame. */
500 class GeneratorFrameGuard : public FrameGuard
504 * Stack layout
506 * Each JSThreadData has one associated StackSpace object which allocates all
507 * segments for the thread. StackSpace performs all such allocations in a
508 * single, fixed-size buffer using a specific layout scheme that allows some
509 * associations between segments, frames, and slots to be implicit, rather
510 * than explicitly stored as pointers. To maintain useful invariants, stack
511 * space is not given out arbitrarily, but rather allocated/deallocated for
512 * specific purposes. The use cases currently supported are: calling a function
513 * with arguments (e.g. Invoke), executing a script (e.g. Execute), inline
514 * interpreter calls, and pushing "dummy" frames for bookkeeping purposes. See
515 * associated member functions below.
517 * First, we consider the layout of individual segments. (See the
518 * js::StackSegment comment for terminology.) A non-empty segment (i.e., a
519 * segment in a context) has the following layout:
521 * initial frame current frame ------. if regs,
522 * .------------. | | regs->sp
523 * | V V V
524 * |segment| slots |frame| slots |frame| slots |frame| slots |
525 * | ^ | ^ |
526 * ? <----------' `----------' `----------'
527 * prev prev prev
529 * Moreover, the bytes in the following ranges form a contiguous array of
530 * Values that are marked during GC:
531 * 1. between a segment and its first frame
532 * 2. between two adjacent frames in a segment
533 * 3. between a segment's current frame and (if fp->regs) fp->regs->sp
534 * Thus, the VM must ensure that all such Values are safe to be marked.
536 * An empty segment is followed by arguments that are rooted by the
537 * StackSpace::invokeArgEnd pointer:
539 * invokeArgEnd
542 * |segment| slots |
544 * Above the level of segments, a StackSpace is simply a contiguous sequence
545 * of segments kept in a linked list:
547 * base currentSegment firstUnused end
548 * | | | |
549 * V V V V
550 * |segment| --- |segment| --- |segment| ------- | |
551 * | ^ | ^ |
552 * 0 <---' `-----------' `-----------'
553 * previous previous previous
555 * Both js::StackSpace and JSContext maintain a stack of segments, the top of
556 * which is the "current segment" for that thread or context, respectively.
557 * Since different contexts can arbitrarily interleave execution in a single
558 * thread, these stacks are different enough that a segment needs both
559 * "previousInMemory" and "previousInContext".
561 * For example, in a single thread, a function in segment S1 in a context CX1
562 * may call out into C++ code that reenters the VM in a context CX2, which
563 * creates a new segment S2 in CX2, and CX1 may or may not equal CX2.
565 * Note that there is some structure to this interleaving of segments:
566 * 1. the inclusion from segments in a context to segments in a thread
567 * preserves order (in terms of previousInContext and previousInMemory,
568 * respectively).
569 * 2. the mapping from stack frames to their containing segment preserves
570 * order (in terms of prev and previousInContext, respectively).
572 class StackSpace
574 Value *base;
575 #ifdef XP_WIN
576 mutable Value *commitEnd;
577 #endif
578 Value *end;
579 StackSegment *currentSegment;
580 #ifdef DEBUG
582 * Keep track of which segment/frame bumped invokeArgEnd so that
583 * firstUnused() can assert that, when invokeArgEnd is used as the top of
584 * the stack, it is being used appropriately.
586 StackSegment *invokeSegment;
587 JSStackFrame *invokeFrame;
588 #endif
589 Value *invokeArgEnd;
591 friend class InvokeArgsGuard;
592 friend class InvokeFrameGuard;
593 friend class FrameGuard;
595 bool pushSegmentForInvoke(JSContext *cx, uintN argc, InvokeArgsGuard *ag);
596 void popSegmentForInvoke(const InvokeArgsGuard &ag);
598 bool pushInvokeFrameSlow(JSContext *cx, const InvokeArgsGuard &ag,
599 InvokeFrameGuard *fg);
600 void popInvokeFrameSlow(const CallArgs &args);
602 bool getSegmentAndFrame(JSContext *cx, uintN vplen, uintN nslots,
603 FrameGuard *fg) const;
604 void pushSegmentAndFrame(JSContext *cx, JSFrameRegs *regs, FrameGuard *fg);
605 void popSegmentAndFrame(JSContext *cx);
607 struct EnsureSpaceCheck {
608 inline bool operator()(const StackSpace &, JSContext *, Value *, uintN);
611 struct LimitCheck {
612 JSStackFrame *base;
613 Value **limit;
614 LimitCheck(JSStackFrame *base, Value **limit) : base(base), limit(limit) {}
615 inline bool operator()(const StackSpace &, JSContext *, Value *, uintN);
618 template <class Check>
619 inline JSStackFrame *getCallFrame(JSContext *cx, Value *sp, uintN nactual,
620 JSFunction *fun, JSScript *script,
621 uint32 *pflags, Check check) const;
623 inline void popInvokeArgs(const InvokeArgsGuard &args);
624 inline void popInvokeFrame(const InvokeFrameGuard &ag);
626 inline Value *firstUnused() const;
628 inline bool isCurrentAndActive(JSContext *cx) const;
629 friend class AllFramesIter;
630 StackSegment *getCurrentSegment() const { return currentSegment; }
632 #ifdef XP_WIN
633 /* Commit more memory from the reserved stack space. */
634 JS_FRIEND_API(bool) bumpCommit(Value *from, ptrdiff_t nvals) const;
635 #endif
637 public:
638 static const size_t CAPACITY_VALS = 512 * 1024;
639 static const size_t CAPACITY_BYTES = CAPACITY_VALS * sizeof(Value);
640 static const size_t COMMIT_VALS = 16 * 1024;
641 static const size_t COMMIT_BYTES = COMMIT_VALS * sizeof(Value);
644 * SunSpider and v8bench have roughly an average of 9 slots per script.
645 * Our heuristic for a quick over-recursion check uses a generous slot
646 * count based on this estimate. We take this frame size and multiply it
647 * by the old recursion limit from the interpreter.
649 * Worst case, if an average size script (<=9 slots) over recurses, it'll
650 * effectively be the same as having increased the old inline call count
651 * to <= 5,000.
653 static const size_t STACK_QUOTA = (VALUES_PER_STACK_FRAME + 18) *
654 JS_MAX_INLINE_CALL_COUNT;
656 /* Kept as a member of JSThreadData; cannot use constructor/destructor. */
657 bool init();
658 void finish();
660 #ifdef DEBUG
661 template <class T>
662 bool contains(T *t) const {
663 char *v = (char *)t;
664 JS_ASSERT(size_t(-1) - uintptr_t(t) >= sizeof(T));
665 return v >= (char *)base && v + sizeof(T) <= (char *)end;
667 #endif
670 * When we LeaveTree, we need to rebuild the stack, which requires stack
671 * allocation. There is no good way to handle an OOM for these allocations,
672 * so this function checks that they cannot occur using the size of the
673 * TraceNativeStorage as a conservative upper bound.
675 inline bool ensureEnoughSpaceToEnterTrace();
677 /* +1 for slow native's stack frame. */
678 static const ptrdiff_t MAX_TRACE_SPACE_VALS =
679 MAX_NATIVE_STACK_SLOTS + MAX_CALL_STACK_ENTRIES * VALUES_PER_STACK_FRAME +
680 (VALUES_PER_STACK_SEGMENT + VALUES_PER_STACK_FRAME /* synthesized slow native */);
682 /* Mark all segments, frames, and slots on the stack. */
683 JS_REQUIRES_STACK void mark(JSTracer *trc);
686 * For all five use cases below:
687 * - The boolean-valued functions call js_ReportOutOfScriptQuota on OOM.
688 * - The "get*Frame" functions do not change any global state, they just
689 * check OOM and return pointers to an uninitialized frame with the
690 * requested missing arguments/slots. Only once the "push*Frame"
691 * function has been called is global state updated. Thus, between
692 * "get*Frame" and "push*Frame", the frame and slots are unrooted.
693 * - The "push*Frame" functions will set fp->prev; the caller needn't.
694 * - Functions taking "*Guard" arguments will use the guard's destructor
695 * to pop the allocation. The caller must ensure the guard has the
696 * appropriate lifetime.
697 * - The get*Frame functions put the 'nmissing' slots contiguously after
698 * the arguments.
702 * pushInvokeArgs allocates |argc + 2| rooted values that will be passed as
703 * the arguments to Invoke. A single allocation can be used for multiple
704 * Invoke calls. The InvokeArgumentsGuard passed to Invoke must come from
705 * an immediately-enclosing (stack-wise) call to pushInvokeArgs.
707 bool pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *ag);
709 /* These functions are called inside Invoke, not Invoke clients. */
710 bool getInvokeFrame(JSContext *cx, const CallArgs &args, JSFunction *fun,
711 JSScript *script, uint32 *flags, InvokeFrameGuard *fg) const;
713 void pushInvokeFrame(JSContext *cx, const CallArgs &args, InvokeFrameGuard *fg);
715 /* These functions are called inside Execute, not Execute clients. */
716 bool getExecuteFrame(JSContext *cx, JSScript *script, ExecuteFrameGuard *fg) const;
717 void pushExecuteFrame(JSContext *cx, JSObject *initialVarObj, ExecuteFrameGuard *fg);
720 * Since RAII cannot be used for inline frames, callers must manually
721 * call pushInlineFrame/popInlineFrame.
723 inline JSStackFrame *getInlineFrame(JSContext *cx, Value *sp, uintN nactual,
724 JSFunction *fun, JSScript *script,
725 uint32 *flags) const;
726 inline void pushInlineFrame(JSContext *cx, JSScript *script, JSStackFrame *fp,
727 JSFrameRegs *regs);
728 inline void popInlineFrame(JSContext *cx, JSStackFrame *prev, js::Value *newsp);
730 /* These functions are called inside SendToGenerator. */
731 bool getGeneratorFrame(JSContext *cx, uintN vplen, uintN nslots,
732 GeneratorFrameGuard *fg);
733 void pushGeneratorFrame(JSContext *cx, JSFrameRegs *regs, GeneratorFrameGuard *fg);
735 /* Pushes a JSStackFrame::isDummyFrame. */
736 bool pushDummyFrame(JSContext *cx, JSObject &scopeChain, DummyFrameGuard *fg);
738 /* Check and bump the given stack limit. */
739 inline JSStackFrame *getInlineFrameWithinLimit(JSContext *cx, Value *sp, uintN nactual,
740 JSFunction *fun, JSScript *script, uint32 *flags,
741 JSStackFrame *base, Value **limit) const;
744 * Compute a stack limit for entering method jit code which allows the
745 * method jit to check for end-of-stack and over-recursion with a single
746 * comparison. See STACK_QUOTA above.
748 inline Value *getStackLimit(JSContext *cx);
751 * Try to bump the given 'limit' by bumping the commit limit. Return false
752 * if fully committed or if 'limit' exceeds 'base' + STACK_QUOTA.
754 bool bumpCommitAndLimit(JSStackFrame *base, Value *from, uintN nvals, Value **limit) const;
757 * Allocate nvals on the top of the stack, report error on failure.
758 * N.B. the caller must ensure |from >= firstUnused()|.
760 inline bool ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const;
763 JS_STATIC_ASSERT(StackSpace::CAPACITY_VALS % StackSpace::COMMIT_VALS == 0);
766 * While |cx->fp|'s pc/sp are available in |cx->regs|, to compute the saved
767 * value of pc/sp for any other frame, it is necessary to know about that
768 * frame's next-frame. This iterator maintains this information when walking
769 * a chain of stack frames starting at |cx->fp|.
771 * Usage:
772 * for (FrameRegsIter i(cx); !i.done(); ++i)
773 * ... i.fp() ... i.sp() ... i.pc()
775 class FrameRegsIter
777 JSContext *cx;
778 StackSegment *curseg;
779 JSStackFrame *curfp;
780 Value *cursp;
781 jsbytecode *curpc;
783 void initSlow();
784 void incSlow(JSStackFrame *fp, JSStackFrame *prev);
786 public:
787 JS_REQUIRES_STACK inline FrameRegsIter(JSContext *cx);
789 bool done() const { return curfp == NULL; }
790 inline FrameRegsIter &operator++();
792 JSStackFrame *fp() const { return curfp; }
793 Value *sp() const { return cursp; }
794 jsbytecode *pc() const { return curpc; }
798 * Utility class for iteration over all active stack frames.
800 class AllFramesIter
802 public:
803 AllFramesIter(JSContext *cx);
805 bool done() const { return curfp == NULL; }
806 AllFramesIter& operator++();
808 JSStackFrame *fp() const { return curfp; }
810 private:
811 StackSegment *curcs;
812 JSStackFrame *curfp;
815 } /* namespace js */
817 #ifdef DEBUG
818 # define FUNCTION_KIND_METER_LIST(_) \
819 _(allfun), _(heavy), _(nofreeupvar), _(onlyfreevar), \
820 _(flat), _(badfunarg), \
821 _(joinedsetmethod), _(joinedinitmethod), \
822 _(joinedreplace), _(joinedsort), _(joinedmodulepat), \
823 _(mreadbarrier), _(mwritebarrier), _(mwslotbarrier), \
824 _(unjoined), _(indynamicscope)
825 # define identity(x) x
827 struct JSFunctionMeter {
828 int32 FUNCTION_KIND_METER_LIST(identity);
831 # undef identity
833 # define JS_FUNCTION_METER(cx,x) JS_RUNTIME_METER((cx)->runtime, functionMeter.x)
834 #else
835 # define JS_FUNCTION_METER(cx,x) ((void)0)
836 #endif
839 struct JSPendingProxyOperation {
840 JSPendingProxyOperation *next;
841 JSObject *object;
844 struct JSThreadData {
845 #ifdef JS_THREADSAFE
846 /* The request depth for this thread. */
847 unsigned requestDepth;
848 #endif
850 #ifdef JS_TRACER
852 * During trace execution (or during trace recording or
853 * profiling), these fields point to the compartment doing the
854 * execution on this thread. At other times, they are NULL. If a
855 * thread tries to execute/record/profile one trace while another
856 * is still running, the initial one will abort. Therefore, we
857 * only need to track one at a time.
859 JSCompartment *onTraceCompartment;
860 JSCompartment *recordingCompartment;
861 JSCompartment *profilingCompartment;
862 #endif
865 * If non-zero, we were been asked to call the operation callback as soon
866 * as possible. If the thread has an active request, this contributes
867 * towards rt->interruptCounter.
869 volatile int32 interruptFlags;
871 /* Keeper of the contiguous stack used by all contexts in this thread. */
872 js::StackSpace stackSpace;
875 * Flag indicating that we are waiving any soft limits on the GC heap
876 * because we want allocations to be infallible (except when we hit OOM).
878 bool waiveGCQuota;
881 * The GSN cache is per thread since even multi-cx-per-thread embeddings
882 * do not interleave js_GetSrcNote calls.
884 JSGSNCache gsnCache;
886 /* Property cache for faster call/get/set invocation. */
887 js::PropertyCache propertyCache;
889 #ifdef JS_TRACER
890 /* Maximum size of the tracer's code cache before we start flushing. */
891 uint32 maxCodeCacheBytes;
892 #endif
894 /* State used by dtoa.c. */
895 DtoaState *dtoaState;
897 /* Base address of the native stack for the current thread. */
898 jsuword *nativeStackBase;
900 /* List of currently pending operations on proxies. */
901 JSPendingProxyOperation *pendingProxyOperation;
903 js::ConservativeGCThreadData conservativeGC;
905 bool init();
906 void finish();
907 void mark(JSTracer *trc);
908 void purge(JSContext *cx);
910 /* This must be called with the GC lock held. */
911 inline void triggerOperationCallback(JSRuntime *rt);
914 #ifdef JS_THREADSAFE
917 * Structure uniquely representing a thread. It holds thread-private data
918 * that can be accessed without a global lock.
920 struct JSThread {
921 typedef js::HashMap<void *,
922 JSThread *,
923 js::DefaultHasher<void *>,
924 js::SystemAllocPolicy> Map;
926 /* Linked list of all contexts in use on this thread. */
927 JSCList contextList;
929 /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
930 void *id;
932 /* Number of JS_SuspendRequest calls withot JS_ResumeRequest. */
933 unsigned suspendCount;
935 # ifdef DEBUG
936 unsigned checkRequestDepth;
937 # endif
939 /* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */
940 JSThreadData data;
943 #define JS_THREAD_DATA(cx) (&(cx)->thread->data)
945 extern JSThread *
946 js_CurrentThread(JSRuntime *rt);
949 * The function takes the GC lock and does not release in successful return.
950 * On error (out of memory) the function releases the lock but delegates
951 * the error reporting to the caller.
953 extern JSBool
954 js_InitContextThread(JSContext *cx);
957 * On entrance the GC lock must be held and it will be held on exit.
959 extern void
960 js_ClearContextThread(JSContext *cx);
962 #endif /* JS_THREADSAFE */
964 typedef enum JSDestroyContextMode {
965 JSDCM_NO_GC,
966 JSDCM_MAYBE_GC,
967 JSDCM_FORCE_GC,
968 JSDCM_NEW_FAILED
969 } JSDestroyContextMode;
971 typedef enum JSRuntimeState {
972 JSRTS_DOWN,
973 JSRTS_LAUNCHING,
974 JSRTS_UP,
975 JSRTS_LANDING
976 } JSRuntimeState;
978 typedef struct JSPropertyTreeEntry {
979 JSDHashEntryHdr hdr;
980 js::Shape *child;
981 } JSPropertyTreeEntry;
983 typedef void
984 (* JSActivityCallback)(void *arg, JSBool active);
986 namespace js {
988 typedef js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> WrapperVector;
992 struct JSRuntime {
993 /* Default compartment. */
994 JSCompartment *atomsCompartment;
995 #ifdef JS_THREADSAFE
996 bool atomsCompartmentIsLocked;
997 #endif
999 /* List of compartments (protected by the GC lock). */
1000 js::WrapperVector compartments;
1002 /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
1003 JSRuntimeState state;
1005 /* Context create/destroy callback. */
1006 JSContextCallback cxCallback;
1008 /* Compartment create/destroy callback. */
1009 JSCompartmentCallback compartmentCallback;
1012 * Sets a callback that is run whenever the runtime goes idle - the
1013 * last active request ceases - and begins activity - when it was
1014 * idle and a request begins. Note: The callback is called under the
1015 * GC lock.
1017 void setActivityCallback(JSActivityCallback cb, void *arg) {
1018 activityCallback = cb;
1019 activityCallbackArg = arg;
1022 JSActivityCallback activityCallback;
1023 void *activityCallbackArg;
1026 * Shape regenerated whenever a prototype implicated by an "add property"
1027 * property cache fill and induced trace guard has a readonly property or a
1028 * setter defined on it. This number proxies for the shapes of all objects
1029 * along the prototype chain of all objects in the runtime on which such an
1030 * add-property result has been cached/traced.
1032 * See bug 492355 for more details.
1034 * This comes early in JSRuntime to minimize the immediate format used by
1035 * trace-JITted code that reads it.
1037 uint32 protoHazardShape;
1039 /* Garbage collector state, used by jsgc.c. */
1040 js::GCChunkSet gcChunkSet;
1042 js::RootedValueMap gcRootsHash;
1043 js::GCLocks gcLocksHash;
1044 jsrefcount gcKeepAtoms;
1045 size_t gcBytes;
1046 size_t gcTriggerBytes;
1047 size_t gcLastBytes;
1048 size_t gcMaxBytes;
1049 size_t gcMaxMallocBytes;
1050 uint32 gcEmptyArenaPoolLifespan;
1051 uint32 gcNumber;
1052 js::GCMarker *gcMarkingTracer;
1053 uint32 gcTriggerFactor;
1054 int64 gcJitReleaseTime;
1055 JSGCMode gcMode;
1056 volatile bool gcIsNeeded;
1059 * Compartment that triggered GC. If more than one Compatment need GC,
1060 * gcTriggerCompartment is reset to NULL and a global GC is performed.
1062 JSCompartment *gcTriggerCompartment;
1064 /* Compartment that is currently involved in per-compartment GC */
1065 JSCompartment *gcCurrentCompartment;
1068 * We can pack these flags as only the GC thread writes to them. Atomic
1069 * updates to packed bytes are not guaranteed, so stores issued by one
1070 * thread may be lost due to unsynchronized read-modify-write cycles on
1071 * other threads.
1073 bool gcPoke;
1074 bool gcMarkAndSweep;
1075 bool gcRunning;
1076 bool gcRegenShapes;
1078 #ifdef JS_GC_ZEAL
1079 jsrefcount gcZeal;
1080 #endif
1082 JSGCCallback gcCallback;
1084 private:
1086 * Malloc counter to measure memory pressure for GC scheduling. It runs
1087 * from gcMaxMallocBytes down to zero.
1089 volatile ptrdiff_t gcMallocBytes;
1091 public:
1092 js::GCChunkAllocator *gcChunkAllocator;
1094 void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) {
1095 JS_ASSERT(allocator);
1096 JS_ASSERT(state == JSRTS_DOWN);
1097 gcChunkAllocator = allocator;
1101 * The trace operation and its data argument to trace embedding-specific
1102 * GC roots.
1104 JSTraceDataOp gcExtraRootsTraceOp;
1105 void *gcExtraRootsData;
1107 /* Well-known numbers held for use by this runtime's contexts. */
1108 js::Value NaNValue;
1109 js::Value negativeInfinityValue;
1110 js::Value positiveInfinityValue;
1112 JSFlatString *emptyString;
1114 /* List of active contexts sharing this runtime; protected by gcLock. */
1115 JSCList contextList;
1117 /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
1118 JSDebugHooks globalDebugHooks;
1121 * Right now, we only support runtime-wide debugging.
1123 JSBool debugMode;
1125 #ifdef JS_TRACER
1126 /* True if any debug hooks not supported by the JIT are enabled. */
1127 bool debuggerInhibitsJIT() const {
1128 return (globalDebugHooks.interruptHook ||
1129 globalDebugHooks.callHook);
1131 #endif
1133 /* More debugging state, see jsdbgapi.c. */
1134 JSCList trapList;
1135 JSCList watchPointList;
1137 /* Client opaque pointers */
1138 void *data;
1140 #ifdef JS_THREADSAFE
1141 /* These combine to interlock the GC and new requests. */
1142 PRLock *gcLock;
1143 PRCondVar *gcDone;
1144 PRCondVar *requestDone;
1145 uint32 requestCount;
1146 JSThread *gcThread;
1148 js::GCHelperThread gcHelperThread;
1150 /* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
1151 PRLock *rtLock;
1152 #ifdef DEBUG
1153 void * rtLockOwner;
1154 #endif
1156 /* Used to synchronize down/up state change; protected by gcLock. */
1157 PRCondVar *stateChange;
1160 * Lock serializing trapList and watchPointList accesses, and count of all
1161 * mutations to trapList and watchPointList made by debugger threads. To
1162 * keep the code simple, we define debuggerMutations for the thread-unsafe
1163 * case too.
1165 PRLock *debuggerLock;
1167 JSThread::Map threads;
1168 #endif /* JS_THREADSAFE */
1169 uint32 debuggerMutations;
1172 * Security callbacks set on the runtime are used by each context unless
1173 * an override is set on the context.
1175 JSSecurityCallbacks *securityCallbacks;
1177 /* Structured data callbacks are runtime-wide. */
1178 const JSStructuredCloneCallbacks *structuredCloneCallbacks;
1181 * The propertyRemovals counter is incremented for every JSObject::clear,
1182 * and for each JSObject::remove method call that frees a slot in the given
1183 * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
1185 int32 propertyRemovals;
1187 /* Script filename table. */
1188 struct JSHashTable *scriptFilenameTable;
1189 JSCList scriptFilenamePrefixes;
1190 #ifdef JS_THREADSAFE
1191 PRLock *scriptFilenameTableLock;
1192 #endif
1194 /* Number localization, used by jsnum.c */
1195 const char *thousandsSeparator;
1196 const char *decimalSeparator;
1197 const char *numGrouping;
1200 * Weak references to lazily-created, well-known XML singletons.
1202 * NB: Singleton objects must be carefully disconnected from the rest of
1203 * the object graph usually associated with a JSContext's global object,
1204 * including the set of standard class objects. See jsxml.c for details.
1206 JSObject *anynameObject;
1207 JSObject *functionNamespaceObject;
1209 #ifdef JS_THREADSAFE
1210 /* Number of threads with active requests and unhandled interrupts. */
1211 volatile int32 interruptCounter;
1212 #else
1213 JSThreadData threadData;
1215 #define JS_THREAD_DATA(cx) (&(cx)->runtime->threadData)
1216 #endif
1219 * Object shape (property cache structural type) identifier generator.
1221 * Type 0 stands for the empty scope, and must not be regenerated due to
1222 * uint32 wrap-around. Since js_GenerateShape (in jsinterp.cpp) uses
1223 * atomic pre-increment, the initial value for the first typed non-empty
1224 * scope will be 1.
1226 * If this counter overflows into SHAPE_OVERFLOW_BIT (in jsinterp.h), the
1227 * cache is disabled, to avoid aliasing two different types. It stays
1228 * disabled until a triggered GC at some later moment compresses live
1229 * types, minimizing rt->shapeGen in the process.
1231 volatile uint32 shapeGen;
1233 /* Literal table maintained by jsatom.c functions. */
1234 JSAtomState atomState;
1237 * Various metering fields are defined at the end of JSRuntime. In this
1238 * way there is no need to recompile all the code that refers to other
1239 * fields of JSRuntime after enabling the corresponding metering macro.
1241 #ifdef JS_DUMP_ENUM_CACHE_STATS
1242 int32 nativeEnumProbes;
1243 int32 nativeEnumMisses;
1244 # define ENUM_CACHE_METER(name) JS_ATOMIC_INCREMENT(&cx->runtime->name)
1245 #else
1246 # define ENUM_CACHE_METER(name) ((void) 0)
1247 #endif
1249 #ifdef JS_DUMP_LOOP_STATS
1250 /* Loop statistics, to trigger trace recording and compiling. */
1251 JSBasicStats loopStats;
1252 #endif
1254 #ifdef DEBUG
1255 /* Function invocation metering. */
1256 jsrefcount inlineCalls;
1257 jsrefcount nativeCalls;
1258 jsrefcount nonInlineCalls;
1259 jsrefcount constructs;
1261 jsrefcount liveObjectProps;
1262 jsrefcount liveObjectPropsPreSweep;
1265 * NB: emptyShapes (in JSCompartment) is init'ed iff at least one
1266 * of these envars is set:
1268 * JS_PROPTREE_STATFILE statistics on the property tree forest
1269 * JS_PROPTREE_DUMPFILE all paths in the property tree forest
1271 const char *propTreeStatFilename;
1272 const char *propTreeDumpFilename;
1274 bool meterEmptyShapes() const { return propTreeStatFilename || propTreeDumpFilename; }
1276 /* String instrumentation. */
1277 jsrefcount liveStrings;
1278 jsrefcount totalStrings;
1279 jsrefcount liveDependentStrings;
1280 jsrefcount totalDependentStrings;
1281 jsrefcount badUndependStrings;
1282 double lengthSum;
1283 double lengthSquaredSum;
1284 double strdepLengthSum;
1285 double strdepLengthSquaredSum;
1287 /* Script instrumentation. */
1288 jsrefcount liveScripts;
1289 jsrefcount totalScripts;
1290 jsrefcount liveEmptyScripts;
1291 jsrefcount totalEmptyScripts;
1292 jsrefcount highWaterLiveScripts;
1293 #endif /* DEBUG */
1295 #ifdef JS_SCOPE_DEPTH_METER
1297 * Stats on runtime prototype chain lookups and scope chain depths, i.e.,
1298 * counts of objects traversed on a chain until the wanted id is found.
1300 JSBasicStats protoLookupDepthStats;
1301 JSBasicStats scopeSearchDepthStats;
1304 * Stats on compile-time host environment and lexical scope chain lengths
1305 * (maximum depths).
1307 JSBasicStats hostenvScopeDepthStats;
1308 JSBasicStats lexicalScopeDepthStats;
1309 #endif
1311 #ifdef JS_GCMETER
1312 js::gc::JSGCStats gcStats;
1313 js::gc::JSGCArenaStats globalArenaStats[js::gc::FINALIZE_LIMIT];
1314 #endif
1316 #ifdef DEBUG
1318 * If functionMeterFilename, set from an envariable in JSRuntime's ctor, is
1319 * null, the remaining members in this ifdef'ed group are not initialized.
1321 const char *functionMeterFilename;
1322 JSFunctionMeter functionMeter;
1323 char lastScriptFilename[1024];
1325 typedef js::HashMap<JSFunction *,
1326 int32,
1327 js::DefaultHasher<JSFunction *>,
1328 js::SystemAllocPolicy> FunctionCountMap;
1330 FunctionCountMap methodReadBarrierCountMap;
1331 FunctionCountMap unjoinedFunctionCountMap;
1332 #endif
1334 JSWrapObjectCallback wrapObjectCallback;
1335 JSPreWrapCallback preWrapObjectCallback;
1337 #ifdef JS_METHODJIT
1338 uint32 mjitMemoryUsed;
1339 #endif
1340 uint32 stringMemoryUsed;
1342 JSRuntime();
1343 ~JSRuntime();
1345 bool init(uint32 maxbytes);
1347 void setGCTriggerFactor(uint32 factor);
1348 void setGCLastBytes(size_t lastBytes);
1351 * Call the system malloc while checking for GC memory pressure and
1352 * reporting OOM error when cx is not null.
1354 void* malloc(size_t bytes, JSContext *cx = NULL) {
1355 updateMallocCounter(bytes);
1356 void *p = ::js_malloc(bytes);
1357 return JS_LIKELY(!!p) ? p : onOutOfMemory(NULL, bytes, cx);
1361 * Call the system calloc while checking for GC memory pressure and
1362 * reporting OOM error when cx is not null.
1364 void* calloc(size_t bytes, JSContext *cx = NULL) {
1365 updateMallocCounter(bytes);
1366 void *p = ::js_calloc(bytes);
1367 return JS_LIKELY(!!p) ? p : onOutOfMemory(reinterpret_cast<void *>(1), bytes, cx);
1370 void* realloc(void* p, size_t oldBytes, size_t newBytes, JSContext *cx = NULL) {
1371 JS_ASSERT(oldBytes < newBytes);
1372 updateMallocCounter(newBytes - oldBytes);
1373 void *p2 = ::js_realloc(p, newBytes);
1374 return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, newBytes, cx);
1377 void* realloc(void* p, size_t bytes, JSContext *cx = NULL) {
1379 * For compatibility we do not account for realloc that increases
1380 * previously allocated memory.
1382 if (!p)
1383 updateMallocCounter(bytes);
1384 void *p2 = ::js_realloc(p, bytes);
1385 return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
1388 void free(void* p) { ::js_free(p); }
1390 bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
1392 void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
1394 void setGCMaxMallocBytes(size_t value) {
1396 * For compatibility treat any value that exceeds PTRDIFF_T_MAX to
1397 * mean that value.
1399 gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
1400 resetGCMallocBytes();
1404 * Call this after allocating memory held by GC things, to update memory
1405 * pressure counters or report the OOM error if necessary. If oomError and
1406 * cx is not null the function also reports OOM error.
1408 * The function must be called outside the GC lock and in case of OOM error
1409 * the caller must ensure that no deadlock possible during OOM reporting.
1411 void updateMallocCounter(size_t nbytes) {
1412 /* We tolerate any thread races when updating gcMallocBytes. */
1413 ptrdiff_t newCount = gcMallocBytes - ptrdiff_t(nbytes);
1414 gcMallocBytes = newCount;
1415 if (JS_UNLIKELY(newCount <= 0))
1416 onTooMuchMalloc();
1419 private:
1421 * The function must be called outside the GC lock.
1423 JS_FRIEND_API(void) onTooMuchMalloc();
1426 * This should be called after system malloc/realloc returns NULL to try
1427 * to recove some memory or to report an error. Failures in malloc and
1428 * calloc are signaled by p == null and p == reinterpret_cast<void *>(1).
1429 * Other values of p mean a realloc failure.
1431 * The function must be called outside the GC lock.
1433 JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes, JSContext *cx);
1436 /* Common macros to access thread-local caches in JSThread or JSRuntime. */
1437 #define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache)
1438 #define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache)
1440 #ifdef DEBUG
1441 # define JS_RUNTIME_METER(rt, which) JS_ATOMIC_INCREMENT(&(rt)->which)
1442 # define JS_RUNTIME_UNMETER(rt, which) JS_ATOMIC_DECREMENT(&(rt)->which)
1443 #else
1444 # define JS_RUNTIME_METER(rt, which) /* nothing */
1445 # define JS_RUNTIME_UNMETER(rt, which) /* nothing */
1446 #endif
1448 #define JS_KEEP_ATOMS(rt) JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms);
1449 #define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms);
1451 #ifdef JS_ARGUMENT_FORMATTER_DEFINED
1453 * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to
1454 * formatter functions. Elements are sorted in non-increasing format string
1455 * length order.
1457 struct JSArgumentFormatMap {
1458 const char *format;
1459 size_t length;
1460 JSArgumentFormatter formatter;
1461 JSArgumentFormatMap *next;
1463 #endif
1466 * Key and entry types for the JSContext.resolvingTable hash table, typedef'd
1467 * here because all consumers need to see these declarations (and not just the
1468 * typedef names, as would be the case for an opaque pointer-to-typedef'd-type
1469 * declaration), along with cx->resolvingTable.
1471 typedef struct JSResolvingKey {
1472 JSObject *obj;
1473 jsid id;
1474 } JSResolvingKey;
1476 typedef struct JSResolvingEntry {
1477 JSDHashEntryHdr hdr;
1478 JSResolvingKey key;
1479 uint32 flags;
1480 } JSResolvingEntry;
1482 #define JSRESFLAG_LOOKUP 0x1 /* resolving id from lookup */
1483 #define JSRESFLAG_WATCH 0x2 /* resolving id from watch */
1484 #define JSRESOLVE_INFER 0xffff /* infer bits from current bytecode */
1486 extern const JSDebugHooks js_NullDebugHooks; /* defined in jsdbgapi.cpp */
1488 namespace js {
1490 class AutoGCRooter;
1492 static inline bool
1493 OptionsHasXML(uint32 options)
1495 return !!(options & JSOPTION_XML);
1498 static inline bool
1499 OptionsHasAnonFunFix(uint32 options)
1501 return !!(options & JSOPTION_ANONFUNFIX);
1504 static inline bool
1505 OptionsSameVersionFlags(uint32 self, uint32 other)
1507 static const uint32 mask = JSOPTION_XML | JSOPTION_ANONFUNFIX;
1508 return !((self & mask) ^ (other & mask));
1512 * Flags accompany script version data so that a) dynamically created scripts
1513 * can inherit their caller's compile-time properties and b) scripts can be
1514 * appropriately compared in the eval cache across global option changes. An
1515 * example of the latter is enabling the top-level-anonymous-function-is-error
1516 * option: subsequent evals of the same, previously-valid script text may have
1517 * become invalid.
1519 namespace VersionFlags {
1520 static const uintN MASK = 0x0FFF; /* see JSVersion in jspubtd.h */
1521 static const uintN HAS_XML = 0x1000; /* flag induced by XML option */
1522 static const uintN ANONFUNFIX = 0x2000; /* see jsapi.h comment on JSOPTION_ANONFUNFIX */
1523 static const uintN FULL_MASK = 0x3FFF;
1526 static inline JSVersion
1527 VersionNumber(JSVersion version)
1529 return JSVersion(uint32(version) & VersionFlags::MASK);
1532 static inline bool
1533 VersionHasXML(JSVersion version)
1535 return !!(version & VersionFlags::HAS_XML);
1538 /* @warning This is a distinct condition from having the XML flag set. */
1539 static inline bool
1540 VersionShouldParseXML(JSVersion version)
1542 return VersionHasXML(version) || VersionNumber(version) >= JSVERSION_1_6;
1545 static inline bool
1546 VersionHasAnonFunFix(JSVersion version)
1548 return !!(version & VersionFlags::ANONFUNFIX);
1551 static inline void
1552 VersionSetXML(JSVersion *version, bool enable)
1554 if (enable)
1555 *version = JSVersion(uint32(*version) | VersionFlags::HAS_XML);
1556 else
1557 *version = JSVersion(uint32(*version) & ~VersionFlags::HAS_XML);
1560 static inline void
1561 VersionSetAnonFunFix(JSVersion *version, bool enable)
1563 if (enable)
1564 *version = JSVersion(uint32(*version) | VersionFlags::ANONFUNFIX);
1565 else
1566 *version = JSVersion(uint32(*version) & ~VersionFlags::ANONFUNFIX);
1569 static inline JSVersion
1570 VersionExtractFlags(JSVersion version)
1572 return JSVersion(uint32(version) & ~VersionFlags::MASK);
1575 static inline void
1576 VersionCopyFlags(JSVersion *version, JSVersion from)
1578 *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
1581 static inline bool
1582 VersionHasFlags(JSVersion version)
1584 return !!VersionExtractFlags(version);
1587 static inline uintN
1588 VersionFlagsToOptions(JSVersion version)
1590 uintN copts = (VersionHasXML(version) ? JSOPTION_XML : 0) |
1591 (VersionHasAnonFunFix(version) ? JSOPTION_ANONFUNFIX : 0);
1592 JS_ASSERT((copts & JSCOMPILEOPTION_MASK) == copts);
1593 return copts;
1596 static inline JSVersion
1597 OptionFlagsToVersion(uintN options, JSVersion version)
1599 VersionSetXML(&version, OptionsHasXML(options));
1600 VersionSetAnonFunFix(&version, OptionsHasAnonFunFix(options));
1601 return version;
1604 static inline bool
1605 VersionIsKnown(JSVersion version)
1607 return VersionNumber(version) != JSVERSION_UNKNOWN;
1610 typedef js::HashSet<JSObject *,
1611 js::DefaultHasher<JSObject *>,
1612 js::SystemAllocPolicy> BusyArraysMap;
1614 } /* namespace js */
1616 struct JSContext
1618 explicit JSContext(JSRuntime *rt);
1620 /* JSRuntime contextList linkage. */
1621 JSCList link;
1623 private:
1624 /* See JSContext::findVersion. */
1625 JSVersion defaultVersion; /* script compilation version */
1626 JSVersion versionOverride; /* supercedes defaultVersion when valid */
1627 bool hasVersionOverride;
1629 /* Exception state -- the exception member is a GC root by definition. */
1630 JSBool throwing; /* is there a pending exception? */
1631 js::Value exception; /* most-recently-thrown exception */
1633 /* Per-context run options. */
1634 uintN runOptions; /* see jsapi.h for JSOPTION_* */
1636 public:
1637 /* Locale specific callbacks for string conversion. */
1638 JSLocaleCallbacks *localeCallbacks;
1641 * cx->resolvingTable is non-null and non-empty if we are initializing
1642 * standard classes lazily, or if we are otherwise recursing indirectly
1643 * from js_LookupProperty through a Class.resolve hook. It is used to
1644 * limit runaway recursion (see jsapi.c and jsobj.c).
1646 JSDHashTable *resolvingTable;
1649 * True if generating an error, to prevent runaway recursion.
1650 * NB: generatingError packs with throwing below.
1652 JSPackedBool generatingError;
1654 /* Limit pointer for checking native stack consumption during recursion. */
1655 jsuword stackLimit;
1657 /* Quota on the size of arenas used to compile and execute scripts. */
1658 size_t scriptStackQuota;
1660 /* Data shared by threads in an address space. */
1661 JSRuntime *const runtime;
1663 /* GC heap compartment. */
1664 JSCompartment *compartment;
1666 /* Currently executing frame and regs, set by stack operations. */
1667 JS_REQUIRES_STACK
1668 JSFrameRegs *regs;
1670 /* Current frame accessors. */
1672 JSStackFrame* fp() {
1673 JS_ASSERT(regs && regs->fp);
1674 return regs->fp;
1677 JSStackFrame* maybefp() {
1678 JS_ASSERT_IF(regs, regs->fp);
1679 return regs ? regs->fp : NULL;
1682 bool hasfp() {
1683 JS_ASSERT_IF(regs, regs->fp);
1684 return !!regs;
1687 public:
1688 friend class js::StackSpace;
1689 friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, JSInterpMode);
1691 void resetCompartment();
1692 void wrapPendingException();
1694 /* For grep-ability, changes to 'regs' should call this function. */
1695 void setCurrentRegs(JSFrameRegs *regs) {
1696 JS_ASSERT_IF(regs, regs->fp);
1697 this->regs = regs;
1700 /* Temporary arena pool used while compiling and decompiling. */
1701 JSArenaPool tempPool;
1703 /* Temporary arena pool used while evaluate regular expressions. */
1704 JSArenaPool regExpPool;
1706 /* Top-level object and pointer to top stack frame's scope chain. */
1707 JSObject *globalObject;
1709 /* State for object and array toSource conversion. */
1710 JSSharpObjectMap sharpObjectMap;
1711 js::BusyArraysMap busyArrays;
1713 /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
1714 JSArgumentFormatMap *argumentFormatMap;
1716 /* Last message string and log file for debugging. */
1717 char *lastMessage;
1718 #ifdef DEBUG
1719 void *logfp;
1720 jsbytecode *logPrevPc;
1721 #endif
1723 /* Per-context optional error reporter. */
1724 JSErrorReporter errorReporter;
1726 /* Branch callback. */
1727 JSOperationCallback operationCallback;
1729 /* Interpreter activation count. */
1730 uintN interpLevel;
1732 /* Client opaque pointers. */
1733 void *data;
1734 void *data2;
1736 private:
1737 /* Linked list of segments. See StackSegment. */
1738 js::StackSegment *currentSegment;
1740 public:
1741 void assertSegmentsInSync() const {
1742 #ifdef DEBUG
1743 if (regs) {
1744 JS_ASSERT(currentSegment->isActive());
1745 if (js::StackSegment *prev = currentSegment->getPreviousInContext())
1746 JS_ASSERT(!prev->isActive());
1747 } else {
1748 JS_ASSERT_IF(currentSegment, !currentSegment->isActive());
1750 #endif
1753 /* Return whether this context has an active segment. */
1754 bool hasActiveSegment() const {
1755 assertSegmentsInSync();
1756 return !!regs;
1759 /* Assuming there is an active segment, return it. */
1760 js::StackSegment *activeSegment() const {
1761 JS_ASSERT(hasActiveSegment());
1762 return currentSegment;
1765 /* Return the current segment, which may or may not be active. */
1766 js::StackSegment *getCurrentSegment() const {
1767 assertSegmentsInSync();
1768 return currentSegment;
1771 inline js::RegExpStatics *regExpStatics();
1773 /* Add the given segment to the list as the new active segment. */
1774 void pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs &regs);
1776 /* Remove the active segment and make the next segment active. */
1777 void popSegmentAndFrame();
1779 /* Mark the top segment as suspended, without pushing a new one. */
1780 void saveActiveSegment();
1782 /* Undoes calls to suspendActiveSegment. */
1783 void restoreSegment();
1785 /* Get the frame whose prev() is fp, which may be in any segment. */
1786 inline JSStackFrame *computeNextFrame(JSStackFrame *fp);
1789 * Perform a linear search of all frames in all segments in the given context
1790 * for the given frame, returning the segment, if found, and null otherwise.
1792 js::StackSegment *containingSegment(const JSStackFrame *target);
1794 /* Search the call stack for the nearest frame with static level targetLevel. */
1795 JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
1796 JSStackFrame *fp = regs->fp;
1797 while (true) {
1798 JS_ASSERT(fp && fp->isScriptFrame());
1799 if (fp->script()->staticLevel == targetLevel)
1800 break;
1801 fp = fp->prev();
1803 return fp;
1806 public:
1808 * The default script compilation version can be set iff there is no code running.
1809 * This typically occurs via the JSAPI right after a context is constructed.
1811 bool canSetDefaultVersion() const {
1812 return !regs && !hasVersionOverride;
1815 /* Force a version for future script compilation. */
1816 void overrideVersion(JSVersion newVersion) {
1817 JS_ASSERT(!canSetDefaultVersion());
1818 versionOverride = newVersion;
1819 hasVersionOverride = true;
1822 /* Set the default script compilation version. */
1823 void setDefaultVersion(JSVersion version) {
1824 defaultVersion = version;
1827 void clearVersionOverride() { hasVersionOverride = false; }
1828 JSVersion getDefaultVersion() const { return defaultVersion; }
1829 bool isVersionOverridden() const { return hasVersionOverride; }
1831 JSVersion getVersionOverride() const {
1832 JS_ASSERT(isVersionOverridden());
1833 return versionOverride;
1837 * Set the default version if possible; otherwise, force the version.
1838 * Return whether an override occurred.
1840 bool maybeOverrideVersion(JSVersion newVersion) {
1841 if (canSetDefaultVersion()) {
1842 setDefaultVersion(newVersion);
1843 return false;
1845 overrideVersion(newVersion);
1846 return true;
1849 private:
1851 * If there is no code currently executing, turn the override version into
1852 * the default version.
1854 * NB: the only time the version is potentially capable of migrating is
1855 * on return from the Execute or ExternalInvoke paths as they call through
1856 * JSContext::popSegmentAndFrame.
1858 void maybeMigrateVersionOverride() {
1859 if (JS_LIKELY(!isVersionOverridden() || currentSegment))
1860 return;
1861 defaultVersion = versionOverride;
1862 clearVersionOverride();
1865 public:
1867 * Return:
1868 * - The override version, if there is an override version.
1869 * - The newest scripted frame's version, if there is such a frame.
1870 * - The default verion.
1872 * Note: if this ever shows up in a profile, just add caching!
1874 JSVersion findVersion() const {
1875 if (hasVersionOverride)
1876 return versionOverride;
1878 if (regs) {
1879 /* There may be a scripted function somewhere on the stack! */
1880 JSStackFrame *fp = regs->fp;
1881 while (fp && !fp->isScriptFrame())
1882 fp = fp->prev();
1883 if (fp)
1884 return fp->script()->getVersion();
1887 return defaultVersion;
1890 void setRunOptions(uintN ropts) {
1891 JS_ASSERT((ropts & JSRUNOPTION_MASK) == ropts);
1892 runOptions = ropts;
1895 /* Note: may override the version. */
1896 void setCompileOptions(uintN newcopts) {
1897 JS_ASSERT((newcopts & JSCOMPILEOPTION_MASK) == newcopts);
1898 if (JS_LIKELY(getCompileOptions() == newcopts))
1899 return;
1900 JSVersion version = findVersion();
1901 JSVersion newVersion = js::OptionFlagsToVersion(newcopts, version);
1902 maybeOverrideVersion(newVersion);
1905 uintN getRunOptions() const { return runOptions; }
1906 uintN getCompileOptions() const { return js::VersionFlagsToOptions(findVersion()); }
1907 uintN allOptions() const { return getRunOptions() | getCompileOptions(); }
1909 bool hasRunOption(uintN ropt) const {
1910 JS_ASSERT((ropt & JSRUNOPTION_MASK) == ropt);
1911 return !!(runOptions & ropt);
1914 bool hasStrictOption() const { return hasRunOption(JSOPTION_STRICT); }
1915 bool hasWErrorOption() const { return hasRunOption(JSOPTION_WERROR); }
1916 bool hasAtLineOption() const { return hasRunOption(JSOPTION_ATLINE); }
1918 #ifdef JS_THREADSAFE
1919 JSThread *thread;
1920 unsigned outstandingRequests;/* number of JS_BeginRequest calls
1921 without the corresponding
1922 JS_EndRequest. */
1923 JSCList threadLinks; /* JSThread contextList linkage */
1925 #define CX_FROM_THREAD_LINKS(tl) \
1926 ((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks)))
1927 #endif
1929 /* Stack of thread-stack-allocated GC roots. */
1930 js::AutoGCRooter *autoGCRooters;
1932 /* Debug hooks associated with the current context. */
1933 const JSDebugHooks *debugHooks;
1935 /* Security callbacks that override any defined on the runtime. */
1936 JSSecurityCallbacks *securityCallbacks;
1938 /* Stored here to avoid passing it around as a parameter. */
1939 uintN resolveFlags;
1941 /* Random number generator state, used by jsmath.cpp. */
1942 int64 rngSeed;
1944 /* Location to stash the iteration value between JSOP_MOREITER and JSOP_FOR*. */
1945 js::Value iterValue;
1947 #ifdef JS_TRACER
1949 * True if traces may be executed. Invariant: The value of traceJitenabled
1950 * is always equal to the expression in updateJITEnabled below.
1952 * This flag and the fields accessed by updateJITEnabled are written only
1953 * in runtime->gcLock, to avoid race conditions that would leave the wrong
1954 * value in traceJitEnabled. (But the interpreter reads this without
1955 * locking. That can race against another thread setting debug hooks, but
1956 * we always read cx->debugHooks without locking anyway.)
1958 bool traceJitEnabled;
1959 #endif
1961 #ifdef JS_METHODJIT
1962 bool methodJitEnabled;
1963 bool profilingEnabled;
1964 #endif
1966 /* Caller must be holding runtime->gcLock. */
1967 void updateJITEnabled();
1969 #ifdef MOZ_TRACE_JSCALLS
1970 /* Function entry/exit debugging callback. */
1971 JSFunctionCallback functionCallback;
1973 void doFunctionCallback(const JSFunction *fun,
1974 const JSScript *scr,
1975 int entering) const
1977 if (functionCallback)
1978 functionCallback(fun, scr, this, entering);
1980 #endif
1982 DSTOffsetCache dstOffsetCache;
1984 /* List of currently active non-escaping enumerators (for-in). */
1985 JSObject *enumerators;
1987 private:
1989 * To go from a live generator frame (on the stack) to its generator object
1990 * (see comment js_FloatingFrameIfGenerator), we maintain a stack of active
1991 * generators, pushing and popping when entering and leaving generator
1992 * frames, respectively.
1994 js::Vector<JSGenerator *, 2, js::SystemAllocPolicy> genStack;
1996 public:
1997 #ifdef JS_METHODJIT
1998 inline js::mjit::JaegerCompartment *jaegerCompartment();
1999 #endif
2001 /* Return the generator object for the given generator frame. */
2002 JSGenerator *generatorFor(JSStackFrame *fp) const;
2004 /* Early OOM-check. */
2005 inline bool ensureGeneratorStackSpace();
2007 bool enterGenerator(JSGenerator *gen) {
2008 return genStack.append(gen);
2011 void leaveGenerator(JSGenerator *gen) {
2012 JS_ASSERT(genStack.back() == gen);
2013 genStack.popBack();
2016 #ifdef JS_THREADSAFE
2018 * When non-null JSContext::free delegates the job to the background
2019 * thread.
2021 js::GCHelperThread *gcBackgroundFree;
2022 #endif
2024 inline void* malloc(size_t bytes) {
2025 return runtime->malloc(bytes, this);
2028 inline void* mallocNoReport(size_t bytes) {
2029 JS_ASSERT(bytes != 0);
2030 return runtime->malloc(bytes, NULL);
2033 inline void* calloc(size_t bytes) {
2034 JS_ASSERT(bytes != 0);
2035 return runtime->calloc(bytes, this);
2038 inline void* realloc(void* p, size_t bytes) {
2039 return runtime->realloc(p, bytes, this);
2042 inline void* realloc(void* p, size_t oldBytes, size_t newBytes) {
2043 return runtime->realloc(p, oldBytes, newBytes, this);
2046 inline void free(void* p) {
2047 #ifdef JS_THREADSAFE
2048 if (gcBackgroundFree) {
2049 gcBackgroundFree->freeLater(p);
2050 return;
2052 #endif
2053 runtime->free(p);
2057 * In the common case that we'd like to allocate the memory for an object
2058 * with cx->malloc/free, we cannot use overloaded C++ operators (no
2059 * placement delete). Factor the common workaround into one place.
2061 #define CREATE_BODY(parms) \
2062 void *memory = this->malloc(sizeof(T)); \
2063 if (!memory) \
2064 return NULL; \
2065 return new(memory) T parms;
2067 template <class T>
2068 JS_ALWAYS_INLINE T *create() {
2069 CREATE_BODY(())
2072 template <class T, class P1>
2073 JS_ALWAYS_INLINE T *create(const P1 &p1) {
2074 CREATE_BODY((p1))
2077 template <class T, class P1, class P2>
2078 JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2) {
2079 CREATE_BODY((p1, p2))
2082 template <class T, class P1, class P2, class P3>
2083 JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2, const P3 &p3) {
2084 CREATE_BODY((p1, p2, p3))
2086 #undef CREATE_BODY
2088 template <class T>
2089 JS_ALWAYS_INLINE void destroy(T *p) {
2090 p->~T();
2091 this->free(p);
2094 void purge();
2096 js::StackSpace &stack() const {
2097 return JS_THREAD_DATA(this)->stackSpace;
2100 #ifdef DEBUG
2101 void assertValidStackDepth(uintN depth) {
2102 JS_ASSERT(0 <= regs->sp - regs->fp->base());
2103 JS_ASSERT(depth <= uintptr_t(regs->sp - regs->fp->base()));
2105 #else
2106 void assertValidStackDepth(uintN /*depth*/) {}
2107 #endif
2109 bool isExceptionPending() {
2110 return throwing;
2113 js::Value getPendingException() {
2114 JS_ASSERT(throwing);
2115 return exception;
2118 void setPendingException(js::Value v);
2120 void clearPendingException() {
2121 this->throwing = false;
2122 this->exception.setUndefined();
2125 private:
2127 * The allocation code calls the function to indicate either OOM failure
2128 * when p is null or that a memory pressure counter has reached some
2129 * threshold when p is not null. The function takes the pointer and not
2130 * a boolean flag to minimize the amount of code in its inlined callers.
2132 JS_FRIEND_API(void) checkMallocGCPressure(void *p);
2133 }; /* struct JSContext */
2135 #ifdef JS_THREADSAFE
2136 # define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)
2137 #endif
2139 #if defined JS_THREADSAFE && defined DEBUG
2141 namespace js {
2143 class AutoCheckRequestDepth {
2144 JSContext *cx;
2145 public:
2146 AutoCheckRequestDepth(JSContext *cx) : cx(cx) { cx->thread->checkRequestDepth++; }
2148 ~AutoCheckRequestDepth() {
2149 JS_ASSERT(cx->thread->checkRequestDepth != 0);
2150 cx->thread->checkRequestDepth--;
2156 # define CHECK_REQUEST(cx) \
2157 JS_ASSERT((cx)->thread); \
2158 JS_ASSERT((cx)->thread->data.requestDepth || (cx)->thread == (cx)->runtime->gcThread); \
2159 AutoCheckRequestDepth _autoCheckRequestDepth(cx);
2161 #else
2162 # define CHECK_REQUEST(cx) ((void) 0)
2163 # define CHECK_REQUEST_THREAD(cx) ((void) 0)
2164 #endif
2166 static inline uintN
2167 FramePCOffset(JSContext *cx, JSStackFrame* fp)
2169 jsbytecode *pc = fp->hasImacropc() ? fp->imacropc() : fp->pc(cx);
2170 return uintN(pc - fp->script()->code);
2173 static inline JSAtom **
2174 FrameAtomBase(JSContext *cx, JSStackFrame *fp)
2176 return fp->hasImacropc()
2177 ? COMMON_ATOMS_START(&cx->runtime->atomState)
2178 : fp->script()->atomMap.vector;
2181 namespace js {
2183 class AutoGCRooter {
2184 public:
2185 AutoGCRooter(JSContext *cx, ptrdiff_t tag)
2186 : down(cx->autoGCRooters), tag(tag), context(cx)
2188 JS_ASSERT(this != cx->autoGCRooters);
2189 CHECK_REQUEST(cx);
2190 cx->autoGCRooters = this;
2193 ~AutoGCRooter() {
2194 JS_ASSERT(this == context->autoGCRooters);
2195 CHECK_REQUEST(context);
2196 context->autoGCRooters = down;
2199 /* Implemented in jsgc.cpp. */
2200 inline void trace(JSTracer *trc);
2202 #ifdef __GNUC__
2203 # pragma GCC visibility push(default)
2204 #endif
2205 friend JS_FRIEND_API(void) MarkContext(JSTracer *trc, JSContext *acx);
2206 friend void MarkRuntime(JSTracer *trc);
2207 #ifdef __GNUC__
2208 # pragma GCC visibility pop
2209 #endif
2211 protected:
2212 AutoGCRooter * const down;
2215 * Discriminates actual subclass of this being used. If non-negative, the
2216 * subclass roots an array of values of the length stored in this field.
2217 * If negative, meaning is indicated by the corresponding value in the enum
2218 * below. Any other negative value indicates some deeper problem such as
2219 * memory corruption.
2221 ptrdiff_t tag;
2223 JSContext * const context;
2225 enum {
2226 JSVAL = -1, /* js::AutoValueRooter */
2227 SHAPE = -2, /* js::AutoShapeRooter */
2228 PARSER = -3, /* js::Parser */
2229 SCRIPT = -4, /* js::AutoScriptRooter */
2230 ENUMERATOR = -5, /* js::AutoEnumStateRooter */
2231 IDARRAY = -6, /* js::AutoIdArray */
2232 DESCRIPTORS = -7, /* js::AutoPropDescArrayRooter */
2233 NAMESPACES = -8, /* js::AutoNamespaceArray */
2234 XML = -9, /* js::AutoXMLRooter */
2235 OBJECT = -10, /* js::AutoObjectRooter */
2236 ID = -11, /* js::AutoIdRooter */
2237 VALVECTOR = -12, /* js::AutoValueVector */
2238 DESCRIPTOR = -13, /* js::AutoPropertyDescriptorRooter */
2239 STRING = -14, /* js::AutoStringRooter */
2240 IDVECTOR = -15, /* js::AutoIdVector */
2241 BINDINGS = -16, /* js::Bindings */
2242 SHAPEVECTOR = -17 /* js::AutoShapeVector */
2245 private:
2246 /* No copy or assignment semantics. */
2247 AutoGCRooter(AutoGCRooter &ida);
2248 void operator=(AutoGCRooter &ida);
2251 /* FIXME(bug 332648): Move this into a public header. */
2252 class AutoValueRooter : private AutoGCRooter
2254 public:
2255 explicit AutoValueRooter(JSContext *cx
2256 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2257 : AutoGCRooter(cx, JSVAL), val(js::NullValue())
2259 JS_GUARD_OBJECT_NOTIFIER_INIT;
2262 AutoValueRooter(JSContext *cx, const Value &v
2263 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2264 : AutoGCRooter(cx, JSVAL), val(v)
2266 JS_GUARD_OBJECT_NOTIFIER_INIT;
2269 AutoValueRooter(JSContext *cx, jsval v
2270 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2271 : AutoGCRooter(cx, JSVAL), val(js::Valueify(v))
2273 JS_GUARD_OBJECT_NOTIFIER_INIT;
2277 * If you are looking for Object* overloads, use AutoObjectRooter instead;
2278 * rooting Object*s as a js::Value requires discerning whether or not it is
2279 * a function object. Also, AutoObjectRooter is smaller.
2282 void set(Value v) {
2283 JS_ASSERT(tag == JSVAL);
2284 val = v;
2287 void set(jsval v) {
2288 JS_ASSERT(tag == JSVAL);
2289 val = js::Valueify(v);
2292 const Value &value() const {
2293 JS_ASSERT(tag == JSVAL);
2294 return val;
2297 Value *addr() {
2298 JS_ASSERT(tag == JSVAL);
2299 return &val;
2302 const jsval &jsval_value() const {
2303 JS_ASSERT(tag == JSVAL);
2304 return Jsvalify(val);
2307 jsval *jsval_addr() {
2308 JS_ASSERT(tag == JSVAL);
2309 return Jsvalify(&val);
2312 friend void AutoGCRooter::trace(JSTracer *trc);
2313 friend void MarkRuntime(JSTracer *trc);
2315 private:
2316 Value val;
2317 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2320 class AutoObjectRooter : private AutoGCRooter {
2321 public:
2322 AutoObjectRooter(JSContext *cx, JSObject *obj = NULL
2323 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2324 : AutoGCRooter(cx, OBJECT), obj(obj)
2326 JS_GUARD_OBJECT_NOTIFIER_INIT;
2329 void setObject(JSObject *obj) {
2330 this->obj = obj;
2333 JSObject * object() const {
2334 return obj;
2337 JSObject ** addr() {
2338 return &obj;
2341 friend void AutoGCRooter::trace(JSTracer *trc);
2342 friend void MarkRuntime(JSTracer *trc);
2344 private:
2345 JSObject *obj;
2346 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2349 class AutoStringRooter : private AutoGCRooter {
2350 public:
2351 AutoStringRooter(JSContext *cx, JSString *str = NULL
2352 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2353 : AutoGCRooter(cx, STRING), str(str)
2355 JS_GUARD_OBJECT_NOTIFIER_INIT;
2358 void setString(JSString *str) {
2359 this->str = str;
2362 JSString * string() const {
2363 return str;
2366 JSString ** addr() {
2367 return &str;
2370 friend void AutoGCRooter::trace(JSTracer *trc);
2372 private:
2373 JSString *str;
2374 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2377 class AutoArrayRooter : private AutoGCRooter {
2378 public:
2379 AutoArrayRooter(JSContext *cx, size_t len, Value *vec
2380 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2381 : AutoGCRooter(cx, len), array(vec)
2383 JS_GUARD_OBJECT_NOTIFIER_INIT;
2384 JS_ASSERT(tag >= 0);
2387 AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
2388 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2389 : AutoGCRooter(cx, len), array(Valueify(vec))
2391 JS_GUARD_OBJECT_NOTIFIER_INIT;
2392 JS_ASSERT(tag >= 0);
2395 void changeLength(size_t newLength) {
2396 tag = ptrdiff_t(newLength);
2397 JS_ASSERT(tag >= 0);
2400 void changeArray(Value *newArray, size_t newLength) {
2401 changeLength(newLength);
2402 array = newArray;
2405 Value *array;
2407 friend void AutoGCRooter::trace(JSTracer *trc);
2409 private:
2410 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2413 class AutoShapeRooter : private AutoGCRooter {
2414 public:
2415 AutoShapeRooter(JSContext *cx, const js::Shape *shape
2416 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2417 : AutoGCRooter(cx, SHAPE), shape(shape)
2419 JS_GUARD_OBJECT_NOTIFIER_INIT;
2422 friend void AutoGCRooter::trace(JSTracer *trc);
2423 friend void MarkRuntime(JSTracer *trc);
2425 private:
2426 const js::Shape * const shape;
2427 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2430 class AutoScriptRooter : private AutoGCRooter {
2431 public:
2432 AutoScriptRooter(JSContext *cx, JSScript *script
2433 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2434 : AutoGCRooter(cx, SCRIPT), script(script)
2436 JS_GUARD_OBJECT_NOTIFIER_INIT;
2439 void setScript(JSScript *script) {
2440 this->script = script;
2443 friend void AutoGCRooter::trace(JSTracer *trc);
2445 private:
2446 JSScript *script;
2447 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2450 class AutoIdRooter : private AutoGCRooter
2452 public:
2453 explicit AutoIdRooter(JSContext *cx, jsid id = INT_TO_JSID(0)
2454 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2455 : AutoGCRooter(cx, ID), id_(id)
2457 JS_GUARD_OBJECT_NOTIFIER_INIT;
2460 jsid id() {
2461 return id_;
2464 jsid * addr() {
2465 return &id_;
2468 friend void AutoGCRooter::trace(JSTracer *trc);
2469 friend void MarkRuntime(JSTracer *trc);
2471 private:
2472 jsid id_;
2473 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2476 class AutoIdArray : private AutoGCRooter {
2477 public:
2478 AutoIdArray(JSContext *cx, JSIdArray *ida JS_GUARD_OBJECT_NOTIFIER_PARAM)
2479 : AutoGCRooter(cx, IDARRAY), idArray(ida)
2481 JS_GUARD_OBJECT_NOTIFIER_INIT;
2483 ~AutoIdArray() {
2484 if (idArray)
2485 JS_DestroyIdArray(context, idArray);
2487 bool operator!() {
2488 return idArray == NULL;
2490 jsid operator[](size_t i) const {
2491 JS_ASSERT(idArray);
2492 JS_ASSERT(i < size_t(idArray->length));
2493 return idArray->vector[i];
2495 size_t length() const {
2496 return idArray->length;
2499 friend void AutoGCRooter::trace(JSTracer *trc);
2501 JSIdArray *steal() {
2502 JSIdArray *copy = idArray;
2503 idArray = NULL;
2504 return copy;
2507 protected:
2508 inline void trace(JSTracer *trc);
2510 private:
2511 JSIdArray * idArray;
2512 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2514 /* No copy or assignment semantics. */
2515 AutoIdArray(AutoIdArray &ida);
2516 void operator=(AutoIdArray &ida);
2519 /* The auto-root for enumeration object and its state. */
2520 class AutoEnumStateRooter : private AutoGCRooter
2522 public:
2523 AutoEnumStateRooter(JSContext *cx, JSObject *obj
2524 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2525 : AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue()
2527 JS_GUARD_OBJECT_NOTIFIER_INIT;
2528 JS_ASSERT(obj);
2531 ~AutoEnumStateRooter() {
2532 if (!stateValue.isNull()) {
2533 #ifdef DEBUG
2534 JSBool ok =
2535 #endif
2536 obj->enumerate(context, JSENUMERATE_DESTROY, &stateValue, 0);
2537 JS_ASSERT(ok);
2541 friend void AutoGCRooter::trace(JSTracer *trc);
2543 const Value &state() const { return stateValue; }
2544 Value *addr() { return &stateValue; }
2546 protected:
2547 void trace(JSTracer *trc);
2549 JSObject * const obj;
2551 private:
2552 Value stateValue;
2553 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2556 #ifdef JS_HAS_XML_SUPPORT
2557 class AutoXMLRooter : private AutoGCRooter {
2558 public:
2559 AutoXMLRooter(JSContext *cx, JSXML *xml
2560 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2561 : AutoGCRooter(cx, XML), xml(xml)
2563 JS_GUARD_OBJECT_NOTIFIER_INIT;
2564 JS_ASSERT(xml);
2567 friend void AutoGCRooter::trace(JSTracer *trc);
2568 friend void MarkRuntime(JSTracer *trc);
2570 private:
2571 JSXML * const xml;
2572 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2574 #endif /* JS_HAS_XML_SUPPORT */
2576 class AutoBindingsRooter : private AutoGCRooter {
2577 public:
2578 AutoBindingsRooter(JSContext *cx, Bindings &bindings
2579 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2580 : AutoGCRooter(cx, BINDINGS), bindings(bindings)
2582 JS_GUARD_OBJECT_NOTIFIER_INIT;
2585 friend void AutoGCRooter::trace(JSTracer *trc);
2587 private:
2588 Bindings &bindings;
2589 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2592 class AutoLockGC {
2593 public:
2594 explicit AutoLockGC(JSRuntime *rt
2595 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2596 : rt(rt)
2598 JS_GUARD_OBJECT_NOTIFIER_INIT;
2599 JS_LOCK_GC(rt);
2601 ~AutoLockGC() { JS_UNLOCK_GC(rt); }
2603 private:
2604 JSRuntime *rt;
2605 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2608 class AutoUnlockGC {
2609 private:
2610 JSRuntime *rt;
2611 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2613 public:
2614 explicit AutoUnlockGC(JSRuntime *rt
2615 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2616 : rt(rt)
2618 JS_GUARD_OBJECT_NOTIFIER_INIT;
2619 JS_UNLOCK_GC(rt);
2621 ~AutoUnlockGC() { JS_LOCK_GC(rt); }
2624 class AutoLockAtomsCompartment {
2625 private:
2626 JSContext *cx;
2627 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2629 public:
2630 AutoLockAtomsCompartment(JSContext *cx
2631 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2632 : cx(cx)
2634 JS_GUARD_OBJECT_NOTIFIER_INIT;
2635 JS_LOCK(cx, &cx->runtime->atomState.lock);
2636 #ifdef JS_THREADSAFE
2637 cx->runtime->atomsCompartmentIsLocked = true;
2638 #endif
2640 ~AutoLockAtomsCompartment() {
2641 #ifdef JS_THREADSAFE
2642 cx->runtime->atomsCompartmentIsLocked = false;
2643 #endif
2644 JS_UNLOCK(cx, &cx->runtime->atomState.lock);
2648 class AutoUnlockAtomsCompartment {
2649 JSContext *cx;
2650 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2652 public:
2653 AutoUnlockAtomsCompartment(JSContext *cx
2654 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2655 : cx(cx)
2657 JS_GUARD_OBJECT_NOTIFIER_INIT;
2658 #ifdef JS_THREADSAFE
2659 cx->runtime->atomsCompartmentIsLocked = false;
2660 #endif
2661 JS_UNLOCK(cx, &cx->runtime->atomState.lock);
2663 ~AutoUnlockAtomsCompartment() {
2664 JS_LOCK(cx, &cx->runtime->atomState.lock);
2665 #ifdef JS_THREADSAFE
2666 cx->runtime->atomsCompartmentIsLocked = true;
2667 #endif
2671 class AutoKeepAtoms {
2672 JSRuntime *rt;
2673 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2675 public:
2676 explicit AutoKeepAtoms(JSRuntime *rt
2677 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2678 : rt(rt)
2680 JS_GUARD_OBJECT_NOTIFIER_INIT;
2681 JS_KEEP_ATOMS(rt);
2683 ~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
2686 class AutoArenaAllocator {
2687 JSArenaPool *pool;
2688 void *mark;
2689 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2691 public:
2692 explicit AutoArenaAllocator(JSArenaPool *pool
2693 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2694 : pool(pool), mark(JS_ARENA_MARK(pool))
2696 JS_GUARD_OBJECT_NOTIFIER_INIT;
2698 ~AutoArenaAllocator() { JS_ARENA_RELEASE(pool, mark); }
2700 template <typename T>
2701 T *alloc(size_t elems) {
2702 void *ptr;
2703 JS_ARENA_ALLOCATE(ptr, pool, elems * sizeof(T));
2704 return static_cast<T *>(ptr);
2708 class AutoReleasePtr {
2709 JSContext *cx;
2710 void *ptr;
2711 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2713 AutoReleasePtr operator=(const AutoReleasePtr &other);
2715 public:
2716 explicit AutoReleasePtr(JSContext *cx, void *ptr
2717 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2718 : cx(cx), ptr(ptr)
2720 JS_GUARD_OBJECT_NOTIFIER_INIT;
2722 ~AutoReleasePtr() { cx->free(ptr); }
2726 * FIXME: bug 602774: cleaner API for AutoReleaseNullablePtr
2728 class AutoReleaseNullablePtr {
2729 JSContext *cx;
2730 void *ptr;
2731 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2733 AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other);
2735 public:
2736 explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr
2737 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2738 : cx(cx), ptr(ptr)
2740 JS_GUARD_OBJECT_NOTIFIER_INIT;
2742 void reset(void *ptr2) {
2743 if (ptr)
2744 cx->free(ptr);
2745 ptr = ptr2;
2747 ~AutoReleaseNullablePtr() { if (ptr) cx->free(ptr); }
2750 class AutoLocalNameArray {
2751 public:
2752 explicit AutoLocalNameArray(JSContext *cx, JSFunction *fun
2753 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2754 : context(cx),
2755 mark(JS_ARENA_MARK(&cx->tempPool)),
2756 names(fun->script()->bindings.getLocalNameArray(cx, &cx->tempPool)),
2757 count(fun->script()->bindings.countLocalNames())
2759 JS_GUARD_OBJECT_NOTIFIER_INIT;
2762 ~AutoLocalNameArray() {
2763 JS_ARENA_RELEASE(&context->tempPool, mark);
2766 operator bool() const { return !!names; }
2768 uint32 length() const { return count; }
2770 const jsuword &operator [](unsigned i) const { return names[i]; }
2772 private:
2773 JSContext *context;
2774 void *mark;
2775 jsuword *names;
2776 uint32 count;
2778 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2781 template <class RefCountable>
2782 class AlreadyIncRefed
2784 typedef RefCountable *****ConvertibleToBool;
2786 RefCountable *obj;
2788 public:
2789 explicit AlreadyIncRefed(RefCountable *obj) : obj(obj) {}
2791 bool null() const { return obj == NULL; }
2792 operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2794 RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2795 RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2796 RefCountable *get() const { return obj; }
2799 template <class RefCountable>
2800 class NeedsIncRef
2802 typedef RefCountable *****ConvertibleToBool;
2804 RefCountable *obj;
2806 public:
2807 explicit NeedsIncRef(RefCountable *obj) : obj(obj) {}
2809 bool null() const { return obj == NULL; }
2810 operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2812 RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2813 RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2814 RefCountable *get() const { return obj; }
2817 template <class RefCountable>
2818 class AutoRefCount
2820 typedef RefCountable *****ConvertibleToBool;
2822 JSContext *const cx;
2823 RefCountable *obj;
2825 AutoRefCount(const AutoRefCount &);
2826 void operator=(const AutoRefCount &);
2828 public:
2829 explicit AutoRefCount(JSContext *cx)
2830 : cx(cx), obj(NULL)
2833 AutoRefCount(JSContext *cx, NeedsIncRef<RefCountable> aobj)
2834 : cx(cx), obj(aobj.get())
2836 if (obj)
2837 obj->incref(cx);
2840 AutoRefCount(JSContext *cx, AlreadyIncRefed<RefCountable> aobj)
2841 : cx(cx), obj(aobj.get())
2844 ~AutoRefCount() {
2845 if (obj)
2846 obj->decref(cx);
2849 void reset(NeedsIncRef<RefCountable> aobj) {
2850 if (obj)
2851 obj->decref(cx);
2852 obj = aobj.get();
2853 if (obj)
2854 obj->incref(cx);
2857 void reset(AlreadyIncRefed<RefCountable> aobj) {
2858 if (obj)
2859 obj->decref(cx);
2860 obj = aobj.get();
2863 bool null() const { return obj == NULL; }
2864 operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
2866 RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
2867 RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
2868 RefCountable *get() const { return obj; }
2871 } /* namespace js */
2873 class JSAutoResolveFlags
2875 public:
2876 JSAutoResolveFlags(JSContext *cx, uintN flags
2877 JS_GUARD_OBJECT_NOTIFIER_PARAM)
2878 : mContext(cx), mSaved(cx->resolveFlags)
2880 JS_GUARD_OBJECT_NOTIFIER_INIT;
2881 cx->resolveFlags = flags;
2884 ~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; }
2886 private:
2887 JSContext *mContext;
2888 uintN mSaved;
2889 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
2892 extern JSThreadData *
2893 js_CurrentThreadData(JSRuntime *rt);
2895 extern JSBool
2896 js_InitThreads(JSRuntime *rt);
2898 extern void
2899 js_FinishThreads(JSRuntime *rt);
2901 extern void
2902 js_PurgeThreads(JSContext *cx);
2904 namespace js {
2906 #ifdef JS_THREADSAFE
2908 /* Iterator over JSThreadData from all JSThread instances. */
2909 class ThreadDataIter : public JSThread::Map::Range
2911 public:
2912 ThreadDataIter(JSRuntime *rt) : JSThread::Map::Range(rt->threads.all()) {}
2914 JSThreadData *threadData() const {
2915 return &front().value->data;
2919 #else /* !JS_THREADSAFE */
2921 class ThreadDataIter
2923 JSRuntime *runtime;
2924 bool done;
2925 public:
2926 ThreadDataIter(JSRuntime *rt) : runtime(rt), done(false) {}
2928 bool empty() const {
2929 return done;
2932 void popFront() {
2933 JS_ASSERT(!done);
2934 done = true;
2937 JSThreadData *threadData() const {
2938 JS_ASSERT(!done);
2939 return &runtime->threadData;
2943 #endif /* !JS_THREADSAFE */
2945 } /* namespace js */
2948 * Create and destroy functions for JSContext, which is manually allocated
2949 * and exclusively owned.
2951 extern JSContext *
2952 js_NewContext(JSRuntime *rt, size_t stackChunkSize);
2954 extern void
2955 js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
2957 static JS_INLINE JSContext *
2958 js_ContextFromLinkField(JSCList *link)
2960 JS_ASSERT(link);
2961 return (JSContext *) ((uint8 *) link - offsetof(JSContext, link));
2965 * If unlocked, acquire and release rt->gcLock around *iterp update; otherwise
2966 * the caller must be holding rt->gcLock.
2968 extern JSContext *
2969 js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
2972 * Iterate through contexts with active requests. The caller must be holding
2973 * rt->gcLock in case of a thread-safe build, or otherwise guarantee that the
2974 * context list is not alternated asynchroniously.
2976 extern JS_FRIEND_API(JSContext *)
2977 js_NextActiveContext(JSRuntime *, JSContext *);
2980 * Class.resolve and watchpoint recursion damping machinery.
2982 extern JSBool
2983 js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
2984 JSResolvingEntry **entryp);
2986 extern void
2987 js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
2988 JSResolvingEntry *entry, uint32 generation);
2991 * Report an exception, which is currently realized as a printf-style format
2992 * string and its arguments.
2994 typedef enum JSErrNum {
2995 #define MSG_DEF(name, number, count, exception, format) \
2996 name = number,
2997 #include "js.msg"
2998 #undef MSG_DEF
2999 JSErr_Limit
3000 } JSErrNum;
3002 extern JS_FRIEND_API(const JSErrorFormatString *)
3003 js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
3005 #ifdef va_start
3006 extern JSBool
3007 js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
3009 extern JSBool
3010 js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
3011 void *userRef, const uintN errorNumber,
3012 JSBool charArgs, va_list ap);
3014 extern JSBool
3015 js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
3016 void *userRef, const uintN errorNumber,
3017 char **message, JSErrorReport *reportp,
3018 bool charArgs, va_list ap);
3019 #endif
3021 extern void
3022 js_ReportOutOfMemory(JSContext *cx);
3025 * Report that cx->scriptStackQuota is exhausted.
3027 void
3028 js_ReportOutOfScriptQuota(JSContext *cx);
3030 extern JS_FRIEND_API(void)
3031 js_ReportOverRecursed(JSContext *cx);
3033 extern JS_FRIEND_API(void)
3034 js_ReportAllocationOverflow(JSContext *cx);
3036 #define JS_CHECK_RECURSION(cx, onerror) \
3037 JS_BEGIN_MACRO \
3038 int stackDummy_; \
3040 if (!JS_CHECK_STACK_SIZE(cx->stackLimit, &stackDummy_)) { \
3041 js_ReportOverRecursed(cx); \
3042 onerror; \
3044 JS_END_MACRO
3047 * Report an exception using a previously composed JSErrorReport.
3048 * XXXbe remove from "friend" API
3050 extern JS_FRIEND_API(void)
3051 js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
3053 extern void
3054 js_ReportIsNotDefined(JSContext *cx, const char *name);
3057 * Report an attempt to access the property of a null or undefined value (v).
3059 extern JSBool
3060 js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const js::Value &v,
3061 JSString *fallback);
3063 extern void
3064 js_ReportMissingArg(JSContext *cx, const js::Value &v, uintN arg);
3067 * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
3068 * the first argument for the error message. If the error message has less
3069 * then 3 arguments, use null for arg1 or arg2.
3071 extern JSBool
3072 js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
3073 intN spindex, const js::Value &v, JSString *fallback,
3074 const char *arg1, const char *arg2);
3076 #define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
3077 ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
3078 spindex, v, fallback, NULL, NULL))
3080 #define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1) \
3081 ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
3082 spindex, v, fallback, arg1, NULL))
3084 #define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2) \
3085 ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
3086 spindex, v, fallback, arg1, arg2))
3088 extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
3090 #ifdef JS_THREADSAFE
3091 # define JS_ASSERT_REQUEST_DEPTH(cx) (JS_ASSERT((cx)->thread), \
3092 JS_ASSERT((cx)->thread->data.requestDepth >= 1))
3093 #else
3094 # define JS_ASSERT_REQUEST_DEPTH(cx) ((void) 0)
3095 #endif
3098 * If the operation callback flag was set, call the operation callback.
3099 * This macro can run the full GC. Return true if it is OK to continue and
3100 * false otherwise.
3102 #define JS_CHECK_OPERATION_LIMIT(cx) \
3103 (JS_ASSERT_REQUEST_DEPTH(cx), \
3104 (!JS_THREAD_DATA(cx)->interruptFlags || js_InvokeOperationCallback(cx)))
3106 JS_ALWAYS_INLINE void
3107 JSThreadData::triggerOperationCallback(JSRuntime *rt)
3110 * Use JS_ATOMIC_SET and JS_ATOMIC_INCREMENT in the hope that it ensures
3111 * the write will become immediately visible to other processors polling
3112 * the flag. Note that we only care about visibility here, not read/write
3113 * ordering: this field can only be written with the GC lock held.
3115 if (interruptFlags)
3116 return;
3117 JS_ATOMIC_SET(&interruptFlags, 1);
3119 #ifdef JS_THREADSAFE
3120 /* rt->interruptCounter does not reflect suspended threads. */
3121 if (requestDepth != 0)
3122 JS_ATOMIC_INCREMENT(&rt->interruptCounter);
3123 #endif
3127 * Invoke the operation callback and return false if the current execution
3128 * is to be terminated.
3130 extern JSBool
3131 js_InvokeOperationCallback(JSContext *cx);
3133 extern JSBool
3134 js_HandleExecutionInterrupt(JSContext *cx);
3136 namespace js {
3138 /* These must be called with GC lock taken. */
3140 JS_FRIEND_API(void)
3141 TriggerOperationCallback(JSContext *cx);
3143 void
3144 TriggerAllOperationCallbacks(JSRuntime *rt);
3146 } /* namespace js */
3148 extern JSStackFrame *
3149 js_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
3151 extern jsbytecode*
3152 js_GetCurrentBytecodePC(JSContext* cx);
3154 extern bool
3155 js_CurrentPCIsInImacro(JSContext *cx);
3157 namespace js {
3159 class RegExpStatics;
3161 extern JS_FORCES_STACK JS_FRIEND_API(void)
3162 LeaveTrace(JSContext *cx);
3164 } /* namespace js */
3167 * Get the current frame, first lazily instantiating stack frames if needed.
3168 * (Do not access cx->fp() directly except in JS_REQUIRES_STACK code.)
3170 * Defined in jstracer.cpp if JS_TRACER is defined.
3172 static JS_FORCES_STACK JS_INLINE JSStackFrame *
3173 js_GetTopStackFrame(JSContext *cx)
3175 js::LeaveTrace(cx);
3176 return cx->maybefp();
3179 static JS_INLINE JSBool
3180 js_IsPropertyCacheDisabled(JSContext *cx)
3182 return cx->runtime->shapeGen >= js::SHAPE_OVERFLOW_BIT;
3185 static JS_INLINE uint32
3186 js_RegenerateShapeForGC(JSRuntime *rt)
3188 JS_ASSERT(rt->gcRunning);
3189 JS_ASSERT(rt->gcRegenShapes);
3192 * Under the GC, compared with js_GenerateShape, we don't need to use
3193 * atomic increments but we still must make sure that after an overflow
3194 * the shape stays such.
3196 uint32 shape = rt->shapeGen;
3197 shape = (shape + 1) | (shape & js::SHAPE_OVERFLOW_BIT);
3198 rt->shapeGen = shape;
3199 return shape;
3202 namespace js {
3204 inline void *
3205 ContextAllocPolicy::malloc(size_t bytes)
3207 return cx->malloc(bytes);
3210 inline void
3211 ContextAllocPolicy::free(void *p)
3213 cx->free(p);
3216 inline void *
3217 ContextAllocPolicy::realloc(void *p, size_t bytes)
3219 return cx->realloc(p, bytes);
3222 inline void
3223 ContextAllocPolicy::reportAllocOverflow() const
3225 js_ReportAllocationOverflow(cx);
3228 template<class T>
3229 class AutoVectorRooter : protected AutoGCRooter
3231 public:
3232 explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
3233 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3234 : AutoGCRooter(cx, tag), vector(cx)
3236 JS_GUARD_OBJECT_NOTIFIER_INIT;
3239 size_t length() const { return vector.length(); }
3241 bool append(const T &v) { return vector.append(v); }
3243 void popBack() { vector.popBack(); }
3245 bool growBy(size_t inc) {
3246 size_t oldLength = vector.length();
3247 if (!vector.growByUninitialized(inc))
3248 return false;
3249 MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
3250 return true;
3253 bool resize(size_t newLength) {
3254 size_t oldLength = vector.length();
3255 if (newLength <= oldLength) {
3256 vector.shrinkBy(oldLength - newLength);
3257 return true;
3259 if (!vector.growByUninitialized(newLength - oldLength))
3260 return false;
3261 MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
3262 return true;
3265 bool reserve(size_t newLength) {
3266 return vector.reserve(newLength);
3269 T &operator[](size_t i) { return vector[i]; }
3270 const T &operator[](size_t i) const { return vector[i]; }
3272 const T *begin() const { return vector.begin(); }
3273 T *begin() { return vector.begin(); }
3275 const T *end() const { return vector.end(); }
3276 T *end() { return vector.end(); }
3278 const T &back() const { return vector.back(); }
3280 friend void AutoGCRooter::trace(JSTracer *trc);
3282 private:
3283 Vector<T, 8> vector;
3284 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3287 class AutoValueVector : public AutoVectorRooter<Value>
3289 public:
3290 explicit AutoValueVector(JSContext *cx
3291 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3292 : AutoVectorRooter<Value>(cx, VALVECTOR)
3294 JS_GUARD_OBJECT_NOTIFIER_INIT;
3297 const jsval *jsval_begin() const { return Jsvalify(begin()); }
3298 jsval *jsval_begin() { return Jsvalify(begin()); }
3300 const jsval *jsval_end() const { return Jsvalify(end()); }
3301 jsval *jsval_end() { return Jsvalify(end()); }
3303 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3306 class AutoIdVector : public AutoVectorRooter<jsid>
3308 public:
3309 explicit AutoIdVector(JSContext *cx
3310 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3311 : AutoVectorRooter<jsid>(cx, IDVECTOR)
3313 JS_GUARD_OBJECT_NOTIFIER_INIT;
3316 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3319 class AutoShapeVector : public AutoVectorRooter<const Shape *>
3321 public:
3322 explicit AutoShapeVector(JSContext *cx
3323 JS_GUARD_OBJECT_NOTIFIER_PARAM)
3324 : AutoVectorRooter<const Shape *>(cx, SHAPEVECTOR)
3326 JS_GUARD_OBJECT_NOTIFIER_INIT;
3329 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3332 JSIdArray *
3333 NewIdArray(JSContext *cx, jsint length);
3335 } /* namespace js */
3337 #ifdef _MSC_VER
3338 #pragma warning(pop)
3339 #pragma warning(pop)
3340 #endif
3342 #ifdef JS_CNTXT_UNDEFD_MOZALLOC_WRAPPERS
3343 # include "mozilla/mozalloc_macro_wrappers.h"
3344 #endif
3346 #endif /* jscntxt_h___ */