Bug 1795082 - Part 2/2: Drop post-processing from getURL() r=zombie
[gecko.git] / js / src / vm / SymbolType.cpp
blob6e08ccb52de3cb93814cec77736a32ca66535ae4
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
14 #include "vm/Realm.h"
16 #include "vm/Realm-inl.h"
18 using JS::Symbol;
19 using namespace js;
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);
31 if (description) {
32 atom = AtomizeString(cx, description);
33 if (!atom) {
34 return nullptr;
38 Symbol* sym = newInternal(cx, code, cx->runtime()->randomHashCode(), atom);
39 if (sym) {
40 cx->markAtom(sym);
42 return sym;
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));
52 if (!atom) {
53 return nullptr;
56 SymbolRegistry& registry = cx->symbolRegistry();
57 DependentAddPtr<SymbolRegistry> p(cx, registry, atom);
58 if (p) {
59 cx->markAtom(*p);
60 return *p;
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);
67 if (!sym) {
68 return nullptr;
71 if (!p.add(cx, registry, atom, sym)) {
72 return nullptr;
75 cx->markAtom(sym);
76 return sym;
79 #if defined(DEBUG) || defined(JS_JITSPEW)
80 void Symbol::dump() const {
81 js::Fprinter out(stderr);
82 dump(out);
85 void Symbol::dump(js::GenericPrinter& out) const {
86 js::JSONPrinter json(out);
87 dump(json);
88 out.put("\n");
91 void Symbol::dump(js::JSONPrinter& json) const {
92 json.beginObject();
93 dumpFields(json);
94 json.endObject();
97 template <typename KnownF, typename UnknownF>
98 void SymbolCodeToString(JS::SymbolCode code, KnownF known, UnknownF unknown) {
99 switch (code) {
100 # define DEFINE_CASE(name) \
101 case JS::SymbolCode::name: \
102 known(#name); \
103 break;
104 JS_FOR_EACH_WELL_KNOWN_SYMBOL(DEFINE_CASE)
105 # undef DEFINE_CASE
107 case JS::SymbolCode::Limit:
108 known("Limit");
109 break;
110 case JS::SymbolCode::WellKnownAPILimit:
111 known("WellKnownAPILimit");
112 break;
113 case JS::SymbolCode::PrivateNameSymbol:
114 known("PrivateNameSymbol");
115 break;
116 case JS::SymbolCode::InSymbolRegistry:
117 known("InSymbolRegistry");
118 break;
119 case JS::SymbolCode::UniqueSymbol:
120 known("UniqueSymbol");
121 break;
122 default:
123 unknown(uint32_t(code));
124 break;
128 void Symbol::dumpFields(js::JSONPrinter& json) const {
129 json.formatProperty("address", "(JS::Symbol*)0x%p", this);
131 SymbolCodeToString(
132 code_, [&](const char* name) { json.property("code", name); },
133 [&](uint32_t code) {
134 json.formatProperty("code", "Unknown(%08x)", code);
137 json.formatProperty("hash", "0x%08x", hash());
139 if (description()) {
140 js::GenericPrinter& out = json.beginStringProperty("description");
141 description()->dumpCharsNoQuote(out);
142 json.endStringProperty();
143 } else {
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("
163 : "Symbol(");
165 if (description()) {
166 description()->dumpCharsSingleQuote(out);
167 } else {
168 out.printf("undefined");
171 out.putChar(')');
172 } else if (code_ == SymbolCode::PrivateNameSymbol) {
173 MOZ_ASSERT(description());
174 out.putChar('#');
175 description()->dumpCharsNoQuote(out);
176 } else {
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) {
184 // steps 2-5
185 JSStringBuilder sb(cx);
186 if (!sb.append("Symbol(")) {
187 return false;
189 if (JSAtom* desc = sym->description()) {
190 if (!sb.append(desc)) {
191 return false;
194 if (!sb.append(')')) {
195 return false;
198 // step 6
199 JSString* str = sb.finishString();
200 if (!str) {
201 return false;
203 result.setString(str);
204 return true;
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
210 // this method.
211 MOZ_ASSERT(get().isTenured());
212 return js::gc::Arena::thingSize(get().asTenured().getAllocKind());