[Web Animations] Audit Web Animations classes for memory reduction
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Jan 2019 08:19:39 +0000 (08:19 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Jan 2019 08:19:39 +0000 (08:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=193195

Reviewed by Simon Fraser and Yusuke Suzuki.

The classes, enums and structs added to support Web Animations were not as memory-efficient as they could be. We now order
members in a way that reduces padding, use Markable<T, Traits> instead of Optional<T> where applicable, declare enums as uint8_t
and removed unnecessary members.

As a result, classes and structs have shrunk as follows:

WebAnimation: 256 > 216
DeclarativeAnimation: 392 > 344
CSSAnimation: 416 > 368
CSSTransition: 440 > 392
AnimationEffect: 88 > 72
KeyframeEffect: 208 > 184
AnimationPlaybackEvent: 104 > 88
EffectTiming: 72 > 64
ComputedEffectTiming: 136 > 112
AnimationTimeline: 264 > 248
DocumentTimeline: 496 > 464
OptionalEffectTiming: 112 > 80
BaseKeyframe: 32 > 24
ParsedKeyframe: 80 > 72
BaseComputedKeyframe: 40 > 32

* animation/AnimationEffect.h: Order members in decreasing size, except for m_fill and m_direction, which we put at the top to
save 8 bytes (2 bytes of padding instead of 4 before m_animation and saving 6 bytes of padding at the end).
* animation/AnimationPlaybackEvent.cpp:
(WebCore::AnimationPlaybackEvent::AnimationPlaybackEvent):
* animation/AnimationPlaybackEvent.h:
* animation/AnimationPlaybackEventInit.h:
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::AnimationTimeline):
(WebCore::AnimationTimeline::updateCSSTransitionsForElement):
* animation/AnimationTimeline.h: We remove the m_classType member and instead make isDocumentTimeline() virtual.
(WebCore::AnimationTimeline::isDocumentTimeline const):
(): Deleted.
(WebCore::AnimationTimeline::classType const): Deleted.
* animation/CompositeOperation.h:
* animation/CompositeOperationOrAuto.h:
* animation/ComputedEffectTiming.h:
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::DeclarativeAnimation):
(WebCore::DeclarativeAnimation::invalidateDOMEvents):
* animation/DeclarativeAnimation.h: We keep m_wasPending and m_previousPhase at the top to save some padding at the end.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
* animation/DocumentTimeline.h:
* animation/EffectTiming.h:
* animation/FillMode.h:
* animation/IterationCompositeOperation.h:
* animation/KeyframeEffect.cpp:
(WebCore::computeMissingKeyframeOffsets):
(WebCore::KeyframeEffect::create):
(WebCore::KeyframeEffect::KeyframeEffect):
* animation/KeyframeEffect.h:
* animation/OptionalEffectTiming.h:
* animation/PlaybackDirection.h:
* animation/WebAnimation.h:
* animation/WebAnimationUtilities.h:
(WebCore::WebAnimationsMarkableDoubleTraits::isEmptyValue):
(WebCore::WebAnimationsMarkableDoubleTraits::emptyValue):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239820 268f45cc-cd09-0410-ab3c-d52691b4dbfc

23 files changed:
Source/WebCore/ChangeLog
Source/WebCore/animation/AnimationEffect.h
Source/WebCore/animation/AnimationPlaybackEvent.cpp
Source/WebCore/animation/AnimationPlaybackEvent.h
Source/WebCore/animation/AnimationPlaybackEventInit.h
Source/WebCore/animation/AnimationTimeline.cpp
Source/WebCore/animation/AnimationTimeline.h
Source/WebCore/animation/CompositeOperation.h
Source/WebCore/animation/CompositeOperationOrAuto.h
Source/WebCore/animation/ComputedEffectTiming.h
Source/WebCore/animation/DeclarativeAnimation.cpp
Source/WebCore/animation/DeclarativeAnimation.h
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/DocumentTimeline.h
Source/WebCore/animation/EffectTiming.h
Source/WebCore/animation/FillMode.h
Source/WebCore/animation/IterationCompositeOperation.h
Source/WebCore/animation/KeyframeEffect.cpp
Source/WebCore/animation/KeyframeEffect.h
Source/WebCore/animation/OptionalEffectTiming.h
Source/WebCore/animation/PlaybackDirection.h
Source/WebCore/animation/WebAnimation.h
Source/WebCore/animation/WebAnimationUtilities.h

