summaryrefslogtreecommitdiffstats
path: root/js/src/vm/Symbol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/Symbol.cpp')
-rw-r--r--js/src/vm/Symbol.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/js/src/vm/Symbol.cpp b/js/src/vm/Symbol.cpp
new file mode 100644
index 000000000..59903c38a
--- /dev/null
+++ b/js/src/vm/Symbol.cpp
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/Symbol.h"
+
+#include "jscntxt.h"
+#include "jscompartment.h"
+
+#include "builtin/SymbolObject.h"
+#include "gc/Allocator.h"
+#include "gc/Rooting.h"
+#include "vm/StringBuffer.h"
+
+#include "jscompartmentinlines.h"
+
+using JS::Symbol;
+using namespace js;
+
+Symbol*
+Symbol::newInternal(ExclusiveContext* cx, JS::SymbolCode code, uint32_t hash, JSAtom* description,
+ AutoLockForExclusiveAccess& lock)
+{
+ MOZ_ASSERT(cx->compartment() == cx->atomsCompartment(lock));
+
+ // Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
+ Symbol* p = Allocate<JS::Symbol, NoGC>(cx);
+ if (!p) {
+ ReportOutOfMemory(cx);
+ return nullptr;
+ }
+ return new (p) Symbol(code, hash, description);
+}
+
+Symbol*
+Symbol::new_(ExclusiveContext* cx, JS::SymbolCode code, JSString* description)
+{
+ JSAtom* atom = nullptr;
+ if (description) {
+ atom = AtomizeString(cx, description);
+ if (!atom)
+ return nullptr;
+ }
+
+ // Lock to allocate. If symbol allocation becomes a bottleneck, this can
+ // probably be replaced with an assertion that we're on the main thread.
+ AutoLockForExclusiveAccess lock(cx);
+ AutoCompartment ac(cx, cx->atomsCompartment(lock), &lock);
+ return newInternal(cx, code, cx->compartment()->randomHashCode(), atom, lock);
+}
+
+Symbol*
+Symbol::for_(js::ExclusiveContext* cx, HandleString description)
+{
+ JSAtom* atom = AtomizeString(cx, description);
+ if (!atom)
+ return nullptr;
+
+ AutoLockForExclusiveAccess lock(cx);
+
+ SymbolRegistry& registry = cx->symbolRegistry(lock);
+ SymbolRegistry::AddPtr p = registry.lookupForAdd(atom);
+ if (p)
+ return *p;
+
+ AutoCompartment ac(cx, cx->atomsCompartment(lock), &lock);
+ Symbol* sym = newInternal(cx, SymbolCode::InSymbolRegistry, atom->hash(), atom, lock);
+ if (!sym)
+ return nullptr;
+
+ // p is still valid here because we have held the lock since the
+ // lookupForAdd call, and newInternal can't GC.
+ if (!registry.add(p, sym)) {
+ // SystemAllocPolicy does not report OOM.
+ ReportOutOfMemory(cx);
+ return nullptr;
+ }
+ return sym;
+}
+
+#ifdef DEBUG
+void
+Symbol::dump(FILE* fp)
+{
+ if (isWellKnownSymbol()) {
+ // All the well-known symbol names are ASCII.
+ description_->dumpCharsNoNewline(fp);
+ } else if (code_ == SymbolCode::InSymbolRegistry || code_ == SymbolCode::UniqueSymbol) {
+ fputs(code_ == SymbolCode::InSymbolRegistry ? "Symbol.for(" : "Symbol(", fp);
+
+ if (description_)
+ description_->dumpCharsNoNewline(fp);
+ else
+ fputs("undefined", fp);
+
+ fputc(')', fp);
+
+ if (code_ == SymbolCode::UniqueSymbol)
+ fprintf(fp, "@%p", (void*) this);
+ } else {
+ fprintf(fp, "<Invalid Symbol code=%u>", unsigned(code_));
+ }
+}
+#endif // DEBUG
+
+bool
+js::SymbolDescriptiveString(JSContext* cx, Symbol* sym, MutableHandleValue result)
+{
+ // steps 2-5
+ StringBuffer sb(cx);
+ if (!sb.append("Symbol("))
+ return false;
+ RootedString str(cx, sym->description());
+ if (str) {
+ if (!sb.append(str))
+ return false;
+ }
+ if (!sb.append(')'))
+ return false;
+
+ // step 6
+ str = sb.finishString();
+ if (!str)
+ return false;
+ result.setString(str);
+ return true;
+}
+
+bool
+js::IsSymbolOrSymbolWrapper(const Value& v)
+{
+ return v.isSymbol() || (v.isObject() && v.toObject().is<SymbolObject>());
+}
+
+JS::Symbol*
+js::ToSymbolPrimitive(const Value& v)
+{
+ MOZ_ASSERT(IsSymbolOrSymbolWrapper(v));
+ return v.isSymbol() ? v.toSymbol() : v.toObject().as<SymbolObject>().unbox();
+}
+
+
+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());
+}