Bug 1335998 - Part 1: Implement Gecko_CSSValue_InitSharedList and read the transform from the shared list. draft
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 07 Jun 2017 11:21:01 +0800
changeset 590022 715fafe856f413f3e03214bd009e9581ec498af6
parent 590021 a8c0805475d01a6de44538eef667440a76919115
child 590023 0a86978578a7db7050d4c8854b31780c579652a1
push id62578
push userbmo:boris.chiou@gmail.com
push dateWed, 07 Jun 2017 04:32:00 +0000
bugs1335998
milestone55.0a1
Bug 1335998 - Part 1: Implement Gecko_CSSValue_InitSharedList and read the transform from the shared list. We create interpolatematrix and accumulatematrix from Servo side not on the main thread, so we cannot use nsCSSValueList_heap (which is not thread safe so we cannot create it and destroy it on different threads). Therefore, we use nsCSSValueSharedList to represent the cloned lists in interpolatematrix and accumulatematrix. MozReview-Commit-ID: L5WBKHwsrUz
js/src/devtools/rootAnalysis/analyzeHeapWrites.js
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/nsStyleTransformMatrix.cpp
--- a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
+++ b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
@@ -385,16 +385,17 @@ function ignoreContents(entry)
         "Gecko_NewStyleQuoteValues",
         "Gecko_NewCSSValueSharedList",
         "Gecko_NewNoneTransform",
         "Gecko_NewGridTemplateAreasValue",
         /nsCSSValue::SetCalcValue/,
         /CSSValueSerializeCalcOps::Append/,
         "Gecko_CSSValue_SetFunction",
         "Gecko_CSSValue_SetArray",
+        "Gecko_CSSValue_InitSharedList",
         "Gecko_EnsureMozBorderColors",
         "Gecko_ClearMozBorderColors",
         "Gecko_AppendMozBorderColors",
         "Gecko_CopyMozBorderColors",
         "Gecko_SetNullImageValue",
 
         // Needs main thread assertions or other fixes.
         /UndisplayedMap::GetEntryFor/,
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -2027,16 +2027,31 @@ Gecko_CSSValue_SetPairList(nsCSSValueBor
   MOZ_ASSERT(NS_IsMainThread());
   nsCSSValuePairList* item = aCSSValue->SetPairListValue();
   for (uint32_t i = 1; i < aLen; ++i) {
     item->mNext = new nsCSSValuePairList;
     item = item->mNext;
   }
 }
 