index becfba6..6f78a73 100644 (file)
@@ -1,3 +1,70 @@
+2019-01-09  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Audit Web Animations classes for memory reduction
+        https://bugs.webkit.org/show_bug.cgi?id=193195
+
+        Reviewed by Simon Fraser and Yusuke Suzuki.
+
+        The classes, enums and structs added to support Web Animations were not as memory-efficient as they could be. We now order
+        members in a way that reduces padding, use Markable<T, Traits> instead of Optional<T> where applicable, declare enums as uint8_t
+        and removed unnecessary members.
+
+        As a result, classes and structs have shrunk as follows:
+
+        WebAnimation: 256 > 216
+        DeclarativeAnimation: 392 > 344
+        CSSAnimation: 416 > 368
+        CSSTransition: 440 > 392
+        AnimationEffect: 88 > 72
+        KeyframeEffect: 208 > 184
+        AnimationPlaybackEvent: 104 > 88
+        EffectTiming: 72 > 64
+        ComputedEffectTiming: 136 > 112
+        AnimationTimeline: 264 > 248
+        DocumentTimeline: 496 > 464
+        OptionalEffectTiming: 112 > 80
+        BaseKeyframe: 32 > 24
+        ParsedKeyframe: 80 > 72
+        BaseComputedKeyframe: 40 > 32
+
+        * animation/AnimationEffect.h: Order members in decreasing size, except for m_fill and m_direction, which we put at the top to
+        save 8 bytes (2 bytes of padding instead of 4 before m_animation and saving 6 bytes of padding at the end).
+        * animation/AnimationPlaybackEvent.cpp:
+        (WebCore::AnimationPlaybackEvent::AnimationPlaybackEvent):
+        * animation/AnimationPlaybackEvent.h:
+        * animation/AnimationPlaybackEventInit.h:
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::AnimationTimeline):
+        (WebCore::AnimationTimeline::updateCSSTransitionsForElement):
+        * animation/AnimationTimeline.h: We remove the m_classType member and instead make isDocumentTimeline() virtual.
+        (WebCore::AnimationTimeline::isDocumentTimeline const):
+        (): Deleted.
+        (WebCore::AnimationTimeline::classType const): Deleted.
+        * animation/CompositeOperation.h:
+        * animation/CompositeOperationOrAuto.h:
+        * animation/ComputedEffectTiming.h:
+        * animation/DeclarativeAnimation.cpp:
+        (WebCore::DeclarativeAnimation::DeclarativeAnimation):
+        (WebCore::DeclarativeAnimation::invalidateDOMEvents):
+        * animation/DeclarativeAnimation.h: We keep m_wasPending and m_previousPhase at the top to save some padding at the end.
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::DocumentTimeline):
+        * animation/DocumentTimeline.h:
+        * animation/EffectTiming.h:
+        * animation/FillMode.h:
+        * animation/IterationCompositeOperation.h:
+        * animation/KeyframeEffect.cpp:
+        (WebCore::computeMissingKeyframeOffsets):
+        (WebCore::KeyframeEffect::create):
+        (WebCore::KeyframeEffect::KeyframeEffect):
+        * animation/KeyframeEffect.h:
+        * animation/OptionalEffectTiming.h:
+        * animation/PlaybackDirection.h:
+        * animation/WebAnimation.h:
+        * animation/WebAnimationUtilities.h:
+        (WebCore::WebAnimationsMarkableDoubleTraits::isEmptyValue):
+        (WebCore::WebAnimationsMarkableDoubleTraits::emptyValue):
+
 2019-01-09  Ryosuke Niwa  <rniwa@webkit.org>
 
         ThreadTimers should not store a raw pointer in its heap
index b364c93..82de742 100644 (file)
@@ -94,17 +94,20 @@ protected:
     explicit AnimationEffect();
 
 private:
-    enum class ComputedDirection { Forwards, Reverse };
+    enum class ComputedDirection : uint8_t { Forwards, Reverse };
 
-    Seconds m_delay { 0_s };
-    Seconds m_endDelay { 0_s };
     FillMode m_fill { FillMode::Auto };
+    PlaybackDirection m_direction { PlaybackDirection::Normal };
+
+    WeakPtr<WebAnimation> m_animation;
+    RefPtr<TimingFunction> m_timingFunction;
+
     double m_iterationStart { 0 };
     double m_iterations { 1 };
+
+    Seconds m_delay { 0_s };
+    Seconds m_endDelay { 0_s };
     Seconds m_iterationDuration { 0_s };
