Bug 1394719 - Optimize HasRTLChars usage and reduce malloc/free, r=ehsan

--HG--
extra : rebase_source : 01deb3b015c31f48c80dc4e0cf518b5cf85be0d4
This commit is contained in:
Olli Pettay 2017-08-31 14:54:46 +03:00
parent a046e03896
commit beb48926f3
2 changed files with 39 additions and 10 deletions

View File

@ -33,7 +33,7 @@
#include "nsCCUncollectableMarker.h"
#include "mozAutoDocUpdate.h"
#include "nsTextNode.h"
#include "nsBidiUtils.h"
#include "PLDHashTable.h"
#include "mozilla/Sprintf.h"
#include "nsWrapperCacheInlines.h"
@ -337,28 +337,35 @@ nsGenericDOMDataNode::SetTextInternal(uint32_t aOffset, uint32_t aCount,
else {
// Merging old and new
bool bidi = mText.IsBidi();
// Allocate new buffer
int32_t newLength = textLength - aCount + aLength;
char16_t* to = new char16_t[newLength];
// Use nsString and not nsAutoString so that we get a nsStringBuffer which
// can be just AddRefed in nsTextFragment.
nsString to;
to.SetCapacity(newLength);
// Copy over appropriate data
if (aOffset) {
mText.CopyTo(to, 0, aOffset);
mText.AppendTo(to, 0, aOffset);
}
if (aLength) {
memcpy(to + aOffset, aBuffer, aLength * sizeof(char16_t));
to.Append(aBuffer, aLength);
if (!bidi && (!document || !document->GetBidiEnabled())) {
bidi = HasRTLChars(aBuffer, aLength);
}
}
if (endOffset != textLength) {
mText.CopyTo(to + aOffset + aLength, endOffset, textLength - endOffset);
mText.AppendTo(to, endOffset, textLength - endOffset);
}
// If this is marked as "maybe modified frequently", the text should be
// stored as char16_t since converting char* to char16_t* is expensive.
bool ok =
mText.SetTo(to, newLength, !document || !document->GetBidiEnabled(),
HasFlag(NS_MAYBE_MODIFIED_FREQUENTLY));
delete [] to;
// Use char16_t also when we have bidi characters.
bool use2b = HasFlag(NS_MAYBE_MODIFIED_FREQUENTLY) || bidi;
bool ok = mText.SetTo(to, false, use2b);
mText.SetBidi(bidi);
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
}

View File

@ -118,6 +118,23 @@ public:
bool SetTo(const char16_t* aBuffer, int32_t aLength, bool aUpdateBidi,
bool aForce2b);
bool SetTo(const nsString& aString, bool aUpdateBidi, bool aForce2b)
{
ReleaseText();
if (aForce2b && !aUpdateBidi) {
nsStringBuffer* buffer = nsStringBuffer::FromString(aString);
if (buffer) {
NS_ADDREF(m2b = buffer);
mState.mInHeap = true;
mState.mIs2b = true;
mState.mLength = aString.Length();
return true;
}
}
return SetTo(aString.get(), aString.Length(), aUpdateBidi, aForce2b);
}
/**
* Append aData to the end of this fragment. If aUpdateBidi is true, contents
* of the fragment will be scanned, and mState.mIsBidi will be turned on if
@ -215,6 +232,11 @@ public:
return mState.mIs2b ? Get2b()[aIndex] : static_cast<unsigned char>(m1b[aIndex]);
}
void SetBidi(bool aBidi)
{
mState.mIsBidi = aBidi;
}
struct FragmentBits {
// uint32_t to ensure that the values are unsigned, because we
// want 0/1, not 0/-1!