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