Title: [199140] trunk/Source
Revision
199140
Author
fpi...@apple.com
Date
2016-04-06 19:02:47 -0700 (Wed, 06 Apr 2016)

Log Message

JSC should have a simple way of gathering IC statistics
https://bugs.webkit.org/show_bug.cgi?id=156317

Reviewed by Benjamin Poulain.
Source/_javascript_Core:


This adds a cheap, runtime-enabled way of gathering statistics about why we take the slow
paths for inline caches. This is complementary to our existing bytecode profiler. Eventually
we may want to combine the two things.
        
This is not a slow-down on anything because we only do extra work on IC slow paths and if
it's disabled it's just a load-and-branch to skip the stats gathering code.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* jit/ICStats.cpp: Added.
* jit/ICStats.h: Added.
* jit/JITOperations.cpp:
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::inherits):
(JSC::JSValue::classInfoOrNull):
(JSC::JSValue::toThis):
* runtime/Options.h:

Source/WTF:

        
Make it easier to do relative sleeping on a condition. Previously you could do this using
std::chrono. I now believe that std::chrono is just a bad decision, and I always want to
use doubles instead. This makes it easier to do the right thing and use doubles.

* wtf/Condition.h:
(WTF::ConditionBase::waitUntilMonotonicClockSeconds):
(WTF::ConditionBase::waitForSeconds):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (199139 => 199140)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2016-04-07 02:02:47 UTC (rev 199140)
@@ -524,6 +524,7 @@
     jit/GCAwareJITStubRoutine.cpp
     jit/GPRInfo.cpp
     jit/HostCallReturnValue.cpp
+    jit/ICStats.cpp
     jit/IntrinsicEmitter.cpp
     jit/JIT.cpp
     jit/JITAddGenerator.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (199139 => 199140)


--- trunk/Source/_javascript_Core/ChangeLog	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-04-07 02:02:47 UTC (rev 199140)
@@ -1,5 +1,31 @@
 2016-04-06  Filip Pizlo  <fpi...@apple.com>
 
+        JSC should have a simple way of gathering IC statistics
+        https://bugs.webkit.org/show_bug.cgi?id=156317
+
+        Reviewed by Benjamin Poulain.
+
+        This adds a cheap, runtime-enabled way of gathering statistics about why we take the slow
+        paths for inline caches. This is complementary to our existing bytecode profiler. Eventually
+        we may want to combine the two things.
+        
+        This is not a slow-down on anything because we only do extra work on IC slow paths and if
+        it's disabled it's just a load-and-branch to skip the stats gathering code.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * jit/ICStats.cpp: Added.
+        * jit/ICStats.h: Added.
+        * jit/JITOperations.cpp:
+        * runtime/JSCJSValue.h:
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::inherits):
+        (JSC::JSValue::classInfoOrNull):
+        (JSC::JSValue::toThis):
+        * runtime/Options.h:
+
+2016-04-06  Filip Pizlo  <fpi...@apple.com>
+
         32-bit JSC stress/multi-put-by-offset-multiple-transitions.js failing
         https://bugs.webkit.org/show_bug.cgi?id=156292
 

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (199139 => 199140)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-04-07 02:02:47 UTC (rev 199140)
@@ -1999,6 +1999,8 @@
 		DE5A0A001BA3AC3E003D4424 /* IntrinsicEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */; };
 		DEA7E2441BBC677200D78440 /* JSTypedArrayViewPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */; };
 		DEA7E2451BBC677F00D78440 /* JSTypedArrayViewPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		DC2143071CA32E55000A8869 /* ICStats.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2143061CA32E52000A8869 /* ICStats.h */; };
+		DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC2143051CA32E52000A8869 /* ICStats.cpp */; };
 		E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; };
 		E18E3A590DF9278C00D90B34 /* VM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18E3A570DF9278C00D90B34 /* VM.cpp */; };
@@ -4198,6 +4200,8 @@
 		D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
 		D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; };
 		DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPreciseLocalClobberize.h; path = dfg/DFGPreciseLocalClobberize.h; sourceTree = "<group>"; };
