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 #include "vm/SymbolType.h"
9 #include "gc/HashUtil.h"
10 #include "js/Printer.h" // js::GenericPrinter, js::Fprinter
11 #include "util/StringBuffer.h"
12 #include "vm/JSContext.h"
13 #include "vm/JSONPrinter.h" // js::JSONPrinter
16 #include "vm/Realm-inl.h"
21 Symbol
* Symbol::newInternal(JSContext
* cx
, JS::SymbolCode code
, uint32_t hash
,
22 Handle
<JSAtom
*> description
) {
23 MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx
->runtime()));
24 AutoAllocInAtomsZone
az(cx
);
25 return cx
->newCell
<Symbol
>(code
, hash
, description
);
28 Symbol
* Symbol::new_(JSContext
* cx
, JS::SymbolCode code
,
29 HandleString description
) {
30 Rooted
<JSAtom
*> atom(cx
);
32 atom
= AtomizeString(cx
, description
);
38 Symbol
* sym
= newInternal(cx
, code
, cx
->runtime()->randomHashCode(), atom
);
45 Symbol
* Symbol::newWellKnown(JSContext
* cx
, JS::SymbolCode code
,
46 Handle
<PropertyName
*> description
) {
47 return newInternal(cx
, code
, cx
->runtime()->randomHashCode(), description
);
50 Symbol
* Symbol::for_(JSContext
* cx
, HandleString description
) {
51 Rooted
<JSAtom
*> atom(cx
, AtomizeString(cx
, description
));
56 SymbolRegistry
& registry
= cx
->symbolRegistry();
57 DependentAddPtr
<SymbolRegistry
> p(cx
, registry
, atom
);
63 // Rehash the hash of the atom to give the corresponding symbol a hash
64 // that is different than the hash of the corresponding atom.
65 HashNumber hash
= mozilla::HashGeneric(atom
->hash());
66 Symbol
* sym
= newInternal(cx
, SymbolCode::InSymbolRegistry
, hash
, atom
);
71 if (!p
.add(cx
, registry
, atom
, sym
)) {
79 #if defined(DEBUG) || defined(JS_JITSPEW)
80 void Symbol::dump() const {
81 js::Fprinter
out(stderr
);
85 void Symbol::dump(js::GenericPrinter
& out
) const {
86 js::JSONPrinter
json(out
);
91 void Symbol::dump(js::JSONPrinter
& json
) const {
97 template <typename KnownF
, typename UnknownF
>
98 void SymbolCodeToString(JS::SymbolCode code
, KnownF known
, UnknownF unknown
) {
100 # define DEFINE_CASE(name) \
101 case JS::SymbolCode::name: \
104 JS_FOR_EACH_WELL_KNOWN_SYMBOL(DEFINE_CASE
)
107 case JS::SymbolCode::Limit
:
110 case JS::SymbolCode::WellKnownAPILimit
:
111 known("WellKnownAPILimit");
113 case JS::SymbolCode::PrivateNameSymbol
:
114 known("PrivateNameSymbol");
116 case JS::SymbolCode::InSymbolRegistry
:
117 known("InSymbolRegistry");
119 case JS::SymbolCode::UniqueSymbol
:
120 known("UniqueSymbol");
123 unknown(uint32_t(code
));
128 void Symbol::dumpFields(js::JSONPrinter
& json
) const {
129 json
.formatProperty("address", "(JS::Symbol*)0x%p", this);
132 code_
, [&](const char* name
) { json
.property("code", name
); },
134 json
.formatProperty("code", "Unknown(%08x)", code
);
137 json
.formatProperty("hash", "0x%08x", hash());
140 js::GenericPrinter
& out
= json
.beginStringProperty("description");
141 description()->dumpCharsNoQuote(out
);
142 json
.endStringProperty();
144 json
.nullProperty("description");
148 void Symbol::dumpStringContent(js::GenericPrinter
& out
) const {
149 dumpPropertyName(out
);
151 if (!isWellKnownSymbol()) {
152 out
.printf(" @ (JS::Symbol*)0x%p", this);
156 void Symbol::dumpPropertyName(js::GenericPrinter
& out
) const {
157 if (isWellKnownSymbol()) {
158 // All the well-known symbol names are ASCII.
159 description()->dumpCharsNoQuote(out
);
160 } else if (code_
== SymbolCode::InSymbolRegistry
||
161 code_
== SymbolCode::UniqueSymbol
) {
162 out
.printf(code_
== SymbolCode::InSymbolRegistry
? "Symbol.for("
166 description()->dumpCharsSingleQuote(out
);
168 out
.printf("undefined");
172 } else if (code_
== SymbolCode::PrivateNameSymbol
) {
173 MOZ_ASSERT(description());
175 description()->dumpCharsNoQuote(out
);
177 out
.printf("<Invalid Symbol code=%u>", unsigned(code_
));
180 #endif // defined(DEBUG) || defined(JS_JITSPEW)
182 bool js::SymbolDescriptiveString(JSContext
* cx
, Symbol
* sym
,
183 MutableHandleValue result
) {
185 JSStringBuilder
sb(cx
);
186 if (!sb
.append("Symbol(")) {
189 if (JSAtom
* desc
= sym
->description()) {
190 if (!sb
.append(desc
)) {
194 if (!sb
.append(')')) {
199 JSString
* str
= sb
.finishString();
203 result
.setString(str
);
207 JS::ubi::Node::Size
JS::ubi::Concrete
<JS::Symbol
>::size(
208 mozilla::MallocSizeOf mallocSizeOf
) const {
209 // If we start allocating symbols in the nursery, we will need to update
211 MOZ_ASSERT(get().isTenured());
212 return js::gc::Arena::thingSize(get().asTenured().getAllocKind());