eb7e1e92ce97dd1d95089727c84a9c5ec7f57c7c
[WebKit-https.git] / Source / JavaScriptCore / jit / ICStats.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include "ClassInfo.h"
29 #include "Identifier.h"
30 #include <wtf/Condition.h>
31 #include <wtf/HashTable.h>
32 #include <wtf/FastMalloc.h>
33 #include <wtf/Lock.h>
34 #include <wtf/Noncopyable.h>
35 #include <wtf/PrintStream.h>
36 #include <wtf/Spectrum.h>
37
38 namespace JSC {
39
40 #define FOR_EACH_ICEVENT_KIND(macro) \
41     macro(InvalidKind) \
42     macro(GetByIdAddAccessCase) \
43     macro(GetByIdReplaceWithJump) \
44     macro(GetByIdSelfPatch) \
45     macro(InAddAccessCase) \
46     macro(InReplaceWithJump) \
47     macro(OperationGetById) \
48     macro(OperationGetByIdGeneric) \
49     macro(OperationGetByIdBuildList) \
50     macro(OperationGetByIdOptimize) \
51     macro(OperationGetByIdWithThisOptimize) \
52     macro(OperationInOptimize) \
53     macro(OperationIn) \
54     macro(OperationGenericIn) \
55     macro(OperationPutByIdStrict) \
56     macro(OperationPutByIdNonStrict) \
57     macro(OperationPutByIdDirectStrict) \
58     macro(OperationPutByIdDirectNonStrict) \
59     macro(OperationPutByIdStrictOptimize) \
60     macro(OperationPutByIdNonStrictOptimize) \
61     macro(OperationPutByIdDirectStrictOptimize) \
62     macro(OperationPutByIdDirectNonStrictOptimize) \
63     macro(OperationPutByIdStrictBuildList) \
64     macro(OperationPutByIdNonStrictBuildList) \
65     macro(OperationPutByIdDirectStrictBuildList) \
66     macro(OperationPutByIdDirectNonStrictBuildList) \
67     macro(PutByIdAddAccessCase) \
68     macro(PutByIdReplaceWithJump) \
69     macro(PutByIdSelfPatch)
70
71 class ICEvent {
72 public:
73     enum Kind {
74 #define ICEVENT_KIND_DECLARATION(name) name,
75         FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DECLARATION)
76 #undef ICEVENT_KIND_DECLARATION
77     };
78     
79     ICEvent()
80     {
81     }
82     
83     ICEvent(Kind kind, const ClassInfo* classInfo, const Identifier propertyName)
84         : m_kind(kind)
85         , m_classInfo(classInfo)
86         , m_propertyName(propertyName)
87     {
88     }
89
90     ICEvent(WTF::HashTableDeletedValueType)
91         : m_kind(OperationGetById)
92     {
93     }
94     
95     bool operator==(const ICEvent& other) const
96     {
97         return m_kind == other.m_kind
98             && m_classInfo == other.m_classInfo
99             && m_propertyName == other.m_propertyName;
100     }
101     
102     bool operator!=(const ICEvent& other) const
103     {
104         return !(*this == other);
105     }
106     
107     bool operator<(const ICEvent& other) const;
108     bool operator>(const ICEvent& other) const { return other < *this; }
109     bool operator<=(const ICEvent& other) const { return !(*this > other); }
110     bool operator>=(const ICEvent& other) const { return !(*this < other); }
111     
112     explicit operator bool() const
113     {
114         return *this != ICEvent();
115     }
116     
117     Kind kind() const { return m_kind; }
118     const ClassInfo* classInfo() const { return m_classInfo; }
119     const Identifier& propertyName() const { return m_propertyName; }
120     
121     unsigned hash() const
122     {
123         return m_kind + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
124     }
125     
126     bool isHashTableDeletedValue() const
127     {
128         return *this == ICEvent(WTF::HashTableDeletedValue);
129     }
130     
131     void dump(PrintStream&) const;
132     
133     void log() const;
134     
135 private:
136     
137     Kind m_kind { InvalidKind };
138     const ClassInfo* m_classInfo { nullptr };
139     Identifier m_propertyName;
140 };
141
142 struct ICEventHash {
143     static unsigned hash(const ICEvent& key) { return key.hash(); }
144     static bool equal(const ICEvent& a, const ICEvent& b) { return a == b; }
145     static const bool safeToCompareToEmptyOrDeleted = true;
146 };
147
148 } // namespace JSC
149
150 namespace WTF {
151
152 void printInternal(PrintStream&, JSC::ICEvent::Kind);
153
154 template<typename T> struct DefaultHash;
155 template<> struct DefaultHash<JSC::ICEvent> {
156     typedef JSC::ICEventHash Hash;
157 };
158
159 template<typename T> struct HashTraits;
160 template<> struct HashTraits<JSC::ICEvent> : SimpleClassHashTraits<JSC::ICEvent> {
161     static const bool emptyValueIsZero = false;
162 };
163
164 } // namespace WTF
165
166 namespace JSC {
167
168 class ICStats {
169     WTF_MAKE_NONCOPYABLE(ICStats);
170     WTF_MAKE_FAST_ALLOCATED;
171 public:
172     ICStats();
173     ~ICStats();
174     
175     void add(const ICEvent& event);
176     
177     static ICStats& instance();
178     
179 private:
180
181     Spectrum<ICEvent, uint64_t> m_spectrum;
182     RefPtr<Thread> m_thread;
183     Lock m_lock;
184     Condition m_condition;
185     bool m_shouldStop { false };
186     
187     static Atomic<ICStats*> s_instance;
188 };
189
190 #define LOG_IC(arguments) do {                  \
191         if (Options::useICStats())              \
192             (ICEvent arguments).log();          \
193     } while (false)
194
195 } // namespace JSC