Backed out changeset 9d8b4c0b99ed (bug 1945683) for causing btime failures. CLOSED...
[gecko.git] / js / public / StableStringChars.h
blob84429041da6120083fedc1a5c693c1dc5377d193
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * Safely access the contents of a string even as GC can cause the string's
8 * contents to move around in memory.
9 */
11 #ifndef js_StableStringChars_h
12 #define js_StableStringChars_h
14 #include "mozilla/Assertions.h" // MOZ_ASSERT
15 #include "mozilla/Attributes.h" // MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS
16 #include "mozilla/Maybe.h" // mozilla::Maybe
17 #include "mozilla/Range.h" // mozilla::Range
19 #include <stddef.h> // size_t
20 #include <stdint.h> // uint8_t
22 #include "jstypes.h" // JS_PUBLIC_API
24 #include "js/AllocPolicy.h"
25 #include "js/RootingAPI.h" // JS::Handle, JS::Rooted
26 #include "js/String.h" // JS::GetStringLength
27 #include "js/TypeDecls.h" // JSContext, JS::Latin1Char, JSString
28 #include "js/Vector.h" // js::Vector
30 class JSLinearString;
32 namespace JS {
34 /**
35 * This class provides safe access to a string's chars across a GC. When it
36 * has nursery-allocated out of lines chars, this class will have to make a
37 * copy, so it's best to avoid using this class unless you really need it. It's
38 * usually more efficient to use the latin1Chars/twoByteChars JSString methods
39 * and often the code can be rewritten so that only indexes instead of char
40 * pointers are used in parts of the code that can GC.
42 class MOZ_STACK_CLASS JS_PUBLIC_API AutoStableStringChars final {
44 * When copying string char, use this many bytes of inline storage. This is
45 * chosen to allow the inline string types to be copied without allocating.
46 * This is asserted in AutoStableStringChars::allocOwnChars.
48 static const size_t InlineCapacity = 24;
50 /* Ensure the string is kept alive while we're using its chars. */
51 Rooted<JSString*> s_;
52 union MOZ_INIT_OUTSIDE_CTOR {
53 const char16_t* twoByteChars_;
54 const Latin1Char* latin1Chars_;
56 MOZ_INIT_OUTSIDE_CTOR uint32_t length_;
57 mozilla::Maybe<js::Vector<uint8_t, InlineCapacity>> ownChars_;
58 enum State { Uninitialized, Latin1, TwoByte };
59 State state_;
61 // Prevent the string that owns s's chars from being collected (by storing it
62 // in s_) or deduplicated.
63 void holdStableChars(JSLinearString* s);
65 public:
66 explicit AutoStableStringChars(JSContext* cx)
67 : s_(cx), state_(Uninitialized) {}
69 [[nodiscard]] bool init(JSContext* cx, JSString* s);
71 /* Like init(), but Latin1 chars are inflated to TwoByte. */
72 [[nodiscard]] bool initTwoByte(JSContext* cx, JSString* s);
74 bool isLatin1() const { return state_ == Latin1; }
75 bool isTwoByte() const { return state_ == TwoByte; }
77 const Latin1Char* latin1Chars() const {
78 MOZ_ASSERT(state_ == Latin1);
79 return latin1Chars_;
81 const char16_t* twoByteChars() const {
82 MOZ_ASSERT(state_ == TwoByte);
83 return twoByteChars_;
86 mozilla::Range<const Latin1Char> latin1Range() const {
87 MOZ_ASSERT(state_ == Latin1);
88 return mozilla::Range<const Latin1Char>(latin1Chars_, length());
91 mozilla::Range<const char16_t> twoByteRange() const {
92 MOZ_ASSERT(state_ == TwoByte);
93 return mozilla::Range<const char16_t>(twoByteChars_, length());
96 /* If we own the chars, transfer ownership to the caller. */
97 bool maybeGiveOwnershipToCaller() {
98 MOZ_ASSERT(state_ != Uninitialized);
99 if (!ownChars_.isSome() || !ownChars_->extractRawBuffer()) {
100 return false;
102 state_ = Uninitialized;
103 ownChars_.reset();
104 return true;
107 size_t length() const {
108 MOZ_ASSERT(state_ != Uninitialized);
109 return length_;
112 private:
113 AutoStableStringChars(const AutoStableStringChars& other) = delete;
114 void operator=(const AutoStableStringChars& other) = delete;
116 template <typename T>
117 T* allocOwnChars(JSContext* cx, size_t count);
118 bool copyLatin1Chars(JSContext* cx, Handle<JSLinearString*> linearString);
119 bool copyTwoByteChars(JSContext* cx, Handle<JSLinearString*> linearString);
120 bool copyAndInflateLatin1Chars(JSContext*,
121 Handle<JSLinearString*> linearString);
124 } // namespace JS
126 #endif /* js_StableStringChars_h */