-    PlaybackDirection m_direction { PlaybackDirection::Normal };
-    RefPtr<TimingFunction> m_timingFunction;
-    WeakPtr<WebAnimation> m_animation;
 };
 
 } // namespace WebCore
index 8cfa54f..3ad1aed 100644 (file)
@@ -33,15 +33,15 @@ namespace WebCore {
 AnimationPlaybackEvent::AnimationPlaybackEvent(const AtomicString& type, const AnimationPlaybackEventInit& initializer, IsTrusted isTrusted)
     : Event(type, initializer, isTrusted)
 {
-    if (initializer.currentTime == WTF::nullopt)
-        m_currentTime = WTF::nullopt;
+    if (initializer.currentTime)
+        m_currentTime = Seconds::fromMilliseconds(*initializer.currentTime);
     else
-        m_currentTime = Seconds::fromMilliseconds(initializer.currentTime.value());
+        m_currentTime = WTF::nullopt;
 
-    if (initializer.timelineTime == WTF::nullopt)
-        m_timelineTime = WTF::nullopt;
+    if (initializer.timelineTime)
+        m_timelineTime = Seconds::fromMilliseconds(*initializer.timelineTime);
     else
-        m_timelineTime = Seconds::fromMilliseconds(initializer.timelineTime.value());
+        m_timelineTime = WTF::nullopt;
 }
 
 AnimationPlaybackEvent::AnimationPlaybackEvent(const AtomicString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime)
index cb7fb88..ea88d14 100644 (file)
@@ -25,8 +25,9 @@
 
 #pragma once
 
-#include "Event.h"
 #include "AnimationPlaybackEventInit.h"
+#include "Event.h"
+#include <wtf/Markable.h>
 
 namespace WebCore {
 
@@ -55,8 +56,8 @@ private:
     AnimationPlaybackEvent(const AtomicString&, Optional<Seconds>, Optional<Seconds>);
     AnimationPlaybackEvent(const AtomicString&, const AnimationPlaybackEventInit&, IsTrusted);
 
-    Optional<Seconds> m_currentTime;
-    Optional<Seconds> m_timelineTime;
+    Markable<Seconds, Seconds::MarkableTraits> m_currentTime;
+    Markable<Seconds, Seconds::MarkableTraits> m_timelineTime;
 };
 
 }
index dc1e788..ef714c8 100644 (file)
 #pragma once
 
 #include "EventInit.h"
-#include <wtf/Optional.h>
+#include "WebAnimationUtilities.h"
 
 namespace WebCore {
 
 struct AnimationPlaybackEventInit : EventInit {
-    Optional<double> currentTime;
-    Optional<double> timelineTime;
+    MarkableDouble currentTime;
+    MarkableDouble timelineTime;
 };
 
 }
