Title: [244204] trunk
Revision
244204
Author
msab...@apple.com
Date
2019-04-11 17:53:12 -0700 (Thu, 11 Apr 2019)

Log Message

Improve the Inline Cache Stats code
https://bugs.webkit.org/show_bug.cgi?id=196836

Reviewed by Saam Barati.

Source/_javascript_Core:

Needed to handle the case where the Identifier could be null, for example with InstanceOfAddAccessCase
and InstanceOfReplaceWithJump.

Added the ability to log the location of a GetBy and PutBy property as either on self or up the
protocol chain.

* jit/ICStats.cpp:
(JSC::ICEvent::operator< const):
(JSC::ICEvent::dump const):
* jit/ICStats.h:
(JSC::ICEvent::ICEvent):
(JSC::ICEvent::hash const):
* jit/JITOperations.cpp:
* jit/Repatch.cpp:
(JSC::tryCacheGetByID):
(JSC::tryCachePutByID):
(JSC::tryCacheInByID):

Tools:

Added a new script to consolidate and arrange the output of --useICStats option.

This script merges the output from every group into one large table and sorts it from most common to
least common.  It also counts the slow path GetById and PutById variants and then calculates the
percentage of gets or puts for each unique base,property pair compared to all the gets and puts.
Put together, this is useful to see what property accesses are not getting cached.

* Scripts/ic-stats.py: Added.
(ICStats):
(ICStats.__init__):
(ICStats.parse):
(ICStats.dumpStats):
(usage):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (244203 => 244204)


--- trunk/Source/_javascript_Core/ChangeLog	2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-04-12 00:53:12 UTC (rev 244204)
@@ -1,3 +1,28 @@
+2019-04-11  Michael Saboff  <msab...@apple.com>
+
+        Improve the Inline Cache Stats code
+        https://bugs.webkit.org/show_bug.cgi?id=196836
+
+        Reviewed by Saam Barati.
+
+        Needed to handle the case where the Identifier could be null, for example with InstanceOfAddAccessCase
+        and InstanceOfReplaceWithJump.
+
+        Added the ability to log the location of a GetBy and PutBy property as either on self or up the
+        protocol chain.
+
+        * jit/ICStats.cpp:
+        (JSC::ICEvent::operator< const):
+        (JSC::ICEvent::dump const):
+        * jit/ICStats.h:
+        (JSC::ICEvent::ICEvent):
+        (JSC::ICEvent::hash const):
+        * jit/JITOperations.cpp:
+        * jit/Repatch.cpp:
+        (JSC::tryCacheGetByID):
+        (JSC::tryCachePutByID):
+        (JSC::tryCacheInByID):
+
 2019-04-11  Devin Rousso  <drou...@apple.com>
 
         Web Inspector: Timelines: can't reliably stop/start a recording

Modified: trunk/Source/_javascript_Core/jit/ICStats.cpp (244203 => 244204)


--- trunk/Source/_javascript_Core/jit/ICStats.cpp	2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/ICStats.cpp	2019-04-12 00:53:12 UTC (rev 244204)
@@ -40,13 +40,18 @@
     
     if (m_propertyName != other.m_propertyName)
         return codePointCompare(m_propertyName.string(), other.m_propertyName.string()) < 0;
-    
-    return m_kind < other.m_kind;
+
+    if (m_kind != other.m_kind)
+        return m_kind < other.m_kind;
+
+    return m_propertyLocation < other.m_propertyLocation;
 }
 
 void ICEvent::dump(PrintStream& out) const
 {
     out.print(m_kind, "(", m_classInfo ? m_classInfo->className : "<null>", ", ", m_propertyName, ")");
+    if (m_propertyLocation != Unknown)
+        out.print(m_propertyLocation == BaseObject ? " self" : " proto lookup");
 }
 
 void ICEvent::log() const

Modified: trunk/Source/_javascript_Core/jit/ICStats.h (244203 => 244204)


