Bug 1477898 - Make AutoRestoreEditorState not call EditorBase::SetFlags() since the virtual call cost appears in profile r=m_kato

Unfortunately, EditorBase::SetFlags() is virtual call even though
AutoRestoreEditorState always works only with TextEditor (the method is
overridden only by HTMLEditor).  And AutoRestoreEditorState is a hot path
when <input>.value or <textarea>.value is set a lot.

Fortunately, EditorBase::Flags() can be an inline method.  So, we can make
both constructor and destructor of the class check if it'll change flags
actually.

Additionally, this patch fixes nsTextEditorState::PrepareEditor() too.

MozReview-Commit-ID: 7S4hLRRrbfB

--HG--
extra : rebase_source : 3c3e7438cd7e6c9853e5cf876277d7459b86c343
This commit is contained in:
Masayuki Nakano 2018-07-23 22:04:54 +09:00
Родитель acd8ea2c75
Коммит 5f1e6f2a03
1 изменённых файлов: 26 добавлений и 8 удалений

Просмотреть файл

@ -50,6 +50,15 @@
using namespace mozilla;
using namespace mozilla::dom;
inline nsresult
SetEditorFlagsIfNecessary(EditorBase& aEditorBase, uint32_t aFlags)
{
if (aEditorBase.Flags() == aFlags) {
return NS_OK;
}
return aEditorBase.SetFlags(aFlags);
}
class MOZ_STACK_CLASS ValueSetter
{
public:
@ -139,19 +148,24 @@ public:
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(mTextEditor);
// EditorBase::SetFlags() is a virtual method. Even though it does nothing
// if new flags and current flags are same, the calling cost causes
// appearing the method in profile. So, this class should check if it's
// necessary to call.
uint32_t flags = mSavedFlags;
flags &= ~(nsIPlaintextEditor::eEditorDisabledMask);
flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask);
flags |= nsIPlaintextEditor::eEditorDontEchoPassword;
mTextEditor->SetFlags(flags);
if (mSavedFlags != flags) {
mTextEditor->SetFlags(flags);
}
mTextEditor->SetMaxTextLength(-1);
}
~AutoRestoreEditorState()
{
mTextEditor->SetMaxTextLength(mSavedMaxLength);
mTextEditor->SetFlags(mSavedFlags);
SetEditorFlagsIfNecessary(*mTextEditor, mSavedFlags);
}
private:
@ -1482,7 +1496,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
}
newTextEditor->SetFlags(editorFlags);
SetEditorFlagsIfNecessary(*newTextEditor, editorFlags);
}
if (shouldInitializeEditor) {
@ -1496,8 +1510,10 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// editor for us.
if (!defaultValue.IsEmpty()) {
rv = newTextEditor->SetFlags(editorFlags);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetEditorFlagsIfNecessary(*newTextEditor, editorFlags);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Now call SetValue() which will make the necessary editor calls to set
// the default value. Make sure to turn off undo before setting the default
@ -1509,8 +1525,10 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
// Now restore the original editor flags.
rv = newTextEditor->SetFlags(editorFlags);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetEditorFlagsIfNecessary(*newTextEditor, editorFlags);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (IsPasswordTextControl()) {