Bug 1272813 - part 3 - try to take advantage of string sharing in JSEventHandler::HandleEvent; r=peterv
authorNathan Froyd <froydnj@gmail.com>
Wed, 01 Jun 2016 16:26:59 -0400
changeset 338943 c3c15fd63bd8e483cea22981587c4d9a998c8046
parent 338942 fa493b763fb7f7131fa723a2b49b6f744302a973
child 338944 fd184690f95c861e5e492cae580756afdb554f09
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1272813
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1272813 - part 3 - try to take advantage of string sharing in JSEventHandler::HandleEvent; r=peterv The Rebind() call in HandleEvent was attempting to be clever by sharing string data with the error event's message. Unfortunately, we eventually needed to pass the message out to JS, which required copying the string for JS's purposes. Fortunately, we can attempt to be even more clever by noticing whether the error event's message is already allocated as a string buffer and sharing that, rather than just the raw data. In the best case, the string buffer can be shared out to JS and we avoid some needless copying.
dom/bindings/BindingUtils.h
dom/events/JSEventHandler.cpp
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1890,16 +1890,29 @@ struct FakeString {
   }
 
   void Rebind(const nsString::char_type* aData, nsString::size_type aLength) {
     MOZ_ASSERT(mFlags == nsString::F_TERMINATED);
     mData = const_cast<nsString::char_type*>(aData);
     mLength = aLength;
   }
 
+  // Share aString's string buffer, if it has one; otherwise, make this string
+  // depend upon aString's data.  aString should outlive this instance of
+  // FakeString.
+  void ShareOrDependUpon(const nsAString& aString) {
+    RefPtr<nsStringBuffer> sharedBuffer = nsStringBuffer::FromString(aString);
+    if (!sharedBuffer) {
+      Rebind(aString.Data(), aString.Length());
+    } else {
+      AssignFromStringBuffer(sharedBuffer.forget());
+      mLength = aString.Length();
+    }
+  }
+
   void Truncate() {
     MOZ_ASSERT(mFlags == nsString::F_TERMINATED);
     mData = nsString::char_traits::sEmptyBuffer;
     mLength = 0;
   }
 
   void SetIsVoid(bool aValue) {
     MOZ_ASSERT(aValue,
--- a/dom/events/JSEventHandler.cpp
+++ b/dom/events/JSEventHandler.cpp
@@ -138,17 +138,17 @@ JSEventHandler::HandleEvent(nsIDOMEvent*
     Optional<uint32_t> lineNumber;
     Optional<uint32_t> columnNumber;
     Optional<JS::Handle<JS::Value>> error;
 
     NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED);
     ErrorEvent* scriptEvent = aEvent->InternalDOMEvent()->AsErrorEvent();
     if (scriptEvent) {
       scriptEvent->GetMessage(errorMsg);
-      msgOrEvent.SetAsString().Rebind(errorMsg.Data(), errorMsg.Length());
+      msgOrEvent.SetAsString().ShareOrDependUpon(errorMsg);
 
       scriptEvent->GetFilename(file);
       fileName = &file;
 
       lineNumber.Construct();
       lineNumber.Value() = scriptEvent->Lineno();
 
       columnNumber.Construct();