Bug 1352687, try to recycle HTMLInputElement's nsTextEditorState, r=baku

--HG--
extra : rebase_source : 05c8dc2bd0c29ce3064548e1cabac2d62803cabc
This commit is contained in:
Olli Pettay 2017-04-03 20:40:48 +03:00
parent 7c9aab27bc
commit d5caa7c6c0
5 changed files with 79 additions and 4 deletions

View File

@ -44,6 +44,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FileSystemSecurity.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/HTMLContentElement.h"
@ -1990,6 +1991,8 @@ nsContentUtils::Shutdown()
sModifierSeparator = nullptr;
NS_IF_RELEASE(sSameOriginChecker);
HTMLInputElement::Shutdown();
}
/**

View File

@ -1048,6 +1048,28 @@ static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
const nsAString& aEventType);
#endif
nsTextEditorState* HTMLInputElement::sCachedTextEditorState = nullptr;
bool HTMLInputElement::sShutdown = false;
/* static */ void
HTMLInputElement::ReleaseTextEditorState(nsTextEditorState* aState)
{
if (!sShutdown && !sCachedTextEditorState) {
aState->PrepareForReuse();
sCachedTextEditorState = aState;
} else {
delete aState;
}
}
/* static */ void
HTMLInputElement::Shutdown()
{
sShutdown = true;
delete sCachedTextEditorState;
sCachedTextEditorState = nullptr;
}
//
// construction, destruction
//
@ -1079,7 +1101,8 @@ HTMLInputElement::HTMLInputElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
, mSelectionCached(true)
{
// We are in a type=text so we now we currenty need a nsTextEditorState.
mInputData.mState = new nsTextEditorState(this);
mInputData.mState =
nsTextEditorState::Construct(this, &sCachedTextEditorState);
if (!gUploadLastDir)
HTMLInputElement::InitUploadLastDir();
@ -1112,7 +1135,7 @@ HTMLInputElement::FreeData()
mInputData.mValue = nullptr;
} else {
UnbindFromFrame(nullptr);
delete mInputData.mState;
ReleaseTextEditorState(mInputData.mState);
mInputData.mState = nullptr;
}
}
@ -5027,7 +5050,8 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify)
if (IsSingleLineTextControl()) {
mInputData.mState = new nsTextEditorState(this);
mInputData.mState =
nsTextEditorState::Construct(this, &sCachedTextEditorState);
if (!sp.IsDefault()) {
mInputData.mState->SetSelectionProperties(sp);
}

View File

@ -858,6 +858,8 @@ public:
void UpdateEntries(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories);
static void Shutdown();
protected:
virtual ~HTMLInputElement();
@ -1771,6 +1773,11 @@ private:
nsCOMPtr<nsIFilePicker> mFilePicker;
RefPtr<HTMLInputElement> mInput;
};
static void ReleaseTextEditorState(nsTextEditorState* aState);
static nsTextEditorState* sCachedTextEditorState;
static bool sShutdown;
};
} // namespace dom

View File

@ -1068,10 +1068,38 @@ nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
, mSelectionRestoreEagerInit(false)
, mPlaceholderVisibility(false)
, mIsCommittingComposition(false)
// When adding more member variable initializations here, add the same
// also to ::Construct.
{
MOZ_COUNT_CTOR(nsTextEditorState);
}
nsTextEditorState*
nsTextEditorState::Construct(nsITextControlElement* aOwningElement,
nsTextEditorState** aReusedState)
{
if (*aReusedState) {
nsTextEditorState* state = *aReusedState;
*aReusedState = nullptr;
state->mTextCtrlElement = aOwningElement;
state->mBoundFrame = nullptr;
state->mSelectionProperties = SelectionProperties();
state->mEverInited = false;
state->mEditorInitialized = false;
state->mInitializing = false;
state->mValueTransferInProgress = false;
state->mSelectionCached = true;
state->mSelectionRestoreEagerInit = false;
state->mPlaceholderVisibility = false;
state->mIsCommittingComposition = false;
// When adding more member variable initializations here, add the same
// also to the constructor.
return state;
}
return new nsTextEditorState(aOwningElement);
}
nsTextEditorState::~nsTextEditorState()
{
MOZ_COUNT_DTOR(nsTextEditorState);

View File

@ -135,11 +135,24 @@ class nsTextEditorState : public mozilla::SupportsWeakPtr<nsTextEditorState> {
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsTextEditorState)
explicit nsTextEditorState(nsITextControlElement* aOwningElement);
static nsTextEditorState*
Construct(nsITextControlElement* aOwningElement,
nsTextEditorState** aReusedState);
~nsTextEditorState();
void Traverse(nsCycleCollectionTraversalCallback& cb);
void Unlink();
void PrepareForReuse()
{
Unlink();
mValue.reset();
mCachedValue.Truncate();
mValueBeingSet.Truncate();
mTextCtrlElement = nullptr;
MOZ_ASSERT(!mMutationObserver);
}
nsIEditor* GetEditor();
nsISelectionController* GetSelectionController() const;
nsFrameSelection* GetConstFrameSelection();
@ -401,7 +414,7 @@ private:
// The text control element owns this object, and ensures that this object
// has a smaller lifetime.
nsITextControlElement* const MOZ_NON_OWNING_REF mTextCtrlElement;
nsITextControlElement* MOZ_NON_OWNING_REF mTextCtrlElement;
// mSelCon is non-null while we have an mBoundFrame.
RefPtr<nsTextInputSelectionImpl> mSelCon;
RefPtr<RestoreSelectionState> mRestoringSelection;