+		DC2143051CA32E52000A8869 /* ICStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ICStats.cpp; sourceTree = "<group>"; };
+		DC2143061CA32E52000A8869 /* ICStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICStats.h; sourceTree = "<group>"; };
 		DC17E8131C9C7FD4008A6AB3 /* ShadowChicken.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowChicken.cpp; sourceTree = "<group>"; };
 		DC17E8141C9C7FD4008A6AB3 /* ShadowChicken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowChicken.h; sourceTree = "<group>"; };
 		DC17E8151C9C7FD4008A6AB3 /* ShadowChickenInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowChickenInlines.h; sourceTree = "<group>"; };
@@ -4994,6 +4998,8 @@
 				0F24E53F17EA9F5900ABB217 /* GPRInfo.h */,
 				0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
 				0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
+				DC2143051CA32E52000A8869 /* ICStats.cpp */,
+				DC2143061CA32E52000A8869 /* ICStats.h */,
 				DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */,
 				1429D92D0ED22D7000B89619 /* JIT.cpp */,
 				1429D92E0ED22D7000B89619 /* JIT.h */,
@@ -7924,6 +7930,7 @@
 				A5BA15EB182340B400A82E69 /* RemoteConnectionToTarget.h in Headers */,
 				A5BA15ED182340B400A82E69 /* RemoteInspectorXPCConnection.h in Headers */,
 				0F24E55117EE274900ABB217 /* Repatch.h in Headers */,
+				DC2143071CA32E55000A8869 /* ICStats.h in Headers */,
 				869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */,
 				70B0A9D11A9B66460001306A /* RuntimeFlags.h in Headers */,
 				52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */,
@@ -8849,6 +8856,7 @@
 				FE3A06B11C10CB8400390FDD /* JITBitAndGenerator.cpp in Sources */,
 				0FC09776146943B000CF2442 /* DFGOSRExitCompiler32_64.cpp in Sources */,
 				0FC0977214693AF900CF2442 /* DFGOSRExitCompiler64.cpp in Sources */,
+				DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */,
 				0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */,
 				0F392C891B46188400844728 /* DFGOSRExitFuzz.cpp in Sources */,
 				0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */,

Added: trunk/Source/_javascript_Core/jit/ICStats.cpp (0 => 199140)


