diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/vm/SymbolType.cpp | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/vm/SymbolType.cpp')
-rw-r--r-- | js/src/vm/SymbolType.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/js/src/vm/SymbolType.cpp b/js/src/vm/SymbolType.cpp new file mode 100644 index 0000000000..6e08ccb52d --- /dev/null +++ b/js/src/vm/SymbolType.cpp @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "vm/SymbolType.h" + +#include "gc/HashUtil.h" +#include "js/Printer.h" // js::GenericPrinter, js::Fprinter +#include "util/StringBuffer.h" +#include "vm/JSContext.h" +#include "vm/JSONPrinter.h" // js::JSONPrinter +#include "vm/Realm.h" + +#include "vm/Realm-inl.h" + +using JS::Symbol; +using namespace js; + +Symbol* Symbol::newInternal(JSContext* cx, JS::SymbolCode code, uint32_t hash, + Handle<JSAtom*> description) { + MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime())); + AutoAllocInAtomsZone az(cx); + return cx->newCell<Symbol>(code, hash, description); +} + +Symbol* Symbol::new_(JSContext* cx, JS::SymbolCode code, + HandleString description) { + Rooted<JSAtom*> atom(cx); + if (description) { + atom = AtomizeString(cx, description); + if (!atom) { + return nullptr; + } + } + + Symbol* sym = newInternal(cx, code, cx->runtime()->randomHashCode(), atom); + if (sym) { + cx->markAtom(sym); + } + return sym; +} + +Symbol* Symbol::newWellKnown(JSContext* cx, JS::SymbolCode code, + Handle<PropertyName*> description) { + return newInternal(cx, code, cx->runtime()->randomHashCode(), description); +} + +Symbol* Symbol::for_(JSContext* cx, HandleString description) { + Rooted<JSAtom*> atom(cx, AtomizeString(cx, description)); + if (!atom) { + return nullptr; + } + + SymbolRegistry& registry = cx->symbolRegistry(); + DependentAddPtr<SymbolRegistry> p(cx, registry, atom); + if (p) { + cx->markAtom(*p); + return *p; + } + + // Rehash the hash of the atom to give the corresponding symbol a hash + // that is different than the hash of the corresponding atom. + HashNumber hash = mozilla::HashGeneric(atom->hash()); + Symbol* sym = newInternal(cx, SymbolCode::InSymbolRegistry, hash, atom); + if (!sym) { + return nullptr; + } + + if (!p.add(cx, registry, atom, sym)) { + return nullptr; + } + + cx->markAtom(sym); + return sym; +} + +#if defined(DEBUG) || defined(JS_JITSPEW) +void Symbol::dump() const { + js::Fprinter out(stderr); + dump(out); +} + +void Symbol::dump(js::GenericPrinter& out) const { + js::JSONPrinter json(out); + dump(json); + out.put("\n"); +} + +void Symbol::dump(js::JSONPrinter& json) const { + json.beginObject(); + dumpFields(json); + json.endObject(); +} + +template <typename KnownF, typename UnknownF> +void SymbolCodeToString(JS::SymbolCode code, KnownF known, UnknownF unknown) { + switch (code) { +# define DEFINE_CASE(name) \ + case JS::SymbolCode::name: \ + known(#name); \ + break; + JS_FOR_EACH_WELL_KNOWN_SYMBOL(DEFINE_CASE) +# undef DEFINE_CASE + + case JS::SymbolCode::Limit: + known("Limit"); + break; + case JS::SymbolCode::WellKnownAPILimit: + known("WellKnownAPILimit"); + break; + case JS::SymbolCode::PrivateNameSymbol: + known("PrivateNameSymbol"); + break; + case JS::SymbolCode::InSymbolRegistry: + known("InSymbolRegistry"); + break; + case JS::SymbolCode::UniqueSymbol: + known("UniqueSymbol"); + break; + default: + unknown(uint32_t(code)); + break; + } +} + +void Symbol::dumpFields(js::JSONPrinter& json) const { + json.formatProperty("address", "(JS::Symbol*)0x%p", this); + + SymbolCodeToString( + code_, [&](const char* name) { json.property("code", name); }, + [&](uint32_t code) { + json.formatProperty("code", "Unknown(%08x)", code); + }); + + json.formatProperty("hash", "0x%08x", hash()); + + if (description()) { + js::GenericPrinter& out = json.beginStringProperty("description"); + description()->dumpCharsNoQuote(out); + json.endStringProperty(); + } else { + json.nullProperty("description"); + } +} + +void Symbol::dumpStringContent(js::GenericPrinter& out) const { + dumpPropertyName(out); + + if (!isWellKnownSymbol()) { + out.printf(" @ (JS::Symbol*)0x%p", this); + } +} + +void Symbol::dumpPropertyName(js::GenericPrinter& out) const { + if (isWellKnownSymbol()) { + // All the well-known symbol names are ASCII. + description()->dumpCharsNoQuote(out); + } else if (code_ == SymbolCode::InSymbolRegistry || + code_ == SymbolCode::UniqueSymbol) { + out.printf(code_ == SymbolCode::InSymbolRegistry ? "Symbol.for(" + : "Symbol("); + + if (description()) { + description()->dumpCharsSingleQuote(out); + } else { + out.printf("undefined"); + } + + out.putChar(')'); + } else if (code_ == SymbolCode::PrivateNameSymbol) { + MOZ_ASSERT(description()); + out.putChar('#'); + description()->dumpCharsNoQuote(out); + } else { + out.printf("<Invalid Symbol code=%u>", unsigned(code_)); + } +} +#endif // defined(DEBUG) || defined(JS_JITSPEW) + +bool js::SymbolDescriptiveString(JSContext* cx, Symbol* sym, + MutableHandleValue result) { + // steps 2-5 + JSStringBuilder sb(cx); + if (!sb.append("Symbol(")) { + return false; + } + if (JSAtom* desc = sym->description()) { + if (!sb.append(desc)) { + return false; + } + } + if (!sb.append(')')) { + return false; + } + + // step 6 + JSString* str = sb.finishString(); + if (!str) { + return false; + } + result.setString(str); + return true; +} + +JS::ubi::Node::Size JS::ubi::Concrete<JS::Symbol>::size( + mozilla::MallocSizeOf mallocSizeOf) const { + // If we start allocating symbols in the nursery, we will need to update + // this method. + MOZ_ASSERT(get().isTenured()); + return js::gc::Arena::thingSize(get().asTenured().getAllocKind()); +} |