2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "ProfilerCompilation.h"
29 #include "JSGlobalObject.h"
30 #include "ObjectConstructor.h"
31 #include "JSCInlines.h"
32 #include "ProfilerDatabase.h"
33 #include "Watchpoint.h"
34 #include <wtf/StringPrintStream.h>
36 namespace JSC
{ namespace Profiler
{
38 Compilation::Compilation(Bytecodes
* bytecodes
, CompilationKind kind
)
39 : m_bytecodes(bytecodes
)
41 , m_jettisonReason(NotJettisoned
)
42 , m_numInlinedGetByIds(0)
43 , m_numInlinedPutByIds(0)
44 , m_numInlinedCalls(0)
48 Compilation::~Compilation() { }
50 void Compilation::addProfiledBytecodes(Database
& database
, CodeBlock
* profiledBlock
)
52 Bytecodes
* bytecodes
= database
.ensureBytecodesFor(profiledBlock
);
54 // First make sure that we haven't already added profiled bytecodes for this code
55 // block. We do this using an O(N) search because I suspect that this list will
56 // tend to be fairly small, and the additional space costs of having a HashMap/Set
57 // would be greater than the time cost of occasionally doing this search.
59 for (unsigned i
= m_profiledBytecodes
.size(); i
--;) {
60 if (m_profiledBytecodes
[i
].bytecodes() == bytecodes
)
64 m_profiledBytecodes
.append(ProfiledBytecodes(bytecodes
, profiledBlock
));
67 void Compilation::addDescription(const CompiledBytecode
& compiledBytecode
)
69 m_descriptions
.append(compiledBytecode
);
72 void Compilation::addDescription(const OriginStack
& stack
, const CString
& description
)
74 addDescription(CompiledBytecode(stack
, description
));
77 ExecutionCounter
* Compilation::executionCounterFor(const OriginStack
& origin
)
79 std::unique_ptr
<ExecutionCounter
>& counter
= m_counters
.add(origin
, nullptr).iterator
->value
;
81 counter
= std::make_unique
<ExecutionCounter
>();
86 void Compilation::addOSRExitSite(const Vector
<const void*>& codeAddresses
)
88 m_osrExitSites
.append(OSRExitSite(codeAddresses
));
91 OSRExit
* Compilation::addOSRExit(unsigned id
, const OriginStack
& originStack
, ExitKind exitKind
, bool isWatchpoint
)
93 m_osrExits
.append(OSRExit(id
, originStack
, exitKind
, isWatchpoint
));
94 return &m_osrExits
.last();
97 void Compilation::setJettisonReason(JettisonReason jettisonReason
, const FireDetail
* detail
)
99 if (m_jettisonReason
!= NotJettisoned
)
100 return; // We only care about the original jettison reason.
102 m_jettisonReason
= jettisonReason
;
104 m_additionalJettisonReason
= toCString(*detail
);
106 m_additionalJettisonReason
= CString();
109 JSValue
Compilation::toJS(ExecState
* exec
) const
111 JSObject
* result
= constructEmptyObject(exec
);
113 result
->putDirect(exec
->vm(), exec
->propertyNames().bytecodesID
, jsNumber(m_bytecodes
->id()));
114 result
->putDirect(exec
->vm(), exec
->propertyNames().compilationKind
, jsString(exec
, String::fromUTF8(toCString(m_kind
))));
116 JSArray
* profiledBytecodes
= constructEmptyArray(exec
, 0);
117 for (unsigned i
= 0; i
< m_profiledBytecodes
.size(); ++i
)
118 profiledBytecodes
->putDirectIndex(exec
, i
, m_profiledBytecodes
[i
].toJS(exec
));
119 result
->putDirect(exec
->vm(), exec
->propertyNames().profiledBytecodes
, profiledBytecodes
);
121 JSArray
* descriptions
= constructEmptyArray(exec
, 0);
122 for (unsigned i
= 0; i
< m_descriptions
.size(); ++i
)
123 descriptions
->putDirectIndex(exec
, i
, m_descriptions
[i
].toJS(exec
));
124 result
->putDirect(exec
->vm(), exec
->propertyNames().descriptions
, descriptions
);
126 JSArray
* counters
= constructEmptyArray(exec
, 0);
127 for (auto it
= m_counters
.begin(), end
= m_counters
.end(); it
!= end
; ++it
) {
128 JSObject
* counterEntry
= constructEmptyObject(exec
);
129 counterEntry
->putDirect(exec
->vm(), exec
->propertyNames().origin
, it
->key
.toJS(exec
));
130 counterEntry
->putDirect(exec
->vm(), exec
->propertyNames().executionCount
, jsNumber(it
->value
->count()));
131 counters
->push(exec
, counterEntry
);
133 result
->putDirect(exec
->vm(), exec
->propertyNames().counters
, counters
);
135 JSArray
* exitSites
= constructEmptyArray(exec
, 0);
136 for (unsigned i
= 0; i
< m_osrExitSites
.size(); ++i
)
137 exitSites
->putDirectIndex(exec
, i
, m_osrExitSites
[i
].toJS(exec
));
138 result
->putDirect(exec
->vm(), exec
->propertyNames().osrExitSites
, exitSites
);
140 JSArray
* exits
= constructEmptyArray(exec
, 0);
141 for (unsigned i
= 0; i
< m_osrExits
.size(); ++i
)
142 exits
->putDirectIndex(exec
, i
, m_osrExits
[i
].toJS(exec
));
143 result
->putDirect(exec
->vm(), exec
->propertyNames().osrExits
, exits
);
145 result
->putDirect(exec
->vm(), exec
->propertyNames().numInlinedGetByIds
, jsNumber(m_numInlinedGetByIds
));
146 result
->putDirect(exec
->vm(), exec
->propertyNames().numInlinedPutByIds
, jsNumber(m_numInlinedPutByIds
));
147 result
->putDirect(exec
->vm(), exec
->propertyNames().numInlinedCalls
, jsNumber(m_numInlinedCalls
));
148 result
->putDirect(exec
->vm(), exec
->propertyNames().jettisonReason
, jsString(exec
, String::fromUTF8(toCString(m_jettisonReason
))));
149 if (!m_additionalJettisonReason
.isNull())
150 result
->putDirect(exec
->vm(), exec
->propertyNames().additionalJettisonReason
, jsString(exec
, String::fromUTF8(m_additionalJettisonReason
)));
155 } } // namespace JSC::Profiler