+void
+Gecko_CSSValue_InitSharedList(nsCSSValueBorrowedMut aCSSValue,
+                              uint32_t aLen)
+{
+  MOZ_ASSERT(aLen > 0, "Must create at least one nsCSSValueList (mHead)");
+
+  nsCSSValueSharedList* list = new nsCSSValueSharedList;
+  aCSSValue->SetSharedListValue(list);
+  list->mHead = new nsCSSValueList;
+  nsCSSValueList* cur = list->mHead;
+  for (uint32_t i = 1; i < aLen; ++i) {
+    cur->mNext = new nsCSSValueList;
+    cur = cur->mNext;
+  }
+}
 
 bool
 Gecko_PropertyId_IsPrefEnabled(nsCSSPropertyID id)
 {
   return nsCSSProps::IsEnabled(id);
 }
 
 void
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -503,16 +503,17 @@ void Gecko_CSSValue_SetStringFromAtom(ns
 void Gecko_CSSValue_SetAtomIdent(nsCSSValueBorrowedMut css_value, nsIAtom* atom);
 void Gecko_CSSValue_SetArray(nsCSSValueBorrowedMut css_value, int32_t len);
 void Gecko_CSSValue_SetURL(nsCSSValueBorrowedMut css_value, ServoBundledURI uri);
 void Gecko_CSSValue_SetInt(nsCSSValueBorrowedMut css_value, int32_t integer, nsCSSUnit unit);
 void Gecko_CSSValue_SetPair(nsCSSValueBorrowedMut css_value,
                             nsCSSValueBorrowed xvalue, nsCSSValueBorrowed yvalue);
 void Gecko_CSSValue_SetList(nsCSSValueBorrowedMut css_value, uint32_t len);
 void Gecko_CSSValue_SetPairList(nsCSSValueBorrowedMut css_value, uint32_t len);
+void Gecko_CSSValue_InitSharedList(nsCSSValueBorrowedMut css_value, uint32_t len);
 void Gecko_CSSValue_Drop(nsCSSValueBorrowedMut css_value);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
 bool Gecko_PropertyId_IsPrefEnabled(nsCSSPropertyID id);
 
 void Gecko_nsStyleFont_SetLang(nsStyleFont* font, nsIAtom* atom);
 void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont, const nsStyleFont* aSource);
 void Gecko_nsStyleFont_FixupNoneGeneric(nsStyleFont* font,
                                         RawGeckoPresContextBorrowed pres_context);
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -435,33 +435,53 @@ ProcessMatrixOperator(Matrix4x4& aMatrix
                       nsStyleContext* aContext,
                       nsPresContext* aPresContext,
                       RuleNodeCacheConditions& aConditions,
                       TransformReferenceBox& aRefBox,
                       bool* aContains3dTransform)
 {
   NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
 
-  Matrix4x4 matrix1, matrix2;
-  if (aData->Item(1).GetUnit() == eCSSUnit_List) {
-    matrix1 = nsStyleTransformMatrix::ReadTransforms(aData->Item(1).GetListValue(),
-                             aContext, aPresContext,
-                             aConditions,
-                             aRefBox, nsPresContext::AppUnitsPerCSSPixel(),
-                             aContains3dTransform);
-  }
-  if (aData->Item(2).GetUnit() == eCSSUnit_List) {
-    matrix2 = ReadTransforms(aData->Item(2).GetListValue(),
-                             aContext, aPresContext,
-                             aConditions,
-                             aRefBox, nsPresContext::AppUnitsPerCSSPixel(),
-                             aContains3dTransform);
-  }
+  auto readTransform = [&](const nsCSSValue& aValue) -> Matrix4x4 {
+    const nsCSSValueList* list = nullptr;
+    switch (aValue.GetUnit()) {
+      case eCSSUnit_List:
+        // For Gecko style backend.
+        list = aValue.GetListValue();
+        break;
+      case eCSSUnit_SharedList:
+        // For Servo style backend. The transform lists of interpolatematrix
+        // are not created on the main thread (i.e. during parallel traversal),
+        // and nsCSSValueList_heap is not thread safe. Therefore, we use
+        // nsCSSValueSharedList as a workaround.
+        list = aValue.GetSharedListValue()->mHead;
+        break;
+      default:
+        list = nullptr;
+    }
+
+    Matrix4x4 matrix;
+    if (!list) {
+      return matrix;
+    }
+
+    float appUnitPerCSSPixel = nsPresContext::AppUnitsPerCSSPixel();
+    matrix = nsStyleTransformMatrix::ReadTransforms(list,
+                                                    aContext,
+                                                    aPresContext,
+                                                    aConditions,
+                                                    aRefBox,
+                                                    appUnitPerCSSPixel,
+                                                    aContains3dTransform);
+    return matrix;
+  };
+
+  Matrix4x4 matrix1 = readTransform(aData->Item(1));
+  Matrix4x4 matrix2 = readTransform(aData->Item(2));
   double progress = aData->Item(3).GetPercentValue();
-
   aMatrix =
     OperateTransformMatrix<Operator>(matrix1, matrix2, progress) * aMatrix;
 }
 
 /* Helper function to process two matrices that we need to interpolate between */
 void
 ProcessInterpolateMatrix(Matrix4x4& aMatrix,
                          const nsCSSValue::Array* aData,