--- trunk/Source/_javascript_Core/jit/ICStats.h	2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/ICStats.h	2019-04-12 00:53:12 UTC (rev 244204)
@@ -78,7 +78,13 @@
         FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DECLARATION)
 #undef ICEVENT_KIND_DECLARATION
     };
-    
+
+    enum PropertyLocation {
+        Unknown,
+        BaseObject,
+        ProtoLookup
+    };
+
     ICEvent()
     {
     }
@@ -87,9 +93,18 @@
         : m_kind(kind)
         , m_classInfo(classInfo)
         , m_propertyName(propertyName)
+        , m_propertyLocation(Unknown)
     {
     }
 
+    ICEvent(Kind kind, const ClassInfo* classInfo, const Identifier propertyName, bool isBaseProperty)
+        : m_kind(kind)
+        , m_classInfo(classInfo)
+        , m_propertyName(propertyName)
+        , m_propertyLocation(isBaseProperty ? BaseObject : ProtoLookup)
+    {
+    }
+    
     ICEvent(WTF::HashTableDeletedValueType)
         : m_kind(OperationGetById)
     {
@@ -123,7 +138,9 @@
     
     unsigned hash() const
     {
-        return m_kind + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
+        if (m_propertyName.isNull())
+            return m_kind + m_propertyLocation + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo);
+        return m_kind + m_propertyLocation + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
     }
     
     bool isHashTableDeletedValue() const
@@ -140,6 +157,7 @@
     Kind m_kind { InvalidKind };
     const ClassInfo* m_classInfo { nullptr };
     Identifier m_propertyName;
+    PropertyLocation m_propertyLocation;
 };
 
 struct ICEventHash {

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (244203 => 244204)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2019-04-12 00:53:12 UTC (rev 244204)
@@ -252,9 +252,11 @@
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
     Identifier ident = Identifier::fromUid(vm, uid);
-    
-    LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(*vm), ident));
-    return JSValue::encode(baseValue.get(exec, ident, slot));
+    JSValue result = baseValue.get(exec, ident, slot);
+
+    LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+
+    return JSValue::encode(result);
 }
 
 EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
@@ -267,8 +269,11 @@
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
     Identifier ident = Identifier::fromUid(vm, uid);
-    LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(*vm), ident));
-    return JSValue::encode(baseValue.get(exec, ident, slot));
+    JSValue result = baseValue.get(exec, ident, slot);
+    
+    LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+    
+    return JSValue::encode(result);
 }
 
 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
@@ -280,9 +285,11 @@
     Identifier ident = Identifier::fromUid(vm, uid);
 
     JSValue baseValue = JSValue::decode(base);
-    LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(*vm), ident));
 
     return JSValue::encode(baseValue.getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
+        
+        LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+        
         if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
             repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
         return found ? slot.getValue(exec, ident) : jsUndefined();
@@ -331,10 +338,11 @@
 
     JSValue baseValue = JSValue::decode(base);
     JSValue thisValue = JSValue::decode(thisEncoded);
-    LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(*vm), ident));
 
     PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
     return JSValue::encode(baseValue.getPropertySlot(exec, ident, slot, [&] (bool found, PropertySlot& slot) -> JSValue {
+        LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+        
         if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
             repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::WithThis);
         return found ? slot.getValue(exec, ident) : jsUndefined();
@@ -439,10 +447,10 @@
     
     JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(vm, uid);
-    LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(*vm), ident));
-
     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
     baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
+    
+    LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
 }
 
 void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -456,9 +464,10 @@
     
     JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(vm, uid);
-    LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(*vm), ident));
     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
     baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
+
+    LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
 }
 
 void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -472,9 +481,10 @@
     
     JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(&vm, uid);
-    LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(vm), ident));
     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
     CommonSlowPaths::putDirectWithReify(vm, exec, asObject(baseValue), ident, JSValue::decode(encodedValue), slot);
+
+    LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(vm), ident, slot.base() == baseValue));
 }
 
 void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -488,9 +498,10 @@
     
     JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(&vm, uid);
-    LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(vm), ident));
     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
     CommonSlowPaths::putDirectWithReify(vm, exec, asObject(baseValue), ident, JSValue::decode(encodedValue), slot);
