Title: [132970] trunk/Source/WebCore
Revision
132970
Author
[email protected]
Date
2012-10-30 18:10:11 -0700 (Tue, 30 Oct 2012)

Log Message

Improve performance of MaskPtr.
https://bugs.webkit.org/show_bug.cgi?id=100790

Reviewed by Eric Seidel.

Calculate the mask once, and store it as a fast-access member variable.
Also avoid unneccessary integer width expansion in index calculation.
Parser/tiny-innerHTML.html has a high stddev.
Best result I've seen pre-patch is 5.70 runs/s.
Best result I've seen post-patch is 5.72 runs/s, but this is not statistically significant.
MaskPtr is still showing as ~2% in the profile, so we're not sure we trust the profile symbolization at this time.
MaskPtr is now reduced to a single inline instruction (was: 4) so this seems like a strict improvement worth landing.

* rendering/RenderArena.cpp:
(MaskPtr): Use a passed-in mask for the mask operation.
(WebCore::RenderArena::RenderArena): Calculate the mask and store it.
(WebCore::RenderArena::allocate):
(WebCore::RenderArena::free): Use stored mask and avoid unneccessary casts.
* rendering/RenderArena.h:
(RenderArena): Store the freelist mask as a member variable.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (132969 => 132970)


--- trunk/Source/WebCore/ChangeLog	2012-10-31 00:45:16 UTC (rev 132969)
+++ trunk/Source/WebCore/ChangeLog	2012-10-31 01:10:11 UTC (rev 132970)
@@ -1,3 +1,26 @@
+2012-10-30  Chris Evans  <[email protected]>
+
+        Improve performance of MaskPtr.
+        https://bugs.webkit.org/show_bug.cgi?id=100790
+
+        Reviewed by Eric Seidel.
+
+        Calculate the mask once, and store it as a fast-access member variable.
+        Also avoid unneccessary integer width expansion in index calculation.
+        Parser/tiny-innerHTML.html has a high stddev.
+        Best result I've seen pre-patch is 5.70 runs/s.
+        Best result I've seen post-patch is 5.72 runs/s, but this is not statistically significant.
+        MaskPtr is still showing as ~2% in the profile, so we're not sure we trust the profile symbolization at this time.
+        MaskPtr is now reduced to a single inline instruction (was: 4) so this seems like a strict improvement worth landing.
+
+        * rendering/RenderArena.cpp:
+        (MaskPtr): Use a passed-in mask for the mask operation.
+        (WebCore::RenderArena::RenderArena): Calculate the mask and store it.
+        (WebCore::RenderArena::allocate):
+        (WebCore::RenderArena::free): Use stored mask and avoid unneccessary casts.
+        * rendering/RenderArena.h:
+        (RenderArena): Store the freelist mask as a member variable.
+
 2012-10-30  Kenichi Ishibashi  <[email protected]>
 
         local(Helvetica) in src descriptor prevent fallback

Modified: trunk/Source/WebCore/rendering/RenderArena.cpp (132969 => 132970)


--- trunk/Source/WebCore/rendering/RenderArena.cpp	2012-10-31 00:45:16 UTC (rev 132969)
+++ trunk/Source/WebCore/rendering/RenderArena.cpp	2012-10-31 01:10:11 UTC (rev 132970)
@@ -43,18 +43,8 @@
 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
 
 #ifdef NDEBUG
-// Mask freelist pointers to detect corruption and prevent freelist spraying.
-// We use an arbitray function and rely on ASLR to randomize it.
-// The first value in RenderObject (or any class) is a vtable pointer, which always
-// overlaps with the next pointer. This change guarantees that the masked vtable/next
-// pointer will never point to valid memory. So, we should immediately crash on the
-// first invalid vtable access for a stale RenderObject pointer.
-// See http://download.crowdstrike.com/papers/hes-exploiting-a-coalmine.pdf.
-static void* MaskPtr(void* p)
+static void* MaskPtr(void* p, uintptr_t mask)
 {
-    // The bottom bits are predictable because the binary is loaded on a boundary.
-    // This just shifts most of those predictable bits out.
-    const uintptr_t mask = ~(reinterpret_cast<uintptr_t>(WTF::fastMalloc) >> 13);
     return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) ^ mask);
 }
 #endif
@@ -85,6 +75,19 @@
 
     // Zero out the recyclers array
     memset(m_recyclers, 0, sizeof(m_recyclers));
+
+    // Mask freelist pointers to detect corruption and stop freelist spraying.
+    // We use an arbitray function and rely on ASLR to randomize it.
+    // The first value in RenderObject (or any class) is a vtable pointer, which
+    // always overlaps with the next pointer. This change guarantees that the
+    // masked vtable/next pointer will never point to valid memory. So, we
+    // should immediately crash on the first invalid vtable access for a stale
+    // RenderObject pointer.
+    // See http://download.crowdstrike.com/papers/hes-exploiting-a-coalmine.pdf.
+
+    // The bottom bits are predictable because the binary is loaded on a
+    // boundary. This just shifts most of those predictable bits out.
+    m_mask = ~(reinterpret_cast<uintptr_t>(WTF::fastMalloc) >> 13);
 }
 
 RenderArena::~RenderArena()
@@ -115,12 +118,12 @@
 
     // Check recyclers first
     if (size < gMaxRecycledSize) {
-        const int index = size >> 2;
+        const size_t index = size >> 2;
 
         result = m_recyclers[index];
         if (result) {
             // Need to move to the next object
-            void* next = MaskPtr(*((void**)result));
+            void* next = MaskPtr(*((void**)result), m_mask);
             m_recyclers[index] = next;
         }
     }
@@ -157,10 +160,10 @@
 
     // See if it's a size that we recycle
     if (size < gMaxRecycledSize) {
-        const int index = size >> 2;
+        const size_t index = size >> 2;
         void* currentTop = m_recyclers[index];
         m_recyclers[index] = ptr;
-        *((void**)ptr) = MaskPtr(currentTop);
+        *((void**)ptr) = MaskPtr(currentTop, m_mask);
     }
 #endif
 }

Modified: trunk/Source/WebCore/rendering/RenderArena.h (132969 => 132970)


--- trunk/Source/WebCore/rendering/RenderArena.h	2012-10-31 00:45:16 UTC (rev 132969)
+++ trunk/Source/WebCore/rendering/RenderArena.h	2012-10-31 01:10:11 UTC (rev 132970)
@@ -60,6 +60,8 @@
     // Underlying arena pool
     ArenaPool m_pool;
 
+    // The mask used to secure the recycled freelist pointers.
+    uintptr_t m_mask;
     // The recycler array is sparse with the indices being multiples of 4,
     // i.e., 0, 4, 8, 12, 16, 20, ...
     void* m_recyclers[gMaxRecycledSize >> 2];
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to