2 * Copyright (C) 2008 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
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.
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.
30 #include "JSGlobalData.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"
41 #include "JSByteArray.h"
42 #include "JSClassRef.h"
43 #include "JSFunction.h"
45 #include "JSNotAnObject.h"
46 #include "JSPropertyNameIterator.h"
47 #include "JSStaticScopeObject.h"
52 #include "RegExpCache.h"
53 #include "StrictEvalActivation.h"
54 #include <wtf/WTFThreadData.h>
55 #if ENABLE(REGEXP_TRACING)
60 #if ENABLE(JSC_MULTIPLE_THREADS)
61 #include <wtf/Threading.h>
65 #include "ProfilerServer.h"
66 #include <CoreFoundation/CoreFoundation.h>
73 extern JSC_CONST_HASHTABLE HashTable arrayTable;
74 extern JSC_CONST_HASHTABLE HashTable jsonTable;
75 extern JSC_CONST_HASHTABLE HashTable dateTable;
76 extern JSC_CONST_HASHTABLE HashTable mathTable;
77 extern JSC_CONST_HASHTABLE HashTable numberTable;
78 extern JSC_CONST_HASHTABLE HashTable regExpTable;
79 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
80 extern JSC_CONST_HASHTABLE HashTable stringTable;
82 void* JSGlobalData::jsArrayVPtr;
83 void* JSGlobalData::jsByteArrayVPtr;
84 void* JSGlobalData::jsStringVPtr;
85 void* JSGlobalData::jsFunctionVPtr;
87 void JSGlobalData::storeVPtrs()
89 // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
90 // COMPILE_ASSERTS below check that this is true.
93 COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
94 JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
95 JSGlobalData::jsArrayVPtr = jsArray->vptr();
98 COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
99 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
100 JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
101 jsByteArray->~JSCell();
103 COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
104 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
105 JSGlobalData::jsStringVPtr = jsString->vptr();
108 COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
109 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
110 JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
111 jsFunction->~JSCell();
114 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
115 : globalDataType(globalDataType)
117 , arrayTable(fastNew<HashTable>(JSC::arrayTable))
118 , dateTable(fastNew<HashTable>(JSC::dateTable))
119 , jsonTable(fastNew<HashTable>(JSC::jsonTable))
120 , mathTable(fastNew<HashTable>(JSC::mathTable))
121 , numberTable(fastNew<HashTable>(JSC::numberTable))
122 , regExpTable(fastNew<HashTable>(JSC::regExpTable))
123 , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
124 , stringTable(fastNew<HashTable>(JSC::stringTable))
125 , activationStructure(JSActivation::createStructure(jsNull()))
126 , interruptedExecutionErrorStructure(createEmptyObjectStructure(jsNull()))
127 , terminatedExecutionErrorStructure(createEmptyObjectStructure(jsNull()))
128 , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
129 , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull()))
130 , stringStructure(JSString::createStructure(jsNull()))
131 , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
132 , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
133 , getterSetterStructure(GetterSetter::createStructure(jsNull()))
134 , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
135 , dummyMarkableCellStructure(JSCell::createDummyStructure())
136 , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
137 , propertyNames(new CommonIdentifiers(this))
138 , emptyList(new MarkedArgumentBuffer)
139 , lexer(new Lexer(this))
143 , dynamicGlobalObject(0)
144 , firstStringifierToMark(0)
145 , cachedUTCOffset(NaN)
146 , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
147 , m_regExpCache(new RegExpCache(this))
148 #if ENABLE(REGEXP_TRACING)
149 , m_rtTraceList(new RTTraceList())
155 interpreter = new Interpreter(*this);
156 if (globalDataType == Default)
157 m_stack = wtfThreadData().stack();
160 startProfilerServerIfNeeded();
162 #if ENABLE(JIT) && ENABLE(INTERPRETER)
164 CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
165 CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
167 m_canUseJIT = kCFBooleanTrue == canUseJIT;
168 CFRelease(canUseJIT);
170 char* canUseJITString = getenv("JavaScriptCoreUseJIT");
171 m_canUseJIT = !canUseJITString || atoi(canUseJITString);
173 CFRelease(canUseJITKey);
175 char* canUseJITString = getenv("JavaScriptCoreUseJIT");
176 m_canUseJIT = !canUseJITString || atoi(canUseJITString);
182 #if ENABLE(INTERPRETER)
184 m_canUseJIT = executableAllocator.isValid();
186 jitStubs = new JITThunks(this);
190 JSGlobalData::~JSGlobalData()
192 // By the time this is destroyed, heap.destroy() must already have been called.
196 // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
200 arrayTable->deleteTable();
201 dateTable->deleteTable();
202 jsonTable->deleteTable();
203 mathTable->deleteTable();
204 numberTable->deleteTable();
205 regExpTable->deleteTable();
206 regExpConstructorTable->deleteTable();
207 stringTable->deleteTable();
209 fastDelete(const_cast<HashTable*>(arrayTable));
210 fastDelete(const_cast<HashTable*>(dateTable));
211 fastDelete(const_cast<HashTable*>(jsonTable));
212 fastDelete(const_cast<HashTable*>(mathTable));
213 fastDelete(const_cast<HashTable*>(numberTable));
214 fastDelete(const_cast<HashTable*>(regExpTable));
215 fastDelete(const_cast<HashTable*>(regExpConstructorTable));
216 fastDelete(const_cast<HashTable*>(stringTable));
221 deleteAllValues(opaqueJSClassData);
225 delete propertyNames;
226 if (globalDataType != Default)
227 deleteIdentifierTable(identifierTable);
230 delete m_regExpCache;
231 #if ENABLE(REGEXP_TRACING)
232 delete m_rtTraceList;
236 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
238 return adoptRef(new JSGlobalData(APIContextGroup, type));
241 PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
243 return adoptRef(new JSGlobalData(Default, type));
246 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
248 Structure::startIgnoringLeaks();
249 RefPtr<JSGlobalData> data = create(type);
250 Structure::stopIgnoringLeaks();
251 return data.release();
254 bool JSGlobalData::sharedInstanceExists()
256 return sharedInstanceInternal();
259 JSGlobalData& JSGlobalData::sharedInstance()
261 JSGlobalData*& instance = sharedInstanceInternal();
263 instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef();
264 #if ENABLE(JSC_MULTIPLE_THREADS)
265 instance->makeUsableFromMultipleThreads();
271 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
273 ASSERT(JSLock::currentThreadIsHoldingLock());
274 static JSGlobalData* sharedInstance;
275 return sharedInstance;
279 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
281 return jitStubs->hostFunctionStub(this, function);
283 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
285 return jitStubs->hostFunctionStub(this, function, generator);
288 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
290 return NativeExecutable::create(function, callHostFunctionAsConstructor);
294 JSGlobalData::ClientData::~ClientData()
298 void JSGlobalData::resetDateCache()
300 cachedUTCOffset = NaN;
301 dstOffsetCache.reset();
302 cachedDateString = UString();
303 cachedDateStringValue = NaN;
304 dateInstanceCache.reset();
307 void JSGlobalData::startSampling()
309 interpreter->startSampling();
312 void JSGlobalData::stopSampling()
314 interpreter->stopSampling();
317 void JSGlobalData::dumpSampleData(ExecState* exec)
319 interpreter->dumpSampleData(exec);
324 void operator()(JSCell*);
327 inline void Recompiler::operator()(JSCell* cell)
329 if (!cell->inherits(&JSFunction::s_info))
331 JSFunction* function = asFunction(cell);
332 if (function->executable()->isHostFunction())
334 function->jsExecutable()->discardCode();
338 void JSGlobalData::recompileAllJSFunctions()
340 // If JavaScript is running, it's not safe to recompile, since we'll end
341 // up throwing away code that is live on the stack.
342 ASSERT(!dynamicGlobalObject);
344 Recompiler recompiler;
345 heap.forEach(recompiler);
348 #if ENABLE(REGEXP_TRACING)
349 void JSGlobalData::addRegExpToTrace(PassRefPtr<RegExp> regExp)
351 m_rtTraceList->add(regExp);
354 void JSGlobalData::dumpRegExpTrace()
356 // The first RegExp object is ignored. It is create by the RegExpPrototype ctor and not used.
357 RTTraceList::iterator iter = ++m_rtTraceList->begin();
359 if (iter != m_rtTraceList->end()) {
360 printf("\nRegExp Tracing\n");
361 printf(" match() matches\n");
362 printf("Regular Expression JIT Address calls found\n");
363 printf("----------------------------------------+----------------+----------+----------\n");
365 unsigned reCount = 0;
367 for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
368 (*iter)->printTraceData();
370 printf("%d Regular Expressions\n", reCount);
373 m_rtTraceList->clear();
376 void JSGlobalData::dumpRegExpTrace()