+
+    LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(vm), ident, slot.base() == baseValue));
 }
 
 void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -506,12 +517,14 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue = JSValue::decode(encodedBase);
-    LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(*vm), ident));
     CodeBlock* codeBlock = exec->codeBlock();
     PutPropertySlot slot(baseValue, true, codeBlock->putByIdContext());
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
     baseValue.putInline(exec, ident, value, slot);
+
+    LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
+
     RETURN_IF_EXCEPTION(scope, void());
 
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
@@ -534,12 +547,14 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue = JSValue::decode(encodedBase);
-    LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(*vm), ident));
     CodeBlock* codeBlock = exec->codeBlock();
     PutPropertySlot slot(baseValue, false, codeBlock->putByIdContext());
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;    
     baseValue.putInline(exec, ident, value, slot);
+
+    LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
+
     RETURN_IF_EXCEPTION(scope, void());
 
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
@@ -562,11 +577,13 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
-    LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(vm), ident));
     CodeBlock* codeBlock = exec->codeBlock();
     PutPropertySlot slot(baseObject, true, codeBlock->putByIdContext());
     Structure* structure = nullptr;
     CommonSlowPaths::putDirectWithReify(vm, exec, baseObject, ident, value, slot, &structure);
+
+    LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(vm), ident, slot.base() == baseObject));
+
     RETURN_IF_EXCEPTION(scope, void());
     
     if (accessType != static_cast<AccessType>(stubInfo->accessType))
@@ -589,11 +606,13 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
-    LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(vm), ident));
     CodeBlock* codeBlock = exec->codeBlock();
     PutPropertySlot slot(baseObject, false, codeBlock->putByIdContext());
     Structure* structure = nullptr;
     CommonSlowPaths::putDirectWithReify(vm, exec, baseObject, ident, value, slot, &structure);
+
+    LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(vm), ident, slot.base() == baseObject));
+
     RETURN_IF_EXCEPTION(scope, void());
     
     if (accessType != static_cast<AccessType>(stubInfo->accessType))

Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (244203 => 244204)


--- trunk/Source/_javascript_Core/jit/Repatch.cpp	2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp	2019-04-12 00:53:12 UTC (rev 244204)
@@ -267,7 +267,7 @@
 
                 bool generatedCodeInline = InlineAccess::generateSelfPropertyAccess(stubInfo, structure, slot.cachedOffset());
                 if (generatedCodeInline) {
-                    LOG_IC((ICEvent::GetByIdSelfPatch, structure->classInfo(), propertyName));
+                    LOG_IC((ICEvent::GetByIdSelfPatch, structure->classInfo(), propertyName, slot.slotBase() == baseValue));
                     structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
                     ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
                     stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
@@ -376,12 +376,12 @@
             }
         }
 
-        LOG_IC((ICEvent::GetByIdAddAccessCase, baseValue.classInfoOrNull(vm), propertyName));
+        LOG_IC((ICEvent::GetByIdAddAccessCase, baseValue.classInfoOrNull(vm), propertyName, slot.slotBase() == baseValue));
 
         result = stubInfo.addAccessCase(locker, codeBlock, propertyName, WTFMove(newCase));
 
         if (result.generatedSomeCode()) {
-            LOG_IC((ICEvent::GetByIdReplaceWithJump, baseValue.classInfoOrNull(vm), propertyName));
+            LOG_IC((ICEvent::GetByIdReplaceWithJump, baseValue.classInfoOrNull(vm), propertyName, slot.slotBase() == baseValue));
             
             RELEASE_ASSERT(result.code());
             InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
@@ -475,7 +475,7 @@
                     
                     bool generatedCodeInline = InlineAccess::generateSelfPropertyReplace(stubInfo, structure, slot.cachedOffset());
                     if (generatedCodeInline) {
-                        LOG_IC((ICEvent::PutByIdSelfPatch, structure->classInfo(), ident));
+                        LOG_IC((ICEvent::PutByIdSelfPatch, structure->classInfo(), ident, slot.base() == baseValue));
                         ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingPutByIdFunction(slot, putKind));
                         stubInfo.initPutByIdReplace(codeBlock, structure, slot.cachedOffset());
                         return RetryCacheLater;
@@ -588,12 +588,12 @@
             }
         }
 
