Bug 1248864 - Part 2: Add skeleton ServoRestyleManager and a RestyleManagerHandle smart pointer. r=dholbert
authorCameron McCormack <cam@mcc.id.au>
Wed, 24 Feb 2016 18:01:12 +1100
changeset 285252 f3ab6216d197647011cc48b90fff685cb875c983
parent 285251 12e4449dd3d1afc725f84059677bf1087f0be369
child 285253 06bc3102b90004470fba71fcaff4ba7b437ebfd7
push id72299
push usercmccormack@mozilla.com
push dateWed, 24 Feb 2016 07:01:43 +0000
treeherdermozilla-inbound@f1ee875a249c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1248864
milestone47.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 1248864 - Part 2: Add skeleton ServoRestyleManager and a RestyleManagerHandle smart pointer. r=dholbert
layout/base/RestyleManagerHandle.h
layout/base/RestyleManagerHandleInlines.h
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
layout/base/moz.build
new file mode 100644
--- /dev/null
+++ b/layout/base/RestyleManagerHandle.h
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_RestyleManagerHandle_h
+#define mozilla_RestyleManagerHandle_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/EventStates.h"
+#include "mozilla/HandleRefPtr.h"
+#include "mozilla/RefCountType.h"
+#include "mozilla/StyleBackendType.h"
+#include "nsChangeHint.h"
+
+namespace mozilla {
+class RestyleManager;
+class ServoRestyleManager;
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+class nsAttrValue;
+class nsIAtom;
+class nsIContent;
+class nsIFrame;
+
+namespace mozilla {
+
+#define SERVO_BIT 0x1
+
+/**
+ * Smart pointer class that can hold a pointer to either a RestyleManager
+ * or a ServoRestyleManager.
+ */
+class RestyleManagerHandle
+{
+public:
+  typedef HandleRefPtr<RestyleManagerHandle> RefPtr;
+
+  // We define this Ptr class with a RestyleManager API that forwards on to the
+  // wrapped pointer, rather than putting these methods on RestyleManagerHandle
+  // itself, so that we can have RestyleManagerHandle behave like a smart
+  // pointer and be dereferenced with operator->.
+  class Ptr
+  {
+  public:
+    friend class ::mozilla::RestyleManagerHandle;
+
+    bool IsGecko() const { return !IsServo(); }
+    bool IsServo() const
+    {
+      MOZ_ASSERT(mValue, "RestyleManagerHandle null pointer dereference");
+#ifdef MOZ_STYLO
+      return mValue & SERVO_BIT;
+#else
+      return false;
+#endif
+    }
+
+    StyleBackendType BackendType() const
+    {
+      return IsGecko() ? StyleBackendType::Gecko :
+                         StyleBackendType::Servo;
+    }
+
+    RestyleManager* AsGecko()
+    {
+      MOZ_ASSERT(IsGecko());
+      return reinterpret_cast<RestyleManager*>(mValue);
+    }
+
+    ServoRestyleManager* AsServo()
+    {
+      MOZ_ASSERT(IsServo());
+      return reinterpret_cast<ServoRestyleManager*>(mValue & ~SERVO_BIT);
+    }
+
+    RestyleManager* GetAsGecko() { return IsGecko() ? AsGecko() : nullptr; }
+    ServoRestyleManager* GetAsServo() { return IsServo() ? AsServo() : nullptr; }
+
+    const RestyleManager* AsGecko() const
+    {
+      return const_cast<Ptr*>(this)->AsGecko();
+    }
+
+    const ServoRestyleManager* AsServo() const
+    {
+      MOZ_ASSERT(IsServo());
+      return const_cast<Ptr*>(this)->AsServo();
+    }
+
+    const RestyleManager* GetAsGecko() const { return IsGecko() ? AsGecko() : nullptr; }
+    const ServoRestyleManager* GetAsServo() const { return IsServo() ? AsServo() : nullptr; }
+
+    // These inline methods are defined in RestyleManagerHandleInlines.h.
+    inline MozExternalRefCountType AddRef();
+    inline MozExternalRefCountType Release();
+
+    // Restyle manager interface.  These inline methods are defined in
+    // RestyleManagerHandleInlines.h and just forward to the underlying
+    // RestyleManager or ServoRestyleManager.  See corresponding comments in
+    // RestyleManager.h for descriptions of these methods.
+
+    inline void Disconnect();
+    inline void PostRestyleEvent(dom::Element* aElement,
+                                 nsRestyleHint aRestyleHint,
+                                 nsChangeHint aMinChangeHint);
+    inline void PostRestyleEventForLazyConstruction();
+    inline void RebuildAllStyleData(nsChangeHint aExtraHint,
+                                    nsRestyleHint aRestyleHint);
+    inline void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
+                                             nsRestyleHint aRestyleHint);
+    inline void ProcessPendingRestyles();
+    inline void RestyleForInsertOrChange(dom::Element* aContainer,
+                                         nsIContent* aChild);
+    inline void RestyleForAppend(dom::Element* aContainer,
+                                 nsIContent* aFirstNewContent);
+    inline void RestyleForRemove(dom::Element* aContainer,
+                                 nsIContent* aOldChild,
+                                 nsIContent* aFollowingSibling);
+    inline nsresult ContentStateChanged(nsIContent* aContent,
+                                        EventStates aStateMask);
+    inline void AttributeWillChange(dom::Element* aElement,
+                                    int32_t aNameSpaceID,
+                                    nsIAtom* aAttribute,
+                                    int32_t aModType,
+                                    const nsAttrValue* aNewValue);
+    inline void AttributeChanged(dom::Element* aElement,
+                                 int32_t aNameSpaceID,
+                                 nsIAtom* aAttribute,
+                                 int32_t aModType,
+                                 const nsAttrValue* aOldValue);
+    inline nsresult ReparentStyleContext(nsIFrame* aFrame);
+    inline bool HasPendingRestyles();
+    inline uint64_t GetRestyleGeneration() const;
+
+  private:
+    // Stores a pointer to an RestyleManager or a ServoRestyleManager.  The least
+    // significant bit is 0 for the former, 1 for the latter.  This is
+    // valid as the least significant bit will never be used for a pointer
+    // value on platforms we care about.
+    uintptr_t mValue;
+  };
+
+  MOZ_IMPLICIT RestyleManagerHandle(decltype(nullptr) = nullptr)
+  {
+    mPtr.mValue = 0;
+  }
+  RestyleManagerHandle(const RestyleManagerHandle& aOth)
+  {
+    mPtr.mValue = aOth.mPtr.mValue;
+  }
+  MOZ_IMPLICIT RestyleManagerHandle(RestyleManager* aManager)
+  {
+    *this = aManager;
+  }
+  MOZ_IMPLICIT RestyleManagerHandle(ServoRestyleManager* aManager)
+  {
+    *this = aManager;
+  }
+
+  RestyleManagerHandle& operator=(decltype(nullptr))
+  {
+    mPtr.mValue = 0;
+    return *this;
+  }
+
+  RestyleManagerHandle& operator=(RestyleManager* aManager)
+  {
+    MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aManager) & SERVO_BIT),
+               "least significant bit shouldn't be set; we use it for state");
+    mPtr.mValue = reinterpret_cast<uintptr_t>(aManager);
+    return *this;
+  }
+
+  RestyleManagerHandle& operator=(ServoRestyleManager* aManager)
+  {
+#ifdef MOZ_STYLO
+    MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aManager) & SERVO_BIT),
+               "least significant bit shouldn't be set; we use it for state");
+    mPtr.mValue =
+      aManager ? (reinterpret_cast<uintptr_t>(aManager) | SERVO_BIT) : 0;
+    return *this;
+#else
+    MOZ_CRASH("should not have a ServoRestyleManager object when MOZ_STYLO is "
+              "disabled");
+#endif
+  }
+
+  // Make RestyleManagerHandle usable in boolean contexts.
+  explicit operator bool() const { return !!mPtr.mValue; }
+  bool operator!() const { return !mPtr.mValue; }
+
+  // Make RestyleManagerHandle behave like a smart pointer.
+  Ptr* operator->() { return &mPtr; }
+  const Ptr* operator->() const { return &mPtr; }
+
+private:
+  Ptr mPtr;
+};
+
+#undef SERVO_BIT
+
+} // namespace mozilla
+
+#endif // mozilla_RestyleManagerHandle_h
new file mode 100644
--- /dev/null
+++ b/layout/base/RestyleManagerHandleInlines.h
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_RestyleManagerHandleInlines_h
+#define mozilla_RestyleManagerHandleInlines_h
+
+#include "mozilla/RestyleManager.h"
+#include "mozilla/ServoRestyleManager.h"
+
+#define FORWARD_CONCRETE(method_, geckoargs_, servoargs_) \
+  if (IsGecko()) { \
+    return AsGecko()->method_ geckoargs_; \
+  } else { \
+    return AsServo()->method_ servoargs_; \
+  }
+
+#define FORWARD(method_, args_) FORWARD_CONCRETE(method_, args_, args_)
+
+namespace mozilla {
+
+MozExternalRefCountType
+RestyleManagerHandle::Ptr::AddRef()
+{
+  FORWARD(AddRef, ());
+}
+
+MozExternalRefCountType
+RestyleManagerHandle::Ptr::Release()
+{
+  FORWARD(Release, ());
+}
+
+void
+RestyleManagerHandle::Ptr::Disconnect()
+{
+  FORWARD(Disconnect, ());
+}
+
+void
+RestyleManagerHandle::Ptr::PostRestyleEvent(dom::Element* aElement,
+                                            nsRestyleHint aRestyleHint,
+                                            nsChangeHint aMinChangeHint)
+{
+  FORWARD(PostRestyleEvent, (aElement, aRestyleHint, aMinChangeHint));
+}
+
+void
+RestyleManagerHandle::Ptr::PostRestyleEventForLazyConstruction()
+{
+  FORWARD(PostRestyleEventForLazyConstruction, ());
+}
+
+void
+RestyleManagerHandle::Ptr::RebuildAllStyleData(nsChangeHint aExtraHint,
+                                               nsRestyleHint aRestyleHint)
+{
+  FORWARD(RebuildAllStyleData, (aExtraHint, aRestyleHint));
+}
+
+void
+RestyleManagerHandle::Ptr::PostRebuildAllStyleDataEvent(
+    nsChangeHint aExtraHint,
+    nsRestyleHint aRestyleHint)
+{
+  FORWARD(PostRebuildAllStyleDataEvent, (aExtraHint, aRestyleHint));
+}
+
+void
+RestyleManagerHandle::Ptr::ProcessPendingRestyles()
+{
+  FORWARD(ProcessPendingRestyles, ());
+}
+
+void
+RestyleManagerHandle::Ptr::RestyleForInsertOrChange(dom::Element* aContainer,
+                                                    nsIContent* aChild)
+{
+  FORWARD(RestyleForInsertOrChange, (aContainer, aChild));
+}
+
+void
+RestyleManagerHandle::Ptr::RestyleForAppend(dom::Element* aContainer,
+                                            nsIContent* aFirstNewContent)
+{
+  FORWARD(RestyleForAppend, (aContainer, aFirstNewContent));
+}
+
+void
+RestyleManagerHandle::Ptr::RestyleForRemove(dom::Element* aContainer,
+                                            nsIContent* aOldChild,
+                                            nsIContent* aFollowingSibling)
+{
+  FORWARD(RestyleForRemove, (aContainer, aOldChild, aFollowingSibling));
+}
+
+nsresult
+RestyleManagerHandle::Ptr::ContentStateChanged(nsIContent* aContent,
+                                          EventStates aStateMask)
+{
+  FORWARD(ContentStateChanged, (aContent, aStateMask));
+}
+
+void
+RestyleManagerHandle::Ptr::AttributeWillChange(dom::Element* aElement,
+                                               int32_t aNameSpaceID,
+                                               nsIAtom* aAttribute,
+                                               int32_t aModType,
+                                               const nsAttrValue* aNewValue)
+{
+  FORWARD(AttributeWillChange, (aElement, aNameSpaceID, aAttribute, aModType,
+                                aNewValue));
+}
+
+void
+RestyleManagerHandle::Ptr::AttributeChanged(dom::Element* aElement,
+                                            int32_t aNameSpaceID,
+                                            nsIAtom* aAttribute,
+                                            int32_t aModType,
+                                            const nsAttrValue* aOldValue)
+{
+  FORWARD(AttributeChanged, (aElement, aNameSpaceID, aAttribute, aModType,
+                             aOldValue));
+}
+
+nsresult
+RestyleManagerHandle::Ptr::ReparentStyleContext(nsIFrame* aFrame)
+{
+  FORWARD(ReparentStyleContext, (aFrame));
+}
+
+bool
+RestyleManagerHandle::Ptr::HasPendingRestyles()
+{
+  FORWARD(HasPendingRestyles, ());
+}
+
+uint64_t
+RestyleManagerHandle::Ptr::GetRestyleGeneration() const
+{
+  FORWARD(GetRestyleGeneration, ());
+}
+
+} // namespace mozilla
+
+#undef FORWARD
+#undef FORWARD_CONCRETE
+
+#endif // mozilla_RestyleManagerHandleInlines_h
new file mode 100644
--- /dev/null
+++ b/layout/base/ServoRestyleManager.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ServoRestyleManager.h"
+
+using namespace mozilla::dom;
+
+namespace mozilla {
+
+void
+ServoRestyleManager::Disconnect()
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::PostRestyleEvent(Element* aElement,
+                                      nsRestyleHint aRestyleHint,
+                                      nsChangeHint aMinChangeHint)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::PostRestyleEventForLazyConstruction()
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
+                                         nsRestyleHint aRestyleHint)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
+                                                  nsRestyleHint aRestyleHint)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::ProcessPendingRestyles()
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::RestyleForInsertOrChange(Element* aContainer,
+                                              nsIContent* aChild)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::RestyleForAppend(Element* aContainer,
+                                      nsIContent* aFirstNewContent)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::RestyleForRemove(Element* aContainer,
+                                      nsIContent* aOldChild,
+                                      nsIContent* aFollowingSibling)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+nsresult
+ServoRestyleManager::ContentStateChanged(nsIContent* aContent,
+                                         EventStates aStateMask)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::AttributeWillChange(Element* aElement,
+                                         int32_t aNameSpaceID,
+                                         nsIAtom* aAttribute,
+                                         int32_t aModType,
+                                         const nsAttrValue* aNewValue)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+void
+ServoRestyleManager::AttributeChanged(Element* aElement,
+                                      int32_t aNameSpaceID,
+                                      nsIAtom* aAttribute,
+                                      int32_t aModType,
+                                      const nsAttrValue* aOldValue)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+nsresult
+ServoRestyleManager::ReparentStyleContext(nsIFrame* aFrame)
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+bool
+ServoRestyleManager::HasPendingRestyles()
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+uint64_t
+ServoRestyleManager::GetRestyleGeneration() const
+{
+  MOZ_CRASH("stylo: not implemented");
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/base/ServoRestyleManager.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ServoRestyleManager_h
+#define mozilla_ServoRestyleManager_h
+
+#include "mozilla/EventStates.h"
+#include "nsChangeHint.h"
+#include "nsISupportsImpl.h"
+
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+class nsAttrValue;
+class nsIAtom;
+class nsIContent;
+class nsIFrame;
+
+namespace mozilla {
+
+/**
+ * Restyle manager for a Servo-backed style system.
+ */
+class ServoRestyleManager
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(ServoRestyleManager)
+
+  void Disconnect();
+  void PostRestyleEvent(dom::Element* aElement,
+                        nsRestyleHint aRestyleHint,
+                        nsChangeHint aMinChangeHint);
+  void PostRestyleEventForLazyConstruction();
+  void RebuildAllStyleData(nsChangeHint aExtraHint,
+                           nsRestyleHint aRestyleHint);
+  void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
+                                    nsRestyleHint aRestyleHint);
+  void ProcessPendingRestyles();
+  void RestyleForInsertOrChange(dom::Element* aContainer,
+                                nsIContent* aChild);
+  void RestyleForAppend(dom::Element* aContainer,
+                        nsIContent* aFirstNewContent);
+  void RestyleForRemove(dom::Element* aContainer,
+                        nsIContent* aOldChild,
+                        nsIContent* aFollowingSibling);
+  nsresult ContentStateChanged(nsIContent* aContent,
+                               EventStates aStateMask);
+  void AttributeWillChange(dom::Element* aElement,
+                           int32_t aNameSpaceID,
+                           nsIAtom* aAttribute,
+                           int32_t aModType,
+                           const nsAttrValue* aNewValue);
+  void AttributeChanged(dom::Element* aElement,
+                        int32_t aNameSpaceID,
+                        nsIAtom* aAttribute,
+                        int32_t aModType,
+                        const nsAttrValue* aOldValue);
+  nsresult ReparentStyleContext(nsIFrame* aFrame);
+  bool HasPendingRestyles();
+  uint64_t GetRestyleGeneration() const;
+
+protected:
+  ~ServoRestyleManager() {}
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoRestyleManager_h
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -101,16 +101,19 @@ EXPORTS += [
 EXPORTS.mozilla += [
     'ArenaObjectID.h',
     'ArenaRefPtr.h',
     'ArenaRefPtrInlines.h',
     'GeometryUtils.h',
     'PaintTracker.h',
     'RestyleLogging.h',
     'RestyleManager.h',
+    'RestyleManagerHandle.h',
+    'RestyleManagerHandleInlines.h',
+    'ServoRestyleManager.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleCaret.cpp',
     'AccessibleCaretEventHub.cpp',
     'AccessibleCaretManager.cpp',
     'ActiveLayerTracker.cpp',
     'DisplayItemClip.cpp',
@@ -144,16 +147,17 @@ UNIFIED_SOURCES += [
     'nsQuoteList.cpp',
     'nsStyleChangeList.cpp',
     'nsStyleSheetService.cpp',
     'PaintTracker.cpp',
     'PositionedEventTargeting.cpp',
     'RestyleManager.cpp',
     'RestyleTracker.cpp',
     'ScrollbarStyles.cpp',
+    'ServoRestyleManager.cpp',
     'StackArena.cpp',
     'TouchManager.cpp',
     'ZoomConstraintsClient.cpp',
 ]
 
 # nsPresArena.cpp needs to be built separately because it uses plarena.h.
 # nsRefreshDriver.cpp needs to be built separately because of name clashes in the OS X headers
 SOURCES += [