mirror of
https://github.com/mozilla-firefox/firefox
synced 2026-08-12 20:45:22 +00:00
Make DOMString a regular nsAutoTString with some special methods for performance in some hot getters. For that, we need to change a bit nsTString: * Support for unowned buffers: Owned buffers now are represented by STRINGBUFFER|OWNED flags, rather than REFCOUNTED. * Inlining of the destructor: It showed up in profiles, it's also just a few instructions, so probably worth it. We could OOL the owned path I guess, if we wanted to. * Inlinling and reordering of NonVoidStringToJsval. Old code had special DOMString path inline with [buffer, literal, copy] paths, then out of line code with [literal, buffer, copy]. Instead, consolidate everything in a [buffer, literal, copy] inline path. Do the same for UTF8/Latin1 strings too for consistency. Differential Revision: https://phabricator.services.mozilla.com/D288148
84 lines
3.0 KiB
C++
84 lines
3.0 KiB
C++
/* 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/. */
|
|
|
|
#ifndef mozilla_dom_DOMString_h
|
|
#define mozilla_dom_DOMString_h
|
|
|
|
#include "nsAtom.h"
|
|
#include "nsDOMString.h"
|
|
#include "nsString.h"
|
|
|
|
namespace mozilla::dom {
|
|
|
|
// DOMString is an AutoTString with a few extra dangerous methods needed for
|
|
// performance in some cases, where we want to propagate a "weak" reference to a
|
|
// string up. See bug 2023628 for some context.
|
|
//
|
|
// Some of these methods could actually live in nsTSubString, perhaps, but
|
|
// they're hard to get right, and make assumptions about what kind of strings
|
|
// they are called with in order to save cycles.
|
|
class DOMString final : public nsAutoString {
|
|
public:
|
|
enum NullHandling { eTreatNullAsNull, eTreatNullAsEmpty, eNullNotExpected };
|
|
|
|
void SetKnownLiveAtom(nsAtom* aAtom, NullHandling aNullHandling) {
|
|
AssertSetKnownLivePrecondition();
|
|
MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected);
|
|
if (aNullHandling == eNullNotExpected || aAtom) {
|
|
// Static atoms are backed by literals, and dynamic ones by StringBuffer.
|
|
DataFlags flags = DataFlags::TERMINATED;
|
|
const char_type* data;
|
|
if (aAtom->IsStatic()) {
|
|
data = aAtom->AsStatic()->String();
|
|
flags |= DataFlags::LITERAL;
|
|
} else {
|
|
MOZ_ASSERT(aAtom->AsDynamic()->StringBuffer());
|
|
data = aAtom->AsDynamic()->String();
|
|
flags |= DataFlags::STRINGBUFFER;
|
|
}
|
|
SetData(const_cast<char_type*>(data), aAtom->GetLength(), flags);
|
|
AssertValid();
|
|
} else if (aNullHandling == eTreatNullAsNull) {
|
|
SetNull();
|
|
}
|
|
}
|
|
|
|
void SetKnownLiveString(const nsAString& aString) {
|
|
AssertSetKnownLivePrecondition();
|
|
MOZ_ASSERT(aString.IsTerminated(),
|
|
"If we are not terminated, then we need copying or so");
|
|
// NOTE: This is a bit subtle, but the data flags we copy are basically "all
|
|
// except OWNED | INLINE", which cause us to copy null-ness,
|
|
// refcounted-ness, etc.
|
|
const char_type* data = aString.Data();
|
|
SetData(
|
|
const_cast<char_type*>(data), aString.Length(),
|
|
aString.GetDataFlags() & (DataFlags::TERMINATED | DataFlags::LITERAL |
|
|
DataFlags::STRINGBUFFER | DataFlags::VOIDED));
|
|
AssertValid();
|
|
}
|
|
|
|
void SetKnownLiveStringBuffer(StringBuffer* aBuffer, LengthStorage aLen) {
|
|
AssertSetKnownLivePrecondition();
|
|
MOZ_ASSERT(aBuffer);
|
|
// NOTE: No DataFlags::OWNED.
|
|
SetData(static_cast<char_type*>(aBuffer->Data()), aLen,
|
|
DataFlags::STRINGBUFFER | DataFlags::TERMINATED);
|
|
AssertValid();
|
|
}
|
|
|
|
void SetNull() { SetIsVoid(true); }
|
|
bool IsNull() const { return IsVoid(); }
|
|
|
|
private:
|
|
void AssertSetKnownLivePrecondition() {
|
|
MOZ_ASSERT(IsEmpty(), "We rely on this being called only on empty strings");
|
|
MOZ_ASSERT(!(mDataFlags & DataFlags::OWNED), "Would leak");
|
|
}
|
|
};
|
|
|
|
} // namespace mozilla::dom
|
|
|
|
#endif // mozilla_dom_DOMString_h
|