summaryrefslogtreecommitdiff
path: root/js/src/vm/SharedImmutableStringsCache.cpp
blob: 84422810f42cefe5c2c9ab1303baae98ab105277 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* -*- 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/SharedImmutableStringsCache-inl.h"

#include "jsstr.h"

namespace js {

SharedImmutableString::SharedImmutableString(
    ExclusiveData<SharedImmutableStringsCache::Inner>::Guard& locked,
    SharedImmutableStringsCache::StringBox* box)
  : cache_(locked)
  , box_(box)
{
    MOZ_ASSERT(box);
    box->refcount++;
}

SharedImmutableString::SharedImmutableString(SharedImmutableString&& rhs)
  : cache_(mozilla::Move(rhs.cache_))
  , box_(rhs.box_)
{
    MOZ_ASSERT(this != &rhs, "self move not allowed");
    MOZ_ASSERT(rhs.box_);
    MOZ_ASSERT(rhs.box_->refcount > 0);

    rhs.box_ = nullptr;
}

SharedImmutableString&
SharedImmutableString::operator=(SharedImmutableString&& rhs) {
    this->~SharedImmutableString();
    new (this) SharedImmutableString(mozilla::Move(rhs));
    return *this;
}

SharedImmutableTwoByteString::SharedImmutableTwoByteString(SharedImmutableString&& string)
  : string_(mozilla::Move(string))
{ }

SharedImmutableTwoByteString::SharedImmutableTwoByteString(
    ExclusiveData<SharedImmutableStringsCache::Inner>::Guard& locked,
    SharedImmutableStringsCache::StringBox* box)
  : string_(locked, box)
{
    MOZ_ASSERT(box->length() % sizeof(char16_t) == 0);
}

SharedImmutableTwoByteString::SharedImmutableTwoByteString(SharedImmutableTwoByteString&& rhs)
  : string_(mozilla::Move(rhs.string_))
{
    MOZ_ASSERT(this != &rhs, "self move not allowed");
}

SharedImmutableTwoByteString&
SharedImmutableTwoByteString::operator=(SharedImmutableTwoByteString&& rhs)
{
    this->~SharedImmutableTwoByteString();
    new (this) SharedImmutableTwoByteString(mozilla::Move(rhs));
    return *this;
}

SharedImmutableString::~SharedImmutableString() {
    if (!box_)
        return;

    auto locked = cache_.inner_->lock();

    MOZ_ASSERT(box_->refcount > 0);

    box_->refcount--;
    if (box_->refcount == 0)
        box_->chars_.reset(nullptr);
}

SharedImmutableString
SharedImmutableString::clone() const
{
    auto locked = cache_.inner_->lock();
    MOZ_ASSERT(box_);
    MOZ_ASSERT(box_->refcount > 0);
    return SharedImmutableString(locked, box_);
}

SharedImmutableTwoByteString
SharedImmutableTwoByteString::clone() const
{
    return SharedImmutableTwoByteString(string_.clone());
}

MOZ_MUST_USE mozilla::Maybe<SharedImmutableString>
SharedImmutableStringsCache::getOrCreate(OwnedChars&& chars, size_t length)
{
    OwnedChars owned(mozilla::Move(chars));
    MOZ_ASSERT(owned);
    return getOrCreate(owned.get(), length, [&]() { return mozilla::Move(owned); });
}

MOZ_MUST_USE mozilla::Maybe<SharedImmutableString>
SharedImmutableStringsCache::getOrCreate(const char* chars, size_t length)
{
    return getOrCreate(chars, length, [&]() { return DuplicateString(chars, length); });
}

MOZ_MUST_USE mozilla::Maybe<SharedImmutableTwoByteString>
SharedImmutableStringsCache::getOrCreate(OwnedTwoByteChars&& chars, size_t length)
{
    OwnedTwoByteChars owned(mozilla::Move(chars));
    MOZ_ASSERT(owned);
    return getOrCreate(owned.get(), length, [&]() { return mozilla::Move(owned); });
}

MOZ_MUST_USE mozilla::Maybe<SharedImmutableTwoByteString>
SharedImmutableStringsCache::getOrCreate(const char16_t* chars, size_t length)
{
    return getOrCreate(chars, length, [&]() { return DuplicateString(chars, length); });
}

} // namespace js