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 | |
53 | #if ENABLE(JSC_MULTIPLE_THREADS) |
54 | #include <wtf/Threading.h> |
55 | #endif |
56 | |
57 | #if PLATFORM(MAC) |
58 | #include "ProfilerServer.h" |
59 | #endif |
60 | |
61 | using namespace WTF; |
62 | |
63 | namespace JSC { |
64 | |
65 | extern JSC_CONST_HASHTABLE HashTable arrayTable; |
66 | extern JSC_CONST_HASHTABLE HashTable jsonTable; |
67 | extern JSC_CONST_HASHTABLE HashTable dateTable; |
68 | extern JSC_CONST_HASHTABLE HashTable mathTable; |
69 | extern JSC_CONST_HASHTABLE HashTable numberTable; |
70 | extern JSC_CONST_HASHTABLE HashTable regExpTable; |
71 | extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable; |
72 | extern JSC_CONST_HASHTABLE HashTable stringTable; |
73 | |
74 | void* JSGlobalData::jsArrayVPtr; |
75 | void* JSGlobalData::jsByteArrayVPtr; |
76 | void* JSGlobalData::jsStringVPtr; |
77 | void* JSGlobalData::jsFunctionVPtr; |
78 | |
79 | void JSGlobalData::storeVPtrs() |
80 | { |
81 | CollectorCell cell; |
82 | void* storage = &cell; |
83 | |
84 | COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell); |
85 | JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(prototype: jsNull())); |
86 | JSGlobalData::jsArrayVPtr = jsArray->vptr(); |
87 | jsArray->~JSCell(); |
88 | |
89 | COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell); |
90 | JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); |
91 | JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr(); |
92 | jsByteArray->~JSCell(); |
93 | |
94 | COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell); |
95 | JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); |
96 | JSGlobalData::jsStringVPtr = jsString->vptr(); |
97 | jsString->~JSCell(); |
98 | |
99 | COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell); |
100 | JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(prototype: jsNull())); |
101 | JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); |
102 | jsFunction->~JSCell(); |
103 | } |
104 | |
105 | JSGlobalData::JSGlobalData(bool isShared) |
106 | : isSharedInstance(isShared) |
107 | , clientData(0) |
108 | , arrayTable(fastNew<HashTable>(JSC::arrayTable)) |
109 | , dateTable(fastNew<HashTable>(JSC::dateTable)) |
110 | , jsonTable(fastNew<HashTable>(JSC::jsonTable)) |
111 | , mathTable(fastNew<HashTable>(JSC::mathTable)) |
112 | , numberTable(fastNew<HashTable>(JSC::numberTable)) |
113 | , regExpTable(fastNew<HashTable>(JSC::regExpTable)) |
114 | , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) |
115 | , stringTable(fastNew<HashTable>(JSC::stringTable)) |
116 | , activationStructure(JSActivation::createStructure(proto: jsNull())) |
117 | , interruptedExecutionErrorStructure(JSObject::createStructure(prototype: jsNull())) |
118 | , staticScopeStructure(JSStaticScopeObject::createStructure(proto: jsNull())) |
119 | , stringStructure(JSString::createStructure(proto: jsNull())) |
120 | , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(prototype: jsNull())) |
121 | , notAnObjectStructure(JSNotAnObject::createStructure(prototype: jsNull())) |
122 | , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(prototype: jsNull())) |
123 | , getterSetterStructure(GetterSetter::createStructure(prototype: jsNull())) |
124 | , apiWrapperStructure(JSAPIValueWrapper::createStructure(prototype: jsNull())) |
125 | , dummyMarkableCellStructure(JSCell::createDummyStructure()) |
126 | #if USE(JSVALUE32) |
127 | , numberStructure(JSNumberCell::createStructure(jsNull())) |
128 | #endif |
129 | , identifierTable(createIdentifierTable()) |
130 | , propertyNames(new CommonIdentifiers(this)) |
131 | , emptyList(new MarkedArgumentBuffer) |
132 | , lexer(new Lexer(this)) |
133 | , parser(new Parser) |
134 | , interpreter(new Interpreter) |
135 | #if ENABLE(JIT) |
136 | , jitStubs(this) |
137 | #endif |
138 | , timeoutChecker(new TimeoutChecker) |
139 | , heap(this) |
140 | , initializingLazyNumericCompareFunction(false) |
141 | , head(0) |
142 | , dynamicGlobalObject(0) |
143 | , functionCodeBlockBeingReparsed(0) |
144 | , firstStringifierToMark(0) |
145 | , markStack(jsArrayVPtr) |
146 | #ifndef NDEBUG |
147 | , mainThreadOnly(false) |
148 | #endif |
149 | { |
150 | #if PLATFORM(MAC) |
151 | startProfilerServerIfNeeded(); |
152 | #endif |
153 | } |
154 | |
155 | JSGlobalData::~JSGlobalData() |
156 | { |
157 | // By the time this is destroyed, heap.destroy() must already have been called. |
158 | |
159 | delete interpreter; |
160 | #ifndef NDEBUG |
161 | // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance. |
162 | interpreter = 0; |
163 | #endif |
164 | |
165 | arrayTable->deleteTable(); |
166 | dateTable->deleteTable(); |
167 | jsonTable->deleteTable(); |
168 | mathTable->deleteTable(); |
169 | numberTable->deleteTable(); |
170 | regExpTable->deleteTable(); |
171 | regExpConstructorTable->deleteTable(); |
172 | stringTable->deleteTable(); |
173 | |
174 | fastDelete(p: const_cast<HashTable*>(arrayTable)); |
175 | fastDelete(p: const_cast<HashTable*>(dateTable)); |
176 | fastDelete(p: const_cast<HashTable*>(jsonTable)); |
177 | fastDelete(p: const_cast<HashTable*>(mathTable)); |
178 | fastDelete(p: const_cast<HashTable*>(numberTable)); |
179 | fastDelete(p: const_cast<HashTable*>(regExpTable)); |
180 | fastDelete(p: const_cast<HashTable*>(regExpConstructorTable)); |
181 | fastDelete(p: const_cast<HashTable*>(stringTable)); |
182 | |
183 | delete parser; |
184 | delete lexer; |
185 | delete timeoutChecker; |
186 | |
187 | deleteAllValues(collection: opaqueJSClassData); |
188 | |
189 | delete emptyList; |
190 | |
191 | delete propertyNames; |
192 | deleteIdentifierTable(identifierTable); |
193 | |
194 | delete clientData; |
195 | } |
196 | |
197 | PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault() |
198 | { |
199 | return adoptRef(p: new JSGlobalData(false)); |
200 | } |
201 | |
202 | PassRefPtr<JSGlobalData> JSGlobalData::create() |
203 | { |
204 | JSGlobalData* globalData = new JSGlobalData(false); |
205 | setDefaultIdentifierTable(globalData->identifierTable); |
206 | setCurrentIdentifierTable(globalData->identifierTable); |
207 | return adoptRef(p: globalData); |
208 | } |
209 | |
210 | PassRefPtr<JSGlobalData> JSGlobalData::createLeaked() |
211 | { |
212 | Structure::startIgnoringLeaks(); |
213 | RefPtr<JSGlobalData> data = create(); |
214 | Structure::stopIgnoringLeaks(); |
215 | return data.release(); |
216 | } |
217 | |
218 | bool JSGlobalData::sharedInstanceExists() |
219 | { |
220 | return sharedInstanceInternal(); |
221 | } |
222 | |
223 | JSGlobalData& JSGlobalData::sharedInstance() |
224 | { |
225 | JSGlobalData*& instance = sharedInstanceInternal(); |
226 | if (!instance) { |
227 | instance = new JSGlobalData(true); |
228 | #if ENABLE(JSC_MULTIPLE_THREADS) |
229 | instance->makeUsableFromMultipleThreads(); |
230 | #endif |
231 | } |
232 | return *instance; |
233 | } |
234 | |
235 | JSGlobalData*& JSGlobalData::sharedInstanceInternal() |
236 | { |
237 | ASSERT(JSLock::currentThreadIsHoldingLock()); |
238 | static JSGlobalData* sharedInstance; |
239 | return sharedInstance; |
240 | } |
241 | |
242 | // FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc. |
243 | const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec) |
244 | { |
245 | if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) { |
246 | initializingLazyNumericCompareFunction = true; |
247 | RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare" ), exec, 0, makeSource(source: UString("(function (v1, v2) { return v1 - v2; })" )), errLine: 0, errMsg: 0); |
248 | lazyNumericCompareFunction = function->bytecode(exec, scopeChainNode: exec->scopeChain()).instructions(); |
249 | initializingLazyNumericCompareFunction = false; |
250 | } |
251 | |
252 | return lazyNumericCompareFunction; |
253 | } |
254 | |
255 | JSGlobalData::ClientData::~ClientData() |
256 | { |
257 | } |
258 | |
259 | void JSGlobalData::resetDateCache() |
260 | { |
261 | localTimeOffsetCache.reset(); |
262 | cachedDateString = UString(); |
263 | dateInstanceCache.reset(); |
264 | } |
265 | |
266 | void JSGlobalData::startSampling() |
267 | { |
268 | interpreter->startSampling(); |
269 | } |
270 | |
271 | void JSGlobalData::stopSampling() |
272 | { |
273 | interpreter->stopSampling(); |
274 | } |
275 | |
276 | void JSGlobalData::dumpSampleData(ExecState* exec) |
277 | { |
278 | interpreter->dumpSampleData(exec); |
279 | } |
280 | |
281 | } // namespace JSC |
282 | |