summaryrefslogtreecommitdiffstats
path: root/js/src/vm/SharedImmutableStringsCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/SharedImmutableStringsCache.cpp')
-rw-r--r--js/src/vm/SharedImmutableStringsCache.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/js/src/vm/SharedImmutableStringsCache.cpp b/js/src/vm/SharedImmutableStringsCache.cpp
new file mode 100644
index 0000000000..4428121400
--- /dev/null
+++ b/js/src/vm/SharedImmutableStringsCache.cpp
@@ -0,0 +1,147 @@
+/* -*- 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/SharedImmutableStringsCache-inl.h"
+
+#include "util/Text.h"
+#include "vm/MutexIDs.h" // js::mutexid
+#include "vm/Runtime.h" // JSRuntime
+
+namespace js {
+
+/* static */
+SharedImmutableStringsCache SharedImmutableStringsCache::singleton_;
+
+SharedImmutableString::SharedImmutableString(
+ SharedImmutableStringsCache::StringBox* box)
+ : box_(box) {
+ MOZ_ASSERT(box);
+ box->refcount++;
+}
+
+SharedImmutableString::SharedImmutableString(SharedImmutableString&& rhs)
+ : box_(rhs.box_) {
+ MOZ_ASSERT(this != &rhs, "self move not allowed");
+
+ MOZ_ASSERT_IF(rhs.box_, rhs.box_->refcount > 0);
+
+ rhs.box_ = nullptr;
+}
+
+SharedImmutableString& SharedImmutableString::operator=(
+ SharedImmutableString&& rhs) {
+ this->~SharedImmutableString();
+ new (this) SharedImmutableString(std::move(rhs));
+ return *this;
+}
+
+SharedImmutableTwoByteString::SharedImmutableTwoByteString(
+ SharedImmutableString&& string)
+ : string_(std::move(string)) {}
+
+SharedImmutableTwoByteString::SharedImmutableTwoByteString(
+ SharedImmutableStringsCache::StringBox* box)
+ : string_(box) {
+ MOZ_ASSERT(box->length() % sizeof(char16_t) == 0);
+}
+
+SharedImmutableTwoByteString::SharedImmutableTwoByteString(
+ SharedImmutableTwoByteString&& rhs)
+ : string_(std::move(rhs.string_)) {
+ MOZ_ASSERT(this != &rhs, "self move not allowed");
+}
+
+SharedImmutableTwoByteString& SharedImmutableTwoByteString::operator=(
+ SharedImmutableTwoByteString&& rhs) {
+ this->~SharedImmutableTwoByteString();
+ new (this) SharedImmutableTwoByteString(std::move(rhs));
+ return *this;
+}
+
+SharedImmutableString::~SharedImmutableString() {
+ if (!box_) {
+ return;
+ }
+
+ auto locked = box_->cache_->lock();
+
+ MOZ_ASSERT(box_->refcount > 0);
+
+ box_->refcount--;
+ if (box_->refcount == 0) {
+ box_->chars_.reset(nullptr);
+ }
+}
+
+SharedImmutableString SharedImmutableString::clone() const {
+ auto locked = box_->cache_->lock();
+ MOZ_ASSERT(box_);
+ MOZ_ASSERT(box_->refcount > 0);
+ return SharedImmutableString(box_);
+}
+
+SharedImmutableTwoByteString SharedImmutableTwoByteString::clone() const {
+ return SharedImmutableTwoByteString(string_.clone());
+}
+
+[[nodiscard]] SharedImmutableString SharedImmutableStringsCache::getOrCreate(
+ OwnedChars&& chars, size_t length) {
+ OwnedChars owned(std::move(chars));
+ MOZ_ASSERT(owned);
+ return getOrCreate(owned.get(), length, [&]() { return std::move(owned); });
+}
+
+[[nodiscard]] SharedImmutableString SharedImmutableStringsCache::getOrCreate(
+ const char* chars, size_t length) {
+ return getOrCreate(chars, length,
+ [&]() { return DuplicateString(chars, length); });
+}
+
+bool SharedImmutableStringsCache::init() {
+ MOZ_ASSERT(!inner_);
+
+ auto* inner =
+ js_new<ExclusiveData<Inner>>(mutexid::SharedImmutableStringsCache);
+ if (!inner) {
+ return false;
+ }
+
+ auto locked = inner->lock();
+ inner_ = locked.parent();
+
+ return true;
+}
+
+void SharedImmutableStringsCache::free() {
+ if (inner_) {
+ js_delete(inner_);
+ inner_ = nullptr;
+ }
+}
+
+bool SharedImmutableStringsCache::initSingleton() { return singleton_.init(); }
+
+void SharedImmutableStringsCache::freeSingleton() {
+ if (!JSRuntime::hasLiveRuntimes()) {
+ singleton_.free();
+ }
+}
+
+[[nodiscard]] SharedImmutableTwoByteString
+SharedImmutableStringsCache::getOrCreate(OwnedTwoByteChars&& chars,
+ size_t length) {
+ OwnedTwoByteChars owned(std::move(chars));
+ MOZ_ASSERT(owned);
+ return getOrCreate(owned.get(), length, [&]() { return std::move(owned); });
+}
+
+[[nodiscard]] SharedImmutableTwoByteString
+SharedImmutableStringsCache::getOrCreate(const char16_t* chars, size_t length) {
+ return getOrCreate(chars, length,
+ [&]() { return DuplicateString(chars, length); });
+}
+
+} // namespace js