index f550fc9..faad34c 100644 (file)
@@ -46,8 +46,7 @@
 
 namespace WebCore {
 
-AnimationTimeline::AnimationTimeline(ClassType classType)
-    : m_classType(classType)
+AnimationTimeline::AnimationTimeline()
 {
 }
 
@@ -459,8 +458,10 @@ void AnimationTimeline::updateCSSTransitionsForElement(Element& element, const R
                 //   - end value is the value of the property in the after-change style
                 auto& reversingAdjustedStartStyle = previouslyRunningTransition->targetStyle();
                 double transformedProgress = 1;
-                if (auto* effect = previouslyRunningTransition->effect())
-                    transformedProgress = effect->getComputedTiming().progress.valueOr(transformedProgress);
+                if (auto* effect = previouslyRunningTransition->effect()) {
+                    if (auto computedTimingProgress = effect->getComputedTiming().progress)
+                        transformedProgress = *computedTimingProgress;
+                }
                 auto reversingShorteningFactor = std::max(std::min(((transformedProgress * previouslyRunningTransition->reversingShorteningFactor()) + (1 - previouslyRunningTransition->reversingShorteningFactor())), 1.0), 0.0);
                 auto delay = matchingBackingAnimation->delay() < 0 ? Seconds(matchingBackingAnimation->delay()) * reversingShorteningFactor : Seconds(matchingBackingAnimation->delay());
                 auto duration = Seconds(matchingBackingAnimation->duration()) * reversingShorteningFactor;
index 583e666..0f318bf 100644 (file)
@@ -33,6 +33,7 @@
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/ListHashSet.h>
+#include <wtf/Markable.h>
 #include <wtf/Optional.h>
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
@@ -47,7 +48,7 @@ class Element;
 
 class AnimationTimeline : public RefCounted<AnimationTimeline> {
 public:
-    bool isDocumentTimeline() const { return m_classType == DocumentTimelineClass; }
+    virtual bool isDocumentTimeline() const { return false; }
 
     void forgetAnimation(WebAnimation*);
     virtual void animationTimingDidChange(WebAnimation&);
@@ -56,7 +57,7 @@ public:
     Optional<double> bindingsCurrentTime();
     virtual Optional<Seconds> currentTime() { return m_currentTime; }
 
-    enum class Ordering { Sorted, Unsorted };
+    enum class Ordering : uint8_t { Sorted, Unsorted };
     Vector<RefPtr<WebAnimation>> animationsForElement(Element&, Ordering ordering = Ordering::Unsorted) const;
     void elementWasRemoved(Element&);
     void removeAnimationsForElement(Element&);
@@ -74,13 +75,7 @@ public:
     virtual ~AnimationTimeline();
 
 protected:
-    enum ClassType {
-        DocumentTimelineClass
-    };
-
-    ClassType classType() const { return m_classType; }
-
-    explicit AnimationTimeline(ClassType);
+    explicit AnimationTimeline();
 
     ListHashSet<WebAnimation*> m_allAnimations;
     ListHashSet<RefPtr<WebAnimation>> m_animations;
@@ -91,13 +86,13 @@ private:
     PropertyToTransitionMap& ensureRunningTransitionsByProperty(Element&);
     void cancelDeclarativeAnimation(DeclarativeAnimation&);
 
-    ClassType m_classType;
-    Optional<Seconds> m_currentTime;
     ElementToAnimationsMap m_elementToAnimationsMap;
     ElementToAnimationsMap m_elementToCSSAnimationsMap;
     ElementToAnimationsMap m_elementToCSSTransitionsMap;
     HashMap<Element*, HashMap<String, RefPtr<CSSAnimation>>> m_elementToCSSAnimationByName;
     HashMap<Element*, PropertyToTransitionMap> m_elementToRunningCSSTransitionByCSSPropertyID;
+
+    Markable<Seconds, Seconds::MarkableTraits> m_currentTime;
 };
 
 } // namespace WebCore
index 209a577..0f75e74 100644 (file)
@@ -27,6 +27,6 @@
 
 namespace WebCore {
 
-enum class CompositeOperation { Replace, Add, Accumulate };
+enum class CompositeOperation : uint8_t { Replace, Add, Accumulate };
 
 } // namespace WebCore
index a27de4e..0279ca7 100644 (file)
@@ -27,6 +27,6 @@
 
 namespace WebCore {
 
-enum class CompositeOperationOrAuto { Replace, Add, Accumulate, Auto };
+enum class CompositeOperationOrAuto : uint8_t { Replace, Add, Accumulate, Auto };
 
 } // namespace WebCore
index a909a2c..57aaba1 100644 (file)
 
 #include "AnimationEffectPhase.h"
 #include "EffectTiming.h"
-#include <wtf/Optional.h>
+#include "WebAnimationUtilities.h"
 
 namespace WebCore {
 
 struct ComputedEffectTiming : EffectTiming {
     AnimationEffectPhase phase { AnimationEffectPhase::Idle };
+    MarkableDouble localTime;
+    MarkableDouble simpleIterationProgress;
+    MarkableDouble progress;
+    MarkableDouble currentIteration;
     double endTime;
     double activeDuration;
-    Optional<double> localTime;
-    Optional<double> simpleIterationProgress;
-    Optional<double> progress;
-    Optional<double> currentIteration;
 };
 
 } // namespace WebCore
index 417acef..f76191f 100644 (file)
@@ -38,9 +38,9 @@ namespace WebCore {
 
 DeclarativeAnimation::DeclarativeAnimation(Element& owningElement, const Animation& backingAnimation)
     : WebAnimation(owningElement.document())
+    , m_eventQueue(owningElement)
     , m_owningElement(&owningElement)
     , m_backingAnimation(const_cast<Animation&>(backingAnimation))
-    , m_eventQueue(owningElement)
 {
 }
 
@@ -236,7 +236,7 @@ void DeclarativeAnimation::invalidateDOMEvents(Seconds elapsedTime)
     if (isPending && m_wasPending)
         return;
 
-    double iteration;
+    double iteration = 0;
     AnimationEffectPhase currentPhase;
     Seconds intervalStart;
     Seconds intervalEnd;
@@ -244,7 +244,8 @@ void DeclarativeAnimation::invalidateDOMEvents(Seconds elapsedTime)
     auto* animationEffect = effect();
     if (animationEffect) {
         auto timing = animationEffect->getComputedTiming();
-        iteration = timing.currentIteration.valueOr(0);
+        if (auto computedIteration = timing.currentIteration)
+            iteration = *computedIteration;
         currentPhase = timing.phase;
         intervalStart = std::max(0_s, Seconds::fromMilliseconds(std::min(-timing.delay, timing.activeDuration)));
         intervalEnd = std::max(0_s, Seconds::fromMilliseconds(std::min(timing.endTime - timing.delay, timing.activeDuration)));
index 2105750..5d96d26 100644 (file)
@@ -84,12 +84,14 @@ private:
     void resume() final;
     void stop() final;
 
-    Element* m_owningElement;
-    Ref<Animation> m_backingAnimation;
     bool m_wasPending { false };
     AnimationEffectPhase m_previousPhase { AnimationEffectPhase::Idle };
-    double m_previousIteration;
+
     GenericEventQueue m_eventQueue;
+
+    Element* m_owningElement;
+    Ref<Animation> m_backingAnimation;
+    double m_previousIteration;
 };
 
 } // namespace WebCore
index fb445c1..3018cbb 100644 (file)
@@ -60,13 +60,13 @@ Ref<DocumentTimeline> DocumentTimeline::create(Document& document, DocumentTimel
 }
 
 DocumentTimeline::DocumentTimeline(Document& document, Seconds originTime)
-    : AnimationTimeline(DocumentTimelineClass)
-    , m_document(&document)
-    , m_originTime(originTime)
-    , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolutionIfNeeded)
+    : AnimationTimeline()
 #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     , m_animationResolutionTimer(*this, &DocumentTimeline::animationResolutionTimerFired)
 #endif
