]> git.saurik.com Git - apple/javascriptcore.git/blame - profiler/ProfilerDatabase.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / profiler / ProfilerDatabase.cpp
CommitLineData
93a37866
A
1/*
2 * Copyright (C) 2012, 2013 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 "ProfilerDatabase.h"
28
29#include "CodeBlock.h"
30#include "JSONObject.h"
31#include "ObjectConstructor.h"
81345200 32#include "JSCInlines.h"
93a37866
A
33
34namespace JSC { namespace Profiler {
35
81345200
A
36static std::atomic<int> databaseCounter;
37
93a37866 38static SpinLock registrationLock = SPINLOCK_INITIALIZER;
81345200 39static std::atomic<int> didRegisterAtExit;
93a37866
A
40static Database* firstDatabase;
41
42Database::Database(VM& vm)
81345200 43 : m_databaseID(++databaseCounter)
93a37866
A
44 , m_vm(vm)
45 , m_shouldSaveAtExit(false)
46 , m_nextRegisteredDatabase(0)
47{
48}
49
50Database::~Database()
51{
52 if (m_shouldSaveAtExit) {
53 removeDatabaseFromAtExit();
54 performAtExitSave();
55 }
56}
57
58Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
59{
81345200
A
60 Locker locker(m_lock);
61
93a37866
A
62 codeBlock = codeBlock->baselineVersion();
63
64 HashMap<CodeBlock*, Bytecodes*>::iterator iter = m_bytecodesMap.find(codeBlock);
65 if (iter != m_bytecodesMap.end())
66 return iter->value;
67
68 m_bytecodes.append(Bytecodes(m_bytecodes.size(), codeBlock));
69 Bytecodes* result = &m_bytecodes.last();
70
71 m_bytecodesMap.add(codeBlock, result);
72
73 return result;
74}
75
76void Database::notifyDestruction(CodeBlock* codeBlock)
77{
81345200
A
78 Locker locker(m_lock);
79
93a37866
A
80 m_bytecodesMap.remove(codeBlock);
81}
82
81345200 83void Database::addCompilation(PassRefPtr<Compilation> compilation)
93a37866 84{
81345200
A
85 ASSERT(!isCompilationThread());
86
93a37866 87 m_compilations.append(compilation);
93a37866
A
88}
89
90JSValue Database::toJS(ExecState* exec) const
91{
92 JSObject* result = constructEmptyObject(exec);
93
94 JSArray* bytecodes = constructEmptyArray(exec, 0);
95 for (unsigned i = 0; i < m_bytecodes.size(); ++i)
96 bytecodes->putDirectIndex(exec, i, m_bytecodes[i].toJS(exec));
97 result->putDirect(exec->vm(), exec->propertyNames().bytecodes, bytecodes);
98
99 JSArray* compilations = constructEmptyArray(exec, 0);
100 for (unsigned i = 0; i < m_compilations.size(); ++i)
101 compilations->putDirectIndex(exec, i, m_compilations[i]->toJS(exec));
102 result->putDirect(exec->vm(), exec->propertyNames().compilations, compilations);
103
104 return result;
105}
106
107String Database::toJSON() const
108{
109 JSGlobalObject* globalObject = JSGlobalObject::create(
110 m_vm, JSGlobalObject::createStructure(m_vm, jsNull()));
111
112 return JSONStringify(globalObject->globalExec(), toJS(globalObject->globalExec()), 0);
113}
114
115bool Database::save(const char* filename) const
116{
81345200 117 auto out = FilePrintStream::open(filename, "w");
93a37866
A
118 if (!out)
119 return false;
120
121 out->print(toJSON());
122 return true;
123}
124
125void Database::registerToSaveAtExit(const char* filename)
126{
127 m_atExitSaveFilename = filename;
128
129 if (m_shouldSaveAtExit)
130 return;
131
132 addDatabaseToAtExit();
133 m_shouldSaveAtExit = true;
134}
135
136void Database::addDatabaseToAtExit()
137{
81345200 138 if (++didRegisterAtExit == 1)
93a37866
A
139 atexit(atExitCallback);
140
141 TCMalloc_SpinLockHolder holder(&registrationLock);
142 m_nextRegisteredDatabase = firstDatabase;
143 firstDatabase = this;
144}
145
146void Database::removeDatabaseFromAtExit()
147{
148 TCMalloc_SpinLockHolder holder(&registrationLock);
149 for (Database** current = &firstDatabase; *current; current = &(*current)->m_nextRegisteredDatabase) {
150 if (*current != this)
151 continue;
152 *current = m_nextRegisteredDatabase;
153 m_nextRegisteredDatabase = 0;
154 m_shouldSaveAtExit = false;
155 break;
156 }
157}
158
159void Database::performAtExitSave() const
160{
161 save(m_atExitSaveFilename.data());
162}
163
164Database* Database::removeFirstAtExitDatabase()
165{
166 TCMalloc_SpinLockHolder holder(&registrationLock);
167 Database* result = firstDatabase;
168 if (result) {
169 firstDatabase = result->m_nextRegisteredDatabase;
170 result->m_nextRegisteredDatabase = 0;
171 result->m_shouldSaveAtExit = false;
172 }
173 return result;
174}
175
176void Database::atExitCallback()
177{
178 while (Database* database = removeFirstAtExitDatabase())
179 database->performAtExitSave();
180}
181
182} } // namespace JSC::Profiler
183