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()