|
1 /* |
|
2 * Copyright (C) 2008 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 * |
|
8 * 1. Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * 2. Redistributions in binary form must reproduce the above copyright |
|
11 * notice, this list of conditions and the following disclaimer in the |
|
12 * documentation and/or other materials provided with the distribution. |
|
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
|
14 * its contributors may be used to endorse or promote products derived |
|
15 * from this software without specific prior written permission. |
|
16 * |
|
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
|
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #include "config.h" |
|
30 #include "JSGlobalData.h" |
|
31 |
|
32 #include "ArgList.h" |
|
33 #include "Collector.h" |
|
34 #include "CommonIdentifiers.h" |
|
35 #include "FunctionConstructor.h" |
|
36 #include "GetterSetter.h" |
|
37 #include "Interpreter.h" |
|
38 #include "JSActivation.h" |
|
39 #include "JSAPIValueWrapper.h" |
|
40 #include "JSArray.h" |
|
41 #include "JSByteArray.h" |
|
42 #include "JSClassRef.h" |
|
43 #include "JSFunction.h" |
|
44 #include "JSLock.h" |
|
45 #include "JSNotAnObject.h" |
|
46 #include "JSPropertyNameIterator.h" |
|
47 #include "JSStaticScopeObject.h" |
|
48 #include "Lexer.h" |
|
49 #include "Lookup.h" |
|
50 #include "Nodes.h" |
|
51 #include "Parser.h" |
|
52 #include "RegExpCache.h" |
|
53 #include <wtf/WTFThreadData.h> |
|
54 |
|
55 #if ENABLE(JSC_MULTIPLE_THREADS) |
|
56 #include <wtf/Threading.h> |
|
57 #endif |
|
58 |
|
59 #if PLATFORM(MAC) |
|
60 #include "ProfilerServer.h" |
|
61 #include <CoreFoundation/CoreFoundation.h> |
|
62 #endif |
|
63 |
|
64 using namespace WTF; |
|
65 |
|
66 namespace JSC { |
|
67 |
|
68 extern JSC_CONST_HASHTABLE HashTable arrayTable; |
|
69 extern JSC_CONST_HASHTABLE HashTable jsonTable; |
|
70 extern JSC_CONST_HASHTABLE HashTable dateTable; |
|
71 extern JSC_CONST_HASHTABLE HashTable mathTable; |
|
72 extern JSC_CONST_HASHTABLE HashTable numberTable; |
|
73 extern JSC_CONST_HASHTABLE HashTable regExpTable; |
|
74 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable; |
|
75 extern JSC_CONST_HASHTABLE HashTable stringTable; |
|
76 |
|
77 void* JSGlobalData::jsArrayVPtr; |
|
78 void* JSGlobalData::jsByteArrayVPtr; |
|
79 void* JSGlobalData::jsStringVPtr; |
|
80 void* JSGlobalData::jsFunctionVPtr; |
|
81 |
|
82 void JSGlobalData::storeVPtrs() |
|
83 { |
|
84 CollectorCell cell; |
|
85 void* storage = &cell; |
|
86 |
|
87 COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell); |
|
88 JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull())); |
|
89 JSGlobalData::jsArrayVPtr = jsArray->vptr(); |
|
90 jsArray->~JSCell(); |
|
91 |
|
92 COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell); |
|
93 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); |
|
94 JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr(); |
|
95 jsByteArray->~JSCell(); |
|
96 |
|
97 COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell); |
|
98 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); |
|
99 JSGlobalData::jsStringVPtr = jsString->vptr(); |
|
100 jsString->~JSCell(); |
|
101 |
|
102 COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell); |
|
103 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); |
|
104 JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); |
|
105 jsFunction->~JSCell(); |
|
106 } |
|
107 |
|
108 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType) |
|
109 : globalDataType(globalDataType) |
|
110 , clientData(0) |
|
111 , arrayTable(fastNew<HashTable>(JSC::arrayTable)) |
|
112 , dateTable(fastNew<HashTable>(JSC::dateTable)) |
|
113 , jsonTable(fastNew<HashTable>(JSC::jsonTable)) |
|
114 , mathTable(fastNew<HashTable>(JSC::mathTable)) |
|
115 , numberTable(fastNew<HashTable>(JSC::numberTable)) |
|
116 , regExpTable(fastNew<HashTable>(JSC::regExpTable)) |
|
117 , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) |
|
118 , stringTable(fastNew<HashTable>(JSC::stringTable)) |
|
119 , activationStructure(JSActivation::createStructure(jsNull())) |
|
120 , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull())) |
|
121 , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull())) |
|
122 , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) |
|
123 , stringStructure(JSString::createStructure(jsNull())) |
|
124 , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) |
|
125 , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) |
|
126 , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull())) |
|
127 , getterSetterStructure(GetterSetter::createStructure(jsNull())) |
|
128 , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) |
|
129 , dummyMarkableCellStructure(JSCell::createDummyStructure()) |
|
130 #if USE(JSVALUE32) |
|
131 , numberStructure(JSNumberCell::createStructure(jsNull())) |
|
132 #endif |
|
133 , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) |
|
134 , propertyNames(new CommonIdentifiers(this)) |
|
135 , emptyList(new MarkedArgumentBuffer) |
|
136 , lexer(new Lexer(this)) |
|
137 , parser(new Parser) |
|
138 , interpreter(new Interpreter) |
|
139 , heap(this) |
|
140 , head(0) |
|
141 , dynamicGlobalObject(0) |
|
142 , functionCodeBlockBeingReparsed(0) |
|
143 , firstStringifierToMark(0) |
|
144 , markStack(jsArrayVPtr) |
|
145 , cachedUTCOffset(NaN) |
|
146 , weakRandom(static_cast<int>(currentTime())) |
|
147 , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) |
|
148 , m_regExpCache(new RegExpCache(this)) |
|
149 #ifndef NDEBUG |
|
150 , exclusiveThread(0) |
|
151 #endif |
|
152 { |
|
153 #if PLATFORM(MAC) |
|
154 startProfilerServerIfNeeded(); |
|
155 #endif |
|
156 #if ENABLE(JIT) && ENABLE(INTERPRETER) |
|
157 #if PLATFORM(CF) |
|
158 CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); |
|
159 CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); |
|
160 if (canUseJIT) { |
|
161 m_canUseJIT = kCFBooleanTrue == canUseJIT; |
|
162 CFRelease(canUseJIT); |
|
163 } else |
|
164 m_canUseJIT = !getenv("JavaScriptCoreUseJIT"); |
|
165 CFRelease(canUseJITKey); |
|
166 #elif OS(UNIX) |
|
167 m_canUseJIT = !getenv("JavaScriptCoreUseJIT"); |
|
168 #else |
|
169 m_canUseJIT = true; |
|
170 #endif |
|
171 #endif |
|
172 #if ENABLE(JIT) |
|
173 #if ENABLE(INTERPRETER) |
|
174 if (m_canUseJIT) |
|
175 m_canUseJIT = executableAllocator.isValid(); |
|
176 #endif |
|
177 jitStubs = new JITThunks(this); |
|
178 #endif |
|
179 } |
|
180 |
|
181 JSGlobalData::~JSGlobalData() |
|
182 { |
|
183 // By the time this is destroyed, heap.destroy() must already have been called. |
|
184 |
|
185 delete interpreter; |
|
186 #ifndef NDEBUG |
|
187 // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance. |
|
188 interpreter = 0; |
|
189 #endif |
|
190 |
|
191 arrayTable->deleteTable(); |
|
192 dateTable->deleteTable(); |
|
193 jsonTable->deleteTable(); |
|
194 mathTable->deleteTable(); |
|
195 numberTable->deleteTable(); |
|
196 regExpTable->deleteTable(); |
|
197 regExpConstructorTable->deleteTable(); |
|
198 stringTable->deleteTable(); |
|
199 |
|
200 fastDelete(const_cast<HashTable*>(arrayTable)); |
|
201 fastDelete(const_cast<HashTable*>(dateTable)); |
|
202 fastDelete(const_cast<HashTable*>(jsonTable)); |
|
203 fastDelete(const_cast<HashTable*>(mathTable)); |
|
204 fastDelete(const_cast<HashTable*>(numberTable)); |
|
205 fastDelete(const_cast<HashTable*>(regExpTable)); |
|
206 fastDelete(const_cast<HashTable*>(regExpConstructorTable)); |
|
207 fastDelete(const_cast<HashTable*>(stringTable)); |
|
208 |
|
209 delete parser; |
|
210 delete lexer; |
|
211 |
|
212 deleteAllValues(opaqueJSClassData); |
|
213 |
|
214 delete emptyList; |
|
215 |
|
216 delete propertyNames; |
|
217 if (globalDataType != Default) |
|
218 deleteIdentifierTable(identifierTable); |
|
219 |
|
220 delete clientData; |
|
221 delete m_regExpCache; |
|
222 } |
|
223 |
|
224 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type) |
|
225 { |
|
226 return adoptRef(new JSGlobalData(APIContextGroup, type)); |
|
227 } |
|
228 |
|
229 PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type) |
|
230 { |
|
231 return adoptRef(new JSGlobalData(Default, type)); |
|
232 } |
|
233 |
|
234 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type) |
|
235 { |
|
236 Structure::startIgnoringLeaks(); |
|
237 RefPtr<JSGlobalData> data = create(type); |
|
238 Structure::stopIgnoringLeaks(); |
|
239 return data.release(); |
|
240 } |
|
241 |
|
242 bool JSGlobalData::sharedInstanceExists() |
|
243 { |
|
244 return sharedInstanceInternal(); |
|
245 } |
|
246 |
|
247 JSGlobalData& JSGlobalData::sharedInstance() |
|
248 { |
|
249 JSGlobalData*& instance = sharedInstanceInternal(); |
|
250 if (!instance) { |
|
251 instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef(); |
|
252 #if ENABLE(JSC_MULTIPLE_THREADS) |
|
253 instance->makeUsableFromMultipleThreads(); |
|
254 #endif |
|
255 } |
|
256 return *instance; |
|
257 } |
|
258 |
|
259 JSGlobalData*& JSGlobalData::sharedInstanceInternal() |
|
260 { |
|
261 ASSERT(JSLock::currentThreadIsHoldingLock()); |
|
262 static JSGlobalData* sharedInstance; |
|
263 return sharedInstance; |
|
264 } |
|
265 |
|
266 #if ENABLE(JIT) |
|
267 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function) |
|
268 { |
|
269 return jitStubs->hostFunctionStub(this, function); |
|
270 } |
|
271 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator) |
|
272 { |
|
273 return jitStubs->hostFunctionStub(this, function, generator); |
|
274 } |
|
275 #endif |
|
276 |
|
277 JSGlobalData::ClientData::~ClientData() |
|
278 { |
|
279 } |
|
280 |
|
281 void JSGlobalData::resetDateCache() |
|
282 { |
|
283 cachedUTCOffset = NaN; |
|
284 dstOffsetCache.reset(); |
|
285 cachedDateString = UString(); |
|
286 dateInstanceCache.reset(); |
|
287 } |
|
288 |
|
289 void JSGlobalData::startSampling() |
|
290 { |
|
291 interpreter->startSampling(); |
|
292 } |
|
293 |
|
294 void JSGlobalData::stopSampling() |
|
295 { |
|
296 interpreter->stopSampling(); |
|
297 } |
|
298 |
|
299 void JSGlobalData::dumpSampleData(ExecState* exec) |
|
300 { |
|
301 interpreter->dumpSampleData(exec); |
|
302 } |
|
303 |
|
304 } // namespace JSC |