-        LOG_IC((ICEvent::PutByIdAddAccessCase, structure->classInfo(), ident));
+        LOG_IC((ICEvent::PutByIdAddAccessCase, structure->classInfo(), ident, slot.base() == baseValue));
         
         result = stubInfo.addAccessCase(locker, codeBlock, ident, WTFMove(newCase));
 
         if (result.generatedSomeCode()) {
-            LOG_IC((ICEvent::PutByIdReplaceWithJump, structure->classInfo(), ident));
+            LOG_IC((ICEvent::PutByIdReplaceWithJump, structure->classInfo(), ident, slot.base() == baseValue));
             
             RELEASE_ASSERT(result.code());
 
@@ -654,7 +654,7 @@
                 && !structure->needImpurePropertyWatchpoint()) {
                 bool generatedCodeInline = InlineAccess::generateSelfInAccess(stubInfo, structure);
                 if (generatedCodeInline) {
-                    LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident));
+                    LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident, slot.slotBase() == base));
                     structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
                     ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInByIdOptimize);
                     stubInfo.initInByIdSelf(codeBlock, structure, slot.cachedOffset());
@@ -692,7 +692,7 @@
         if (!conditionSet.isValid())
             return GiveUpOnCache;
 
-        LOG_IC((ICEvent::InAddAccessCase, structure->classInfo(), ident));
+        LOG_IC((ICEvent::InAddAccessCase, structure->classInfo(), ident, slot.slotBase() == base));
 
         std::unique_ptr<AccessCase> newCase = AccessCase::create(
             vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, wasFound ? slot.cachedOffset() : invalidOffset, structure, conditionSet, WTFMove(prototypeAccessChain));
@@ -700,7 +700,7 @@
         result = stubInfo.addAccessCase(locker, codeBlock, ident, WTFMove(newCase));
 
         if (result.generatedSomeCode()) {
-            LOG_IC((ICEvent::InReplaceWithJump, structure->classInfo(), ident));
+            LOG_IC((ICEvent::InReplaceWithJump, structure->classInfo(), ident, slot.slotBase() == base));
             
             RELEASE_ASSERT(result.code());
             InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));

Modified: trunk/Tools/ChangeLog (244203 => 244204)


--- trunk/Tools/ChangeLog	2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Tools/ChangeLog	2019-04-12 00:53:12 UTC (rev 244204)
@@ -1,3 +1,24 @@
+2019-04-11  Michael Saboff  <msab...@apple.com>
+
+        Improve the Inline Cache Stats code
+        https://bugs.webkit.org/show_bug.cgi?id=196836
+
+        Reviewed by Saam Barati.
+
+        Added a new script to consolidate and arrange the output of --useICStats option.
+
+        This script merges the output from every group into one large table and sorts it from most common to
+        least common.  It also counts the slow path GetById and PutById variants and then calculates the
+        percentage of gets or puts for each unique base,property pair compared to all the gets and puts.
+        Put together, this is useful to see what property accesses are not getting cached.
+
+        * Scripts/ic-stats.py: Added.
+        (ICStats):
+        (ICStats.__init__):
+        (ICStats.parse):
+        (ICStats.dumpStats):
+        (usage):
+
 2019-04-10  Alex Christensen  <achristen...@webkit.org>
 
         WKNavigationResponse._downloadAttribute should be nil when no download attribute is present

Added: trunk/Tools/Scripts/ic-stats.py (0 => 244204)


