ba63bc040c7192247704a0345e9481964a79e7fc
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSGlobalData.cpp
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 "Heap.h"
34 #include "CollectorHeapIterator.h"
35 #include "CommonIdentifiers.h"
36 #include "FunctionConstructor.h"
37 #include "GetterSetter.h"
38 #include "Interpreter.h"
39 #include "JSActivation.h"
40 #include "JSAPIValueWrapper.h"
41 #include "JSArray.h"
42 #include "JSByteArray.h"
43 #include "JSClassRef.h"
44 #include "JSFunction.h"
45 #include "JSLock.h"
46 #include "JSNotAnObject.h"
47 #include "JSPropertyNameIterator.h"
48 #include "JSStaticScopeObject.h"
49 #include "Lexer.h"
50 #include "Lookup.h"
51 #include "Nodes.h"
52 #include "Parser.h"
53 #include "RegExpCache.h"
54 #include "StrictEvalActivation.h"
55 #include <wtf/WTFThreadData.h>
56 #if ENABLE(REGEXP_TRACING)
57 #include "RegExp.h"
58 #endif
59
60
61 #if ENABLE(JSC_MULTIPLE_THREADS)
62 #include <wtf/Threading.h>
63 #endif
64
65 #if PLATFORM(MAC)
66 #include "ProfilerServer.h"
67 #include <CoreFoundation/CoreFoundation.h>
68 #endif
69
70 using namespace WTF;
71
72 namespace JSC {
73
74 extern JSC_CONST_HASHTABLE HashTable arrayTable;
75 extern JSC_CONST_HASHTABLE HashTable jsonTable;
76 extern JSC_CONST_HASHTABLE HashTable dateTable;
77 extern JSC_CONST_HASHTABLE HashTable mathTable;
78 extern JSC_CONST_HASHTABLE HashTable numberTable;
79 extern JSC_CONST_HASHTABLE HashTable regExpTable;
80 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
81 extern JSC_CONST_HASHTABLE HashTable stringTable;
82
83 void* JSGlobalData::jsArrayVPtr;
84 void* JSGlobalData::jsByteArrayVPtr;
85 void* JSGlobalData::jsStringVPtr;
86 void* JSGlobalData::jsFunctionVPtr;
87
88 void JSGlobalData::storeVPtrs()
89 {
90     CollectorCell cell;
91     void* storage = &cell;
92
93     COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
94     JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
95     JSGlobalData::jsArrayVPtr = jsArray->vptr();
96     jsArray->~JSCell();
97
98     COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
99     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
100     JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
101     jsByteArray->~JSCell();
102
103     COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
104     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
105     JSGlobalData::jsStringVPtr = jsString->vptr();
106     jsString->~JSCell();
107
108     COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
109     JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
110     JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
111     jsFunction->~JSCell();
112 }
113
114 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
115     : globalDataType(globalDataType)
116     , clientData(0)
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(JSObject::createStructure(jsNull()))
127     , terminatedExecutionErrorStructure(JSObject::createStructure(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))
140     , parser(new Parser)
141     , interpreter(new Interpreter)
142     , heap(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())
150 #endif
151 #ifndef NDEBUG
152     , exclusiveThread(0)
153 #endif
154 {
155     if (globalDataType == Default)
156         m_stack = wtfThreadData().stack();
157
158 #if PLATFORM(MAC)
159     startProfilerServerIfNeeded();
160 #endif
161 #if ENABLE(JIT) && ENABLE(INTERPRETER)
162 #if PLATFORM(CF)
163     CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
164     CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
165     if (canUseJIT) {
166         m_canUseJIT = kCFBooleanTrue == canUseJIT;
167         CFRelease(canUseJIT);
168     } else {
169       char* canUseJITString = getenv("JavaScriptCoreUseJIT");
170       m_canUseJIT = !canUseJITString || atoi(canUseJITString);
171     }
172     CFRelease(canUseJITKey);
173 #elif OS(UNIX)
174     char* canUseJITString = getenv("JavaScriptCoreUseJIT");
175     m_canUseJIT = !canUseJITString || atoi(canUseJITString);
176 #else
177     m_canUseJIT = true;
178 #endif
179 #endif
180 #if ENABLE(JIT)
181 #if ENABLE(INTERPRETER)
182     if (m_canUseJIT)
183         m_canUseJIT = executableAllocator.isValid();
184 #endif
185     jitStubs = new JITThunks(this);
186 #endif
187 }
188
189 JSGlobalData::~JSGlobalData()
190 {
191     // By the time this is destroyed, heap.destroy() must already have been called.
192
193     delete interpreter;
194 #ifndef NDEBUG
195     // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
196     interpreter = 0;
197 #endif
198
199     arrayTable->deleteTable();
200     dateTable->deleteTable();
201     jsonTable->deleteTable();
202     mathTable->deleteTable();
203     numberTable->deleteTable();
204     regExpTable->deleteTable();
205     regExpConstructorTable->deleteTable();
206     stringTable->deleteTable();
207
208     fastDelete(const_cast<HashTable*>(arrayTable));
209     fastDelete(const_cast<HashTable*>(dateTable));
210     fastDelete(const_cast<HashTable*>(jsonTable));
211     fastDelete(const_cast<HashTable*>(mathTable));
212     fastDelete(const_cast<HashTable*>(numberTable));
213     fastDelete(const_cast<HashTable*>(regExpTable));
214     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
215     fastDelete(const_cast<HashTable*>(stringTable));
216
217     delete parser;
218     delete lexer;
219
220     deleteAllValues(opaqueJSClassData);
221
222     delete emptyList;
223
224     delete propertyNames;
225     if (globalDataType != Default)
226         deleteIdentifierTable(identifierTable);
227
228     delete clientData;
229     delete m_regExpCache;
230 #if ENABLE(REGEXP_TRACING)
231     delete m_rtTraceList;
232 #endif
233 }
234
235 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
236 {
237     return adoptRef(new JSGlobalData(APIContextGroup, type));
238 }
239
240 PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
241 {
242     return adoptRef(new JSGlobalData(Default, type));
243 }
244
245 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
246 {
247     Structure::startIgnoringLeaks();
248     RefPtr<JSGlobalData> data = create(type);
249     Structure::stopIgnoringLeaks();
250     return data.release();
251 }
252
253 bool JSGlobalData::sharedInstanceExists()
254 {
255     return sharedInstanceInternal();
256 }
257
258 JSGlobalData& JSGlobalData::sharedInstance()
259 {
260     JSGlobalData*& instance = sharedInstanceInternal();
261     if (!instance) {
262         instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef();
263 #if ENABLE(JSC_MULTIPLE_THREADS)
264         instance->makeUsableFromMultipleThreads();
265 #endif
266     }
267     return *instance;
268 }
269
270 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
271 {
272     ASSERT(JSLock::currentThreadIsHoldingLock());
273     static JSGlobalData* sharedInstance;
274     return sharedInstance;
275 }
276
277 #if ENABLE(JIT)
278 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
279 {
280     return jitStubs->hostFunctionStub(this, function);
281 }
282 PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
283 {
284     return jitStubs->hostFunctionStub(this, function, generator);
285 }
286 #endif
287
288 JSGlobalData::ClientData::~ClientData()
289 {
290 }
291
292 void JSGlobalData::resetDateCache()
293 {
294     cachedUTCOffset = NaN;
295     dstOffsetCache.reset();
296     cachedDateString = UString();
297     cachedDateStringValue = NaN;
298     dateInstanceCache.reset();
299 }
300
301 void JSGlobalData::startSampling()
302 {
303     interpreter->startSampling();
304 }
305
306 void JSGlobalData::stopSampling()
307 {
308     interpreter->stopSampling();
309 }
310
311 void JSGlobalData::dumpSampleData(ExecState* exec)
312 {
313     interpreter->dumpSampleData(exec);
314 }
315
316 void JSGlobalData::recompileAllJSFunctions()
317 {
318     // If JavaScript is running, it's not safe to recompile, since we'll end
319     // up throwing away code that is live on the stack.
320     ASSERT(!dynamicGlobalObject);
321
322     LiveObjectIterator it = heap.primaryHeapBegin();
323     LiveObjectIterator heapEnd = heap.primaryHeapEnd();
324     for ( ; it != heapEnd; ++it) {
325         if ((*it)->inherits(&JSFunction::info)) {
326             JSFunction* function = asFunction(*it);
327             if (!function->executable()->isHostFunction())
328                 function->jsExecutable()->discardCode();
329         }
330     }
331 }
332
333 #if ENABLE(REGEXP_TRACING)
334 void JSGlobalData::addRegExpToTrace(PassRefPtr<RegExp> regExp)
335 {
336     m_rtTraceList->add(regExp);
337 }
338
339 void JSGlobalData::dumpRegExpTrace()
340 {
341     // The first RegExp object is ignored.  It is create by the RegExpPrototype ctor and not used.
342     RTTraceList::iterator iter = ++m_rtTraceList->begin();
343     
344     if (iter != m_rtTraceList->end()) {
345         printf("\nRegExp Tracing\n");
346         printf("                                                            match()    matches\n");
347         printf("Regular Expression                          JIT Address      calls      found\n");
348         printf("----------------------------------------+----------------+----------+----------\n");
349     
350         unsigned reCount = 0;
351     
352         for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
353             (*iter)->printTraceData();
354
355         printf("%d Regular Expressions\n", reCount);
356     }
357     
358     m_rtTraceList->clear();
359 }
360 #else
361 void JSGlobalData::dumpRegExpTrace()
362 {
363 }
364 #endif
365
366 } // namespace JSC