+    , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolutionIfNeeded)
+    , m_document(&document)
+    , m_originTime(originTime)
 {
     if (m_document && m_document->page() && !m_document->page()->isVisible())
         suspendAnimations();
index 1e880f5..7cc81c9 100644 (file)
@@ -29,6 +29,7 @@
 #include "DocumentTimelineOptions.h"
 #include "GenericTaskQueue.h"
 #include "Timer.h"
+#include <wtf/Markable.h>
 #include <wtf/Ref.h>
 
 namespace WebCore {
@@ -43,6 +44,8 @@ public:
     static Ref<DocumentTimeline> create(Document&, DocumentTimelineOptions&&);
     ~DocumentTimeline();
 
+    bool isDocumentTimeline() const final { return true; }
+
     Vector<RefPtr<WebAnimation>> getAnimations() const;
 
     Document* document() const { return m_document.get(); }
@@ -100,23 +103,23 @@ private:
     void transitionDidComplete(RefPtr<CSSTransition>);
     void scheduleNextTick();
 
+#if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    void animationResolutionTimerFired();
+    Timer m_animationResolutionTimer;
+#endif
+
+    Timer m_tickScheduleTimer;
+    GenericTaskQueue<Timer> m_currentTimeClearingTaskQueue;
+    HashSet<RefPtr<WebAnimation>> m_acceleratedAnimationsPendingRunningStateChange;
+    HashSet<Element*> m_elementsWithRunningAcceleratedAnimations;
+    Vector<Ref<AnimationPlaybackEvent>> m_pendingAnimationEvents;
     RefPtr<Document> m_document;
+    Markable<Seconds, Seconds::MarkableTraits> m_cachedCurrentTime;
     Seconds m_originTime;
+    unsigned m_numberOfAnimationTimelineInvalidationsForTesting { 0 };
     bool m_isSuspended { false };
     bool m_waitingOnVMIdle { false };
     bool m_isUpdatingAnimations { false };
-    Optional<Seconds> m_cachedCurrentTime;
-    GenericTaskQueue<Timer> m_currentTimeClearingTaskQueue;
-    HashSet<RefPtr<WebAnimation>> m_acceleratedAnimationsPendingRunningStateChange;
-    Vector<Ref<AnimationPlaybackEvent>> m_pendingAnimationEvents;
-    unsigned m_numberOfAnimationTimelineInvalidationsForTesting { 0 };
-    HashSet<Element*> m_elementsWithRunningAcceleratedAnimations;
-    Timer m_tickScheduleTimer;
-
-#if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    void animationResolutionTimerFired();
-    Timer m_animationResolutionTimer;
-#endif
 };
 
 } // namespace WebCore