--- trunk/Source/_javascript_Core/jit/ICStats.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/jit/ICStats.cpp	2016-04-07 02:02:47 UTC (rev 199140)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 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. ``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
+ * 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. 
+ */
+
+#include "config.h"
+#include "ICStats.h"
+
+namespace JSC {
+
+bool ICEvent::operator<(const ICEvent& other) const
+{
+    if (m_classInfo != other.m_classInfo) {
+        if (!m_classInfo)
+            return true;
+        if (!other.m_classInfo)
+            return false;
+        return strcmp(m_classInfo->className, other.m_classInfo->className) < 0;
+    }
+    
+    if (m_propertyName != other.m_propertyName)
+        return codePointCompare(m_propertyName.string(), other.m_propertyName.string()) < 0;
+    
+    return m_kind < other.m_kind;
+}
+
+void ICEvent::dump(PrintStream& out) const
+{
+    out.print(m_kind, "(", m_classInfo ? m_classInfo->className : "<null>", ", ", m_propertyName, ")");
+}
+
+void ICEvent::log() const
+{
+    ICStats::instance().add(*this);
+}
+
+Atomic<ICStats*> ICStats::s_instance;
+
+ICStats::ICStats()
+{
+    m_thread = createThread(
+        "JSC ICStats",
+        [this] () {
+            LockHolder locker(m_lock);
+            for (;;) {
+                m_condition.waitForSeconds(m_lock, 1, [this] () -> bool { return m_shouldStop; });
+                if (m_shouldStop)
+                    break;
+                
+                dataLog("ICStats:\n");
+                auto list = m_spectrum.buildList();
+                for (unsigned i = list.size(); i--;)
+                    dataLog("    ", list[i].key, ": ", list[i].count, "\n");
+            }
+        });
+}
+
+ICStats::~ICStats()
+{
+    {
+        LockHolder locker(m_lock);
+        m_shouldStop = true;
+        m_condition.notifyAll();
+    }
+    
+    waitForThreadCompletion(m_thread);
+}
+
+void ICStats::add(const ICEvent& event)
+{
+    m_spectrum.add(event);
+}
+
+ICStats& ICStats::instance()
+{
+    for (;;) {
+        ICStats* result = s_instance.load();
+        if (result)
+            return *result;
+        
+        ICStats* newStats = new ICStats();
+        if (s_instance.compareExchangeWeak(nullptr, newStats))
+            return *newStats;
+        
+        delete newStats;
+    }
+}
+
+} // namespace JSC
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream& out, ICEvent::Kind kind)
+{
+    switch (kind) {
+#define ICEVENT_KIND_DUMP(name) case ICEvent::name: out.print(#name); return;
+        FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DUMP);
+#undef ICEVENT_KIND_DUMP
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
+

Added: trunk/Source/_javascript_Core/jit/ICStats.h (0 => 199140)


--- trunk/Source/_javascript_Core/jit/ICStats.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/jit/ICStats.h	2016-04-07 02:02:47 UTC (rev 199140)
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2016 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. ``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
+ * 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. 
+ */
+
+#ifndef ICStats_h
+#define ICStats_h
+
+#include "ClassInfo.h"
+#include "Identifier.h"
+#include <wtf/Condition.h>
+#include <wtf/HashTable.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Lock.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PrintStream.h>
+#include <wtf/Spectrum.h>
+
+namespace JSC {
+
+#define FOR_EACH_ICEVENT_KIND(macro) \
+    macro(InvalidKind) \
+    macro(OperationGetById) \
+    macro(OperationGetByIdGeneric) \
+    macro(OperationGetByIdBuildList) \
+    macro(OperationGetByIdOptimize) \
+    macro(OperationInOptimize) \
+    macro(OperationIn) \
+    macro(OperationGenericIn) \
+    macro(OperationPutByIdStrict) \
+    macro(OperationPutByIdNonStrict) \
+    macro(OperationPutByIdDirectStrict) \
+    macro(OperationPutByIdDirectNonStrict) \
+    macro(OperationPutByIdStrictOptimize) \
+    macro(OperationPutByIdNonStrictOptimize) \
+    macro(OperationPutByIdDirectStrictOptimize) \
+    macro(OperationPutByIdDirectNonStrictOptimize) \
+    macro(OperationPutByIdStrictBuildList) \
+    macro(OperationPutByIdNonStrictBuildList) \
+    macro(OperationPutByIdDirectStrictBuildList) \
+    macro(OperationPutByIdDirectNonStrictBuildList)
+
+class ICEvent {
+public:
+    enum Kind {
+#define ICEVENT_KIND_DECLARATION(name) name,
+        FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DECLARATION)
+#undef ICEVENT_KIND_DECLARATION
+    };
+    
+    ICEvent()
+    {
+    }
+    
+    ICEvent(Kind kind, const ClassInfo* classInfo, const Identifier propertyName)
+        : m_kind(kind)
+        , m_classInfo(classInfo)
+        , m_propertyName(propertyName)
+    {
+    }
+
+    ICEvent(WTF::HashTableDeletedValueType)
+        : m_kind(OperationGetById)
+    {
+    }
+    
+    bool operator==(const ICEvent& other) const
+    {
+        return m_kind == other.m_kind
+            && m_classInfo == other.m_classInfo
+            && m_propertyName == other.m_propertyName;
+    }
+    
+    bool operator!=(const ICEvent& other) const
+    {
+        return !(*this == other);
+    }
+    
+    bool operator<(const ICEvent& other) const;
+    bool operator>(const ICEvent& other) const { return other < *this; }
+    bool operator<=(const ICEvent& other) const { return !(*this > other); }
+    bool operator>=(const ICEvent& other) const { return !(*this < other); }
+    
+    explicit operator bool() const
+    {
+        return *this != ICEvent();
+    }
+    
+    Kind kind() const { return m_kind; }
+    const ClassInfo* classInfo() const { return m_classInfo; }
+    const Identifier& propertyName() const { return m_propertyName; }
+    
+    unsigned hash() const
+    {
+        return m_kind + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
+    }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return *this == ICEvent(WTF::HashTableDeletedValue);
+    }
+    
+    void dump(PrintStream&) const;
+    
+    void log() const;
+    
+private:
+    
+    Kind m_kind { InvalidKind };
+    const ClassInfo* m_classInfo { nullptr };
+    Identifier m_propertyName;
+};
+
+struct ICEventHash {
+    static unsigned hash(const ICEvent& key) { return key.hash(); }
+    static bool equal(const ICEvent& a, const ICEvent& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream&, JSC::ICEvent::Kind);
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::ICEvent> {
+    typedef JSC::ICEventHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::ICEvent> : SimpleClassHashTraits<JSC::ICEvent> {
+    static const bool emptyValueIsZero = false;
+};
+
+} // namespace WTF
+
+namespace JSC {
+
+class ICStats {
+    WTF_MAKE_NONCOPYABLE(ICStats);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ICStats();
+    ~ICStats();
+    
+    void add(const ICEvent& event);
+    
+    static ICStats& instance();
+    
+private:
+
+    Spectrum<ICEvent, uint64_t> m_spectrum;
+    ThreadIdentifier m_thread;
+    Lock m_lock;
+    Condition m_condition;
+    bool m_shouldStop { false };
+    
+    static Atomic<ICStats*> s_instance;
+};
+
+#define LOG_IC(arguments) do {                  \
+        if (Options::useICStats())              \
+            (ICEvent arguments).log();          \
+    } while (false)
+
+} // namespace JSC
+
+#endif // ICStats_h
+

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (199139 => 199140)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-04-07 02:02:47 UTC (rev 199140)
@@ -42,6 +42,7 @@
 #include "ExceptionFuzz.h"
 #include "GetterSetter.h"
 #include "HostCallReturnValue.h"
