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