index 7d67d16..f5adf4c 100644 (file)
 namespace WebCore {
 
 struct EffectTiming {
+    Variant<double, String> duration { "auto" };
     double delay { 0 };
     double endDelay { 0 };
-    FillMode fill { FillMode::Auto };
     double iterationStart { 0 };
     double iterations { 1 };
-    Variant<double, String> duration { "auto" };
-    PlaybackDirection direction { PlaybackDirection::Normal };
     String easing { "linear" };
+    FillMode fill { FillMode::Auto };
+    PlaybackDirection direction { PlaybackDirection::Normal };
 };
 
 } // namespace WebCore
index 6984af4..2254852 100644 (file)
 
 #pragma once
 
+#include <wtf/Markable.h>
+
 namespace WebCore {
 
-enum class FillMode { None, Forwards, Backwards, Both, Auto };
+enum class FillMode : uint8_t { None, Forwards, Backwards, Both, Auto };
+
+using OptionalFillMode = Markable<FillMode, EnumMarkableTraits<FillMode>>;
 
 } // namespace WebCore
index ded5f4e..32ed234 100644 (file)
@@ -27,6 +27,6 @@
 
 namespace WebCore {
 
-enum class IterationCompositeOperation { Replace, Accumulate };
+enum class IterationCompositeOperation : uint8_t { Replace, Accumulate };
 
 } // namespace WebCore