+#include "ICStats.h"
 #include "JIT.h"
 #include "JITExceptions.h"
 #include "JITToDFGDeferredCompilationCallback.h"
@@ -54,6 +55,7 @@
 #include "JSWithScope.h"
 #include "LegacyProfiler.h"
 #include "ObjectConstructor.h"
+#include "PolymorphicAccess.h"
 #include "PropertyName.h"
 #include "Repatch.h"
 #include "ScopedArguments.h"
@@ -164,6 +166,8 @@
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
     Identifier ident = Identifier::fromUid(vm, uid);
+    
+    LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(), ident));
     return JSValue::encode(baseValue.get(exec, ident, slot));
 }
 
@@ -175,6 +179,7 @@
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
     Identifier ident = Identifier::fromUid(vm, uid);
+    LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(), ident));
     return JSValue::encode(baseValue.get(exec, ident, slot));
 }
 
@@ -185,6 +190,7 @@
     Identifier ident = Identifier::fromUid(vm, uid);
 
     JSValue baseValue = JSValue::decode(base);
+    LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(), ident));
     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
     
     bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
@@ -207,6 +213,7 @@
     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
 
     Identifier ident = Identifier::fromUid(vm, key);
+    LOG_IC((ICEvent::OperationInOptimize, base->classInfo(), ident));
     PropertySlot slot(base, PropertySlot::InternalMethodType::HasProperty);
     bool result = asObject(base)->getPropertySlot(exec, ident, slot);
     
@@ -231,6 +238,7 @@
     }
 
     Identifier ident = Identifier::fromUid(vm, key);
+    LOG_IC((ICEvent::OperationIn, base->classInfo(), ident));
     return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
 }
 
@@ -249,9 +257,12 @@
     
     stubInfo->tookSlowPath = true;
     
+    JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(vm, uid);
-    PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
-    JSValue::decode(encodedBase).putInline(exec, ident, JSValue::decode(encodedValue), slot);
+    LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(), ident));
+
+    PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
+    baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
 }
 
 void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -261,9 +272,11 @@
     
     stubInfo->tookSlowPath = true;
     
+    JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(vm, uid);
-    PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
-    JSValue::decode(encodedBase).putInline(exec, ident, JSValue::decode(encodedValue), slot);
+    LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(), ident));
+    PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
+    baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
 }
 
 void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -273,9 +286,11 @@
     
     stubInfo->tookSlowPath = true;
     
+    JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(vm, uid);
-    PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
-    asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
+    LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(), ident));
+    PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
+    asObject(baseValue)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
 }
 
 void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -285,9 +300,11 @@
     
     stubInfo->tookSlowPath = true;
     
+    JSValue baseValue = JSValue::decode(encodedBase);
     Identifier ident = Identifier::fromUid(vm, uid);
-    PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
-    asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
+    LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(), ident));
+    PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
+    asObject(baseValue)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
 }
 
 void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -300,6 +317,7 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue = JSValue::decode(encodedBase);
+    LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(), ident));
     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
@@ -322,6 +340,7 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSValue baseValue = JSValue::decode(encodedBase);
+    LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(), ident));
     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
 
     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;    
@@ -344,6 +363,7 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
+    LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(), ident));
     PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
     
     Structure* structure = baseObject->structure(*vm);
@@ -366,6 +386,7 @@
 
     JSValue value = JSValue::decode(encodedValue);
     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
+    LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(), ident));
     PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
     
     Structure* structure = baseObject->structure(*vm);

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValue.h (199139 => 199140)


--- trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2016-04-07 02:02:47 UTC (rev 199140)
@@ -241,6 +241,7 @@
     bool isCustomGetterSetter() const;
     bool isObject() const;
     bool inherits(const ClassInfo*) const;
+    const ClassInfo* classInfoOrNull() const;
         
     // Extracting the value.
     bool getString(ExecState*, WTF::String&) const;

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h (199139 => 199140)


--- trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2016-04-07 02:02:47 UTC (rev 199140)
@@ -746,6 +746,11 @@
     return isCell() && asCell()->inherits(classInfo);
 }
 
+inline const ClassInfo* JSValue::classInfoOrNull() const
+{
+    return isCell() ? asCell()->classInfo() : nullptr;
+}
+
 inline JSValue JSValue::toThis(ExecState* exec, ECMAMode ecmaMode) const
 {
     return isCell() ? asCell()->methodTable(exec->vm())->toThis(asCell(), exec, ecmaMode) : toThisSlowCase(exec, ecmaMode);

Modified: trunk/Source/_javascript_Core/runtime/Options.h (199139 => 199140)


--- trunk/Source/_javascript_Core/runtime/Options.h	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2016-04-07 02:02:47 UTC (rev 199140)
@@ -351,6 +351,8 @@
     \
     v(unsigned, watchdog, 0, "watchdog timeout (0 = Disabled, N = a timeout period of N milliseconds)") \
     \
+    v(bool, useICStats, false, nullptr) \
+    \
     v(bool, dumpModuleRecord, false, nullptr) \
     v(bool, dumpModuleLoadingState, false, nullptr) \
     v(bool, exposeInternalModuleLoader, false, "expose the internal module loader object to the global space for debugging") \

Modified: trunk/Source/WTF/ChangeLog (199139 => 199140)


--- trunk/Source/WTF/ChangeLog	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/WTF/ChangeLog	2016-04-07 02:02:47 UTC (rev 199140)
@@ -1,3 +1,18 @@
+2016-04-06  Filip Pizlo  <fpi...@apple.com>
+
+        JSC should have a simple way of gathering IC statistics
+        https://bugs.webkit.org/show_bug.cgi?id=156317
+
+        Reviewed by Benjamin Poulain.
+        
+        Make it easier to do relative sleeping on a condition. Previously you could do this using
+        std::chrono. I now believe that std::chrono is just a bad decision, and I always want to
+        use doubles instead. This makes it easier to do the right thing and use doubles.
+
+        * wtf/Condition.h:
+        (WTF::ConditionBase::waitUntilMonotonicClockSeconds):
+        (WTF::ConditionBase::waitForSeconds):
+
 2016-04-06  Simon Fraser  <simon.fra...@apple.com>
 
         Fix Windows build by converting clampToInteger() into a template that only

Modified: trunk/Source/WTF/wtf/Condition.h (199139 => 199140)


--- trunk/Source/WTF/wtf/Condition.h	2016-04-07 01:59:45 UTC (rev 199139)
+++ trunk/Source/WTF/wtf/Condition.h	2016-04-07 02:02:47 UTC (rev 199140)
@@ -141,7 +141,32 @@
     {
         return waitForSecondsImpl(lock, absoluteTimeoutSeconds - monotonicallyIncreasingTime());
     }
+    
+    template<typename LockType, typename Functor>
+    bool waitForSeconds(LockType& lock, double relativeTimeoutSeconds, const Functor& predicate)
+    {
+        double relativeTimeoutNanoseconds = relativeTimeoutSeconds * (1000.0 * 1000.0 * 1000.0);
+        
+        if (!(relativeTimeoutNanoseconds > 0)) {
+            // This handles insta-timeouts as well as NaN.
+            lock.unlock();
+            lock.lock();
+            return false;
+        }
 
+        if (relativeTimeoutNanoseconds > static_cast<double>(std::numeric_limits<int64_t>::max())) {
+            // If the timeout in nanoseconds cannot be expressed using a 64-bit integer, then we
+            // might as well wait forever.
+            wait(lock, predicate);
+            return true;
+        }
+        
+        auto relativeTimeout =
+            std::chrono::nanoseconds(static_cast<int64_t>(relativeTimeoutNanoseconds));
+
+        return waitFor(lock, relativeTimeout, predicate);
+    }
+
     // Note that this method is extremely fast when nobody is waiting. It is not necessary to try to
     // avoid calling this method.
     void notifyOne()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to