--- trunk/Tools/Scripts/ic-stats.py	                        (rev 0)
+++ trunk/Tools/Scripts/ic-stats.py	2019-04-12 00:53:12 UTC (rev 244204)
@@ -0,0 +1,125 @@
+#! /usr/bin/python
+
+# Copyright (C) 2019 Apple 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:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. 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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+
+import re
+import sys
+
+icStatRecord = re.compile(" +(\w+)\(([^,]+), ([^)]+)\)([^:]*): (\d+)")
+getByIdPrefix = "OperationGetById"
+putByIdPrefix = "OperationPutById"
+
+
+class ICStats:
+    def __init__(self):
+        self.combinedRecords = {}
+        self.slowGetById = {}
+        self.slowPutById = {}
+        self.totalSlowGetById = 0
+        self.totalSlowPutById = 0
+
+    def parse(self, file):
+        for line in file:
+            match = re.match(icStatRecord, line)
+            if match:
+                operation = match.group(1)
+                base = match.group(2)
+                property = match.group(3)
+                location = match.group(4).strip()
+                count = int(match.group(5))
+                recordKey = (operation, base, property, location)
+
+                if recordKey not in self.combinedRecords:
+                    self.combinedRecords[recordKey] = count
+                else:
+                    self.combinedRecords[recordKey] += count
+
+                if operation.startswith(getByIdPrefix):
+                    self.totalSlowGetById += count
+
+                    slowGetByIdKey = (base, property)
+                    if slowGetByIdKey not in self.slowGetById:
+                        self.slowGetById[slowGetByIdKey] = count
+                    else:
+                        self.slowGetById[slowGetByIdKey] += count
+
+                elif operation.startswith(putByIdPrefix):
+                    self.totalSlowPutById += count
+
+                    slowPutByIdKey = (base, property)
+                    if slowPutByIdKey not in self.slowPutById:
+                        self.slowPutById[slowPutByIdKey] = count
+                    else:
+                        self.slowPutById[slowPutByIdKey] += count
+
+    def dumpStats(self):
+        print "Total Slow getById = {0:>13,d}".format(self.totalSlowGetById)
+        print "Total Slow putById = {0:>13,d}".format(self.totalSlowPutById)
+
+        print "Operation                            Base                  Property                              Location          Count  % tot"
+        print "-----------------------------------  --------------------  ------------------------------------  ------------  ---------   slow"
+
+        keys = sorted(self.combinedRecords.keys(), key=lambda t: self.combinedRecords[t], reverse=True)
+        for key in keys:
+            count = self.combinedRecords[key]
+            operation = key[0]
+            base = key[1]
+            property = key[2]
+
+            if operation.startswith(getByIdPrefix):
+                slowPercent = "  {0:>4.1f}%".format(float(self.slowGetById[(base, property)] * 100) / float(self.totalSlowGetById))
+            elif operation.startswith(putByIdPrefix):
+                slowPercent = "  {0:>4.1f}%".format(float(self.slowPutById[(base, property)] * 100) / float(self.totalSlowPutById))
+            else:
+                slowPercent = ""
+
+            if len(property) > 36:
+                property = property[0:32] + "..."
+
+            print "{0:35}  {1:20}  {2:36}  {3:12}  {4:>9d}{5}".format(operation[0:34], base, property, key[3], count, slowPercent)
+
+
+def usage():
+    print "Usage: {0} [ic-stats-file]".format(sys.argv[0])
+    print "        Where <ic-stats-file> is the results of using the useICStats option."
+    exit(1)
+
+if __name__ == "__main__":
+    if len(sys.argv) > 1:
+        if sys.argv[1] == "-h" or sys.argv[1].lower() == "--help" or sys.argv[1] == "-?":
+            usage()
+        try:
+            file = open(sys.argv[1], "r")
+        except IOError as e:
+            print "Couldn't open {0}, {1}".format(sys.argv[1], e.strerror)
+            usage()
+        except:
+            print "Unexpected error:", sys.exc_info()[0]
+            usage()
+    else:
+        file = sys.stdin
+
+    icStats = ICStats()
+    icStats.parse(file)
+    icStats.dumpStats()
Property changes on: trunk/Tools/Scripts/ic-stats.py
___________________________________________________________________

Added: svn:executable

+* \ No newline at end of property
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to