index 7f27f14..90c6ad3 100644 (file)
@@ -115,8 +115,10 @@ static inline void computeMissingKeyframeOffsets(Vector<KeyframeEffect::ParsedKe
     // In our implementation, we only set non-null values to avoid making computedOffset Optional<double>. Instead, we'll know
     // that a keyframe hasn't had a computed offset by checking if it has a null offset and a 0 computedOffset, since the first
     // keyframe will already have a 0 computedOffset.
-    for (auto& keyframe : keyframes)
-        keyframe.computedOffset = keyframe.offset.valueOr(0);
+    for (auto& keyframe : keyframes) {
+        auto computedOffset = keyframe.offset;
+        keyframe.computedOffset = computedOffset ? *computedOffset : 0;
+    }
 
     // 2. If keyframes contains more than one keyframe and the computed keyframe offset of the first keyframe in keyframes is null,
     //    set the computed keyframe offset of the first keyframe to 0.
@@ -472,17 +474,16 @@ ExceptionOr<Ref<KeyframeEffect>> KeyframeEffect::create(ExecState& state, Elemen
         } else {
             auto keyframeEffectOptions = WTF::get<KeyframeEffectOptions>(optionsValue);
             timing = {
+                keyframeEffectOptions.duration,
+                keyframeEffectOptions.iterations,
                 keyframeEffectOptions.delay,
                 keyframeEffectOptions.endDelay,
-                keyframeEffectOptions.fill,
                 keyframeEffectOptions.iterationStart,
-                keyframeEffectOptions.iterations,
-                keyframeEffectOptions.duration,
-                keyframeEffectOptions.direction,
-                keyframeEffectOptions.easing
+                keyframeEffectOptions.easing,
+                keyframeEffectOptions.fill,
+                keyframeEffectOptions.direction
             };
         }
-
         auto updateTimingResult = keyframeEffect->updateTiming(timing);
         if (updateTimingResult.hasException())
             return updateTimingResult.releaseException();
@@ -509,7 +510,6 @@ Ref<KeyframeEffect> KeyframeEffect::create(const Element& target)
 
 KeyframeEffect::KeyframeEffect(Element* target)
     : m_target(target)
-    , m_blendingKeyframes(emptyString())
 {
 }
 
index 4f64ca4..2dffdb7 100644 (file)
@@ -36,6 +36,7 @@
 #include "KeyframeList.h"
 #include "RenderStyle.h"
 #include "StyleProperties.h"
+#include "WebAnimationUtilities.h"
 #include <wtf/Ref.h>
 
 namespace WebCore {
@@ -60,7 +61,7 @@ public:
     };
 
     struct BaseKeyframe {
-        Optional<double> offset;
+        MarkableDouble offset;
         String easing { "linear" };
         CompositeOperationOrAuto composite { CompositeOperationOrAuto::Auto };
     };
@@ -76,7 +77,7 @@ public:
     };
 
     struct ParsedKeyframe {
-        Optional<double> offset;
+        MarkableDouble offset;
         double computedOffset;
         CompositeOperationOrAuto composite { CompositeOperationOrAuto::Auto };
         String easing;
@@ -91,7 +92,7 @@ public:
     };
 
     struct BaseComputedKeyframe {
-        Optional<double> offset;
+        MarkableDouble offset;
         double computedOffset;
         String easing { "linear" };
         CompositeOperationOrAuto composite { CompositeOperationOrAuto::Auto };
@@ -139,7 +140,7 @@ public:
 private:
     KeyframeEffect(Element*);
 
-    enum class AcceleratedAction { Play, Pause, Seek, Stop };
+    enum class AcceleratedAction : uint8_t { Play, Pause, Seek, Stop };
 
     void copyPropertiesFromSource(Ref<KeyframeEffect>&&);
     ExceptionOr<void> processKeyframes(JSC::ExecState&, JSC::Strong<JSC::JSObject>&&);
@@ -157,14 +158,20 @@ private:
     void setBlendingKeyframes(KeyframeList&);
     void checkForMatchingTransformFunctionLists();
     void checkForMatchingFilterFunctionLists();
+    void checkForMatchingColorFilterFunctionLists();
+    bool checkForMatchingFilterFunctionLists(CSSPropertyID, const std::function<const FilterOperations& (const RenderStyle&)>&) const;
 #if ENABLE(FILTERS_LEVEL_2)
     void checkForMatchingBackdropFilterFunctionLists();
 #endif
-    void checkForMatchingColorFilterFunctionLists();
 
-    bool checkForMatchingFilterFunctionLists(CSSPropertyID, const std::function<const FilterOperations& (const RenderStyle&)>&) const;
+    KeyframeList m_blendingKeyframes { emptyString() };
+    Vector<ParsedKeyframe> m_parsedKeyframes;
+    Vector<AcceleratedAction> m_pendingAcceleratedActions;
+    RefPtr<Element> m_target;
 
     AcceleratedAction m_lastRecordedAcceleratedAction { AcceleratedAction::Stop };
+    IterationCompositeOperation m_iterationCompositeOperation { IterationCompositeOperation::Replace };
+    CompositeOperation m_compositeOperation { CompositeOperation::Replace };
     bool m_shouldRunAccelerated { false };
     bool m_needsForcedLayout { false };
     bool m_triggersStackingContext { false };
@@ -174,14 +181,6 @@ private:
     bool m_backdropFilterFunctionListsMatch { false };
 #endif
     bool m_colorFilterFunctionListsMatch { false };
-
-    RefPtr<Element> m_target;
-    KeyframeList m_blendingKeyframes;
-    Vector<ParsedKeyframe> m_parsedKeyframes;
-    IterationCompositeOperation m_iterationCompositeOperation { IterationCompositeOperation::Replace };
-    CompositeOperation m_compositeOperation { CompositeOperation::Replace };
-
-    Vector<AcceleratedAction> m_pendingAcceleratedActions;
 };
 
 } // namespace WebCore
index 6d91181..16632d9 100644 (file)
 
 #include "FillMode.h"
 #include "PlaybackDirection.h"
+#include "WebAnimationUtilities.h"
 #include <wtf/Variant.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
 struct OptionalEffectTiming {
-    Optional<double> delay;
-    Optional<double> endDelay;
-    Optional<FillMode> fill;
-    Optional<double> iterationStart;
-    Optional<double> iterations;
     Optional<Variant<double, String>> duration;
-    Optional<PlaybackDirection> direction;
+    Optional<double> iterations; // This value cannot be a MarkableDouble since we need to check for a NaN value.
+    MarkableDouble delay;
+    MarkableDouble endDelay;
+    MarkableDouble iterationStart;
     String easing;
+    OptionalFillMode fill;
+    OptionalPlaybackDirection direction;
 };
 
 } // namespace WebCore
index 4ba9ad6..824605a 100644 (file)
 
 #pragma once
 
+#include <wtf/Markable.h>
+
 namespace WebCore {
 
-enum class PlaybackDirection { Normal, Reverse, Alternate, AlternateReverse };
+enum class PlaybackDirection : uint8_t { Normal, Reverse, Alternate, AlternateReverse };
+
+using OptionalPlaybackDirection = Markable<PlaybackDirection, EnumMarkableTraits<PlaybackDirection>>;
 
 } // namespace WebCore
