Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / js / src / vm / SymbolType.h
blob2a66e6c30f7667a80191dcbf5141820d66811604
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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/. */
7 #ifndef vm_SymbolType_h
8 #define vm_SymbolType_h
10 #include <stdio.h>
12 #include "gc/Barrier.h"
13 #include "gc/Tracer.h"
14 #include "js/AllocPolicy.h"
15 #include "js/GCHashTable.h"
16 #include "js/RootingAPI.h"
17 #include "js/shadow/Symbol.h" // JS::shadow::Symbol
18 #include "js/Symbol.h"
19 #include "js/TypeDecls.h"
20 #include "vm/StringType.h"
22 namespace js {
23 class JS_PUBLIC_API GenericPrinter;
26 namespace JS {
28 class Symbol
29 : public js::gc::CellWithTenuredGCPointer<js::gc::TenuredCell, JSAtom> {
30 friend class js::gc::CellAllocator;
32 public:
33 // User description of symbol, stored in the cell header.
34 JSAtom* description() const { return headerPtr(); }
36 private:
37 SymbolCode code_;
39 // Each Symbol gets its own hash code so that we don't have to use
40 // addresses as hash codes (a security hazard).
41 js::HashNumber hash_;
43 Symbol(SymbolCode code, js::HashNumber hash, Handle<JSAtom*> desc)
44 : CellWithTenuredGCPointer(desc), code_(code), hash_(hash) {}
46 Symbol(const Symbol&) = delete;
47 void operator=(const Symbol&) = delete;
49 static Symbol* newInternal(JSContext* cx, SymbolCode code,
50 js::HashNumber hash, Handle<JSAtom*> description);
52 static void staticAsserts() {
53 static_assert(uint32_t(SymbolCode::WellKnownAPILimit) ==
54 JS::shadow::Symbol::WellKnownAPILimit,
55 "JS::shadow::Symbol::WellKnownAPILimit must match "
56 "SymbolCode::WellKnownAPILimit");
57 static_assert(
58 offsetof(Symbol, code_) == offsetof(JS::shadow::Symbol, code_),
59 "JS::shadow::Symbol::code_ offset must match SymbolCode::code_");
62 public:
63 static Symbol* new_(JSContext* cx, SymbolCode code,
64 js::HandleString description);
65 static Symbol* newWellKnown(JSContext* cx, SymbolCode code,
66 Handle<js::PropertyName*> description);
67 static Symbol* for_(JSContext* cx, js::HandleString description);
69 SymbolCode code() const { return code_; }
70 js::HashNumber hash() const { return hash_; }
72 bool isWellKnownSymbol() const {
73 return uint32_t(code_) < WellKnownSymbolLimit;
76 // An "interesting symbol" is a well-known symbol, like @@toStringTag,
77 // that's often looked up on random objects but is usually not present. We
78 // optimize this by setting a flag on the object's BaseShape when such
79 // symbol properties are added, so we can optimize lookups on objects that
80 // don't have the BaseShape flag.
81 bool isInterestingSymbol() const {
82 return code_ == SymbolCode::toStringTag ||
83 code_ == SymbolCode::toPrimitive ||
84 code_ == SymbolCode::isConcatSpreadable;
87 // Symbol created for the #PrivateName syntax.
88 bool isPrivateName() const { return code_ == SymbolCode::PrivateNameSymbol; }
90 static const JS::TraceKind TraceKind = JS::TraceKind::Symbol;
92 void traceChildren(JSTracer* trc);
93 void finalize(JS::GCContext* gcx) {}
95 // Override base class implementation to tell GC about well-known symbols.
96 bool isPermanentAndMayBeShared() const { return isWellKnownSymbol(); }
98 size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
99 return mallocSizeOf(this);
102 #if defined(DEBUG) || defined(JS_JITSPEW)
103 void dump(); // Debugger-friendly stderr dump.
104 void dump(js::GenericPrinter& out);
105 #endif
107 static constexpr size_t offsetOfHash() { return offsetof(Symbol, hash_); }
110 } /* namespace JS */
112 namespace js {
114 /* Hash policy used by the SymbolRegistry. */
115 struct HashSymbolsByDescription {
116 using Key = JS::Symbol*;
117 using Lookup = JSAtom*;
119 static HashNumber hash(Lookup l) { return HashNumber(l->hash()); }
120 static bool match(Key sym, Lookup l) { return sym->description() == l; }
124 * [SMDOC] Symbol.for() registry (ES6 GlobalSymbolRegistry)
126 * The runtime-wide symbol registry, used to implement Symbol.for().
128 * ES6 draft rev 25 (2014 May 22) calls this the GlobalSymbolRegistry List. In
129 * our implementation, it is not global. There is one per JSRuntime. The
130 * symbols in the symbol registry, like all symbols, are allocated in the atoms
131 * compartment and can be directly referenced from any compartment. They are
132 * never shared across runtimes.
134 * The memory management strategy here is modeled after js::AtomSet. It's like
135 * a WeakSet. The registry itself does not keep any symbols alive; when a
136 * symbol in the registry is collected, the registry entry is removed. No GC
137 * nondeterminism is exposed to scripts, because there is no API for
138 * enumerating the symbol registry, querying its size, etc.
140 class SymbolRegistry
141 : public GCHashSet<WeakHeapPtr<JS::Symbol*>, HashSymbolsByDescription,
142 SystemAllocPolicy> {
143 public:
144 SymbolRegistry() = default;
147 // ES6 rev 27 (2014 Aug 24) 19.4.3.3
148 bool SymbolDescriptiveString(JSContext* cx, JS::Symbol* sym,
149 JS::MutableHandleValue result);
151 } /* namespace js */
153 #endif /* vm_SymbolType_h */