Merge from Chromium at DEPS revision 269336

This commit was generated by merge_to_master.py.

Change-Id: Ibf41f59c608fa0127526255ada8e255a93306a7e
diff --git a/Source/core/animation/ActiveAnimations.cpp b/Source/core/animation/ActiveAnimations.cpp
index e12cbdc..3509885 100644
--- a/Source/core/animation/ActiveAnimations.cpp
+++ b/Source/core/animation/ActiveAnimations.cpp
@@ -37,10 +37,6 @@
 
 ActiveAnimations::~ActiveAnimations()
 {
-}
-
-void ActiveAnimations::dispose()
-{
     for (size_t i = 0; i < m_animations.size(); ++i)
         m_animations[i]->notifyElementDestroyed();
     m_animations.clear();
@@ -96,6 +92,9 @@
 void ActiveAnimations::trace(Visitor* visitor)
 {
     visitor->trace(m_cssAnimations);
+#if ENABLE(OILPAN)
+    visitor->trace(m_target);
+#endif
 }
 
 } // namespace WebCore
diff --git a/Source/core/animation/ActiveAnimations.h b/Source/core/animation/ActiveAnimations.h
index 1a4c0a0..966f73c 100644
--- a/Source/core/animation/ActiveAnimations.h
+++ b/Source/core/animation/ActiveAnimations.h
@@ -53,7 +53,6 @@
     }
 
     ~ActiveAnimations();
-    void dispose();
 
     // Animations that are currently active for this element, their effects will be applied
     // during a style recalc. CSS Transitions are included in this stack.
@@ -94,6 +93,16 @@
     // won't be needed once Element and Animation are moved to Oilpan.
     Vector<Animation*> m_animations;
 
+#if ENABLE(OILPAN)
+    // Keep a back reference to the target Element, so that this object
+    // will be finalized during the same GC sweep as the target (as the
+    // Element keeps a reference in the other direction via its
+    // rare data.) This is done so that we can accurately notify the
+    // the Element as destroyed to the above vector of Animations in
+    // the ActiveAnimations finalizer.
+    Member<Element> m_target;
+#endif
+
     // CSSAnimations checks if a style change is due to animation.
     friend class CSSAnimations;
 };
diff --git a/Source/core/animation/AnimatableClipPathOperation.h b/Source/core/animation/AnimatableClipPathOperation.h
index 2cffa78..0a0188d 100644
--- a/Source/core/animation/AnimatableClipPathOperation.h
+++ b/Source/core/animation/AnimatableClipPathOperation.h
@@ -45,7 +45,7 @@
     }
     ClipPathOperation* clipPathOperation() const { return m_operation.get(); }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableColor.h b/Source/core/animation/AnimatableColor.h
index 5723248..87196a0 100644
--- a/Source/core/animation/AnimatableColor.h
+++ b/Source/core/animation/AnimatableColor.h
@@ -62,7 +62,7 @@
     Color color() const { return m_color.toColor(); }
     Color visitedLinkColor() const { return m_visitedLinkColor.toColor(); }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableDouble.cpp b/Source/core/animation/AnimatableDouble.cpp
index eaadd00..b27e515 100644
--- a/Source/core/animation/AnimatableDouble.cpp
+++ b/Source/core/animation/AnimatableDouble.cpp
@@ -31,18 +31,11 @@
 #include "config.h"
 #include "core/animation/AnimatableDouble.h"
 
-#include "core/css/CSSPrimitiveValue.h"
-#include "core/css/CSSValuePool.h"
 #include "platform/animation/AnimationUtilities.h"
 #include <math.h>
 
 namespace WebCore {
 
-PassRefPtrWillBeRawPtr<CSSValue> AnimatableDouble::toCSSValue() const
-{
-    return cssValuePool().createValue(m_number, CSSPrimitiveValue::CSS_NUMBER);
-}
-
 bool AnimatableDouble::usesDefaultInterpolationWith(const AnimatableValue* value) const
 {
     const AnimatableDouble* other = toAnimatableDouble(value);
diff --git a/Source/core/animation/AnimatableDouble.h b/Source/core/animation/AnimatableDouble.h
index 0d6496a..88ef247 100644
--- a/Source/core/animation/AnimatableDouble.h
+++ b/Source/core/animation/AnimatableDouble.h
@@ -32,7 +32,6 @@
 #define AnimatableDouble_h
 
 #include "core/animation/AnimatableValue.h"
-#include "core/css/CSSValue.h"
 
 namespace WebCore {
 
@@ -50,10 +49,9 @@
         return adoptRefWillBeNoop(new AnimatableDouble(number, constraint));
     }
 
-    PassRefPtrWillBeRawPtr<CSSValue> toCSSValue() const;
     double toDouble() const { return m_number; }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableDoubleTest.cpp b/Source/core/animation/AnimatableDoubleTest.cpp
index 1f6e8cc..f1948fb 100644
--- a/Source/core/animation/AnimatableDoubleTest.cpp
+++ b/Source/core/animation/AnimatableDoubleTest.cpp
@@ -31,8 +31,6 @@
 #include "config.h"
 #include "core/animation/AnimatableDouble.h"
 
-#include "core/css/CSSPrimitiveValue.h"
-
 #include <gtest/gtest.h>
 
 using namespace WebCore;
@@ -51,14 +49,6 @@
     EXPECT_FALSE(AnimatableDouble::create(5)->equals(AnimatableDouble::create(10).get()));
 }
 
-TEST(AnimationAnimatableDoubleTest, ToCSSValue)
-{
-    RefPtrWillBeRawPtr<CSSValue> cssValue5 = CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_NUMBER);
-    RefPtrWillBeRawPtr<CSSValue> cssValue10 = CSSPrimitiveValue::create(10, CSSPrimitiveValue::CSS_NUMBER);
-    EXPECT_TRUE(AnimatableDouble::create(5)->toCSSValue()->equals(*cssValue5.get()));
-    EXPECT_FALSE(AnimatableDouble::create(5)->toCSSValue()->equals(*cssValue10.get()));
-}
-
 TEST(AnimationAnimatableDoubleTest, ToDouble)
 {
     EXPECT_EQ(5.9, AnimatableDouble::create(5.9)->toDouble());
diff --git a/Source/core/animation/AnimatableFilterOperations.h b/Source/core/animation/AnimatableFilterOperations.h
index 569d694..e047201 100644
--- a/Source/core/animation/AnimatableFilterOperations.h
+++ b/Source/core/animation/AnimatableFilterOperations.h
@@ -45,7 +45,7 @@
     }
     const FilterOperations& operations() const { return m_operations; }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableImage.h b/Source/core/animation/AnimatableImage.h
index c7e535c..e76b619 100644
--- a/Source/core/animation/AnimatableImage.h
+++ b/Source/core/animation/AnimatableImage.h
@@ -46,7 +46,11 @@
     }
     CSSValue* toCSSValue() const { return m_value.get(); }
 
-    virtual void trace(Visitor* visitor) OVERRIDE { visitor->trace(m_value); }
+    virtual void trace(Visitor* visitor) OVERRIDE
+    {
+        visitor->trace(m_value);
+        AnimatableValue::trace(visitor);
+    }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableLength.cpp b/Source/core/animation/AnimatableLength.cpp
index fcc2668..c167c20 100644
--- a/Source/core/animation/AnimatableLength.cpp
+++ b/Source/core/animation/AnimatableLength.cpp
@@ -31,127 +31,53 @@
 #include "config.h"
 #include "core/animation/AnimatableLength.h"
 
-#include "core/css/CSSPrimitiveValueMappings.h"
 #include "platform/CalculationValue.h"
 #include "platform/animation/AnimationUtilities.h"
 
 namespace WebCore {
 
-PassRefPtrWillBeRawPtr<AnimatableLength> AnimatableLength::create(CSSValue* value)
+namespace {
+
+double clampNumber(double value, ValueRange range)
 {
-    ASSERT(canCreateFrom(value));
-    if (value->isPrimitiveValue()) {
-        CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(value);
-        const CSSCalcValue* calcValue = primitiveValue->cssCalcValue();
-        if (calcValue)
-            return create(calcValue->expressionNode(), primitiveValue);
-        CSSPrimitiveValue::LengthUnitType unitType;
-        bool isPrimitiveLength = CSSPrimitiveValue::unitTypeToLengthUnitType(primitiveValue->primitiveType(), unitType);
-        ASSERT_UNUSED(isPrimitiveLength, isPrimitiveLength);
-        const double scale = CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(primitiveValue->primitiveType());
-        return create(primitiveValue->getDoubleValue() * scale, unitType, primitiveValue);
-    }
-
-    if (value->isCalcValue())
-        return create(toCSSCalcValue(value)->expressionNode());
-
-    ASSERT_NOT_REACHED();
-    return nullptr;
+    if (range == ValueRangeNonNegative)
+        return std::max(value, 0.0);
+    ASSERT(range == ValueRangeAll);
+    return value;
 }
 
-bool AnimatableLength::canCreateFrom(const CSSValue* value)
-{
-    ASSERT(value);
-    if (value->isPrimitiveValue()) {
-        const CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(value);
-        if (primitiveValue->cssCalcValue())
-            return true;
+} // namespace
 
-        CSSPrimitiveValue::LengthUnitType type;
-        // Only returns true if the type is a primitive length unit.
-        return CSSPrimitiveValue::unitTypeToLengthUnitType(primitiveValue->primitiveType(), type);
-    }
-    return value->isCalcValue();
+AnimatableLength::AnimatableLength(const Length& length, float zoom)
+{
+    ASSERT(zoom);
+    PixelsAndPercent pixelsAndPercent = length.pixelsAndPercent();
+    m_pixels = pixelsAndPercent.pixels / zoom;
+    m_percent = pixelsAndPercent.percent;
+    m_hasPixels = length.type() != Percent;
+    m_hasPercent = !length.isFixed();
 }
 
-PassRefPtrWillBeRawPtr<CSSValue> AnimatableLength::toCSSValue(NumberRange range) const
+Length AnimatableLength::length(float zoom, ValueRange range) const
 {
-    return toCSSPrimitiveValue(range);
-}
-
-Length AnimatableLength::toLength(const CSSToLengthConversionData& conversionData, NumberRange range) const
-{
-    // Avoid creating a CSSValue in the common cases
-    if (m_lengthUnitType == CSSPrimitiveValue::UnitTypePixels)
-        return Length(clampedNumber(range) * conversionData.zoom(), Fixed);
-    if (m_lengthUnitType == CSSPrimitiveValue::UnitTypePercentage)
-        return Length(clampedNumber(range), Percent);
-
-    return toCSSPrimitiveValue(range)->convertToLength<AnyConversion>(conversionData);
+    if (!m_hasPercent)
+        return Length(clampNumber(m_pixels, range) * zoom, Fixed);
+    if (!m_hasPixels)
+        return Length(clampNumber(m_percent, range), Percent);
+    return Length(CalculationValue::create(PixelsAndPercent(m_pixels * zoom, m_percent), range));
 }
 
 PassRefPtrWillBeRawPtr<AnimatableValue> AnimatableLength::interpolateTo(const AnimatableValue* value, double fraction) const
 {
     const AnimatableLength* length = toAnimatableLength(value);
-    CSSPrimitiveValue::LengthUnitType type = commonUnitType(length);
-    if (!isCalc(type))
-        return AnimatableLength::create(blend(m_lengthValue, length->m_lengthValue, fraction), type);
-    return AnimatableLength::create(scale(1 - fraction).get(), length->scale(fraction).get());
+    return create(blend(m_pixels, length->m_pixels, fraction), blend(m_percent, length->m_percent, fraction),
+        m_hasPixels || length->m_hasPixels, m_hasPercent || length->m_hasPercent);
 }
 
 bool AnimatableLength::equalTo(const AnimatableValue* value) const
 {
     const AnimatableLength* length = toAnimatableLength(value);
-    if (m_lengthUnitType != length->m_lengthUnitType)
-        return false;
-    if (isCalc())
-        return m_calcExpression == length->m_calcExpression || m_calcExpression->equals(*length->m_calcExpression);
-    return m_lengthValue == length->m_lengthValue;
-}
-
-PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> AnimatableLength::toCSSCalcExpressionNode() const
-{
-    if (isCalc())
-        return m_calcExpression;
-    return CSSCalcValue::createExpressionNode(toCSSPrimitiveValue(AllValues), m_lengthValue == trunc(m_lengthValue));
-}
-
-static bool isCompatibleWithRange(const CSSPrimitiveValue* primitiveValue, NumberRange range)
-{
-    ASSERT(primitiveValue);
-    if (range == AllValues)
-        return true;
-    if (primitiveValue->isCalculated())
-        return primitiveValue->cssCalcValue()->permittedValueRange() == ValueRangeNonNegative;
-    return primitiveValue->getDoubleValue() >= 0;
-}
-
-PassRefPtrWillBeRawPtr<CSSPrimitiveValue> AnimatableLength::toCSSPrimitiveValue(NumberRange range) const
-{
-    if (!m_cachedCSSPrimitiveValue || !isCompatibleWithRange(m_cachedCSSPrimitiveValue.get(), range)) {
-        if (isCalc())
-            m_cachedCSSPrimitiveValue = CSSPrimitiveValue::create(CSSCalcValue::create(m_calcExpression, range == AllValues ? ValueRangeAll : ValueRangeNonNegative));
-        else
-            m_cachedCSSPrimitiveValue = CSSPrimitiveValue::create(clampedNumber(range), static_cast<CSSPrimitiveValue::UnitTypes>(CSSPrimitiveValue::lengthUnitTypeToUnitType(m_lengthUnitType)));
-    }
-    return m_cachedCSSPrimitiveValue;
-}
-
-PassRefPtrWillBeRawPtr<AnimatableLength> AnimatableLength::scale(double factor) const
-{
-    if (isCalc()) {
-        return AnimatableLength::create(CSSCalcValue::createExpressionNode(
-            m_calcExpression,
-            CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(factor, CSSPrimitiveValue::CSS_NUMBER)),
-            CalcMultiply));
-    }
-    return AnimatableLength::create(m_lengthValue * factor, m_lengthUnitType);
-}
-
-void AnimatableLength::trace(Visitor* visitor)
-{
-    visitor->trace(m_calcExpression);
-    visitor->trace(m_cachedCSSPrimitiveValue);
+    return m_pixels == length->m_pixels && m_percent == length->m_percent && m_hasPixels == length->m_hasPixels && m_hasPercent == length->m_hasPercent;
 }
 
 } // namespace WebCore
diff --git a/Source/core/animation/AnimatableLength.h b/Source/core/animation/AnimatableLength.h
index adfb136..754c043 100644
--- a/Source/core/animation/AnimatableLength.h
+++ b/Source/core/animation/AnimatableLength.h
@@ -32,109 +32,44 @@
 #define AnimatableLength_h
 
 #include "core/animation/AnimatableValue.h"
