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"
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"
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 <wtf/WTFThreadData.h>
55 #if ENABLE(JSC_MULTIPLE_THREADS)
56 #include <wtf/Threading.h>
60 #include "ProfilerServer.h"
61 #include <CoreFoundation/CoreFoundation.h>
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
;
77 void* JSGlobalData::jsArrayVPtr
;
78 void* JSGlobalData::jsByteArrayVPtr
;
79 void* JSGlobalData::jsStringVPtr
;
80 void* JSGlobalData::jsFunctionVPtr
;
82 void JSGlobalData::storeVPtrs()
85 void* storage
= &cell
;
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();
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();
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();
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();
108 JSGlobalData::JSGlobalData(GlobalDataType globalDataType
, ThreadStackType threadStackType
)
109 : globalDataType(globalDataType
)
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())
131 , numberStructure(JSNumberCell::createStructure(jsNull()))
133 , identifierTable(globalDataType
== Default
? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
134 , propertyNames(new CommonIdentifiers(this))
135 , emptyList(new MarkedArgumentBuffer
)
136 , lexer(new Lexer(this))
138 , interpreter(new Interpreter
)
140 , initializingLazyNumericCompareFunction(false)
142 , dynamicGlobalObject(0)
143 , functionCodeBlockBeingReparsed(0)
144 , firstStringifierToMark(0)
145 , markStack(jsArrayVPtr
)
146 , cachedUTCOffset(NaN
)
147 , maxReentryDepth(threadStackType
== ThreadStackTypeSmall
? MaxSmallThreadReentryDepth
: MaxLargeThreadReentryDepth
)
148 , m_regExpCache(new RegExpCache(this))
154 startProfilerServerIfNeeded();
156 #if ENABLE(JIT) && ENABLE(INTERPRETER)
158 CFStringRef canUseJITKey
= CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman
);
159 CFBooleanRef canUseJIT
= (CFBooleanRef
)CFPreferencesCopyAppValue(canUseJITKey
, kCFPreferencesCurrentApplication
);
161 m_canUseJIT
= kCFBooleanTrue
== canUseJIT
;
162 CFRelease(canUseJIT
);
164 m_canUseJIT
= !getenv("JavaScriptCoreUseJIT");
165 CFRelease(canUseJITKey
);
167 m_canUseJIT
= !getenv("JavaScriptCoreUseJIT");
173 #if ENABLE(INTERPRETER)
175 m_canUseJIT
= executableAllocator
.isValid();
177 jitStubs
.set(new JITThunks(this));
181 JSGlobalData::~JSGlobalData()
183 // By the time this is destroyed, heap.destroy() must already have been called.
187 // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
191 arrayTable
->deleteTable();
192 dateTable
->deleteTable();
193 jsonTable
->deleteTable();
194 mathTable
->deleteTable();
195 numberTable
->deleteTable();
196 regExpTable
->deleteTable();
197 regExpConstructorTable
->deleteTable();
198 stringTable
->deleteTable();
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
));
212 deleteAllValues(opaqueJSClassData
);
216 delete propertyNames
;
217 if (globalDataType
!= Default
)
218 deleteIdentifierTable(identifierTable
);
221 delete m_regExpCache
;
224 PassRefPtr
<JSGlobalData
> JSGlobalData::createContextGroup(ThreadStackType type
)
226 return adoptRef(new JSGlobalData(APIContextGroup
, type
));
229 PassRefPtr
<JSGlobalData
> JSGlobalData::create(ThreadStackType type
)
231 return adoptRef(new JSGlobalData(Default
, type
));
234 PassRefPtr
<JSGlobalData
> JSGlobalData::createLeaked(ThreadStackType type
)
236 Structure::startIgnoringLeaks();
237 RefPtr
<JSGlobalData
> data
= create(type
);
238 Structure::stopIgnoringLeaks();
239 return data
.release();
242 bool JSGlobalData::sharedInstanceExists()
244 return sharedInstanceInternal();
247 JSGlobalData
& JSGlobalData::sharedInstance()
249 JSGlobalData
*& instance
= sharedInstanceInternal();
251 instance
= new JSGlobalData(APIShared
, ThreadStackTypeSmall
);
252 #if ENABLE(JSC_MULTIPLE_THREADS)
253 instance
->makeUsableFromMultipleThreads();
259 JSGlobalData
*& JSGlobalData::sharedInstanceInternal()
261 ASSERT(JSLock::currentThreadIsHoldingLock());
262 static JSGlobalData
* sharedInstance
;
263 return sharedInstance
;
266 // FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc.
267 const Vector
<Instruction
>& JSGlobalData::numericCompareFunction(ExecState
* exec
)
269 if (!lazyNumericCompareFunction
.size() && !initializingLazyNumericCompareFunction
) {
270 initializingLazyNumericCompareFunction
= true;
271 RefPtr
<FunctionExecutable
> function
= FunctionExecutable::fromGlobalCode(Identifier(exec
, "numericCompare"), exec
, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
272 lazyNumericCompareFunction
= function
->bytecode(exec
, exec
->scopeChain()).instructions();
273 initializingLazyNumericCompareFunction
= false;
276 return lazyNumericCompareFunction
;
279 JSGlobalData::ClientData::~ClientData()
283 void JSGlobalData::resetDateCache()
285 cachedUTCOffset
= NaN
;
286 dstOffsetCache
.reset();
287 cachedDateString
= UString();
288 dateInstanceCache
.reset();
291 void JSGlobalData::startSampling()
293 interpreter
->startSampling();
296 void JSGlobalData::stopSampling()
298 interpreter
->stopSampling();
301 void JSGlobalData::dumpSampleData(ExecState
* exec
)
303 interpreter
->dumpSampleData(exec
);