Fixes cache misses and extra allocations.
Bug #3421454

Change-Id: If4d5c960a7e4c581a9d213073e658284b4e1c497
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index c1deed3..136e9b4 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -104,7 +104,7 @@
     public Canvas() {
         // 0 means no native bitmap
         mNativeCanvas = initRaster(0);
-        mFinalizer = new CanvasFinalizer(0);
+        mFinalizer = new CanvasFinalizer(mNativeCanvas);
     }
 
     /**
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index ebf7aa0..4f5edd5 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -76,8 +76,14 @@
     LOGD("  PathCache            %8d / %8d", pathCache.getSize(), pathCache.getMaxSize());
     LOGD("  CircleShapeCache     %8d / %8d",
             circleShapeCache.getSize(), circleShapeCache.getMaxSize());
+    LOGD("  OvalShapeCache       %8d / %8d",
+            ovalShapeCache.getSize(), ovalShapeCache.getMaxSize());
     LOGD("  RoundRectShapeCache  %8d / %8d",
             roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
+    LOGD("  RectShapeCache       %8d / %8d",
+            rectShapeCache.getSize(), rectShapeCache.getMaxSize());
+    LOGD("  ArcShapeCache        %8d / %8d",
+            arcShapeCache.getSize(), arcShapeCache.getMaxSize());
     LOGD("  TextDropShadowCache  %8d / %8d", dropShadowCache.getSize(),
             dropShadowCache.getMaxSize());
     for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
@@ -94,6 +100,11 @@
     total += gradientCache.getSize();
     total += pathCache.getSize();
     total += dropShadowCache.getSize();
+    total += roundRectShapeCache.getSize();
+    total += circleShapeCache.getSize();
+    total += ovalShapeCache.getSize();
+    total += rectShapeCache.getSize();
+    total += arcShapeCache.getSize();
     for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
         total += fontRenderer.getFontRendererSize(i);
     }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index cfc853c..51c81b0 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -22,62 +22,6 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#define PATH_HEAP_SIZE 64
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers
-///////////////////////////////////////////////////////////////////////////////
-
-PathHeap::PathHeap(): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) {
-}
-
-PathHeap::PathHeap(SkFlattenableReadBuffer& buffer): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) {
-    int count = buffer.readS32();
-
-    mPaths.setCount(count);
-    SkPath** ptr = mPaths.begin();
-    SkPath* p = (SkPath*) mHeap.allocThrow(count * sizeof(SkPath));
-
-    for (int i = 0; i < count; i++) {
-        new (p) SkPath;
-        p->unflatten(buffer);
-        *ptr++ = p;
-        p++;
-    }
-}
-
-PathHeap::~PathHeap() {
-    SkPath** iter = mPaths.begin();
-    SkPath** stop = mPaths.end();
-    while (iter < stop) {
-        (*iter)->~SkPath();
-        iter++;
-    }
-}
-
-int PathHeap::append(const SkPath& path) {
-    SkPath* p = (SkPath*) mHeap.allocThrow(sizeof(SkPath));
-    new (p) SkPath(path);
-    *mPaths.append() = p;
-    return mPaths.count();
-}
-
-void PathHeap::flatten(SkFlattenableWriteBuffer& buffer) const {
-    int count = mPaths.count();
-
-    buffer.write32(count);
-    SkPath** iter = mPaths.begin();
-    SkPath** stop = mPaths.end();
-    while (iter < stop) {
-        (*iter)->flatten(buffer);
-        iter++;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // Display list
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -143,17 +87,15 @@
     }
     mPaints.clear();
 
+    for (size_t i = 0; i < mPaths.size(); i++) {
+        delete mPaths.itemAt(i);
+    }
+    mPaths.clear();
+
     for (size_t i = 0; i < mMatrices.size(); i++) {
         delete mMatrices.itemAt(i);
     }
     mMatrices.clear();
-
-    if (mPathHeap) {
-        for (int i = 0; i < mPathHeap->count(); i++) {
-            caches.pathCache.removeDeferred(&(*mPathHeap)[i]);
-        }
-        mPathHeap->safeUnref();
-    }
 }
 
 void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder) {
@@ -169,12 +111,6 @@
     writer.flatten(buffer);
     mReader.setMemory(buffer, size);
 
-    mRCPlayback.reset(&recorder.mRCRecorder);
-    mRCPlayback.setupBuffer(mReader);
-
-    mTFPlayback.reset(&recorder.mTFRecorder);
-    mTFPlayback.setupBuffer(mReader);
-
     Caches& caches = Caches::getInstance();
 
     const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources();
@@ -196,19 +132,18 @@
         mPaints.add(paints.itemAt(i));
     }
 
+    const Vector<SkPath*> &paths = recorder.getPaths();
+    for (size_t i = 0; i < paths.size(); i++) {
+        mPaths.add(paths.itemAt(i));
+    }
+
     const Vector<SkMatrix*> &matrices = recorder.getMatrices();
     for (size_t i = 0; i < matrices.size(); i++) {
         mMatrices.add(matrices.itemAt(i));
     }
-
-    mPathHeap = recorder.mPathHeap;
-    if (mPathHeap) {
-        mPathHeap->safeRef();
-    }
 }
 
 void DisplayList::init() {
-    mPathHeap = NULL;
 }
 
 bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
@@ -557,9 +492,7 @@
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayListRenderer::DisplayListRenderer():
-        mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) {
-    mPathHeap = NULL;
+DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
     mDisplayList = NULL;
 }
 
@@ -568,16 +501,7 @@
 }
 
 void DisplayListRenderer::reset() {
-    if (mPathHeap) {
-        mPathHeap->unref();
-        mPathHeap = NULL;
-    }
-
     mWriter.reset();
-    mHeap.reset();
-
-    mRCRecorder.reset();
-    mTFRecorder.reset();
 
     Caches& caches = Caches::getInstance();
     for (size_t i = 0; i < mBitmapResources.size(); i++) {
@@ -594,6 +518,8 @@
 
     mPaints.clear();
     mPaintMap.clear();
+    mPaths.clear();
+    mPathMap.clear();
     mMatrices.clear();
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index a6d2bfe..e762dfb 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -38,7 +38,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #define MIN_WRITER_SIZE 16384
-#define HEAP_BLOCK_SIZE 4096
 
 // Debug
 #if DEBUG_DISPLAY_LIST
@@ -48,31 +47,6 @@
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
-// Helpers
-///////////////////////////////////////////////////////////////////////////////
-
-class PathHeap: public SkRefCnt {
-public:
-    PathHeap();
-    PathHeap(SkFlattenableReadBuffer& buffer);
-    ~PathHeap();
-
-    int append(const SkPath& path);
-
-    int count() const { return mPaths.count(); }
-
-    SkPath& operator[](int index) const {
-        return *mPaths[index];
-    }
-
-    void flatten(SkFlattenableWriteBuffer& buffer) const;
-
-private:
-    SkChunkAlloc mHeap;
-    SkTDArray<SkPath*> mPaths;
-};
-
-///////////////////////////////////////////////////////////////////////////////
 // Display list
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -174,7 +148,7 @@
     }
 
     SkPath* getPath() {
-        return &(*mPathHeap)[getInt() - 1];
+        return (SkPath*) getInt();
     }
 
     SkPaint* getPaint() {
@@ -209,19 +183,15 @@
         text->mText = (const char*) mReader.skip(length);
     }
 
-    PathHeap* mPathHeap;
-
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
+    Vector<SkPath*> mPaths;
     Vector<SkMatrix*> mMatrices;
     Vector<SkiaShader*> mShaders;
 
     mutable SkFlattenableReadBuffer mReader;
-
-    SkRefCntPlayback mRCPlayback;
-    SkTypefacePlayback mTFPlayback;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -317,6 +287,10 @@
         return mPaints;
     }
 
+    const Vector<SkPath*>& getPaths() const {
+        return mPaths;
+    }
+
     const Vector<SkMatrix*>& getMatrices() const {
         return mMatrices;
     }
@@ -385,11 +359,24 @@
         mWriter.writePad(text, byteLength);
     }
 
-    inline void addPath(const SkPath* path) {
-        if (mPathHeap == NULL) {
-            mPathHeap = new PathHeap();
+    inline void addPath(SkPath* path) {
+        if (!path) {
+            addInt((int) NULL);
+            return;
         }
-        addInt(mPathHeap->append(*path));
+
+        SkPath* pathCopy = mPathMap.valueFor(path);
+        if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
+            if (pathCopy == NULL) {
+                pathCopy = path;
+            } else {
+                pathCopy = new SkPath(*path);
+                mPaths.add(pathCopy);
+            }
+            mPathMap.add(path, pathCopy);
+        }
+
+        addInt((int) pathCopy);
     }
 
     inline void addPaint(SkPaint* paint) {
@@ -457,25 +444,22 @@
         caches.resourceCache.incrementRefcount(colorFilter);
     }
 
-    SkChunkAlloc mHeap;
-
     Vector<SkBitmap*> mBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
 
+    Vector<SkPath*> mPaths;
+    DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
+
     Vector<SkiaShader*> mShaders;
     DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
 
     Vector<SkMatrix*> mMatrices;
 
-    PathHeap* mPathHeap;
     SkWriter32 mWriter;
 
-    SkRefCntRecorder mRCRecorder;
-    SkRefCntRecorder mTFRecorder;
-
     DisplayList *mDisplayList;
 
     int mRestoreSaveCount;
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 28c302e..0f22bea 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -65,7 +65,6 @@
 
 PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
     PathCacheEntry entry(path, paint);
-
     PathTexture* texture = mCache.get(entry);
 
     if (!texture) {
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 8cefc8c..ffccfa2 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -32,7 +32,7 @@
 namespace uirenderer {
 
 struct ShadowText {
-    ShadowText(): radius(0), len(0), hash(0), textSize(0.0f), typeface(NULL) {
+    ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
     }
 
     ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
@@ -42,20 +42,11 @@
 
         textSize = paint->getTextSize();
         typeface = paint->getTypeface();
-
-        hash = 0;
-        uint32_t multiplier = 1;
-        const char* text = str.string();
-        for (uint32_t i = 0; i < len; i++) {
-            hash += text[i] * multiplier;
-            uint32_t shifted = multiplier << 5;
-            multiplier = shifted - multiplier;
-        }
     }
 
     ShadowText(const ShadowText& shadow):
-            radius(shadow.radius), len(shadow.len), hash(shadow.hash),
-            textSize(shadow.textSize), typeface(shadow.typeface), str(shadow.str) {
+            radius(shadow.radius), len(shadow.len), textSize(shadow.textSize),
+            typeface(shadow.typeface), str(shadow.str) {
     }
 
     ~ShadowText() {
@@ -63,20 +54,17 @@
 
     uint32_t radius;
     uint32_t len;
-    uint32_t hash;
     float textSize;
     SkTypeface* typeface;
     String8 str;
 
     bool operator<(const ShadowText& rhs) const {
-        LTE_INT(hash) {
-            LTE_INT(len) {
-                LTE_INT(radius) {
-                    LTE_FLOAT(textSize) {
-                        if (typeface < rhs.typeface) return true;
-                        else if (typeface == rhs.typeface) {
-                            return str.compare(rhs.str) < 0;
-                        }
+        LTE_INT(len) {
+            LTE_INT(radius) {
+                LTE_FLOAT(textSize) {
+                    if (typeface < rhs.typeface) return true;
+                    else if (typeface == rhs.typeface) {
+                        return str.compare(rhs.str) < 0;
                     }
                 }
             }