1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jspubtd_h
8 #define jspubtd_h
9 
10 /*
11  * JS public API typedefs.
12  */
13 
14 #include "mozilla/Assertions.h"
15 #include "mozilla/LinkedList.h"
16 #include "mozilla/PodOperations.h"
17 
18 #include "jsprototypes.h"
19 #include "jstypes.h"
20 
21 #include "js/TypeDecls.h"
22 
23 #if defined(JS_GC_ZEAL) || defined(DEBUG)
24 # define JSGC_HASH_TABLE_CHECKS
25 #endif
26 
27 namespace JS {
28 
29 template <typename T>
30 class AutoVectorRooter;
31 typedef AutoVectorRooter<jsid> AutoIdVector;
32 class CallArgs;
33 
34 template <typename T>
35 class Rooted;
36 
37 class JS_FRIEND_API(CompileOptions);
38 class JS_FRIEND_API(ReadOnlyCompileOptions);
39 class JS_FRIEND_API(OwningCompileOptions);
40 class JS_FRIEND_API(TransitiveCompileOptions);
41 class JS_PUBLIC_API(CompartmentOptions);
42 
43 class Value;
44 struct Zone;
45 
46 } /* namespace JS */
47 
48 namespace js {
49 struct ContextFriendFields;
50 class RootLists;
51 } // namespace js
52 
53 /*
54  * Run-time version enumeration.  For compile-time version checking, please use
55  * the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION,
56  * MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions.
57  */
58 enum JSVersion {
59     JSVERSION_ECMA_3  = 148,
60     JSVERSION_1_6     = 160,
61     JSVERSION_1_7     = 170,
62     JSVERSION_1_8     = 180,
63     JSVERSION_ECMA_5  = 185,
64     JSVERSION_DEFAULT = 0,
65     JSVERSION_UNKNOWN = -1,
66     JSVERSION_LATEST  = JSVERSION_ECMA_5
67 };
68 
69 /* Result of typeof operator enumeration. */
70 enum JSType {
71     JSTYPE_VOID,                /* undefined */
72     JSTYPE_OBJECT,              /* object */
73     JSTYPE_FUNCTION,            /* function */
74     JSTYPE_STRING,              /* string */
75     JSTYPE_NUMBER,              /* number */
76     JSTYPE_BOOLEAN,             /* boolean */
77     JSTYPE_NULL,                /* null */
78     JSTYPE_SYMBOL,              /* symbol */
79     JSTYPE_LIMIT
80 };
81 
82 /* Dense index into cached prototypes and class atoms for standard objects. */
83 enum JSProtoKey {
84 #define PROTOKEY_AND_INITIALIZER(name,code,init,clasp) JSProto_##name = code,
85     JS_FOR_EACH_PROTOTYPE(PROTOKEY_AND_INITIALIZER)
86 #undef PROTOKEY_AND_INITIALIZER
87     JSProto_LIMIT
88 };
89 
90 /* Struct forward declarations. */
91 struct JSClass;
92 struct JSCompartment;
93 struct JSCrossCompartmentCall;
94 class JSErrorReport;
95 struct JSExceptionState;
96 struct JSFunctionSpec;
97 struct JSLocaleCallbacks;
98 struct JSObjectMap;
99 struct JSPrincipals;
100 struct JSPropertyDescriptor;
101 struct JSPropertyName;
102 struct JSPropertySpec;
103 struct JSRuntime;
104 struct JSSecurityCallbacks;
105 struct JSStructuredCloneCallbacks;
106 struct JSStructuredCloneReader;
107 struct JSStructuredCloneWriter;
108 class JS_PUBLIC_API(JSTracer);
109 
110 class JSFlatString;
111 
112 typedef struct PRCallOnceType   JSCallOnceType;
113 typedef bool                    (*JSInitCallback)(void);
114 
115 template<typename T> struct JSConstScalarSpec;
116 typedef JSConstScalarSpec<double> JSConstDoubleSpec;
117 typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
118 
119 /*
120  * Generic trace operation that calls JS_CallTracer on each traceable thing
121  * stored in data.
122  */
123 typedef void
124 (* JSTraceDataOp)(JSTracer* trc, void* data);
125 
126 namespace js {
127 
128 void FinishGC(JSRuntime* rt);
129 
130 namespace gc {
131 class AutoTraceSession;
132 class StoreBuffer;
133 void MarkPersistentRootedChains(JSTracer*);
134 void MarkPersistentRootedChainsInLists(js::RootLists&, JSTracer*);
135 void FinishPersistentRootedChains(js::RootLists&);
136 } // namespace gc
137 } // namespace js
138 
139 namespace JS {
140 
141 typedef void (*OffThreadCompileCallback)(void* token, void* callbackData);
142 
143 enum class HeapState {
144     Idle,             // doing nothing with the GC heap
145     Tracing,          // tracing the GC heap without collecting, e.g. IterateCompartments()
146     MajorCollecting,  // doing a GC of the major heap
147     MinorCollecting   // doing a GC of the minor heap (nursery)
148 };
149 
150 namespace shadow {
151 
152 struct Runtime
153 {
154   protected:
155     // Allow inlining of heapState checks.
156     friend class js::gc::AutoTraceSession;
157     JS::HeapState heapState_;
158 
159     js::gc::StoreBuffer* gcStoreBufferPtr_;
160 
161   public:
RuntimeRuntime162     Runtime()
163       : heapState_(JS::HeapState::Idle)
164       , gcStoreBufferPtr_(nullptr)
165     {}
166 
isHeapBusyRuntime167     bool isHeapBusy() const { return heapState_ != JS::HeapState::Idle; }
isHeapMajorCollectingRuntime168     bool isHeapMajorCollecting() const { return heapState_ == JS::HeapState::MajorCollecting; }
isHeapMinorCollectingRuntime169     bool isHeapMinorCollecting() const { return heapState_ == JS::HeapState::MinorCollecting; }
isHeapCollectingRuntime170     bool isHeapCollecting() const { return isHeapMinorCollecting() || isHeapMajorCollecting(); }
171 
gcStoreBufferPtrRuntime172     js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
173 
asShadowRuntimeRuntime174     static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) {
175         return reinterpret_cast<JS::shadow::Runtime*>(rt);
176     }
177 
178   protected:
setGCStoreBufferPtrRuntime179     void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) {
180         gcStoreBufferPtr_ = storeBuffer;
181     }
182 };
183 
184 } /* namespace shadow */
185 
JS_PUBLIC_API(AutoGCRooter)186 class JS_PUBLIC_API(AutoGCRooter)
187 {
188   public:
189     AutoGCRooter(JSContext* cx, ptrdiff_t tag);
190     AutoGCRooter(js::ContextFriendFields* cx, ptrdiff_t tag);
191 
192     ~AutoGCRooter() {
193         MOZ_ASSERT(this == *stackTop);
194         *stackTop = down;
195     }
196 
197     /* Implemented in gc/RootMarking.cpp. */
198     inline void trace(JSTracer* trc);
199     static void traceAll(JSTracer* trc);
200     static void traceAllWrappers(JSTracer* trc);
201 
202     /* T must be a context type */
203     template<typename T>
204     static void traceAllInContext(T* cx, JSTracer* trc) {
205         for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down)
206             gcr->trace(trc);
207     }
208 
209   protected:
210     AutoGCRooter * const down;
211 
212     /*
213      * Discriminates actual subclass of this being used.  If non-negative, the
214      * subclass roots an array of values of the length stored in this field.
215      * If negative, meaning is indicated by the corresponding value in the enum
216      * below.  Any other negative value indicates some deeper problem such as
217      * memory corruption.
218      */
219     ptrdiff_t tag_;
220 
221     enum {
222         VALARRAY =     -2, /* js::AutoValueArray */
223         PARSER =       -3, /* js::frontend::Parser */
224         VALVECTOR =   -10, /* js::AutoValueVector */
225         IDVECTOR =    -11, /* js::AutoIdVector */
226         OBJVECTOR =   -14, /* js::AutoObjectVector */
227         IONMASM =     -19, /* js::jit::MacroAssembler */
228         WRAPVECTOR =  -20, /* js::AutoWrapperVector */
229         WRAPPER =     -21, /* js::AutoWrapperRooter */
230         CUSTOM =      -26  /* js::CustomAutoRooter */
231     };
232 
233     static ptrdiff_t GetTag(const Value& value) { return VALVECTOR; }
234     static ptrdiff_t GetTag(const jsid& id) { return IDVECTOR; }
235     static ptrdiff_t GetTag(JSObject* obj) { return OBJVECTOR; }
236 
237   private:
238     AutoGCRooter ** const stackTop;
239 
240     /* No copy or assignment semantics. */
241     AutoGCRooter(AutoGCRooter& ida) = delete;
242     void operator=(AutoGCRooter& ida) = delete;
243 };
244 
245 } /* namespace JS */
246 
247 namespace js {
248 
249 class ExclusiveContext;
250 
251 /*
252  * This list enumerates the different types of conceptual stacks we have in
253  * SpiderMonkey. In reality, they all share the C stack, but we allow different
254  * stack limits depending on the type of code running.
255  */
256 enum StackKind
257 {
258     StackForSystemCode,      // C++, such as the GC, running on behalf of the VM.
259     StackForTrustedScript,   // Script running with trusted principals.
260     StackForUntrustedScript, // Script running with untrusted principals.
261     StackKindCount
262 };
263 
264 enum ThingRootKind
265 {
266     THING_ROOT_OBJECT,
267     THING_ROOT_SHAPE,
268     THING_ROOT_BASE_SHAPE,
269     THING_ROOT_OBJECT_GROUP,
270     THING_ROOT_STRING,
271     THING_ROOT_SYMBOL,
272     THING_ROOT_JIT_CODE,
273     THING_ROOT_SCRIPT,
274     THING_ROOT_LAZY_SCRIPT,
275     THING_ROOT_ID,
276     THING_ROOT_VALUE,
277     THING_ROOT_TRACEABLE,
278     THING_ROOT_LIMIT
279 };
280 
281 template <typename T>
282 struct RootKind;
283 
284 /*
285  * Specifically mark the ThingRootKind of externally visible types, so that
286  * JSAPI users may use JSRooted... types without having the class definition
287  * available.
288  */
289 template<typename T, ThingRootKind Kind>
290 struct SpecificRootKind
291 {
rootKindSpecificRootKind292     static ThingRootKind rootKind() { return Kind; }
293 };
294 
295 template <> struct RootKind<JSObject*> : SpecificRootKind<JSObject*, THING_ROOT_OBJECT> {};
296 template <> struct RootKind<JSFlatString*> : SpecificRootKind<JSFlatString*, THING_ROOT_STRING> {};
297 template <> struct RootKind<JSFunction*> : SpecificRootKind<JSFunction*, THING_ROOT_OBJECT> {};
298 template <> struct RootKind<JSString*> : SpecificRootKind<JSString*, THING_ROOT_STRING> {};
299 template <> struct RootKind<JS::Symbol*> : SpecificRootKind<JS::Symbol*, THING_ROOT_SYMBOL> {};
300 template <> struct RootKind<JSScript*> : SpecificRootKind<JSScript*, THING_ROOT_SCRIPT> {};
301 template <> struct RootKind<jsid> : SpecificRootKind<jsid, THING_ROOT_ID> {};
302 template <> struct RootKind<JS::Value> : SpecificRootKind<JS::Value, THING_ROOT_VALUE> {};
303 
304 // Abstracts JS rooting mechanisms so they can be shared between the JSContext
305 // and JSRuntime.
306 class RootLists
307 {
308     // Stack GC roots for stack-allocated GC heap pointers.
309     JS::Rooted<void*>* stackRoots_[THING_ROOT_LIMIT];
310     template <typename T> friend class JS::Rooted;
311 
312     // Stack GC roots for stack-allocated AutoFooRooter classes.
313     JS::AutoGCRooter* autoGCRooters_;
314     friend class JS::AutoGCRooter;
315 
316   public:
317     RootLists() : autoGCRooters_(nullptr) {
318         mozilla::PodArrayZero(stackRoots_);
319     }
320 
321     template <class T>
322     inline JS::Rooted<T>* gcRooters() {
323         js::ThingRootKind kind = RootKind<T>::rootKind();
324         return reinterpret_cast<JS::Rooted<T>*>(stackRoots_[kind]);
325     }
326 
327     void checkNoGCRooters();
328 
329     /* Allow inlining of PersistentRooted constructors and destructors. */
330   private:
331     template <typename Referent> friend class JS::PersistentRooted;
332     friend void js::gc::MarkPersistentRootedChains(JSTracer*);
333     friend void js::gc::MarkPersistentRootedChainsInLists(RootLists&, JSTracer*);
334     friend void js::gc::FinishPersistentRootedChains(RootLists&);
335 
336     mozilla::LinkedList<JS::PersistentRooted<void*>> heapRoots_[THING_ROOT_LIMIT];
337 
338     /* Specializations of this return references to the appropriate list. */
339     template<typename Referent>
340     inline mozilla::LinkedList<JS::PersistentRooted<Referent>>& getPersistentRootedList();
341 };
342 
343 template<>
344 inline mozilla::LinkedList<JS::PersistentRootedFunction>&
345 RootLists::getPersistentRootedList<JSFunction*>() {
346     return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSFunction*>>&>(
347         heapRoots_[THING_ROOT_OBJECT]);
348 }
349 
350 template<>
351 inline mozilla::LinkedList<JS::PersistentRootedObject>&
352 RootLists::getPersistentRootedList<JSObject*>() {
353     return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSObject*>>&>(
354         heapRoots_[THING_ROOT_OBJECT]);
355 }
356 
357 template<>
358 inline mozilla::LinkedList<JS::PersistentRootedId>&
359 RootLists::getPersistentRootedList<jsid>() {
360     return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<jsid>>&>(
361         heapRoots_[THING_ROOT_ID]);
362 }
363 
364 template<>
365 inline mozilla::LinkedList<JS::PersistentRootedScript>&
366 RootLists::getPersistentRootedList<JSScript*>() {
367     return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSScript*>>&>(
368         heapRoots_[THING_ROOT_SCRIPT]);
369 }
370 
371 template<>
372 inline mozilla::LinkedList<JS::PersistentRootedString>&
373 RootLists::getPersistentRootedList<JSString*>() {
374     return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSString*>>&>(
375         heapRoots_[THING_ROOT_STRING]);
376 }
377 
378 template<>
379 inline mozilla::LinkedList<JS::PersistentRootedValue>&
380 RootLists::getPersistentRootedList<JS::Value>() {
381     return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JS::Value>>&>(
382         heapRoots_[THING_ROOT_VALUE]);
383 }
384 
385 struct ContextFriendFields
386 {
387   protected:
388     JSRuntime* const     runtime_;
389 
390     /* The current compartment. */
391     JSCompartment*      compartment_;
392 
393     /* The current zone. */
394     JS::Zone*           zone_;
395 
396   public:
397     /* Rooting structures. */
398     RootLists           roots;
399 
400     explicit ContextFriendFields(JSRuntime* rt)
401       : runtime_(rt), compartment_(nullptr), zone_(nullptr)
402     {}
403 
404     static const ContextFriendFields* get(const JSContext* cx) {
405         return reinterpret_cast<const ContextFriendFields*>(cx);
406     }
407 
408     static ContextFriendFields* get(JSContext* cx) {
409         return reinterpret_cast<ContextFriendFields*>(cx);
410     }
411 
412     friend JSRuntime* GetRuntime(const JSContext* cx);
413     friend JSCompartment* GetContextCompartment(const JSContext* cx);
414     friend JS::Zone* GetContextZone(const JSContext* cx);
415     template <typename T> friend class JS::Rooted;
416 };
417 
418 /*
419  * Inlinable accessors for JSContext.
420  *
421  * - These must not be available on the more restricted superclasses of
422  *   JSContext, so we can't simply define them on ContextFriendFields.
423  *
424  * - They're perfectly ordinary JSContext functionality, so ought to be
425  *   usable without resorting to jsfriendapi.h, and when JSContext is an
426  *   incomplete type.
427  */
428 inline JSRuntime*
429 GetRuntime(const JSContext* cx)
430 {
431     return ContextFriendFields::get(cx)->runtime_;
432 }
433 
434 inline JSCompartment*
435 GetContextCompartment(const JSContext* cx)
436 {
437     return ContextFriendFields::get(cx)->compartment_;
438 }
439 
440 inline JS::Zone*
441 GetContextZone(const JSContext* cx)
442 {
443     return ContextFriendFields::get(cx)->zone_;
444 }
445 
446 class PerThreadData;
447 
448 struct PerThreadDataFriendFields
449 {
450   private:
451     // Note: this type only exists to permit us to derive the offset of
452     // the perThread data within the real JSRuntime* type in a portable
453     // way.
454     struct RuntimeDummy : JS::shadow::Runtime
455     {
456         struct PerThreadDummy {
457             void* field1;
458             uintptr_t field2;
459 #ifdef JS_DEBUG
460             uint64_t field3;
461 #endif
462         } mainThread;
463     };
464 
465   public:
466     /* Rooting structures. */
467     RootLists roots;
468 
469     PerThreadDataFriendFields();
470 
471     /* Limit pointer for checking native stack consumption. */
472     uintptr_t nativeStackLimit[js::StackKindCount];
473 
474     static const size_t RuntimeMainThreadOffset = offsetof(RuntimeDummy, mainThread);
475 
476     static inline PerThreadDataFriendFields* get(js::PerThreadData* pt) {
477         return reinterpret_cast<PerThreadDataFriendFields*>(pt);
478     }
479 
480     static inline PerThreadDataFriendFields* getMainThread(JSRuntime* rt) {
481         // mainThread must always appear directly after |JS::shadow::Runtime|.
482         // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
483         return reinterpret_cast<PerThreadDataFriendFields*>(
484             reinterpret_cast<char*>(rt) + RuntimeMainThreadOffset);
485     }
486 
487     static inline const PerThreadDataFriendFields* getMainThread(const JSRuntime* rt) {
488         // mainThread must always appear directly after |JS::shadow::Runtime|.
489         // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
490         return reinterpret_cast<const PerThreadDataFriendFields*>(
491             reinterpret_cast<const char*>(rt) + RuntimeMainThreadOffset);
492     }
493 
494     template <typename T> friend class JS::Rooted;
495 };
496 
497 } /* namespace js */
498 
499 #endif /* jspubtd_h */
500