index ae1b7ab..ae0e40f 100644 (file)
@@ -29,7 +29,9 @@
 #include "DOMPromiseProxy.h"
 #include "EventTarget.h"
 #include "ExceptionOr.h"
+#include "WebAnimationUtilities.h"
 #include <wtf/Forward.h>
+#include <wtf/Markable.h>
 #include <wtf/Optional.h>
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
@@ -68,11 +70,11 @@ public:
     Optional<Seconds> currentTime() const;
     ExceptionOr<void> setCurrentTime(Optional<Seconds>);
 
-    enum class Silently { Yes, No };
+    enum class Silently : uint8_t { Yes, No };
     double playbackRate() const { return m_playbackRate + 0; }
     void setPlaybackRate(double);
 
-    enum class PlayState { Idle, Running, Paused, Finished };
+    enum class PlayState : uint8_t { Idle, Running, Paused, Finished };
     PlayState playState() const;
 
     bool pending() const { return hasPendingPauseTask() || hasPendingPlayTask(); }
@@ -128,11 +130,11 @@ protected:
     void stop() override;
 
 private:
-    enum class DidSeek { Yes, No };
-    enum class SynchronouslyNotify { Yes, No };
-    enum class RespectHoldTime { Yes, No };
-    enum class AutoRewind { Yes, No };
-    enum class TimeToRunPendingTask { NotScheduled, ASAP, WhenReady };
+    enum class DidSeek : uint8_t { Yes, No };
+    enum class SynchronouslyNotify : uint8_t { Yes, No };
+    enum class RespectHoldTime : uint8_t { Yes, No };
+    enum class AutoRewind : uint8_t { Yes, No };
+    enum class TimeToRunPendingTask : uint8_t { NotScheduled, ASAP, WhenReady };
 
     void timingDidChange(DidSeek, SynchronouslyNotify);
     void updateFinishedState(DidSeek, SynchronouslyNotify);
@@ -158,22 +160,24 @@ private:
     double effectivePlaybackRate() const;
     void applyPendingPlaybackRate();
 
-    String m_id;
     RefPtr<AnimationEffect> m_effect;
     RefPtr<AnimationTimeline> m_timeline;
-    Optional<Seconds> m_previousCurrentTime;
-    Optional<Seconds> m_startTime;
-    Optional<Seconds> m_holdTime;
-    int m_suspendCount { 0 };
+    UniqueRef<ReadyPromise> m_readyPromise;
+    UniqueRef<FinishedPromise> m_finishedPromise;
+    Markable<Seconds, Seconds::MarkableTraits> m_previousCurrentTime;
+    Markable<Seconds, Seconds::MarkableTraits> m_startTime;
+    Markable<Seconds, Seconds::MarkableTraits> m_holdTime;
+    MarkableDouble m_pendingPlaybackRate;
     double m_playbackRate { 1 };
-    Optional<double> m_pendingPlaybackRate;
+    String m_id;
+
+    int m_suspendCount { 0 };
+
     bool m_isStopped { false };
     bool m_isSuspended { false };
     bool m_finishNotificationStepsMicrotaskPending;
     bool m_isRelevant;
     bool m_shouldSkipUpdatingFinishedStateWhenResolving;
-    UniqueRef<ReadyPromise> m_readyPromise;
-    UniqueRef<FinishedPromise> m_finishedPromise;
     TimeToRunPendingTask m_timeToRunPendingPlayTask { TimeToRunPendingTask::NotScheduled };
     TimeToRunPendingTask m_timeToRunPendingPauseTask { TimeToRunPendingTask::NotScheduled };
 
index 97bdd38..831d14d 100644 (file)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include <wtf/Markable.h>
 #include <wtf/Seconds.h>
 
 namespace WebCore {
@@ -45,5 +46,19 @@ inline double secondsToWebAnimationsAPITime(const Seconds time)
 
 const auto timeEpsilon = Seconds::fromMilliseconds(0.001);
 
+struct WebAnimationsMarkableDoubleTraits {
+    static bool isEmptyValue(double value)
+    {
+        return std::isnan(value);
+    }
+
+    static constexpr double emptyValue()
+    {
+        return std::numeric_limits<double>::quiet_NaN();
+    }
+};
+
+using MarkableDouble = Markable<double, WebAnimationsMarkableDoubleTraits>;
+
 } // namespace WebCore