blob: 9499c915a5483a63a3148bbd39a3ad1a89603f2a [file] [log] [blame]
fpizlo@apple.coma3a6837e2016-04-07 02:02:47 +00001/*
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
ryanhaddad@apple.com22104f52016-09-28 17:08:17 +000026#pragma once
fpizlo@apple.coma3a6837e2016-04-07 02:02:47 +000027
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
38namespace JSC {
39
40#define FOR_EACH_ICEVENT_KIND(macro) \
41 macro(InvalidKind) \
fpizlo@apple.comf0e9c5d2016-04-08 19:37:04 +000042 macro(GetByIdAddAccessCase) \
43 macro(GetByIdReplaceWithJump) \
44 macro(GetByIdSelfPatch) \
45 macro(InAddAccessCase) \
46 macro(InReplaceWithJump) \
fpizlo@apple.coma3a6837e2016-04-07 02:02:47 +000047 macro(OperationGetById) \
48 macro(OperationGetByIdGeneric) \
49 macro(OperationGetByIdBuildList) \
50 macro(OperationGetByIdOptimize) \
51 macro(OperationInOptimize) \
52 macro(OperationIn) \
53 macro(OperationGenericIn) \
54 macro(OperationPutByIdStrict) \
55 macro(OperationPutByIdNonStrict) \
56 macro(OperationPutByIdDirectStrict) \
57 macro(OperationPutByIdDirectNonStrict) \
58 macro(OperationPutByIdStrictOptimize) \
59 macro(OperationPutByIdNonStrictOptimize) \
60 macro(OperationPutByIdDirectStrictOptimize) \
61 macro(OperationPutByIdDirectNonStrictOptimize) \
62 macro(OperationPutByIdStrictBuildList) \
63 macro(OperationPutByIdNonStrictBuildList) \
64 macro(OperationPutByIdDirectStrictBuildList) \
fpizlo@apple.comf0e9c5d2016-04-08 19:37:04 +000065 macro(OperationPutByIdDirectNonStrictBuildList) \
66 macro(PutByIdAddAccessCase) \
67 macro(PutByIdReplaceWithJump) \
68 macro(PutByIdSelfPatch)
fpizlo@apple.coma3a6837e2016-04-07 02:02:47 +000069
70class ICEvent {
71public:
72 enum Kind {
73#define ICEVENT_KIND_DECLARATION(name) name,
74 FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DECLARATION)
75#undef ICEVENT_KIND_DECLARATION
76 };
77
78 ICEvent()
79 {
80 }
81
82 ICEvent(Kind kind, const ClassInfo* classInfo, const Identifier propertyName)
83 : m_kind(kind)
84 , m_classInfo(classInfo)
85 , m_propertyName(propertyName)
86 {
87 }
88
89 ICEvent(WTF::HashTableDeletedValueType)
90 : m_kind(OperationGetById)
91 {
92 }
93
94 bool operator==(const ICEvent& other) const
95 {
96 return m_kind == other.m_kind
97 && m_classInfo == other.m_classInfo
98 && m_propertyName == other.m_propertyName;
99 }
100
101 bool operator!=(const ICEvent& other) const
102 {
103 return !(*this == other);
104 }
105
106 bool operator<(const ICEvent& other) const;
107 bool operator>(const ICEvent& other) const { return other < *this; }
108 bool operator<=(const ICEvent& other) const { return !(*this > other); }
109 bool operator>=(const ICEvent& other) const { return !(*this < other); }
110
111 explicit operator bool() const
112 {
113 return *this != ICEvent();
114 }
115
116 Kind kind() const { return m_kind; }
117 const ClassInfo* classInfo() const { return m_classInfo; }
118 const Identifier& propertyName() const { return m_propertyName; }
119
120 unsigned hash() const
121 {
122 return m_kind + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
123 }
124
125 bool isHashTableDeletedValue() const
126 {
127 return *this == ICEvent(WTF::HashTableDeletedValue);
128 }
129
130 void dump(PrintStream&) const;
131
132 void log() const;
133
134private:
135
136 Kind m_kind { InvalidKind };
137 const ClassInfo* m_classInfo { nullptr };
138 Identifier m_propertyName;
139};
140
141struct ICEventHash {
142 static unsigned hash(const ICEvent& key) { return key.hash(); }
143 static bool equal(const ICEvent& a, const ICEvent& b) { return a == b; }
144 static const bool safeToCompareToEmptyOrDeleted = true;
145};
146
147} // namespace JSC
148
149namespace WTF {
150
151void printInternal(PrintStream&, JSC::ICEvent::Kind);
152
153template<typename T> struct DefaultHash;
154template<> struct DefaultHash<JSC::ICEvent> {
155 typedef JSC::ICEventHash Hash;
156};
157
158template<typename T> struct HashTraits;
159template<> struct HashTraits<JSC::ICEvent> : SimpleClassHashTraits<JSC::ICEvent> {
160 static const bool emptyValueIsZero = false;
161};
162
163} // namespace WTF
164
165namespace JSC {
166
167class ICStats {
168 WTF_MAKE_NONCOPYABLE(ICStats);
169 WTF_MAKE_FAST_ALLOCATED;
170public:
171 ICStats();
172 ~ICStats();
173
174 void add(const ICEvent& event);
175
176 static ICStats& instance();
177
178private:
179
180 Spectrum<ICEvent, uint64_t> m_spectrum;
181 ThreadIdentifier m_thread;
182 Lock m_lock;
183 Condition m_condition;
184 bool m_shouldStop { false };
185
186 static Atomic<ICStats*> s_instance;
187};
188
189#define LOG_IC(arguments) do { \
190 if (Options::useICStats()) \
191 (ICEvent arguments).log(); \
192 } while (false)
193
194} // namespace JSC