-#include "core/css/CSSCalculationValue.h"
-#include "core/css/CSSPrimitiveValue.h"
 #include "platform/Length.h"
 
 namespace WebCore {
 
-enum NumberRange {
-    AllValues,
-    NonNegativeValues,
-};
-
-// Handles animation of CSS length and percentage values including CSS calc.
-// See primitiveUnitToLengthType() for the list of supported units.
-// If created from a CSSPrimitiveValue this class will cache it to be returned in toCSSValue().
 class AnimatableLength FINAL : public AnimatableValue {
 public:
-    virtual ~AnimatableLength() { }
-    static bool canCreateFrom(const CSSValue*);
-    static PassRefPtrWillBeRawPtr<AnimatableLength> create(CSSValue*);
-    static PassRefPtrWillBeRawPtr<AnimatableLength> create(double number, CSSPrimitiveValue::LengthUnitType unitType, CSSPrimitiveValue* cssPrimitiveValue = 0)
+    static PassRefPtrWillBeRawPtr<AnimatableLength> create(const Length& length, float zoom)
     {
-        return adoptRefWillBeNoop(new AnimatableLength(number, unitType, cssPrimitiveValue));
+        return adoptRefWillBeNoop(new AnimatableLength(length, zoom));
     }
-    static PassRefPtrWillBeRawPtr<AnimatableLength> create(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> calcExpression, CSSPrimitiveValue* cssPrimitiveValue = 0)
-    {
-        return adoptRefWillBeNoop(new AnimatableLength(calcExpression, cssPrimitiveValue));
-    }
-    PassRefPtrWillBeRawPtr<CSSValue> toCSSValue(NumberRange = AllValues) const;
-    Length toLength(const CSSToLengthConversionData&, NumberRange = AllValues) const;
-
-    virtual void trace(Visitor*) OVERRIDE;
+    Length length(float zoom, ValueRange) const;
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
 
 private:
-    AnimatableLength(double number, CSSPrimitiveValue::LengthUnitType unitType, CSSPrimitiveValue* cssPrimitiveValue)
-        : m_lengthValue(number)
-        , m_lengthUnitType(unitType)
-        , m_cachedCSSPrimitiveValue(cssPrimitiveValue)
+    static PassRefPtrWillBeRawPtr<AnimatableLength> create(double pixels, double percent, bool hasPixels, bool hasPercent)
     {
-        ASSERT(!isCalc());
+        return adoptRefWillBeNoop(new AnimatableLength(pixels, percent, hasPixels, hasPercent));
     }
-    AnimatableLength(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> calcExpression, CSSPrimitiveValue* cssPrimitiveValue)
-        : m_lengthUnitType(CSSPrimitiveValue::UnitTypeCalc)
-        , m_calcExpression(calcExpression)
-        , m_cachedCSSPrimitiveValue(cssPrimitiveValue)
+    AnimatableLength(const Length&, float zoom);
+    AnimatableLength(double pixels, double percent, bool hasPixels, bool hasPercent)
+        : m_pixels(pixels)
+        , m_percent(percent)
+        , m_hasPixels(hasPixels)
+        , m_hasPercent(hasPercent)
     {
-        ASSERT(isCalc());
-        ASSERT(m_calcExpression);
+        ASSERT(m_hasPixels || m_hasPercent);
     }
     virtual AnimatableType type() const OVERRIDE { return TypeLength; }
     virtual bool equalTo(const AnimatableValue*) const OVERRIDE;
 
-    static bool isCalc(CSSPrimitiveValue::LengthUnitType type) { return type == CSSPrimitiveValue::UnitTypeCalc; }
-    bool isCalc() const { return isCalc(m_lengthUnitType); }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
-    static PassRefPtrWillBeRawPtr<AnimatableLength> create(const AnimatableLength* leftAddend, const AnimatableLength* rightAddend)
-    {
-        ASSERT(leftAddend && rightAddend);
-        return create(CSSCalcValue::createExpressionNode(leftAddend->toCSSCalcExpressionNode(), rightAddend->toCSSCalcExpressionNode(), CalcAdd));
-    }
-
-    PassRefPtrWillBeRawPtr<CSSPrimitiveValue> toCSSPrimitiveValue(NumberRange) const;
-    PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> toCSSCalcExpressionNode() const;
-
-    PassRefPtrWillBeRawPtr<AnimatableLength> scale(double) const;
-    double clampedNumber(NumberRange range) const
-    {
-        ASSERT(!isCalc());
-        return (range == NonNegativeValues && m_lengthValue <= 0) ? 0 : m_lengthValue;
-    }
-
-    // Zero is effectively unitless, except in the case of percentage.
-    // http://www.w3.org/TR/css3-values/#calc-computed-value
-    // e.g. calc(100% - 100% + 1em) resolves to calc(0% + 1em), not to calc(1em)
-    bool isUnitlessZero() const
-    {
-        return !isCalc() && !m_lengthValue && m_lengthUnitType != CSSPrimitiveValue::UnitTypePercentage;
-    }
-
-    CSSPrimitiveValue::LengthUnitType commonUnitType(const AnimatableLength* length) const
-    {
-        if (m_lengthUnitType == length->m_lengthUnitType)
-            return m_lengthUnitType;
-
-        if (isUnitlessZero())
-            return length->m_lengthUnitType;
-        if (length->isUnitlessZero())
-            return m_lengthUnitType;
-
-        return CSSPrimitiveValue::UnitTypeCalc;
-    }
-
-    double m_lengthValue;
-    const CSSPrimitiveValue::LengthUnitType m_lengthUnitType;
-
-    RefPtrWillBeMember<CSSCalcExpressionNode> m_calcExpression;
-
-    mutable RefPtrWillBeMember<CSSPrimitiveValue> m_cachedCSSPrimitiveValue;
-
-    friend class AnimationAnimatableLengthTest;
-    friend class LengthStyleInterpolation;
+    double m_pixels;
+    double m_percent;
+    bool m_hasPixels;
+    bool m_hasPercent;
 };
 
 DEFINE_ANIMATABLE_VALUE_TYPE_CASTS(AnimatableLength, isLength());
diff --git a/Source/core/animation/AnimatableLengthBox.cpp b/Source/core/animation/AnimatableLengthBox.cpp
index ebf760e..2589621 100644
--- a/Source/core/animation/AnimatableLengthBox.cpp
+++ b/Source/core/animation/AnimatableLengthBox.cpp
@@ -58,6 +58,7 @@
     visitor->trace(m_right);
     visitor->trace(m_top);
     visitor->trace(m_bottom);
+    AnimatableValue::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/AnimatableLengthBoxAndBool.cpp b/Source/core/animation/AnimatableLengthBoxAndBool.cpp
index 8aec4d7..c598ec4 100644
--- a/Source/core/animation/AnimatableLengthBoxAndBool.cpp
+++ b/Source/core/animation/AnimatableLengthBoxAndBool.cpp
@@ -61,6 +61,7 @@
 void AnimatableLengthBoxAndBool::trace(Visitor* visitor)
 {
     visitor->trace(m_box);
+    AnimatableValue::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/AnimatableLengthPoint.cpp b/Source/core/animation/AnimatableLengthPoint.cpp
index e47279e..b8805d0 100644
--- a/Source/core/animation/AnimatableLengthPoint.cpp
+++ b/Source/core/animation/AnimatableLengthPoint.cpp
@@ -51,6 +51,7 @@
 {
     visitor->trace(m_x);
     visitor->trace(m_y);
+    AnimatableValue::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/AnimatableLengthPoint3D.cpp b/Source/core/animation/AnimatableLengthPoint3D.cpp
index da031a3..402f0a8 100644
--- a/Source/core/animation/AnimatableLengthPoint3D.cpp
+++ b/Source/core/animation/AnimatableLengthPoint3D.cpp
@@ -53,6 +53,7 @@
     visitor->trace(m_x);
     visitor->trace(m_y);
     visitor->trace(m_z);
+    AnimatableValue::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/AnimatableLengthSize.cpp b/Source/core/animation/AnimatableLengthSize.cpp
index 79f52e1..c632395 100644
--- a/Source/core/animation/AnimatableLengthSize.cpp
+++ b/Source/core/animation/AnimatableLengthSize.cpp
@@ -51,6 +51,7 @@
 {
     visitor->trace(m_width);
     visitor->trace(m_height);
+    AnimatableValue::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/AnimatableLengthTest.cpp b/Source/core/animation/AnimatableLengthTest.cpp
index 48d8ec6..c5887e2 100644
--- a/Source/core/animation/AnimatableLengthTest.cpp
+++ b/Source/core/animation/AnimatableLengthTest.cpp
@@ -1,318 +1,73 @@
-/*
- * Copyright (c) 2013, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
 
 #include "config.h"
 
 #include "core/animation/AnimatableLength.h"
-
-#include "core/animation/AnimatableValueTestHelper.h"
-#include "core/css/CSSCalculationValue.h"
-#include "core/css/CSSPrimitiveValue.h"
-#include "core/css/CSSToLengthConversionData.h"
-#include "core/rendering/style/RenderStyle.h"
-#include "core/rendering/style/StyleInheritedData.h"
 #include "platform/CalculationValue.h"
-#include "wtf/MathExtras.h"
 
 #include <gtest/gtest.h>
 
-#define EXPECT_ROUNDTRIP(a, f) EXPECT_REFV_EQ(a, f(a.get()))
-
 namespace WebCore {
 
-class AnimationAnimatableLengthTest : public ::testing::Test {
-protected:
-    AnimationAnimatableLengthTest()
-        : style(RenderStyle::createDefaultStyle())
-        , conversionDataZoom1(style.get(), style.get(), 0, 0, 1.0f)
-        , conversionDataZoom3(style.get(), style.get(), 0, 0, 3.0f)
+namespace {
+
+    PassRefPtrWillBeRawPtr<AnimatableLength> create(const Length& length, double zoom = 1)
     {
+        return AnimatableLength::create(length, zoom);
     }
 
-    PassRefPtrWillBeRawPtr<AnimatableLength> create(double value, CSSPrimitiveValue::UnitTypes type)
-    {
-        return AnimatableLength::create(CSSPrimitiveValue::create(value, type).get());
-    }
+} // namespace
 
-    PassRefPtrWillBeRawPtr<AnimatableLength> create(double valueLeft, CSSPrimitiveValue::UnitTypes typeLeft, double valueRight, CSSPrimitiveValue::UnitTypes typeRight)
-    {
-        return AnimatableLength::create(createCalc(valueLeft, typeLeft, valueRight, typeRight).get());
-    }
-
-    PassRefPtrWillBeRawPtr<CSSCalcValue> createCalc(double valueLeft, CSSPrimitiveValue::UnitTypes typeLeft, double valueRight, CSSPrimitiveValue::UnitTypes typeRight)
-    {
-        return CSSCalcValue::create(CSSCalcValue::createExpressionNode(
-            CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(valueLeft, typeLeft), valueLeft == trunc(valueLeft)),
-            CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(valueRight, typeRight), valueRight == trunc(valueRight)),
-            CalcAdd
-        ));
-    }
-
-    PassRefPtrWillBeRawPtr<CSSValue> toCSSValue(CSSValue* cssValue)
-    {
-        return AnimatableLength::create(cssValue)->toCSSValue();
-    }
-
-    CSSPrimitiveValue::LengthUnitType commonUnitType(PassRefPtrWillBeRawPtr<AnimatableLength> a, PassRefPtrWillBeRawPtr<AnimatableLength> b)
-    {
-        return a->commonUnitType(b.get());
-    }
-
-    bool isUnitlessZero(PassRefPtrWillBeRawPtr<AnimatableLength> a)
-    {
-        return a->isUnitlessZero();
-    }
-
-    RefPtr<RenderStyle> style;
-    CSSToLengthConversionData conversionDataZoom1;
-    CSSToLengthConversionData conversionDataZoom3;
-};
-
-TEST_F(AnimationAnimatableLengthTest, CanCreateFrom)
+TEST(AnimationAnimatableLengthTest, RoundTripConversion)
 {
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_PX).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_MM).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_IN).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_PT).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_PC).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_EMS).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_EXS).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_REMS).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_VW).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_VH).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_VMIN).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_VMAX).get()));
-
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(createCalc(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_TRUE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create(createCalc(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM)).get()));
-
-    EXPECT_FALSE(AnimatableLength::canCreateFrom(CSSPrimitiveValue::create("NaN", CSSPrimitiveValue::CSS_STRING).get()));
+    EXPECT_EQ(Length(0, Fixed), create(Length(0, Fixed))->length(1, ValueRangeAll));
+    EXPECT_EQ(Length(0, Percent), create(Length(0, Percent))->length(1, ValueRangeAll));
+    EXPECT_EQ(Length(10, Fixed), create(Length(10, Fixed))->length(1, ValueRangeAll));
+    EXPECT_EQ(Length(10, Percent), create(Length(10, Percent))->length(1, ValueRangeAll));
+    EXPECT_EQ(Length(-10, Fixed), create(Length(-10, Fixed))->length(1, ValueRangeAll));
+    EXPECT_EQ(Length(-10, Percent), create(Length(-10, Percent))->length(1, ValueRangeAll));
+    Length calc = Length(CalculationValue::create(PixelsAndPercent(5, 10), ValueRangeAll));
+    EXPECT_EQ(calc, create(calc)->length(1, ValueRangeAll));
 }
 
-TEST_F(AnimationAnimatableLengthTest, Create)
+TEST(AnimationAnimatableLengthTest, ValueRangeNonNegative)
 {
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_PX).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_MM).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_IN).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_PT).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_PC).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_EMS).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_EXS).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_REMS).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_VW).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_VH).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_VMIN).get()));
-    EXPECT_TRUE(static_cast<bool>(create(5, CSSPrimitiveValue::CSS_VMAX).get()));
-
-    EXPECT_TRUE(static_cast<bool>(
-        AnimatableLength::create(createCalc(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM).get()).get()
-    ));
-    EXPECT_TRUE(static_cast<bool>(
-        AnimatableLength::create(CSSPrimitiveValue::create(createCalc(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM)).get()).get()
-    ));
+    EXPECT_EQ(Length(10, Fixed), create(Length(10, Fixed))->length(1, ValueRangeNonNegative));
+    EXPECT_EQ(Length(10, Percent), create(Length(10, Percent))->length(1, ValueRangeNonNegative));
+    EXPECT_EQ(Length(0, Fixed), create(Length(-10, Fixed))->length(1, ValueRangeNonNegative));
+    EXPECT_EQ(Length(0, Percent), create(Length(-10, Percent))->length(1, ValueRangeNonNegative));
+    Length calc = Length(CalculationValue::create(PixelsAndPercent(-5, -10), ValueRangeNonNegative));
+    EXPECT_TRUE(calc == create(calc)->length(1, ValueRangeNonNegative));
 }
 
-
-TEST_F(AnimationAnimatableLengthTest, ToCSSValue)
+TEST(AnimationAnimatableLengthTest, Zoom)
 {
-
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_PX), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_CM), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_MM), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_IN), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_PT), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_PC), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_EMS), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_EXS), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_REMS), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_PERCENTAGE), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_VW), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_VH), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_VMIN), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(-5, CSSPrimitiveValue::CSS_VMAX), toCSSValue);
-
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(createCalc(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_IN)), toCSSValue);
-    EXPECT_ROUNDTRIP(CSSPrimitiveValue::create(createCalc(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_IN)), toCSSValue);
+    EXPECT_EQ(Length(4, Fixed), create(Length(10, Fixed), 5)->length(2, ValueRangeAll));
+    EXPECT_EQ(Length(10, Percent), create(Length(10, Percent), 5)->length(2, ValueRangeAll));
+    Length calc = Length(CalculationValue::create(PixelsAndPercent(5, 10), ValueRangeAll));
+    Length result = Length(CalculationValue::create(PixelsAndPercent(2, 10), ValueRangeAll));
+    EXPECT_TRUE(result == create(calc, 5)->length(2, ValueRangeAll));
 }
 
-
-TEST_F(AnimationAnimatableLengthTest, ToLength)
+TEST(AnimationAnimatableLengthTest, Equals)
 {
-    EXPECT_EQ(Length(-5, WebCore::Fixed), create(-5, CSSPrimitiveValue::CSS_PX)->toLength(conversionDataZoom1));
-    EXPECT_EQ(Length(-15, WebCore::Fixed), create(-5, CSSPrimitiveValue::CSS_PX)->toLength(conversionDataZoom3));
-    EXPECT_EQ(Length(0, WebCore::Fixed), create(-5, CSSPrimitiveValue::CSS_PX)->toLength(conversionDataZoom1, NonNegativeValues));
-    EXPECT_EQ(Length(0, WebCore::Fixed), create(-5, CSSPrimitiveValue::CSS_PX)->toLength(conversionDataZoom3, NonNegativeValues));
-
-    EXPECT_EQ(Length(-5, Percent), create(-5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom1));
-    EXPECT_EQ(Length(-5, Percent), create(-5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom3));
-    EXPECT_EQ(Length(0, Percent), create(-5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom1, NonNegativeValues));
-    EXPECT_EQ(Length(0, Percent), create(-5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom3, NonNegativeValues));
-
-    EXPECT_EQ(
-        Length(CalculationValue::create(PixelsAndPercent(-5, -5), ValueRangeAll)),
-        create(-5, CSSPrimitiveValue::CSS_PX, -5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom1));
-    EXPECT_EQ(
-        Length(CalculationValue::create(PixelsAndPercent(-15, -5), ValueRangeAll)),
-        create(-5, CSSPrimitiveValue::CSS_PX, -5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom3));
-    EXPECT_EQ(
-        Length(CalculationValue::create(PixelsAndPercent(-5, -5), ValueRangeNonNegative)),
-        create(-5, CSSPrimitiveValue::CSS_PX, -5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom1, NonNegativeValues));
-    EXPECT_EQ(
-        Length(CalculationValue::create(PixelsAndPercent(-15, -5), ValueRangeNonNegative)),
-        create(-5, CSSPrimitiveValue::CSS_PX, -5, CSSPrimitiveValue::CSS_PERCENTAGE)->toLength(conversionDataZoom3, NonNegativeValues));
+    EXPECT_TRUE(create(Length(10, Fixed))->equals(create(Length(10, Fixed)).get()));
+    EXPECT_TRUE(create(Length(20, Percent))->equals(create(Length(20, Percent)).get()));
+    EXPECT_FALSE(create(Length(10, Fixed))->equals(create(Length(10, Percent)).get()));
+    EXPECT_FALSE(create(Length(0, Percent))->equals(create(Length(0, Fixed)).get()));
+    Length calc = Length(CalculationValue::create(PixelsAndPercent(5, 10), ValueRangeAll));
+    EXPECT_TRUE(create(calc)->equals(create(calc).get()));
+    EXPECT_FALSE(create(calc)->equals(create(Length(10, Percent)).get()));
 }
 
-TEST_F(AnimationAnimatableLengthTest, Interpolate)
+TEST(AnimationAnimatableLengthTest, Interpolate)
 {
-    RefPtrWillBeRawPtr<AnimatableLength> from10px = create(10, CSSPrimitiveValue::CSS_PX);
-    RefPtrWillBeRawPtr<AnimatableLength> to20pxAsInches = create(20.0 / 96, CSSPrimitiveValue::CSS_IN);
-
-    EXPECT_REFV_EQ(create(5,  CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(), -0.5));
-
-    EXPECT_REFV_EQ(create(10, CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(),  0));
-    EXPECT_REFV_EQ(create(14, CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(),  0.4));
-    EXPECT_REFV_EQ(create(15, CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(),  0.5));
-    EXPECT_REFV_EQ(create(16, CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(),  0.6));
-    EXPECT_REFV_EQ(create(20.0 / 96, CSSPrimitiveValue::CSS_IN),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(),  1));
-    EXPECT_REFV_EQ(create(25, CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from10px.get(), to20pxAsInches.get(),  1.5));
-
-    RefPtrWillBeRawPtr<AnimatableLength> from10em = create(10, CSSPrimitiveValue::CSS_EMS);
-    RefPtrWillBeRawPtr<AnimatableLength> to20rem = create(20, CSSPrimitiveValue::CSS_REMS);
-    EXPECT_REFV_EQ(create(15, CSSPrimitiveValue::CSS_EMS, -10, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(), -0.5));
-    EXPECT_REFV_EQ(create(10, CSSPrimitiveValue::CSS_EMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(),  0));
-    EXPECT_REFV_EQ(create(6, CSSPrimitiveValue::CSS_EMS, 8, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(),  0.4));
-    EXPECT_REFV_EQ(create(5, CSSPrimitiveValue::CSS_EMS, 10, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(),  0.5));
-    EXPECT_REFV_EQ(create(4, CSSPrimitiveValue::CSS_EMS, 12, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(),  0.6));
-    EXPECT_REFV_EQ(create(20, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(),  1));
-    EXPECT_REFV_EQ(create(-5, CSSPrimitiveValue::CSS_EMS, 30, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from10em.get(), to20rem.get(),  1.5));
-
-    // Zero values are typeless and hence we can don't get a calc
-    RefPtrWillBeRawPtr<AnimatableLength> from0px = create(0, CSSPrimitiveValue::CSS_PX);
-    EXPECT_REFV_EQ(create(-10, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0px.get(), to20rem.get(), -0.5));
-    // At t=0, interpolate always returns the "from" value.
-    EXPECT_REFV_EQ(create(0, CSSPrimitiveValue::CSS_PX),
-        AnimatableValue::interpolate(from0px.get(), to20rem.get(), 0));
-    EXPECT_REFV_EQ(create(10, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0px.get(), to20rem.get(), 0.5));
-    EXPECT_REFV_EQ(create(20, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0px.get(), to20rem.get(), 1.0));
-    EXPECT_REFV_EQ(create(30, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0px.get(), to20rem.get(), 1.5));
-
-    // Except 0% which is special
-    RefPtrWillBeRawPtr<AnimatableLength> from0percent = create(0, CSSPrimitiveValue::CSS_PERCENTAGE);
-    EXPECT_REFV_EQ(create(0, CSSPrimitiveValue::CSS_PERCENTAGE, -10, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0percent.get(), to20rem.get(), -0.5));
-    // At t=0, interpolate always returns the "from" value.
-    EXPECT_REFV_EQ(create(0, CSSPrimitiveValue::CSS_PERCENTAGE),
-        AnimatableValue::interpolate(from0percent.get(), to20rem.get(), 0));
-    EXPECT_REFV_EQ(create(0, CSSPrimitiveValue::CSS_PERCENTAGE, 10, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0percent.get(), to20rem.get(), 0.5));
-    // At t=1, interpolate always returns the "to" value.
-    EXPECT_REFV_EQ(create(20, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0percent.get(), to20rem.get(), 1.0));
-    EXPECT_REFV_EQ(create(0, CSSPrimitiveValue::CSS_PERCENTAGE, 30, CSSPrimitiveValue::CSS_REMS),
-        AnimatableValue::interpolate(from0percent.get(), to20rem.get(), 1.5));
-}
-
-TEST_F(AnimationAnimatableLengthTest, IsUnitless)
-{
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_PX)));
-    EXPECT_FALSE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_PERCENTAGE)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_EMS)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_EXS)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_REMS)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_VW)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_VH)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_VMIN)));
-    EXPECT_TRUE(isUnitlessZero(create(0, CSSPrimitiveValue::CSS_VMAX)));
-
-    EXPECT_FALSE(isUnitlessZero(create(1, CSSPrimitiveValue::CSS_PX)));
-    EXPECT_FALSE(isUnitlessZero(create(2, CSSPrimitiveValue::CSS_PERCENTAGE)));
-    EXPECT_FALSE(isUnitlessZero(create(3, CSSPrimitiveValue::CSS_EMS)));
-    EXPECT_FALSE(isUnitlessZero(create(4, CSSPrimitiveValue::CSS_EXS)));
-    EXPECT_FALSE(isUnitlessZero(create(5, CSSPrimitiveValue::CSS_REMS)));
-    EXPECT_FALSE(isUnitlessZero(create(6, CSSPrimitiveValue::CSS_VW)));
-    EXPECT_FALSE(isUnitlessZero(create(7, CSSPrimitiveValue::CSS_VH)));
-    EXPECT_FALSE(isUnitlessZero(create(8, CSSPrimitiveValue::CSS_VMIN)));
-    EXPECT_FALSE(isUnitlessZero(create(9, CSSPrimitiveValue::CSS_VMAX)));
-}
-
-TEST_F(AnimationAnimatableLengthTest, CommonUnitType)
-{
-    RefPtrWillBeRawPtr<AnimatableLength> length10px = create(10, CSSPrimitiveValue::CSS_PX);
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypePixels, commonUnitType(length10px, create(1, CSSPrimitiveValue::CSS_PX).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length10px, create(2, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length10px, create(3, CSSPrimitiveValue::CSS_EMS).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length10px, create(4, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length10px, create(0, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-
-    RefPtrWillBeRawPtr<AnimatableLength> length0px = create(0, CSSPrimitiveValue::CSS_PX);
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypePixels, commonUnitType(length0px, create(1, CSSPrimitiveValue::CSS_PX).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypePercentage, commonUnitType(length0px, create(2, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeFontSize, commonUnitType(length0px, create(3, CSSPrimitiveValue::CSS_EMS).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length0px, create(4, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypePercentage, commonUnitType(length0px, create(0, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-
-    RefPtrWillBeRawPtr<AnimatableLength> length0percent = create(0, CSSPrimitiveValue::CSS_PERCENTAGE);
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length0percent, create(1, CSSPrimitiveValue::CSS_PX).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypePercentage, commonUnitType(length0percent, create(2, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length0percent, create(3, CSSPrimitiveValue::CSS_EMS).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(length0percent, create(4, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypePercentage, commonUnitType(length0percent, create(0, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-
-    RefPtrWillBeRawPtr<AnimatableLength> lengthCalc = create(3, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM);
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(lengthCalc, create(1, CSSPrimitiveValue::CSS_PX).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(lengthCalc, create(2, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(lengthCalc, create(3, CSSPrimitiveValue::CSS_EMS).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(lengthCalc, create(4, CSSPrimitiveValue::CSS_PX, 5, CSSPrimitiveValue::CSS_CM).get()));
-    EXPECT_EQ(CSSPrimitiveValue::UnitTypeCalc, commonUnitType(lengthCalc, create(0, CSSPrimitiveValue::CSS_PERCENTAGE).get()));
+    EXPECT_TRUE(AnimatableValue::interpolate(create(Length(10, Fixed)).get(), create(Length(0, Fixed)).get(), 0.2)->equals(create(Length(8, Fixed)).get()));
+    EXPECT_TRUE(AnimatableValue::interpolate(create(Length(4, Percent)).get(), create(Length(12, Percent)).get(), 0.25)->equals(create(Length(6, Percent)).get()));
+    Length calc = Length(CalculationValue::create(PixelsAndPercent(12, 4), ValueRangeAll));
+    EXPECT_TRUE(AnimatableValue::interpolate(create(Length(20, Fixed)).get(), create(Length(10, Percent)).get(), 0.4)->equals(create(calc).get()));
 }
 
 } // namespace WebCore
diff --git a/Source/core/animation/AnimatableNeutral.h b/Source/core/animation/AnimatableNeutral.h
index 30b5cb7..16f8595 100644
--- a/Source/core/animation/AnimatableNeutral.h
+++ b/Source/core/animation/AnimatableNeutral.h
@@ -39,7 +39,7 @@
 public:
     virtual ~AnimatableNeutral() { }
 
-    virtual void trace(Visitor* visitor) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     static PassRefPtrWillBeRawPtr<AnimatableNeutral> create() { return adoptRefWillBeNoop(new AnimatableNeutral()); }
diff --git a/Source/core/animation/AnimatableRepeatable.cpp b/Source/core/animation/AnimatableRepeatable.cpp
index f732f1f..72a4166 100644
--- a/Source/core/animation/AnimatableRepeatable.cpp
+++ b/Source/core/animation/AnimatableRepeatable.cpp
@@ -105,6 +105,7 @@
 void AnimatableRepeatable::trace(Visitor* visitor)
 {
     visitor->trace(m_values);
+    AnimatableValue::trace(visitor);
 }
 
 } // namespace WebCore
diff --git a/Source/core/animation/AnimatableSVGLength.h b/Source/core/animation/AnimatableSVGLength.h
index d390fd4..5b7f791 100644
--- a/Source/core/animation/AnimatableSVGLength.h
+++ b/Source/core/animation/AnimatableSVGLength.h
@@ -50,7 +50,7 @@
         return m_length.get();
     }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableSVGPaint.h b/Source/core/animation/AnimatableSVGPaint.h
index 6a08ac6..c098e1f 100644
--- a/Source/core/animation/AnimatableSVGPaint.h
+++ b/Source/core/animation/AnimatableSVGPaint.h
@@ -52,7 +52,7 @@
     Color color() const { return m_color.toColor(); };
     const String& uri() const { return m_uri; };
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableShadow.h b/Source/core/animation/AnimatableShadow.h
index 146c858..80a7cf5 100644
--- a/Source/core/animation/AnimatableShadow.h
+++ b/Source/core/animation/AnimatableShadow.h
@@ -45,7 +45,7 @@
     }
     ShadowList* shadowList() const { return m_shadowList.get(); }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableShapeValue.h b/Source/core/animation/AnimatableShapeValue.h
index 4306b29..decc6f3 100644
--- a/Source/core/animation/AnimatableShapeValue.h
+++ b/Source/core/animation/AnimatableShapeValue.h
@@ -45,7 +45,7 @@
     }
     ShapeValue* shapeValue() const { return m_shape.get(); }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableStrokeDasharrayList.cpp b/Source/core/animation/AnimatableStrokeDasharrayList.cpp
index 5d4ff29..f81e351 100644
--- a/Source/core/animation/AnimatableStrokeDasharrayList.cpp
+++ b/Source/core/animation/AnimatableStrokeDasharrayList.cpp
@@ -75,11 +75,7 @@
     if (from.isEmpty() && to.isEmpty())
         return takeConstRef(this);
     if (from.isEmpty() || to.isEmpty()) {
-#if ENABLE_OILPAN
-        DEFINE_STATIC_LOCAL(Persistent<AnimatableSVGLength>, zeroPixels, (AnimatableSVGLength::create(SVGLength::create())));
-#else
-        DEFINE_STATIC_REF(AnimatableSVGLength, zeroPixels, AnimatableSVGLength::create(SVGLength::create()).leakRef());
-#endif
+        DEFINE_STATIC_REF_WILL_BE_PERSISTENT(AnimatableSVGLength, zeroPixels, (AnimatableSVGLength::create(SVGLength::create())));
         if (from.isEmpty()) {
             from.append(zeroPixels);
             from.append(zeroPixels);
diff --git a/Source/core/animation/AnimatableTransform.h b/Source/core/animation/AnimatableTransform.h
index 18164de..51896af 100644
--- a/Source/core/animation/AnimatableTransform.h
+++ b/Source/core/animation/AnimatableTransform.h
@@ -45,7 +45,7 @@
         return m_transform;
     }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimatableUnknown.h b/Source/core/animation/AnimatableUnknown.h
index c310416..a483910 100644
--- a/Source/core/animation/AnimatableUnknown.h
+++ b/Source/core/animation/AnimatableUnknown.h
@@ -56,6 +56,7 @@
     virtual void trace(Visitor* visitor) OVERRIDE
     {
         visitor->trace(m_value);
+        AnimatableValue::trace(visitor);
     }
 
 protected:
diff --git a/Source/core/animation/AnimatableValue.cpp b/Source/core/animation/AnimatableValue.cpp
index 4176a8e..af0aec9 100644
--- a/Source/core/animation/AnimatableValue.cpp
+++ b/Source/core/animation/AnimatableValue.cpp
@@ -44,13 +44,8 @@
 
 const AnimatableValue* AnimatableValue::neutralValue()
 {
-#if ENABLE_OILPAN
-    DEFINE_STATIC_LOCAL(Persistent<AnimatableNeutral>, neutralSentinelValue, (AnimatableNeutral::create()));
-    return neutralSentinelValue.get();
-#else
-    DEFINE_STATIC_REF(AnimatableNeutral, neutralSentinelValue, (AnimatableNeutral::create()));
+    DEFINE_STATIC_REF_WILL_BE_PERSISTENT(AnimatableNeutral, neutralSentinelValue, (AnimatableNeutral::create()));
     return neutralSentinelValue;
-#endif
 }
 
 PassRefPtrWillBeRawPtr<AnimatableValue> AnimatableValue::interpolate(const AnimatableValue* left, const AnimatableValue* right, double fraction)
diff --git a/Source/core/animation/AnimatableValue.h b/Source/core/animation/AnimatableValue.h
index 6f59146..2306142 100644
--- a/Source/core/animation/AnimatableValue.h
+++ b/Source/core/animation/AnimatableValue.h
@@ -87,7 +87,7 @@
         return value->type() == type();
     }
 
-    virtual void trace(Visitor*) = 0;
+    virtual void trace(Visitor*) { }
 
 protected:
     enum AnimatableType {
diff --git a/Source/core/animation/AnimatableValueKeyframe.cpp b/Source/core/animation/AnimatableValueKeyframe.cpp
index 75b146b..b131b0e 100644
--- a/Source/core/animation/AnimatableValueKeyframe.cpp
+++ b/Source/core/animation/AnimatableValueKeyframe.cpp
@@ -74,6 +74,7 @@
 void AnimatableValueKeyframe::PropertySpecificKeyframe::trace(Visitor* visitor)
 {
     visitor->trace(m_value);
+    Keyframe::PropertySpecificKeyframe::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/AnimatableValueTestHelper.cpp b/Source/core/animation/AnimatableValueTestHelper.cpp
index 66c2d09..c3f4a60 100644
--- a/Source/core/animation/AnimatableValueTestHelper.cpp
+++ b/Source/core/animation/AnimatableValueTestHelper.cpp
@@ -51,52 +51,11 @@
         << animColor.visitedLinkColor().serialized().utf8().data() << ")";
 }
 
-void PrintTo(const AnimatableDouble& animDouble, ::std::ostream* os)
-{
-    PrintTo(*(animDouble.toCSSValue().get()), os, "AnimatableDouble");
-}
-
 void PrintTo(const AnimatableImage& animImage, ::std::ostream* os)
 {
     PrintTo(*(animImage.toCSSValue()), os, "AnimatableImage");
 }
 
-void PrintTo(const AnimatableLength& animLength, ::std::ostream* os)
-{
-    PrintTo(*(animLength.toCSSValue().get()), os, "AnimatableLength");
-}
-
-void PrintTo(const AnimatableLengthBox& animLengthBox, ::std::ostream* os)
-{
-    *os << "AnimatableLengthBox(";
-    PrintTo(*(animLengthBox.left()), os);
-    *os << ", ";
-    PrintTo(*(animLengthBox.right()), os);
-    *os << ", ";
-    PrintTo(*(animLengthBox.top()), os);
-    *os << ", ";
-    PrintTo(*(animLengthBox.bottom()), os);
-    *os << ")";
-}
-
-void PrintTo(const AnimatableLengthPoint& animLengthPoint, ::std::ostream* os)
-{
-    *os << "AnimatableLengthPoint(";
-    PrintTo(*(animLengthPoint.x()), os);
-    *os << ", ";
-    PrintTo(*(animLengthPoint.y()), os);
-    *os << ")";
-}
-
-void PrintTo(const AnimatableLengthSize& animLengthSize, ::std::ostream* os)
-{
-    *os << "AnimatableLengthSize(";
-    PrintTo(*(animLengthSize.width()), os);
-    *os << ", ";
-    PrintTo(*(animLengthSize.height()), os);
-    *os << ")";
-}
-
 void PrintTo(const AnimatableNeutral& animValue, ::std::ostream* os)
 {
     *os << "AnimatableNeutral@" << &animValue;
@@ -231,18 +190,8 @@
         PrintTo(*(toAnimatableClipPathOperation(&animValue)), os);
     else if (animValue.isColor())
         PrintTo(*(toAnimatableColor(&animValue)), os);
-    else if (animValue.isDouble())
-        PrintTo(*(toAnimatableDouble(&animValue)), os);
     else if (animValue.isImage())
         PrintTo(*(toAnimatableImage(&animValue)), os);
-    else if (animValue.isLength())
-        PrintTo(*(toAnimatableLength(&animValue)), os);
-    else if (animValue.isLengthBox())
-        PrintTo(*(toAnimatableLengthBox(&animValue)), os);
-    else if (animValue.isLengthPoint())
-        PrintTo(*(toAnimatableLengthPoint(&animValue)), os);
-    else if (animValue.isLengthSize())
-        PrintTo(*(toAnimatableLengthSize(&animValue)), os);
     else if (animValue.isNeutral())
         PrintTo(*(static_cast<const AnimatableNeutral*>(&animValue)), os);
     else if (animValue.isRepeatable())
diff --git a/Source/core/animation/AnimatableValueTestHelper.h b/Source/core/animation/AnimatableValueTestHelper.h
index 65a8660..bff27ed 100644
--- a/Source/core/animation/AnimatableValueTestHelper.h
+++ b/Source/core/animation/AnimatableValueTestHelper.h
@@ -38,12 +38,7 @@
 
 #include "core/animation/AnimatableClipPathOperation.h"
 #include "core/animation/AnimatableColor.h"
-#include "core/animation/AnimatableDouble.h"
 #include "core/animation/AnimatableImage.h"
-#include "core/animation/AnimatableLength.h"
-#include "core/animation/AnimatableLengthBox.h"
-#include "core/animation/AnimatableLengthPoint.h"
-#include "core/animation/AnimatableLengthSize.h"
 #include "core/animation/AnimatableNeutral.h"
 #include "core/animation/AnimatableRepeatable.h"
 #include "core/animation/AnimatableSVGLength.h"
@@ -68,12 +63,7 @@
 
 void PrintTo(const AnimatableClipPathOperation&, ::std::ostream*);
 void PrintTo(const AnimatableColor&, ::std::ostream*);
-void PrintTo(const AnimatableDouble&, ::std::ostream*);
 void PrintTo(const AnimatableImage&, ::std::ostream*);
-void PrintTo(const AnimatableLength&, ::std::ostream*);
-void PrintTo(const AnimatableLengthBox&, ::std::ostream*);
-void PrintTo(const AnimatableLengthPoint&, ::std::ostream*);
-void PrintTo(const AnimatableLengthSize&, ::std::ostream*);
 void PrintTo(const AnimatableNeutral&, ::std::ostream*);
 void PrintTo(const AnimatableRepeatable&, ::std::ostream*);
 void PrintTo(const AnimatableSVGLength&, ::std::ostream*);
diff --git a/Source/core/animation/AnimatableValueTestHelperTest.cpp b/Source/core/animation/AnimatableValueTestHelperTest.cpp
index 6ae5965..f1d1c22 100644
--- a/Source/core/animation/AnimatableValueTestHelperTest.cpp
+++ b/Source/core/animation/AnimatableValueTestHelperTest.cpp
@@ -67,48 +67,10 @@
         ::std::string("AnimatableColor(rgba(0, 0, 0, 0), #ff0000)"),
         PrintToString(AnimatableColor::create(Color(0x000000FF), Color(0xFFFF0000))));
 
-    EXPECT_EQ(
-        ::std::string("AnimatableDouble(1)"),
-        PrintToString(AnimatableDouble::create(1.0)));
-
-    EXPECT_EQ(
-        ::std::string("AnimatableLength(5px)"),
-        PrintToString(AnimatableLength::create(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_PX).get())));
-
-    EXPECT_EQ(
-        ::std::string("AnimatableLengthBox(AnimatableLength(1px), AnimatableLength(2em), AnimatableLength(3rem), AnimatableLength(4pt))"),
-        PrintToString(AnimatableLengthBox::create(
-            AnimatableLength::create(CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_PX).get()),
-            AnimatableLength::create(CSSPrimitiveValue::create(2, CSSPrimitiveValue::CSS_EMS).get()),
-            AnimatableLength::create(CSSPrimitiveValue::create(3, CSSPrimitiveValue::CSS_REMS).get()),
-            AnimatableLength::create(CSSPrimitiveValue::create(4, CSSPrimitiveValue::CSS_PT).get())
-            )));
-
-    EXPECT_EQ(
-        ::std::string("AnimatableLengthPoint(AnimatableLength(5%), AnimatableLength(6px))"),
-        PrintToString(AnimatableLengthPoint::create(
-            AnimatableLength::create(CSSPrimitiveValue::create(5, CSSPrimitiveValue::CSS_PERCENTAGE).get()),
-            AnimatableLength::create(CSSPrimitiveValue::create(6, CSSPrimitiveValue::CSS_PX).get())
-            )));
-
-    EXPECT_EQ(
-        ::std::string("AnimatableLengthSize(AnimatableLength(3rem), AnimatableLength(4pt))"),
-        PrintToString(AnimatableLengthSize::create(
-            AnimatableLength::create(CSSPrimitiveValue::create(3, CSSPrimitiveValue::CSS_REMS).get()),
-            AnimatableLength::create(CSSPrimitiveValue::create(4, CSSPrimitiveValue::CSS_PT).get())
-            )));
-
     EXPECT_THAT(
         PrintToString(const_cast<AnimatableValue*>(AnimatableValue::neutralValue())),
         testing::StartsWith("AnimatableNeutral@"));
 
-    WillBeHeapVector<RefPtrWillBeMember<AnimatableValue> > v1;
-    v1.append(AnimatableLength::create(CSSPrimitiveValue::create(3, CSSPrimitiveValue::CSS_REMS).get()));
-    v1.append(AnimatableLength::create(CSSPrimitiveValue::create(4, CSSPrimitiveValue::CSS_PT).get()));
-    EXPECT_EQ(
-        ::std::string("AnimatableRepeatable(AnimatableLength(3rem), AnimatableLength(4pt))"),
-        PrintToString(AnimatableRepeatable::create(v1)));
-
     RefPtr<SVGLength> length1cm = SVGLength::create(LengthModeOther);
     RefPtr<SVGLength> length2cm = SVGLength::create(LengthModeOther);
     length1cm->setValueAsString("1cm", ASSERT_NO_EXCEPTION);
diff --git a/Source/core/animation/AnimatableVisibility.h b/Source/core/animation/AnimatableVisibility.h
index 2b344b3..72d653e 100644
--- a/Source/core/animation/AnimatableVisibility.h
+++ b/Source/core/animation/AnimatableVisibility.h
@@ -46,7 +46,7 @@
 
     EVisibility visibility() const { return m_visibility; }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { AnimatableValue::trace(visitor); }
 
 protected:
     virtual PassRefPtrWillBeRawPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE;
diff --git a/Source/core/animation/AnimationClock.cpp b/Source/core/animation/AnimationClock.cpp
index 6492206..304136c 100644
--- a/Source/core/animation/AnimationClock.cpp
+++ b/Source/core/animation/AnimationClock.cpp
@@ -28,26 +28,54 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <math.h>
 #include "config.h"
 #include "core/animation/AnimationClock.h"
+#include "wtf/CurrentTime.h"
+
+namespace {
+
+// FIXME: This is an approximation of time between frames, used when
+// ticking the animation clock outside of animation frame callbacks.
+// Ideally this would be generated by the compositor.
+const double approximateFrameTime = 1 / 60.0;
+
+}
 
 namespace WebCore {
 
+unsigned AnimationClock::s_currentTask = 0;
+
 void AnimationClock::updateTime(double time)
 {
     if (time > m_time)
         m_time = time;
-    m_frozen = true;
+    m_currentTask = s_currentTask;
 }
 
 double AnimationClock::currentTime()
 {
-    if (!m_frozen) {
-        double newTime = m_monotonicallyIncreasingTime();
-        if (newTime >= m_time + minTimeBeforeUnsynchronizedAnimationClockTick)
-            m_time = newTime;
+    if (m_currentTask != s_currentTask) {
+        const double currentTime = m_monotonicallyIncreasingTime();
+        if (m_time < currentTime) {
+            // Advance to the first estimated frame after the current time.
+            const double frameShift = fmod(currentTime - m_time, approximateFrameTime);
+            const double newTime = currentTime + approximateFrameTime - frameShift;
+            ASSERT(newTime > currentTime);
+            ASSERT(newTime <= currentTime + approximateFrameTime);
+            updateTime(newTime);
+        } else {
+            m_currentTask = s_currentTask;
+        }
     }
     return m_time;
 }
 
+void AnimationClock::resetTimeForTesting()
+{
+    m_time = 0;
+    m_currentTask = 0;
+    s_currentTask = 0;
+}
+
 }
diff --git a/Source/core/animation/AnimationClock.h b/Source/core/animation/AnimationClock.h
index 540dfbe..e5a3bdb 100644
--- a/Source/core/animation/AnimationClock.h
+++ b/Source/core/animation/AnimationClock.h
@@ -31,40 +31,34 @@
 #ifndef AnimationClock_h
 #define AnimationClock_h
 
+#include <limits>
 #include "wtf/CurrentTime.h"
 #include "wtf/PassOwnPtr.h"
+#include "wtf/Noncopyable.h"
 
 namespace WebCore {
 
-// FIXME: This value is used to suppress updates when time is required outside of a frame.
-// The purpose of allowing the clock to update during such periods is to allow animations
-// to have an appropriate start time and for getComputedStyle to attempt to catch-up to a
-// compositor animation. However a more accurate system might be to attempt to phase-lock
-// with the frame clock.
-const double minTimeBeforeUnsynchronizedAnimationClockTick = 0.005;
-
 class AnimationClock {
+    WTF_MAKE_NONCOPYABLE(AnimationClock);
 public:
-    static PassOwnPtr<AnimationClock> create(WTF::TimeFunction monotonicallyIncreasingTime = WTF::monotonicallyIncreasingTime)
+    explicit AnimationClock(WTF::TimeFunction monotonicallyIncreasingTime = WTF::monotonicallyIncreasingTime)
+        : m_monotonicallyIncreasingTime(monotonicallyIncreasingTime)
+        , m_time(0)
+        , m_currentTask(std::numeric_limits<unsigned>::max())
     {
-        return adoptPtr(new AnimationClock(monotonicallyIncreasingTime));
     }
 
     void updateTime(double time);
     double currentTime();
-    void unfreeze() { m_frozen = false; }
-    void resetTimeForTesting() { m_time = 0; m_frozen = true; }
+    void resetTimeForTesting();
+
+    static void notifyTaskStart() { ++s_currentTask; }
 
 private:
-    AnimationClock(WTF::TimeFunction monotonicallyIncreasingTime)
-        : m_monotonicallyIncreasingTime(monotonicallyIncreasingTime)
-        , m_time(0)
-        , m_frozen(false)
-    {
-    }
     WTF::TimeFunction m_monotonicallyIncreasingTime;
     double m_time;
-    bool m_frozen;
+    unsigned m_currentTask;
+    static unsigned s_currentTask;
 };
 
 } // namespace WebCore
diff --git a/Source/core/animation/AnimationClockTest.cpp b/Source/core/animation/AnimationClockTest.cpp
index 7e54cde..2823fb1 100644
--- a/Source/core/animation/AnimationClockTest.cpp
+++ b/Source/core/animation/AnimationClockTest.cpp
@@ -39,11 +39,15 @@
 namespace {
 
 class AnimationAnimationClockTest : public ::testing::Test {
+public:
+    AnimationAnimationClockTest()
+        : animationClock(mockTimeFunction)
+    {}
 protected:
     virtual void SetUp()
     {
-        animationClock = AnimationClock::create(mockTimeFunction);
-        mockTime = 200;
+        mockTime = 0;
+        animationClock.resetTimeForTesting();
     }
 
     static double mockTimeFunction()
@@ -52,36 +56,88 @@
     }
 
     static double mockTime;
-    OwnPtr<AnimationClock> animationClock;
+    AnimationClock animationClock;
 };
 
 double AnimationAnimationClockTest::mockTime;
 
-TEST_F(AnimationAnimationClockTest, CurrentTime)
+TEST_F(AnimationAnimationClockTest, TimeIsGreaterThanZeroForUnitTests)
 {
-    // Current time should not advance until minTimeBeforeUnsynchronizedTick has elapsed
-    EXPECT_EQ(200, animationClock->currentTime());
-    mockTime = 200 + minTimeBeforeUnsynchronizedAnimationClockTick / 2.0;
-    EXPECT_EQ(200, animationClock->currentTime());
-
-    mockTime = 200 + minTimeBeforeUnsynchronizedAnimationClockTick;
-    EXPECT_EQ(mockTime, animationClock->currentTime());
+    AnimationClock clock;
+    // unit tests outside core/animation shouldn't need to do anything to get
+    // a non-zero currentTime().
+    EXPECT_GT(clock.currentTime(), 0);
 }
 
-TEST_F(AnimationAnimationClockTest, UpdateTime)
+TEST_F(AnimationAnimationClockTest, TimeDoesNotChange)
 {
-    animationClock->updateTime(100);
-    EXPECT_EQ(100, animationClock->currentTime());
-    mockTime = 200;
-    EXPECT_EQ(100, animationClock->currentTime());
+    animationClock.updateTime(100);
+    EXPECT_EQ(100, animationClock.currentTime());
+    EXPECT_EQ(100, animationClock.currentTime());
+}
 
-    animationClock->unfreeze();
-    EXPECT_EQ(200, animationClock->currentTime());
+TEST_F(AnimationAnimationClockTest, TimeAdvancesWhenUpdated)
+{
+    animationClock.updateTime(100);
+    EXPECT_EQ(100, animationClock.currentTime());
 
-    animationClock->updateTime(300);
-    EXPECT_EQ(300, animationClock->currentTime());
-    mockTime = 400;
-    EXPECT_EQ(300, animationClock->currentTime());
+    animationClock.updateTime(200);
+    EXPECT_EQ(200, animationClock.currentTime());
+}
+
+TEST_F(AnimationAnimationClockTest, TimeAdvancesToTaskTime)
+{
+    animationClock.updateTime(100);
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    mockTime = 150;
+    AnimationClock::notifyTaskStart();
+    EXPECT_GE(animationClock.currentTime(), mockTime);
+}
+
+TEST_F(AnimationAnimationClockTest, TimeAdvancesToTaskTimeOnlyWhenRequired)
+{
+    animationClock.updateTime(100);
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    AnimationClock::notifyTaskStart();
+    animationClock.updateTime(125);
+    EXPECT_EQ(125, animationClock.currentTime());
+}
+
+TEST_F(AnimationAnimationClockTest, UpdateTimeIsMonotonic)
+{
+    animationClock.updateTime(100);
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    // Update can't go backwards.
+    animationClock.updateTime(50);
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    mockTime = 50;
+    AnimationClock::notifyTaskStart();
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    mockTime = 150;
+    AnimationClock::notifyTaskStart();
+    EXPECT_GE(animationClock.currentTime(), mockTime);
+
+    // Update can't go backwards after advance to estimate.
+    animationClock.updateTime(100);
+    EXPECT_GE(animationClock.currentTime(), mockTime);
+}
+
+TEST_F(AnimationAnimationClockTest, CurrentTimeUpdatesTask)
+{
+    animationClock.updateTime(100);
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    mockTime = 100;
+    AnimationClock::notifyTaskStart();
+    EXPECT_EQ(100, animationClock.currentTime());
+
+    mockTime = 150;
+    EXPECT_EQ(100, animationClock.currentTime());
 }
 
 }
diff --git a/Source/core/animation/AnimationEffect.h b/Source/core/animation/AnimationEffect.h
index f55c8aa..42441e9 100644
--- a/Source/core/animation/AnimationEffect.h
+++ b/Source/core/animation/AnimationEffect.h
@@ -54,7 +54,7 @@
     virtual bool affects(CSSPropertyID) { return false; };
     virtual bool isKeyframeEffectModel() const { return false; }
 
-    virtual void trace(Visitor*) = 0;
+    virtual void trace(Visitor*) { }
 };
 
 } // namespace WebCore
diff --git a/Source/core/animation/AnimationPlayer.cpp b/Source/core/animation/AnimationPlayer.cpp
index 7abd43f..545a737 100644
--- a/Source/core/animation/AnimationPlayer.cpp
+++ b/Source/core/animation/AnimationPlayer.cpp
@@ -64,7 +64,7 @@
     , m_paused(false)
     , m_held(false)
     , m_isPausedForTesting(false)
-    , m_outdated(false)
+    , m_outdated(true)
     , m_finished(false)
 {
     if (m_content) {
@@ -173,17 +173,22 @@
     if (newStartTime == m_startTime)
         return;
     updateCurrentTimingState(); // Update the value of held
+    bool hadStartTime = hasStartTime();
+    double previousCurrentTime = currentTimeInternal();
     m_startTime = newStartTime;
     m_sortInfo.m_startTime = newStartTime;
-    if (!isUpdateFromCompositor)
-        cancelAnimationOnCompositor();
-    if (isUpdateFromCompositor || !m_held)
-        setOutdated();
-    if (m_held)
-        return;
     updateCurrentTimingState();
-    if (!isUpdateFromCompositor)
+    if (previousCurrentTime != currentTimeInternal()) {
+        setOutdated();
+    } else if (!hadStartTime && m_timeline) {
+        // Even though this player is not outdated, time to effect change is
+        // infinity until start time is set.
+        m_timeline->wake();
+    }
+    if (!isUpdateFromCompositor) {
+        cancelAnimationOnCompositor();
         schedulePendingAnimationOnCompositor();
+    }
 }
 
 void AnimationPlayer::setSource(TimedItem* newSource)
@@ -344,7 +349,7 @@
         toAnimation(m_content.get())->cancelAnimationOnCompositor();
 }
 
-bool AnimationPlayer::update(UpdateReason reason)
+bool AnimationPlayer::update(TimingUpdateReason reason)
 {
     m_outdated = false;
 
@@ -353,20 +358,18 @@
 
     if (m_content) {
         double inheritedTime = isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal();
-        m_content->updateInheritedTime(inheritedTime);
+        m_content->updateInheritedTime(inheritedTime, reason);
     }
 
     if (finished() && !m_finished) {
-        const AtomicString& eventType = EventTypeNames::finish;
-        if (executionContext() && hasEventListeners(eventType)) {
-            if (reason == UpdateForAnimationFrame) {
+        if (reason == TimingUpdateForAnimationFrame && hasStartTime()) {
+            const AtomicString& eventType = EventTypeNames::finish;
+            if (executionContext() && hasEventListeners(eventType)) {
                 RefPtrWillBeRawPtr<AnimationPlayerEvent> event = AnimationPlayerEvent::create(eventType, currentTime(), timeline()->currentTime());
                 event->setTarget(this);
                 event->setCurrentTarget(this);
                 m_timeline->document()->enqueueAnimationFrameEvent(event.release());
-                m_finished = true;
             }
-        } else {
             m_finished = true;
         }
     }
diff --git a/Source/core/animation/AnimationPlayer.h b/Source/core/animation/AnimationPlayer.h
index 35d6777..c542533 100644
--- a/Source/core/animation/AnimationPlayer.h
+++ b/Source/core/animation/AnimationPlayer.h
@@ -43,16 +43,12 @@
 class AnimationPlayer FINAL : public RefCounted<AnimationPlayer>, public EventTargetWithInlineData {
     REFCOUNTED_EVENT_TARGET(AnimationPlayer);
 public:
-    enum UpdateReason {
-        UpdateOnDemand,
-        UpdateForAnimationFrame
-    };
 
     ~AnimationPlayer();
     static PassRefPtr<AnimationPlayer> create(DocumentTimeline&, TimedItem*);
 
     // Returns whether the player is finished.
-    bool update(UpdateReason);
+    bool update(TimingUpdateReason);
 
     // timeToEffectChange returns:
     //  infinity  - if this player is no longer in effect
@@ -74,6 +70,9 @@
     void reverse();
     void finish(ExceptionState&);
     bool finished() { return limited(currentTimeInternal()); }
+    // FIXME: Resolve whether finished() should just return the flag, and
+    // remove this method.
+    bool finishedInternal() const { return m_finished; }
 
     DEFINE_ATTRIBUTE_EVENT_LISTENER(finish);
 
diff --git a/Source/core/animation/AnimationPlayerTest.cpp b/Source/core/animation/AnimationPlayerTest.cpp
index 6bb18cf..713af2d 100644
--- a/Source/core/animation/AnimationPlayerTest.cpp
+++ b/Source/core/animation/AnimationPlayerTest.cpp
@@ -80,7 +80,7 @@
     {
         document->animationClock().updateTime(time);
         // The timeline does not know about our player, so we have to explicitly call update().
-        return player->update(AnimationPlayer::UpdateOnDemand);
+        return player->update(TimingUpdateOnDemand);
     }
 
     RefPtr<Document> document;
@@ -599,6 +599,7 @@
 TEST_F(AnimationAnimationPlayerTest, EmptyAnimationPlayersDontUpdateEffects)
 {
     player = timeline->createAnimationPlayer(0);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(std::numeric_limits<double>::infinity(), player->timeToEffectChange());
 
     updateTimeline(1234);
@@ -643,24 +644,24 @@
     EXPECT_EQ(std::numeric_limits<double>::infinity(), player->timeToEffectChange());
 
     player->setCurrentTimeInternal(0);
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(1, player->timeToEffectChange());
 
     player->setPlaybackRate(2);
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(0.5, player->timeToEffectChange());
 
     player->setPlaybackRate(0);
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(std::numeric_limits<double>::infinity(), player->timeToEffectChange());
 
     player->setCurrentTimeInternal(3);
     player->setPlaybackRate(-1);
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(1, player->timeToEffectChange());
 
     player->setPlaybackRate(-2);
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(0.5, player->timeToEffectChange());
 }
 
@@ -668,7 +669,7 @@
 {
     EXPECT_EQ(0, player->timeToEffectChange());
     player->pause();
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(std::numeric_limits<double>::infinity(), player->timeToEffectChange());
 }
 
@@ -678,7 +679,7 @@
     player->setCurrentTimeInternal(-8);
     player->setPlaybackRate(2);
     player->cancel();
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(4, player->timeToEffectChange());
 }
 
@@ -688,7 +689,7 @@
     player->setCurrentTimeInternal(9);
     player->setPlaybackRate(-3);
     player->cancel();
-    player->update(AnimationPlayer::UpdateOnDemand);
+    player->update(TimingUpdateOnDemand);
     EXPECT_EQ(3, player->timeToEffectChange());
 }
 
@@ -699,11 +700,11 @@
     Timing timing;
     RefPtr<Animation> animation = Animation::create(element.get(), nullptr, timing);
     RefPtr<AnimationPlayer> player = timeline->createAnimationPlayer(animation.get());
-    timeline->serviceAnimations(AnimationPlayer::UpdateForAnimationFrame);
+    player->setStartTime(0);
+    timeline->serviceAnimations(TimingUpdateForAnimationFrame);
     EXPECT_EQ(1, element->activeAnimations()->players().find(player.get())->value);
 
     player.release();
-    EXPECT_EQ(0, element->activeAnimations()->players().find(player.get())->value);
     EXPECT_TRUE(element->activeAnimations()->players().isEmpty());
 }
 
diff --git a/Source/core/animation/AnimationStackTest.cpp b/Source/core/animation/AnimationStackTest.cpp
index 7d44ce4..e28259b 100644
--- a/Source/core/animation/AnimationStackTest.cpp
+++ b/Source/core/animation/AnimationStackTest.cpp
@@ -29,14 +29,14 @@
     {
         AnimationPlayer* player = timeline->createAnimationPlayer(animation);
         player->setStartTimeInternal(startTime);
-        player->update(AnimationPlayer::UpdateOnDemand);
+        player->update(TimingUpdateOnDemand);
         return player;
     }
 
     void updateTimeline(double time)
     {
         document->animationClock().updateTime(time);
-        timeline->serviceAnimations(AnimationPlayer::UpdateOnDemand);
+        timeline->serviceAnimations(TimingUpdateForAnimationFrame);
     }
 
     const Vector<OwnPtr<SampledEffect> >& effects()
diff --git a/Source/core/animation/AnimationTest.cpp b/Source/core/animation/AnimationTest.cpp
index ca3dc6f..c16c5ec 100644
--- a/Source/core/animation/AnimationTest.cpp
+++ b/Source/core/animation/AnimationTest.cpp
@@ -6,7 +6,6 @@
 #include "core/animation/Animation.h"
 
 #include "bindings/v8/Dictionary.h"
-#include "core/animation/AnimatableLength.h"
 #include "core/animation/AnimationClock.h"
 #include "core/animation/AnimationHelpers.h"
 #include "core/animation/AnimationTestHelper.h"
diff --git a/Source/core/animation/DocumentAnimations.cpp b/Source/core/animation/DocumentAnimations.cpp
index 9ea1c6b..7fe6e3e 100644
--- a/Source/core/animation/DocumentAnimations.cpp
+++ b/Source/core/animation/DocumentAnimations.cpp
@@ -46,7 +46,7 @@
 
 namespace {
 
-void updateAnimationTiming(Document& document, AnimationPlayer::UpdateReason reason)
+void updateAnimationTiming(Document& document, TimingUpdateReason reason)
 {
     document.timeline().serviceAnimations(reason);
     document.transitionTimeline().serviceAnimations(reason);
@@ -57,13 +57,13 @@
 void DocumentAnimations::updateAnimationTimingForAnimationFrame(Document& document, double monotonicAnimationStartTime)
 {
     document.animationClock().updateTime(monotonicAnimationStartTime);
-    updateAnimationTiming(document, AnimationPlayer::UpdateForAnimationFrame);
+    updateAnimationTiming(document, TimingUpdateForAnimationFrame);
 }
 
 void DocumentAnimations::updateOutdatedAnimationPlayersIfNeeded(Document& document)
 {
     if (needsOutdatedAnimationPlayerUpdate(document))
-        updateAnimationTiming(document, AnimationPlayer::UpdateOnDemand);
+        updateAnimationTiming(document, TimingUpdateOnDemand);
 }
 
 void DocumentAnimations::updateAnimationTimingForGetComputedStyle(Node& node, CSSPropertyID property)
@@ -75,7 +75,7 @@
         if ((property == CSSPropertyOpacity && style->isRunningOpacityAnimationOnCompositor())
             || ((property == CSSPropertyTransform || property == CSSPropertyWebkitTransform) && style->isRunningTransformAnimationOnCompositor())
             || (property == CSSPropertyWebkitFilter && style->isRunningFilterAnimationOnCompositor())) {
-            updateAnimationTiming(element.document(), AnimationPlayer::UpdateOnDemand);
+            updateAnimationTiming(element.document(), TimingUpdateOnDemand);
         }
     }
 }
@@ -92,8 +92,6 @@
         ASSERT(document.view());
         document.view()->scheduleAnimation();
     }
-
-    document.animationClock().unfreeze();
 }
 
 } // namespace WebCore
diff --git a/Source/core/animation/DocumentTimeline.cpp b/Source/core/animation/DocumentTimeline.cpp
index fd815cf..f989159 100644
--- a/Source/core/animation/DocumentTimeline.cpp
+++ b/Source/core/animation/DocumentTimeline.cpp
@@ -92,12 +92,11 @@
     m_timing->serviceOnNextFrame();
 }
 
-void DocumentTimeline::serviceAnimations(AnimationPlayer::UpdateReason reason)
+void DocumentTimeline::serviceAnimations(TimingUpdateReason reason)
 {
     TRACE_EVENT0("webkit", "DocumentTimeline::serviceAnimations");
 
     m_timing->cancelWake();
-    m_hasOutdatedAnimationPlayer = false;
 
     double timeToNextEffect = std::numeric_limits<double>::infinity();
     Vector<AnimationPlayer*> players;
@@ -119,7 +118,7 @@
     else if (timeToNextEffect != std::numeric_limits<double>::infinity())
         m_timing->wakeAfter(timeToNextEffect - s_minimumDelay);
 
-    ASSERT(!m_hasOutdatedAnimationPlayer);
+    ASSERT(!hasOutdatedAnimationPlayer());
 }
 
 void DocumentTimeline::setZeroTime(double zeroTime)
@@ -127,7 +126,7 @@
     ASSERT(isNull(m_zeroTime));
     m_zeroTime = zeroTime;
     ASSERT(!isNull(m_zeroTime));
-    serviceAnimations(AnimationPlayer::UpdateOnDemand);
+    serviceAnimations(TimingUpdateOnDemand);
 }
 
 void DocumentTimeline::DocumentTimelineTiming::wakeAfter(double duration)
@@ -183,13 +182,22 @@
 {
     for (HashSet<RefPtr<AnimationPlayer> >::iterator it = m_playersNeedingUpdate.begin(); it != m_playersNeedingUpdate.end(); ++it)
         (*it)->pauseForTesting(pauseTime);
-    serviceAnimations(AnimationPlayer::UpdateOnDemand);
+    serviceAnimations(TimingUpdateOnDemand);
+}
+
+bool DocumentTimeline::hasOutdatedAnimationPlayer() const
+{
+    for (HashSet<RefPtr<AnimationPlayer> >::iterator it = m_playersNeedingUpdate.begin(); it != m_playersNeedingUpdate.end(); ++it) {
+        if ((*it)->outdated())
+            return true;
+    }
+    return false;
 }
 
 void DocumentTimeline::setOutdatedAnimationPlayer(AnimationPlayer* player)
 {
+    ASSERT(player->outdated());
     m_playersNeedingUpdate.add(player);
-    m_hasOutdatedAnimationPlayer = true;
     if (m_document && m_document->page() && !m_document->page()->animator().isServicingAnimations())
         m_timing->serviceOnNextFrame();
 }
diff --git a/Source/core/animation/DocumentTimeline.h b/Source/core/animation/DocumentTimeline.h
index 6ff8bdf..a151a30 100644
--- a/Source/core/animation/DocumentTimeline.h
+++ b/Source/core/animation/DocumentTimeline.h
@@ -62,7 +62,7 @@
     static PassRefPtr<DocumentTimeline> create(Document*, PassOwnPtr<PlatformTiming> = nullptr);
     ~DocumentTimeline();
 
-    void serviceAnimations(AnimationPlayer::UpdateReason);
+    void serviceAnimations(TimingUpdateReason);
 
     // Creates a player attached to this timeline, but without a start time.
     AnimationPlayer* createAnimationPlayer(TimedItem*);
@@ -89,10 +89,11 @@
     size_t numberOfActiveAnimationsForTesting() const;
 
     void setOutdatedAnimationPlayer(AnimationPlayer*);
-    bool hasOutdatedAnimationPlayer() const { return m_hasOutdatedAnimationPlayer; }
+    bool hasOutdatedAnimationPlayer() const;
 
     Document* document() { return m_document; }
     void detachFromDocument();
+    void wake();
 
 protected:
     DocumentTimeline(Document*, PassOwnPtr<PlatformTiming>);
@@ -104,9 +105,6 @@
     // i.e. current, in effect, or had timing changed
     HashSet<RefPtr<AnimationPlayer> > m_playersNeedingUpdate;
     HashSet<AnimationPlayer*> m_players;
-    bool m_hasOutdatedAnimationPlayer;
-
-    void wake();
 
     friend class SMILTimeContainer;
     static const double s_minimumDelay;
diff --git a/Source/core/animation/DocumentTimelineTest.cpp b/Source/core/animation/DocumentTimelineTest.cpp
index aa7981b..8da102b 100644
--- a/Source/core/animation/DocumentTimelineTest.cpp
+++ b/Source/core/animation/DocumentTimelineTest.cpp
@@ -102,7 +102,7 @@
     void updateClockAndService(double time)
     {
         document->animationClock().updateTime(time);
-        timeline->serviceAnimations(AnimationPlayer::UpdateForAnimationFrame);
+        timeline->serviceAnimations(TimingUpdateForAnimationFrame);
     }
 
     RefPtr<Document> document;
diff --git a/Source/core/animation/InertAnimation.cpp b/Source/core/animation/InertAnimation.cpp
index 4f4ee13..42479bf 100644
--- a/Source/core/animation/InertAnimation.cpp
+++ b/Source/core/animation/InertAnimation.cpp
@@ -48,7 +48,7 @@
 
 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > InertAnimation::sample(double inheritedTime)
 {
-    updateInheritedTime(inheritedTime);
+    updateInheritedTime(inheritedTime, TimingUpdateOnDemand);
     if (!isInEffect())
         return nullptr;
 
diff --git a/Source/core/animation/InterpolableValue.cpp b/Source/core/animation/InterpolableValue.cpp
index 97dd774..e1b43a9 100644
--- a/Source/core/animation/InterpolableValue.cpp
+++ b/Source/core/animation/InterpolableValue.cpp
@@ -53,6 +53,7 @@
 #if ENABLE_OILPAN
     visitor->trace(m_values);
 #endif
+    InterpolableValue::trace(visitor);
 }
 
 PassOwnPtrWillBeRawPtr<InterpolableValue> InterpolableAnimatableValue::interpolate(const InterpolableValue &other, const double percentage) const
@@ -68,6 +69,7 @@
 void InterpolableAnimatableValue::trace(Visitor* visitor)
 {
     visitor->trace(m_value);
+    InterpolableValue::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/InterpolableValue.h b/Source/core/animation/InterpolableValue.h
index 32df14f..3b763aa 100644
--- a/Source/core/animation/InterpolableValue.h
+++ b/Source/core/animation/InterpolableValue.h
@@ -22,7 +22,7 @@
 
     virtual PassOwnPtrWillBeRawPtr<InterpolableValue> clone() const = 0;
 
-    virtual void trace(Visitor*) = 0;
+    virtual void trace(Visitor*) { }
 
 private:
     virtual PassOwnPtrWillBeRawPtr<InterpolableValue> interpolate(const InterpolableValue &to, const double progress) const = 0;
@@ -47,7 +47,7 @@
     double value() const { return m_value; }
     virtual PassOwnPtrWillBeRawPtr<InterpolableValue> clone() const OVERRIDE FINAL { return create(m_value); }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { InterpolableValue::trace(visitor); }
 
 private:
     virtual PassOwnPtrWillBeRawPtr<InterpolableValue> interpolate(const InterpolableValue &to, const double progress) const OVERRIDE FINAL;
@@ -71,7 +71,7 @@
     bool value() const { return m_value; }
     virtual PassOwnPtrWillBeRawPtr<InterpolableValue> clone() const OVERRIDE FINAL { return create(m_value); }
 
-    virtual void trace(Visitor*) OVERRIDE { }
+    virtual void trace(Visitor* visitor) OVERRIDE { InterpolableValue::trace(visitor); }
 
 private:
     virtual PassOwnPtrWillBeRawPtr<InterpolableValue> interpolate(const InterpolableValue &to, const double progress) const OVERRIDE FINAL;
diff --git a/Source/core/animation/Interpolation.cpp b/Source/core/animation/Interpolation.cpp
index 52fdd8d..1738b81 100644
--- a/Source/core/animation/Interpolation.cpp
+++ b/Source/core/animation/Interpolation.cpp
@@ -5,8 +5,7 @@
 #include "config.h"
 #include "core/animation/Interpolation.h"
 
-#include "core/animation/AnimatableDouble.h"
-#include "core/animation/AnimatableLength.h"
+#include "core/css/CSSCalculationValue.h"
 #include "core/css/resolver/AnimatedStyleBuilder.h"
 #include "core/css/resolver/StyleBuilder.h"
 #include "core/css/resolver/StyleResolverState.h"
@@ -81,6 +80,20 @@
     StyleInterpolation::trace(visitor);
 }
 
+bool LengthStyleInterpolation::canCreateFrom(const CSSValue& value)
+{
+    if (value.isPrimitiveValue()) {
+        const CSSPrimitiveValue& primitiveValue = WebCore::toCSSPrimitiveValue(value);
+        if (primitiveValue.cssCalcValue())
+            return true;
+
+        CSSPrimitiveValue::LengthUnitType type;
+        // Only returns true if the type is a primitive length unit.
+        return CSSPrimitiveValue::unitTypeToLengthUnitType(primitiveValue.primitiveType(), type);
+    }
+    return value.isCalcValue();
+}
+
 PassOwnPtrWillBeRawPtr<InterpolableValue> LengthStyleInterpolation::lengthToInterpolableValue(CSSValue* value)
 {
     OwnPtrWillBeRawPtr<InterpolableList> result = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
@@ -159,4 +172,16 @@
     StyleInterpolation::trace(visitor);
 }
 
+void DefaultStyleInterpolation::apply(StyleResolverState& state) const
+{
+    StyleBuilder::applyProperty(m_id, state, toInterpolableBool(m_cachedValue.get())->value() ? m_endCSSValue.get() : m_startCSSValue.get());
+}
+
+void DefaultStyleInterpolation::trace(Visitor* visitor)
+{
+    StyleInterpolation::trace(visitor);
+    visitor->trace(m_startCSSValue);
+    visitor->trace(m_endCSSValue);
+}
+
 }
diff --git a/Source/core/animation/Interpolation.h b/Source/core/animation/Interpolation.h
index 254df7f..206310c 100644
--- a/Source/core/animation/Interpolation.h
+++ b/Source/core/animation/Interpolation.h
@@ -104,6 +104,8 @@
         return adoptRefWillBeNoop(new LengthStyleInterpolation(lengthToInterpolableValue(start), lengthToInterpolableValue(end), id));
     }
 
+    static bool canCreateFrom(const CSSValue&);
+
     virtual void apply(StyleResolverState&) const OVERRIDE;
 
     virtual void trace(Visitor*) OVERRIDE;
@@ -119,6 +121,27 @@
     friend class AnimationInterpolationTest;
 };
 
+class DefaultStyleInterpolation : public StyleInterpolation {
+public:
+    static PassRefPtrWillBeRawPtr<DefaultStyleInterpolation> create(CSSValue* start, CSSValue* end, CSSPropertyID id)
+    {
+        return adoptRefWillBeNoop(new DefaultStyleInterpolation(start, end, id));
+    }
+    virtual void apply(StyleResolverState&) const;
+    virtual void trace(Visitor*) OVERRIDE;
+
+private:
+    DefaultStyleInterpolation(CSSValue* start, CSSValue* end, CSSPropertyID id)
+        : StyleInterpolation(InterpolableBool::create(false), InterpolableBool::create(true), id)
+        , m_startCSSValue(start)
+        , m_endCSSValue(end)
+    {
+    }
+
+    RefPtrWillBeMember<CSSValue> m_startCSSValue;
+    RefPtrWillBeMember<CSSValue> m_endCSSValue;
+};
+
 DEFINE_TYPE_CASTS(StyleInterpolation, Interpolation, value, value->isStyleInterpolation(), value.isStyleInterpolation());
 DEFINE_TYPE_CASTS(LegacyStyleInterpolation, Interpolation, value, value->isLegacyStyleInterpolation(), value.isLegacyStyleInterpolation());
 
diff --git a/Source/core/animation/Keyframe.h b/Source/core/animation/Keyframe.h
index 2e0f933..fa3f70a 100644
--- a/Source/core/animation/Keyframe.h
+++ b/Source/core/animation/Keyframe.h
@@ -66,7 +66,7 @@
         virtual PassOwnPtrWillBeRawPtr<PropertySpecificKeyframe> neutralKeyframe(double offset, PassRefPtr<TimingFunction> easing) const = 0;
         virtual PassRefPtrWillBeRawPtr<Interpolation> createInterpolation(CSSPropertyID, WebCore::Keyframe::PropertySpecificKeyframe* end, Element*) const = 0;
 
-        virtual void trace(Visitor*) = 0;
+        virtual void trace(Visitor*) { }
 
     protected:
         PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, AnimationEffect::CompositeOperation);
diff --git a/Source/core/animation/KeyframeEffectModel.cpp b/Source/core/animation/KeyframeEffectModel.cpp
index c1d0d888..580f621 100644
--- a/Source/core/animation/KeyframeEffectModel.cpp
+++ b/Source/core/animation/KeyframeEffectModel.cpp
@@ -201,6 +201,7 @@
 #if ENABLE_OILPAN
     visitor->trace(m_keyframeGroups);
 #endif
+    AnimationEffect::trace(visitor);
 }
 
 Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, AnimationEffect::CompositeOperation composite)
diff --git a/Source/core/animation/KeyframeEffectModelTest.cpp b/Source/core/animation/KeyframeEffectModelTest.cpp
index 7a1a364..02bec9c 100644
--- a/Source/core/animation/KeyframeEffectModelTest.cpp
+++ b/Source/core/animation/KeyframeEffectModelTest.cpp
@@ -51,7 +51,7 @@
 
 PassRefPtrWillBeRawPtr<AnimatableValue> pixelAnimatableValue(double n)
 {
-    return AnimatableLength::create(CSSPrimitiveValue::create(n, CSSPrimitiveValue::CSS_PX).get());
+    return AnimatableLength::create(Length(n, Fixed), 1);
 }
 
 AnimatableValueKeyframeVector keyframesAtZeroAndOne(PassRefPtrWillBeRawPtr<AnimatableValue> zeroValue, PassRefPtrWillBeRawPtr<AnimatableValue> oneValue)
@@ -81,7 +81,7 @@
 
     double actualValue;
     if (value->isLength())
-        actualValue = toCSSPrimitiveValue(toAnimatableLength(value.get())->toCSSValue().get())->getDoubleValue();
+        actualValue = toAnimatableLength(value.get())->length(1, ValueRangeAll).value();
     else
         actualValue = toCSSPrimitiveValue(toAnimatableUnknown(value.get())->toCSSValue().get())->getDoubleValue();
 
diff --git a/Source/core/animation/StringKeyframe.cpp b/Source/core/animation/StringKeyframe.cpp
index 895e19d..c712425 100644
--- a/Source/core/animation/StringKeyframe.cpp
+++ b/Source/core/animation/StringKeyframe.cpp
@@ -5,7 +5,6 @@
 #include "config.h"
 #include "core/animation/StringKeyframe.h"
 
-#include "core/animation/AnimatableLength.h"
 #include "core/animation/Interpolation.h"
 #include "core/animation/css/CSSAnimations.h"
 #include "core/css/resolver/StyleResolver.h"
@@ -22,7 +21,8 @@
 void StringKeyframe::setPropertyValue(CSSPropertyID property, const String& value, StyleSheetContents* styleSheetContents)
 {
     ASSERT(property != CSSPropertyInvalid);
-    m_propertySet->setProperty(property, value, false, styleSheetContents);
+    if (CSSAnimations::isAllowedAnimation(property))
+        m_propertySet->setProperty(property, value, false, styleSheetContents);
 }
 
 PropertySet StringKeyframe::properties() const
@@ -30,12 +30,8 @@
     // This is not used in time-critical code, so we probably don't need to
     // worry about caching this result.
     PropertySet properties;
-    for (unsigned i = 0; i < m_propertySet->propertyCount(); ++i) {
-        // FIXME: Allow for non-animatable properties.
-        CSSPropertyID property = m_propertySet->propertyAt(i).id();
-        if (CSSAnimations::isAnimatableProperty(property))
-            properties.add(property);
-    }
+    for (unsigned i = 0; i < m_propertySet->propertyCount(); ++i)
+        properties.add(m_propertySet->propertyAt(i).id());
     return properties;
 }
 
@@ -71,12 +67,15 @@
     CSSValue* fromCSSValue = m_value.get();
     CSSValue* toCSSValue = toStringPropertySpecificKeyframe(end)->value();
 
+    if (!CSSAnimations::isAnimatableProperty(property))
+        return DefaultStyleInterpolation::create(fromCSSValue, toCSSValue, property);
+
     switch (property) {
     case CSSPropertyLeft:
     case CSSPropertyRight:
     case CSSPropertyWidth:
     case CSSPropertyHeight:
-        if (AnimatableLength::canCreateFrom(fromCSSValue) && AnimatableLength::canCreateFrom(toCSSValue))
+        if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyleInterpolation::canCreateFrom(*toCSSValue))
             return LengthStyleInterpolation::create(fromCSSValue, toCSSValue, property);
         break;
     default:
@@ -110,6 +109,7 @@
 {
     visitor->trace(m_value);
     visitor->trace(m_animatableValueCache);
+    Keyframe::PropertySpecificKeyframe::trace(visitor);
 }
 
 }
diff --git a/Source/core/animation/TimedItem.cpp b/Source/core/animation/TimedItem.cpp
index 5002823..9743143 100644
--- a/Source/core/animation/TimedItem.cpp
+++ b/Source/core/animation/TimedItem.cpp
@@ -57,7 +57,6 @@
     , m_timing(timing)
     , m_eventDelegate(eventDelegate)
     , m_calculated()
-    , m_isFirstSample(true)
     , m_needsUpdate(true)
     , m_lastUpdateTime(nullValue())
 {
@@ -97,15 +96,12 @@
     specifiedTimingChanged();
 }
 
-void TimedItem::updateInheritedTime(double inheritedTime) const
+void TimedItem::updateInheritedTime(double inheritedTime, TimingUpdateReason reason) const
 {
     bool needsUpdate = m_needsUpdate || (m_lastUpdateTime != inheritedTime && !(isNull(m_lastUpdateTime) && isNull(inheritedTime)));
     m_needsUpdate = false;
     m_lastUpdateTime = inheritedTime;
 
-    const double previousIteration = m_calculated.currentIteration;
-    const Phase previousPhase = m_calculated.phase;
-
     const double localTime = inheritedTime - m_startTime;
     double timeToNextIteration = std::numeric_limits<double>::infinity();
     if (needsUpdate) {
@@ -162,12 +158,9 @@
 
     // Test for events even if timing didn't need an update as the player may have gained a start time.
     // FIXME: Refactor so that we can ASSERT(m_player) here, this is currently required to be nullable for testing.
-    if (!m_player || m_player->hasStartTime()) {
-        // This logic is specific to CSS animation events and assumes that all
-        // animations start after the DocumentTimeline has started.
-        if (m_eventDelegate && (m_isFirstSample || previousPhase != phase() || (phase() == PhaseActive && previousIteration != m_calculated.currentIteration)))
-            m_eventDelegate->onEventCondition(this, m_isFirstSample, previousPhase, previousIteration);
-        m_isFirstSample = false;
+    if (reason == TimingUpdateForAnimationFrame && (!m_player || m_player->hasStartTime())) {
+        if (m_eventDelegate)
+            m_eventDelegate->onEventCondition(this);
     }
 
     if (needsUpdate)  {
@@ -183,7 +176,7 @@
     if (!m_player)
         return m_calculated;
     if (m_player->outdated())
-        m_player->update(AnimationPlayer::UpdateOnDemand);
+        m_player->update(TimingUpdateOnDemand);
     ASSERT(!m_player->outdated());
     return m_calculated;
 }
diff --git a/Source/core/animation/TimedItem.h b/Source/core/animation/TimedItem.h
index 69e82a0..6e026dd 100644
--- a/Source/core/animation/TimedItem.h
+++ b/Source/core/animation/TimedItem.h
@@ -42,6 +42,11 @@
 class TimedItem;
 class TimedItemTiming;
 
+enum TimingUpdateReason {
+    TimingUpdateOnDemand,
+    TimingUpdateForAnimationFrame
+};
+
 static inline bool isNull(double value)
 {
     return std::isnan(value);
@@ -66,7 +71,7 @@
     class EventDelegate {
     public:
         virtual ~EventDelegate() { };
-        virtual void onEventCondition(const TimedItem*, bool isFirstSample, Phase previousPhase, double previousIteration) = 0;
+        virtual void onEventCondition(const TimedItem*) = 0;
     };
 
     virtual ~TimedItem() { }
@@ -111,7 +116,7 @@
     // When TimedItem receives a new inherited time via updateInheritedTime
     // it will (if necessary) recalculate timings and (if necessary) call
     // updateChildrenAndEffects.
-    void updateInheritedTime(double inheritedTime) const;
+    void updateInheritedTime(double inheritedTime, TimingUpdateReason) const;
     void invalidate() const { m_needsUpdate = true; };
     bool hasEvents() const { return m_eventDelegate; }
     void clearEventDelegate() { m_eventDelegate = nullptr; }
@@ -158,7 +163,6 @@
         double timeToForwardsEffectChange;
         double timeToReverseEffectChange;
     } m_calculated;
-    mutable bool m_isFirstSample;
     mutable bool m_needsUpdate;
     mutable double m_lastUpdateTime;
 
diff --git a/Source/core/animation/TimedItemTest.cpp b/Source/core/animation/TimedItemTest.cpp
index 2d48ca3..9bcc621 100644
--- a/Source/core/animation/TimedItemTest.cpp
+++ b/Source/core/animation/TimedItemTest.cpp
@@ -39,27 +39,19 @@
 
 class TestTimedItemEventDelegate : public TimedItem::EventDelegate {
 public:
-    virtual void onEventCondition(const TimedItem* timedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE
+    virtual void onEventCondition(const TimedItem* timedItem) OVERRIDE
     {
         m_eventTriggered = true;
-        m_phaseChanged = previousPhase != timedItem->phase();
-        m_iterationChanged = previousIteration != timedItem->currentIteration();
 
     }
     void reset()
     {
         m_eventTriggered = false;
-        m_phaseChanged = false;
-        m_iterationChanged = false;
     }
     bool eventTriggered() { return m_eventTriggered; }
-    bool phaseChanged() { return m_phaseChanged; }
-    bool iterationChanged() { return m_iterationChanged; }
 
 private:
     bool m_eventTriggered;
-    bool m_phaseChanged;
-    bool m_iterationChanged;
 };
 
 class TestTimedItem : public TimedItem {
@@ -71,8 +63,13 @@
 
     void updateInheritedTime(double time)
     {
+        updateInheritedTime(time, TimingUpdateForAnimationFrame);
+    }
+
+    void updateInheritedTime(double time, TimingUpdateReason reason)
+    {
         m_eventDelegate->reset();
-        TimedItem::updateInheritedTime(time);
+        TimedItem::updateInheritedTime(time, reason);
     }
 
     virtual void updateChildrenAndEffects() const OVERRIDE { }
@@ -723,40 +720,18 @@
     timing.startDelay = 1;
     RefPtr<TestTimedItem> timedItem = TestTimedItem::create(timing);
 
-    // First sample
-    timedItem->updateInheritedTime(0.0);
-    EXPECT_TRUE(timedItem->eventDelegate()->eventTriggered());
-
-    // Before start
-    timedItem->updateInheritedTime(0.5);
+    timedItem->updateInheritedTime(0.0, TimingUpdateOnDemand);
     EXPECT_FALSE(timedItem->eventDelegate()->eventTriggered());
 
-    // First iteration
-    timedItem->updateInheritedTime(1.5);
+    timedItem->updateInheritedTime(0.0, TimingUpdateForAnimationFrame);
     EXPECT_TRUE(timedItem->eventDelegate()->eventTriggered());
-    EXPECT_TRUE(timedItem->eventDelegate()->phaseChanged());
-    EXPECT_TRUE(timedItem->eventDelegate()->iterationChanged());
 
-    timedItem->updateInheritedTime(1.6);
+    timedItem->updateInheritedTime(1.5, TimingUpdateOnDemand);
     EXPECT_FALSE(timedItem->eventDelegate()->eventTriggered());
 
-    // Second iteration
-    timedItem->updateInheritedTime(2.5);
+    timedItem->updateInheritedTime(1.5, TimingUpdateForAnimationFrame);
     EXPECT_TRUE(timedItem->eventDelegate()->eventTriggered());
-    EXPECT_FALSE(timedItem->eventDelegate()->phaseChanged());
-    EXPECT_TRUE(timedItem->eventDelegate()->iterationChanged());
 
-    timedItem->updateInheritedTime(2.6);
-    EXPECT_FALSE(timedItem->eventDelegate()->eventTriggered());
-
-    // After end
-    timedItem->updateInheritedTime(3.5);
-    EXPECT_TRUE(timedItem->eventDelegate()->eventTriggered());
-    EXPECT_TRUE(timedItem->eventDelegate()->phaseChanged());
-    EXPECT_FALSE(timedItem->eventDelegate()->iterationChanged());
-
-    timedItem->updateInheritedTime(3.6);
-    EXPECT_FALSE(timedItem->eventDelegate()->eventTriggered());
 }
 
 TEST(AnimationTimedItemTest, TimeToEffectChange)
diff --git a/Source/core/animation/css/CSSAnimatableValueFactory.cpp b/Source/core/animation/css/CSSAnimatableValueFactory.cpp
index 6151cc5..b9895bb 100644
--- a/Source/core/animation/css/CSSAnimatableValueFactory.cpp
+++ b/Source/core/animation/css/CSSAnimatableValueFactory.cpp
@@ -66,17 +66,9 @@
 {
     switch (length.type()) {
     case Fixed:
-        return AnimatableLength::create(adjustFloatForAbsoluteZoom(length.value(), style), CSSPrimitiveValue::UnitTypePixels);
     case Percent:
-        return AnimatableLength::create(length.value(), CSSPrimitiveValue::UnitTypePercentage);
-    case Calculated: {
-        const CalculationValue& calc = length.calculationValue();
-        if (calc.pixels() && calc.percent())
-            return AnimatableLength::create(CSSCalcValue::createExpressionNode(adjustFloatForAbsoluteZoom(calc.pixels(), style), calc.percent()));
-        if (calc.percent())
-            return createFromLength(Length(calc.percent(), Percent), style);
-        return createFromLength(Length(calc.pixels(), Fixed), style);
-    }
+    case Calculated:
+        return AnimatableLength::create(length, style.effectiveZoom());
     case Auto:
     case Intrinsic:
     case MinIntrinsic:
diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp
index fb33249..f615333 100644
--- a/Source/core/animation/css/CSSAnimations.cpp
+++ b/Source/core/animation/css/CSSAnimations.cpp
@@ -58,20 +58,6 @@
 
 namespace {
 
-bool isEarlierPhase(TimedItem::Phase target, TimedItem::Phase reference)
-{
-    ASSERT(target != TimedItem::PhaseNone);
-    ASSERT(reference != TimedItem::PhaseNone);
-    return target < reference;
-}
-
-bool isLaterPhase(TimedItem::Phase target, TimedItem::Phase reference)
-{
-    ASSERT(target != TimedItem::PhaseNone);
-    ASSERT(reference != TimedItem::PhaseNone);
-    return target > reference;
-}
-
 CSSPropertyID propertyForAnimation(CSSPropertyID property)
 {
     switch (property) {
@@ -160,12 +146,14 @@
     if (startKeyframe->offset()) {
         startKeyframe = AnimatableValueKeyframe::create();
         startKeyframe->setOffset(0);
+        startKeyframe->setEasing(defaultTimingFunction);
         keyframes.prepend(startKeyframe);
     }
     RefPtrWillBeRawPtr<AnimatableValueKeyframe> endKeyframe = keyframes[keyframes.size() - 1];
     if (endKeyframe->offset() != 1) {
         endKeyframe = AnimatableValueKeyframe::create();
         endKeyframe->setOffset(1);
+        endKeyframe->setEasing(defaultTimingFunction);
         keyframes.append(endKeyframe);
     }
     ASSERT(keyframes.size() >= 2);
@@ -378,7 +366,9 @@
     DisableCompositingQueryAsserts disabler;
 
     for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationNames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) {
-        m_animations.take(*iter)->cancel();
+        RefPtr<AnimationPlayer> player = m_animations.take(*iter);
+        player->cancel();
+        player->update(TimingUpdateOnDemand);
     }
 
     for (Vector<AtomicString>::const_iterator iter = update->animationsWithPauseToggled().begin(); iter != update->animationsWithPauseToggled().end(); ++iter) {
@@ -387,6 +377,8 @@
             player->unpause();
         else
             player->pause();
+        if (player->outdated())
+            player->update(TimingUpdateOnDemand);
     }
 
     for (Vector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update->newAnimations().begin(); iter != update->newAnimations().end(); ++iter) {
@@ -397,7 +389,7 @@
         element->document().compositorPendingAnimations().add(player.get());
         if (inertAnimation->paused())
             player->pause();
-        player->update(AnimationPlayer::UpdateOnDemand);
+        player->update(TimingUpdateOnDemand);
         m_animations.set(iter->name, player.get());
     }
 
@@ -416,6 +408,7 @@
         if (animation->hasActiveAnimationsOnCompositor(id) && update->newTransitions().find(id) != update->newTransitions().end())
             retargetedCompositorTransitions.add(id, std::pair<RefPtr<Animation>, double>(animation, player->startTimeInternal()));
         player->cancel();
+        player->update(TimingUpdateOnDemand);
     }
 
     for (CSSAnimationUpdate::NewTransitionMap::const_iterator iter = update->newTransitions().begin(); iter != update->newTransitions().end(); ++iter) {
@@ -456,7 +449,7 @@
         RefPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specifiedTiming(), Animation::TransitionPriority, eventDelegate.release());
         RefPtr<AnimationPlayer> player = element->document().transitionTimeline().createAnimationPlayer(transition.get());
         element->document().compositorPendingAnimations().add(player.get());
-        player->update(AnimationPlayer::UpdateOnDemand);
+        player->update(TimingUpdateOnDemand);
         runningTransition.player = player;
         m_transitions.set(id, runningTransition);
         ASSERT(id != CSSPropertyInvalid);
@@ -577,11 +570,11 @@
 
     if (activeTransitions) {
         for (TransitionMap::const_iterator iter = activeTransitions->begin(); iter != activeTransitions->end(); ++iter) {
-            const TimedItem* timedItem = iter->value.player->source();
+            const AnimationPlayer& player = *iter->value.player;
             CSSPropertyID id = iter->key;
-            if (timedItem->phase() == TimedItem::PhaseAfter || (!anyTransitionHadAnimateAll && !animationStyleRecalc && !listedProperties.get(id))) {
+            if (player.finishedInternal() || (!anyTransitionHadAnimateAll && !animationStyleRecalc && !listedProperties.get(id))) {
                 // TODO: Figure out why this fails on Chrome OS login page. crbug.com/365507
-                // ASSERT(timedItem->phase() == TimedItem::PhaseAfter || !(activeAnimations && activeAnimations->isAnimationStyleChange()));
+                // ASSERT(player.finishedInternal() || !(activeAnimations && activeAnimations->isAnimationStyleChange()));
                 update->cancelTransition(id);
             }
         }
@@ -590,11 +583,15 @@
 
 void CSSAnimations::cancel()
 {
-    for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animations.end(); ++iter)
+    for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animations.end(); ++iter) {
         iter->value->cancel();
+        iter->value->update(TimingUpdateOnDemand);
+    }
 
-    for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transitions.end(); ++iter)
+    for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transitions.end(); ++iter) {
         iter->value.player->cancel();
+        iter->value.player->update(TimingUpdateOnDemand);
+    }
 
     m_animations.clear();
     m_transitions.clear();
@@ -663,39 +660,41 @@
     }
 }
 
-void CSSAnimations::AnimationEventDelegate::onEventCondition(const TimedItem* timedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration)
+void CSSAnimations::AnimationEventDelegate::onEventCondition(const TimedItem* timedItem)
 {
     const TimedItem::Phase currentPhase = timedItem->phase();
     const double currentIteration = timedItem->currentIteration();
 
-    // Note that the elapsedTime is measured from when the animation starts playing.
-    if (!isFirstSample && previousPhase == TimedItem::PhaseActive && currentPhase == TimedItem::PhaseActive && previousIteration != currentIteration) {
-        ASSERT(!isNull(previousIteration));
-        ASSERT(!isNull(currentIteration));
-        // We fire only a single event for all iterations thast terminate
-        // between a single pair of samples. See http://crbug.com/275263. For
-        // compatibility with the existing implementation, this event uses
-        // the elapsedTime for the first iteration in question.
-        ASSERT(!std::isnan(timedItem->specifiedTiming().iterationDuration));
-        const double elapsedTime = timedItem->specifiedTiming().iterationDuration * (previousIteration + 1);
-        maybeDispatch(Document::ANIMATIONITERATION_LISTENER, EventTypeNames::animationiteration, elapsedTime);
-        return;
-    }
-    if ((isFirstSample || previousPhase == TimedItem::PhaseBefore) && isLaterPhase(currentPhase, TimedItem::PhaseBefore)) {
-        ASSERT(timedItem->specifiedTiming().startDelay > 0 || isFirstSample);
+    if (m_previousPhase != currentPhase
+        && (currentPhase == TimedItem::PhaseActive || currentPhase == TimedItem::PhaseAfter)
+        && (m_previousPhase == TimedItem::PhaseNone || m_previousPhase == TimedItem::PhaseBefore)) {
         // The spec states that the elapsed time should be
         // 'delay < 0 ? -delay : 0', but we always use 0 to match the existing
         // implementation. See crbug.com/279611
         maybeDispatch(Document::ANIMATIONSTART_LISTENER, EventTypeNames::animationstart, 0);
     }
-    if ((isFirstSample || isEarlierPhase(previousPhase, TimedItem::PhaseAfter)) && currentPhase == TimedItem::PhaseAfter)
+
+    if (currentPhase == TimedItem::PhaseActive && m_previousPhase == currentPhase && m_previousIteration != currentIteration) {
+        // We fire only a single event for all iterations thast terminate
+        // between a single pair of samples. See http://crbug.com/275263. For
+        // compatibility with the existing implementation, this event uses
+        // the elapsedTime for the first iteration in question.
+        ASSERT(!std::isnan(timedItem->specifiedTiming().iterationDuration));
+        const double elapsedTime = timedItem->specifiedTiming().iterationDuration * (m_previousIteration + 1);
+        maybeDispatch(Document::ANIMATIONITERATION_LISTENER, EventTypeNames::animationiteration, elapsedTime);
+    }
+
+    if (currentPhase == TimedItem::PhaseAfter && m_previousPhase != TimedItem::PhaseAfter)
         maybeDispatch(Document::ANIMATIONEND_LISTENER, EventTypeNames::animationend, timedItem->activeDurationInternal());
+
+    m_previousPhase = currentPhase;
+    m_previousIteration = currentIteration;
 }
 
-void CSSAnimations::TransitionEventDelegate::onEventCondition(const TimedItem* timedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration)
+void CSSAnimations::TransitionEventDelegate::onEventCondition(const TimedItem* timedItem)
 {
     const TimedItem::Phase currentPhase = timedItem->phase();
-    if (currentPhase == TimedItem::PhaseAfter && (isFirstSample || previousPhase != currentPhase) && m_target->document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
+    if (currentPhase == TimedItem::PhaseAfter && currentPhase != m_previousPhase && m_target->document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
         String propertyName = getPropertyNameString(m_property);
         const Timing& timing = timedItem->specifiedTiming();
         double elapsedTime = timing.iterationDuration;
@@ -705,6 +704,8 @@
         event->setTarget(m_target);
         m_target->document().enqueueAnimationFrameEvent(event);
     }
+
+    m_previousPhase = currentPhase;
 }
 
 bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
@@ -843,6 +844,46 @@
     return propertyShorthand;
 }
 
+// Animation properties are not allowed to be affected by Web Animations.
+// http://dev.w3.org/fxtf/web-animations/#not-animatable
+bool CSSAnimations::isAllowedAnimation(CSSPropertyID property)
+{
+    switch (property) {
+    case CSSPropertyAnimation:
+    case CSSPropertyAnimationDelay:
+    case CSSPropertyAnimationDirection:
+    case CSSPropertyAnimationDuration:
+    case CSSPropertyAnimationFillMode:
+    case CSSPropertyAnimationIterationCount:
+    case CSSPropertyAnimationName:
+    case CSSPropertyAnimationPlayState:
+    case CSSPropertyAnimationTimingFunction:
+    case CSSPropertyDisplay:
+    case CSSPropertyTransition:
+    case CSSPropertyTransitionDelay:
+    case CSSPropertyTransitionDuration:
+    case CSSPropertyTransitionProperty:
+    case CSSPropertyTransitionTimingFunction:
+    case CSSPropertyWebkitAnimation:
+    case CSSPropertyWebkitAnimationDelay:
+    case CSSPropertyWebkitAnimationDirection:
+    case CSSPropertyWebkitAnimationDuration:
+    case CSSPropertyWebkitAnimationFillMode:
+    case CSSPropertyWebkitAnimationIterationCount:
+    case CSSPropertyWebkitAnimationName:
+    case CSSPropertyWebkitAnimationPlayState:
+    case CSSPropertyWebkitAnimationTimingFunction:
+    case CSSPropertyWebkitTransition:
+    case CSSPropertyWebkitTransitionDelay:
+    case CSSPropertyWebkitTransitionDuration:
+    case CSSPropertyWebkitTransitionProperty:
+    case CSSPropertyWebkitTransitionTimingFunction:
+        return false;
+    default:
+        return true;
+    }
+}
+
 void CSSAnimations::trace(Visitor* visitor)
 {
     visitor->trace(m_transitions);
diff --git a/Source/core/animation/css/CSSAnimations.h b/Source/core/animation/css/CSSAnimations.h
index 11bb1a6..2f36dfb 100644
--- a/Source/core/animation/css/CSSAnimations.h
+++ b/Source/core/animation/css/CSSAnimations.h
@@ -163,6 +163,7 @@
 
     static bool isAnimatableProperty(CSSPropertyID);
     static const StylePropertyShorthand& animatableProperties();
+    static bool isAllowedAnimation(CSSPropertyID);
     // FIXME: This should take a const ScopedStyleTree instead of a StyleResolver.
     // We should also change the Element* to a const Element*
     static PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> calculateUpdate(Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
@@ -211,13 +212,17 @@
         AnimationEventDelegate(Element* target, const AtomicString& name)
             : m_target(target)
             , m_name(name)
+            , m_previousPhase(TimedItem::PhaseNone)
+            , m_previousIteration(nullValue())
         {
         }
-        virtual void onEventCondition(const TimedItem*, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE;
+        virtual void onEventCondition(const TimedItem*) OVERRIDE;
     private:
         void maybeDispatch(Document::ListenerType, const AtomicString& eventName, double elapsedTime);
         Element* m_target;
         const AtomicString m_name;
+        TimedItem::Phase m_previousPhase;
+        double m_previousIteration;
     };
 
     class TransitionEventDelegate FINAL : public TimedItem::EventDelegate {
@@ -225,12 +230,14 @@
         TransitionEventDelegate(Element* target, CSSPropertyID property)
             : m_target(target)
             , m_property(property)
+            , m_previousPhase(TimedItem::PhaseNone)
         {
         }
-        virtual void onEventCondition(const TimedItem*, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE;
+        virtual void onEventCondition(const TimedItem*) OVERRIDE;
     private:
         Element* m_target;
         const CSSPropertyID m_property;
+        TimedItem::Phase m_previousPhase;
     };
 };
 
diff --git a/Source/core/animation/css/CSSPropertyEquality.cpp b/Source/core/animation/css/CSSPropertyEquality.cpp
index b4c8dd7..c879652 100644
--- a/Source/core/animation/css/CSSPropertyEquality.cpp
+++ b/Source/core/animation/css/CSSPropertyEquality.cpp
@@ -6,6 +6,7 @@
 #include "core/animation/css/CSSPropertyEquality.h"
 
 #include "core/animation/css/CSSAnimations.h"
+#include "core/rendering/style/DataEquivalency.h"
 #include "core/rendering/style/RenderStyle.h"
 #include "core/rendering/style/ShadowList.h"
 
@@ -39,7 +40,7 @@
                 return false;
             break;
         case CSSPropertyBackgroundImage:
-            if (!StyleImage::imagesEquivalent(aLayer->image(), bLayer->image()))
+            if (!dataEquivalent(aLayer->image(), bLayer->image()))
                 return false;
             break;
         default:
@@ -55,12 +56,6 @@
     return true;
 }
 
-template <typename T>
-bool ptrsOrValuesEqual(T a, T b)
-{
-    return a == b || (a && b && *a == *b);
-}
-
 }
 
 bool CSSPropertyEquality::propertiesEqual(CSSPropertyID prop, const RenderStyle& a, const RenderStyle& b)
@@ -78,7 +73,7 @@
     case CSSPropertyBackgroundSize:
         return fillLayersEqual<CSSPropertyBackgroundSize>(a.backgroundLayers(), b.backgroundLayers());
     case CSSPropertyBaselineShift:
-        return ptrsOrValuesEqual<PassRefPtr<SVGLength> >(a.baselineShiftValue(), b.baselineShiftValue());
+        return dataEquivalent(a.baselineShiftValue(), b.baselineShiftValue());
     case CSSPropertyBorderBottomColor:
         return a.borderBottomColor().resolve(a.color()) == b.borderBottomColor().resolve(b.color())
             && a.visitedLinkBorderBottomColor().resolve(a.color()) == b.visitedLinkBorderBottomColor().resolve(b.color());
@@ -93,7 +88,7 @@
     case CSSPropertyBorderImageSlice:
         return a.borderImageSlices() == b.borderImageSlices();
     case CSSPropertyBorderImageSource:
-        return ptrsOrValuesEqual<StyleImage*>(a.borderImageSource(), b.borderImageSource());
+        return dataEquivalent(a.borderImageSource(), b.borderImageSource());
     case CSSPropertyBorderImageWidth:
         return a.borderImageWidth() == b.borderImageWidth();
     case CSSPropertyBorderLeftColor:
@@ -118,7 +113,7 @@
     case CSSPropertyBottom:
         return a.bottom() == b.bottom();
     case CSSPropertyBoxShadow:
-        return ptrsOrValuesEqual<ShadowList*>(a.boxShadow(), b.boxShadow());
+        return dataEquivalent(a.boxShadow(), b.boxShadow());
     case CSSPropertyClip:
         return a.clip() == b.clip();
     case CSSPropertyColor:
@@ -157,7 +152,7 @@
     case CSSPropertyLineHeight:
         return a.specifiedLineHeight() == b.specifiedLineHeight();
     case CSSPropertyListStyleImage:
-        return ptrsOrValuesEqual<StyleImage*>(a.listStyleImage(), b.listStyleImage());
+        return dataEquivalent(a.listStyleImage(), b.listStyleImage());
     case CSSPropertyMarginBottom:
         return a.marginBottom() == b.marginBottom();
     case CSSPropertyMarginLeft:
@@ -202,7 +197,7 @@
     case CSSPropertyShapeMargin:
         return a.shapeMargin() == b.shapeMargin();
     case CSSPropertyShapeOutside:
-        return ptrsOrValuesEqual<ShapeValue*>(a.shapeOutside(), b.shapeOutside());
+        return dataEquivalent(a.shapeOutside(), b.shapeOutside());
     case CSSPropertyStopColor:
         return a.stopColor() == b.stopColor();
     case CSSPropertyStopOpacity:
@@ -211,22 +206,22 @@
         return a.strokePaintType() == b.strokePaintType()
             && (a.strokePaintType() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR || a.strokePaintColor() == b.strokePaintColor());
     case CSSPropertyStrokeDasharray:
-        return ptrsOrValuesEqual<PassRefPtr<SVGLengthList> >(a.strokeDashArray(), b.strokeDashArray());
+        return dataEquivalent(a.strokeDashArray(), b.strokeDashArray());
     case CSSPropertyStrokeDashoffset:
-        return ptrsOrValuesEqual<PassRefPtr<SVGLength> >(a.strokeDashOffset(), b.strokeDashOffset());
+        return dataEquivalent(a.strokeDashOffset(), b.strokeDashOffset());
     case CSSPropertyStrokeMiterlimit:
         return a.strokeMiterLimit() == b.strokeMiterLimit();
     case CSSPropertyStrokeOpacity:
         return a.strokeOpacity() == b.strokeOpacity();
     case CSSPropertyStrokeWidth:
-        return ptrsOrValuesEqual<PassRefPtr<SVGLength> >(a.strokeWidth(), b.strokeWidth());
+        return dataEquivalent(a.strokeWidth(), b.strokeWidth());
     case CSSPropertyTextDecorationColor:
         return a.textDecorationColor().resolve(a.color()) == b.textDecorationColor().resolve(b.color())
             && a.visitedLinkTextDecorationColor().resolve(a.color()) == b.visitedLinkTextDecorationColor().resolve(b.color());
     case CSSPropertyTextIndent:
         return a.textIndent() == b.textIndent();
     case CSSPropertyTextShadow:
-        return ptrsOrValuesEqual<ShadowList*>(a.textShadow(), b.textShadow());
+        return dataEquivalent(a.textShadow(), b.textShadow());
     case CSSPropertyTop:
         return a.top() == b.top();
     case CSSPropertyVisibility:
@@ -238,9 +233,9 @@
     case CSSPropertyWebkitBorderVerticalSpacing:
         return a.verticalBorderSpacing() == b.verticalBorderSpacing();
     case CSSPropertyWebkitBoxShadow:
-        return ptrsOrValuesEqual<ShadowList*>(a.boxShadow(), b.boxShadow());
+        return dataEquivalent(a.boxShadow(), b.boxShadow());
     case CSSPropertyWebkitClipPath:
-        return ptrsOrValuesEqual<ClipPathOperation*>(a.clipPath(), b.clipPath());
+        return dataEquivalent(a.clipPath(), b.clipPath());
     case CSSPropertyWebkitColumnCount:
         return a.columnCount() == b.columnCount();
     case CSSPropertyWebkitColumnGap:
@@ -259,11 +254,11 @@
     case CSSPropertyWebkitMaskBoxImageSlice:
         return a.maskBoxImageSlices() == b.maskBoxImageSlices();
     case CSSPropertyWebkitMaskBoxImageSource:
-        return ptrsOrValuesEqual<StyleImage*>(a.maskBoxImageSource(), b.maskBoxImageSource());
+        return dataEquivalent(a.maskBoxImageSource(), b.maskBoxImageSource());
     case CSSPropertyWebkitMaskBoxImageWidth:
         return a.maskBoxImageWidth() == b.maskBoxImageWidth();
     case CSSPropertyWebkitMaskImage:
-        return ptrsOrValuesEqual<StyleImage*>(a.maskImage(), b.maskImage());
+        return dataEquivalent(a.maskImage(), b.maskImage());
     case CSSPropertyWebkitMaskPositionX:
         return fillLayersEqual<CSSPropertyWebkitMaskPositionX>(a.maskLayers(), b.maskLayers());
     case CSSPropertyWebkitMaskPositionY:
diff --git a/Source/core/animation/css/TransitionTimeline.cpp b/Source/core/animation/css/TransitionTimeline.cpp
index 9680f98..0952326 100644
--- a/Source/core/animation/css/TransitionTimeline.cpp
+++ b/Source/core/animation/css/TransitionTimeline.cpp
@@ -45,7 +45,6 @@
     : DocumentTimeline(document, timing)
 {
     setZeroTime(document->animationClock().currentTime());
-    document->animationClock().unfreeze();
 }
 
 } // namespace WebCore