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 | #include "config.h" |
27 | #include "ICStats.h" |
28 | |
29 | namespace JSC { |
30 | |
31 | bool ICEvent::operator<(const ICEvent& other) const |
32 | { |
33 | if (m_classInfo != other.m_classInfo) { |
34 | if (!m_classInfo) |
35 | return true; |
36 | if (!other.m_classInfo) |
37 | return false; |
38 | return strcmp(m_classInfo->className, other.m_classInfo->className) < 0; |
39 | } |
40 | |
41 | if (m_propertyName != other.m_propertyName) |
42 | return codePointCompare(m_propertyName.string(), other.m_propertyName.string()) < 0; |
43 | |
44 | if (m_kind != other.m_kind) |
45 | return m_kind < other.m_kind; |
46 | |
47 | return m_propertyLocation < other.m_propertyLocation; |
48 | } |
49 | |
50 | void ICEvent::dump(PrintStream& out) const |
51 | { |
52 | out.print(m_kind, "(" , m_classInfo ? m_classInfo->className : "<null>" , ", " , m_propertyName, ")" ); |
53 | if (m_propertyLocation != Unknown) |
54 | out.print(m_propertyLocation == BaseObject ? " self" : " proto lookup" ); |
55 | } |
56 | |
57 | void ICEvent::log() const |
58 | { |
59 | ICStats::instance().add(*this); |
60 | } |
61 | |
62 | Atomic<ICStats*> ICStats::s_instance; |
63 | |
64 | ICStats::ICStats() |
65 | { |
66 | m_thread = Thread::create( |
67 | "JSC ICStats" , |
68 | [this] () { |
69 | LockHolder locker(m_lock); |
70 | for (;;) { |
71 | m_condition.waitFor( |
72 | m_lock, Seconds(1), [this] () -> bool { return m_shouldStop; }); |
73 | if (m_shouldStop) |
74 | break; |
75 | |
76 | dataLog("ICStats:\n" ); |
77 | auto list = m_spectrum.buildList(); |
78 | for (unsigned i = list.size(); i--;) |
79 | dataLog(" " , list[i].key, ": " , list[i].count, "\n" ); |
80 | } |
81 | }); |
82 | } |
83 | |
84 | ICStats::~ICStats() |
85 | { |
86 | { |
87 | LockHolder locker(m_lock); |
88 | m_shouldStop = true; |
89 | m_condition.notifyAll(); |
90 | } |
91 | |
92 | m_thread->waitForCompletion(); |
93 | } |
94 | |
95 | void ICStats::add(const ICEvent& event) |
96 | { |
97 | m_spectrum.add(event); |
98 | } |
99 | |
100 | ICStats& ICStats::instance() |
101 | { |
102 | for (;;) { |
103 | ICStats* result = s_instance.load(); |
104 | if (result) |
105 | return *result; |
106 | |
107 | ICStats* newStats = new ICStats(); |
108 | if (s_instance.compareExchangeWeak(nullptr, newStats)) |
109 | return *newStats; |
110 | |
111 | delete newStats; |
112 | } |
113 | } |
114 | |
115 | } // namespace JSC |
116 | |
117 | namespace WTF { |
118 | |
119 | using namespace JSC; |
120 | |
121 | void printInternal(PrintStream& out, ICEvent::Kind kind) |
122 | { |
123 | switch (kind) { |
124 | #define ICEVENT_KIND_DUMP(name) case ICEvent::name: out.print(#name); return; |
125 | FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DUMP); |
126 | #undef ICEVENT_KIND_DUMP |
127 | } |
128 | RELEASE_ASSERT_NOT_REACHED(); |
129 | } |
130 | |
131 | } // namespace WTF |
132 | |
133 | |
134 | |