]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSGlobalData.h
613753f55d0e6280b4451a453f93688322cb2b4f
[apple/javascriptcore.git] / runtime / JSGlobalData.h
1 /*
2 * Copyright (C) 2008, 2009 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 #ifndef JSGlobalData_h
30 #define JSGlobalData_h
31
32 #include "CachedTranscendentalFunction.h"
33 #include "DateInstanceCache.h"
34 #include "ExecutableAllocator.h"
35 #include "Heap.h"
36 #include "Intrinsic.h"
37 #include "JITStubs.h"
38 #include "JSLock.h"
39 #include "JSValue.h"
40 #include "LLIntData.h"
41 #include "NumericStrings.h"
42 #include "SmallStrings.h"
43 #include "Strong.h"
44 #include "Terminator.h"
45 #include "TimeoutChecker.h"
46 #include "WeakRandom.h"
47 #include <wtf/BumpPointerAllocator.h>
48 #include <wtf/Forward.h>
49 #include <wtf/HashMap.h>
50 #include <wtf/SimpleStats.h>
51 #include <wtf/ThreadSafeRefCounted.h>
52 #include <wtf/ThreadSpecific.h>
53 #include <wtf/WTFThreadData.h>
54 #if ENABLE(REGEXP_TRACING)
55 #include <wtf/ListHashSet.h>
56 #endif
57
58 struct OpaqueJSClass;
59 struct OpaqueJSClassContextData;
60
61 namespace JSC {
62
63 class CodeBlock;
64 class CommonIdentifiers;
65 class HandleStack;
66 class IdentifierTable;
67 class Interpreter;
68 class JSGlobalObject;
69 class JSObject;
70 class Keywords;
71 class LLIntOffsetsExtractor;
72 class NativeExecutable;
73 class ParserArena;
74 class RegExpCache;
75 class Stringifier;
76 class Structure;
77 class UString;
78 #if ENABLE(REGEXP_TRACING)
79 class RegExp;
80 #endif
81
82 struct HashTable;
83 struct Instruction;
84
85 struct DSTOffsetCache {
86 DSTOffsetCache()
87 {
88 reset();
89 }
90
91 void reset()
92 {
93 offset = 0.0;
94 start = 0.0;
95 end = -1.0;
96 increment = 0.0;
97 }
98
99 double offset;
100 double start;
101 double end;
102 double increment;
103 };
104
105 enum ThreadStackType {
106 ThreadStackTypeLarge,
107 ThreadStackTypeSmall
108 };
109
110 struct TypedArrayDescriptor {
111 TypedArrayDescriptor()
112 : m_classInfo(0)
113 , m_storageOffset(0)
114 , m_lengthOffset(0)
115 {
116 }
117 TypedArrayDescriptor(const ClassInfo* classInfo, size_t storageOffset, size_t lengthOffset)
118 : m_classInfo(classInfo)
119 , m_storageOffset(storageOffset)
120 , m_lengthOffset(lengthOffset)
121 {
122 }
123 const ClassInfo* m_classInfo;
124 size_t m_storageOffset;
125 size_t m_lengthOffset;
126 };
127
128 #if ENABLE(DFG_JIT)
129 class ConservativeRoots;
130
131 struct ScratchBuffer {
132 ScratchBuffer()
133 : m_activeLength(0)
134 {
135 }
136
137 static ScratchBuffer* create(size_t size)
138 {
139 ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer;
140
141 return result;
142 }
143
144 static size_t allocationSize(size_t bufferSize) { return sizeof(size_t) + bufferSize; }
145 void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
146 size_t activeLength() const { return m_activeLength; };
147 size_t* activeLengthPtr() { return &m_activeLength; };
148 void* dataBuffer() { return m_buffer; }
149
150 size_t m_activeLength;
151 void* m_buffer[0];
152 };
153 #endif
154
155 class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {
156 public:
157 // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
158 // either create() or createLeaked() should only be called once
159 // on a thread, this is the 'default' JSGlobalData (it uses the
160 // thread's default string uniquing table from wtfThreadData).
161 // API contexts created using the new context group aware interface
162 // create APIContextGroup objects which require less locking of JSC
163 // than the old singleton APIShared JSGlobalData created for use by
164 // the original API.
165 enum GlobalDataType { Default, APIContextGroup, APIShared };
166
167 struct ClientData {
168 JS_EXPORT_PRIVATE virtual ~ClientData() = 0;
169 };
170
171 bool isSharedInstance() { return globalDataType == APIShared; }
172 bool usingAPI() { return globalDataType != Default; }
173 JS_EXPORT_PRIVATE static bool sharedInstanceExists();
174 JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
175
176 JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap);
177 JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap);
178 static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapSize = SmallHeap);
179 JS_EXPORT_PRIVATE ~JSGlobalData();
180
181 void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
182
183 private:
184 JSLock m_apiLock;
185
186 public:
187 Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it.
188
189 GlobalDataType globalDataType;
190 ClientData* clientData;
191 CallFrame* topCallFrame;
192
193 const HashTable* arrayConstructorTable;
194 const HashTable* arrayPrototypeTable;
195 const HashTable* booleanPrototypeTable;
196 const HashTable* dateTable;
197 const HashTable* dateConstructorTable;
198 const HashTable* errorPrototypeTable;
199 const HashTable* globalObjectTable;
200 const HashTable* jsonTable;
201 const HashTable* mathTable;
202 const HashTable* numberConstructorTable;
203 const HashTable* numberPrototypeTable;
204 const HashTable* objectConstructorTable;
205 const HashTable* objectPrototypeTable;
206 const HashTable* regExpTable;
207 const HashTable* regExpConstructorTable;
208 const HashTable* regExpPrototypeTable;
209 const HashTable* stringTable;
210 const HashTable* stringConstructorTable;
211
212 Strong<Structure> structureStructure;
213 Strong<Structure> debuggerActivationStructure;
214 Strong<Structure> activationStructure;
215 Strong<Structure> interruptedExecutionErrorStructure;
216 Strong<Structure> terminatedExecutionErrorStructure;
217 Strong<Structure> staticScopeStructure;
218 Strong<Structure> strictEvalActivationStructure;
219 Strong<Structure> stringStructure;
220 Strong<Structure> notAnObjectStructure;
221 Strong<Structure> propertyNameIteratorStructure;
222 Strong<Structure> getterSetterStructure;
223 Strong<Structure> apiWrapperStructure;
224 Strong<Structure> scopeChainNodeStructure;
225 Strong<Structure> executableStructure;
226 Strong<Structure> nativeExecutableStructure;
227 Strong<Structure> evalExecutableStructure;
228 Strong<Structure> programExecutableStructure;
229 Strong<Structure> functionExecutableStructure;
230 Strong<Structure> regExpStructure;
231 Strong<Structure> structureChainStructure;
232
233 IdentifierTable* identifierTable;
234 CommonIdentifiers* propertyNames;
235 const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
236 SmallStrings smallStrings;
237 NumericStrings numericStrings;
238 DateInstanceCache dateInstanceCache;
239 WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT;
240 Vector<CodeBlock*> codeBlocksBeingCompiled;
241 void startedCompiling(CodeBlock* codeBlock)
242 {
243 codeBlocksBeingCompiled.append(codeBlock);
244 }
245
246 void finishedCompiling(CodeBlock* codeBlock)
247 {
248 ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last());
249 codeBlocksBeingCompiled.removeLast();
250 }
251
252 void setInDefineOwnProperty(bool inDefineOwnProperty)
253 {
254 m_inDefineOwnProperty = inDefineOwnProperty;
255 }
256
257 bool isInDefineOwnProperty()
258 {
259 return m_inDefineOwnProperty;
260 }
261
262 #if ENABLE(ASSEMBLER)
263 ExecutableAllocator executableAllocator;
264 #endif
265
266 #if !ENABLE(JIT)
267 bool canUseJIT() { return false; } // interpreter only
268 #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
269 bool canUseJIT() { return true; } // jit only
270 #else
271 bool canUseJIT() { return m_canUseAssembler; }
272 #endif
273
274 #if !ENABLE(YARR_JIT)
275 bool canUseRegExpJIT() { return false; } // interpreter only
276 #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
277 bool canUseRegExpJIT() { return true; } // jit only
278 #else
279 bool canUseRegExpJIT() { return m_canUseAssembler; }
280 #endif
281
282 OwnPtr<ParserArena> parserArena;
283 OwnPtr<Keywords> keywords;
284 Interpreter* interpreter;
285 #if ENABLE(JIT)
286 OwnPtr<JITThunks> jitStubs;
287 MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator)
288 {
289 return jitStubs->ctiStub(this, generator);
290 }
291 NativeExecutable* getHostFunction(NativeFunction, Intrinsic);
292 #endif
293 NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
294
295 TimeoutChecker timeoutChecker;
296 Terminator terminator;
297
298 JSValue exception;
299
300 const ClassInfo* const jsArrayClassInfo;
301 const ClassInfo* const jsFinalObjectClassInfo;
302
303 LLInt::Data llintData;
304
305 ReturnAddressPtr exceptionLocation;
306 JSValue hostCallReturnValue;
307 CallFrame* callFrameForThrow;
308 void* targetMachinePCForThrow;
309 Instruction* targetInterpreterPCForThrow;
310 #if ENABLE(DFG_JIT)
311 uint32_t osrExitIndex;
312 void* osrExitJumpDestination;
313 Vector<ScratchBuffer*> scratchBuffers;
314 size_t sizeOfLastScratchBuffer;
315
316 ScratchBuffer* scratchBufferForSize(size_t size)
317 {
318 if (!size)
319 return 0;
320
321 if (size > sizeOfLastScratchBuffer) {
322 // Protect against a N^2 memory usage pathology by ensuring
323 // that at worst, we get a geometric series, meaning that the
324 // total memory usage is somewhere around
325 // max(scratch buffer size) * 4.
326 sizeOfLastScratchBuffer = size * 2;
327
328 scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer));
329 }
330
331 ScratchBuffer* result = scratchBuffers.last();
332 result->setActiveLength(0);
333 return result;
334 }
335
336 void gatherConservativeRoots(ConservativeRoots&);
337 #endif
338
339 HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
340
341 JSGlobalObject* dynamicGlobalObject;
342
343 HashSet<JSObject*> stringRecursionCheckVisitedObjects;
344
345 double cachedUTCOffset;
346 DSTOffsetCache dstOffsetCache;
347
348 UString cachedDateString;
349 double cachedDateStringValue;
350
351 int maxReentryDepth;
352
353 RegExpCache* m_regExpCache;
354 BumpPointerAllocator m_regExpAllocator;
355
356 #if ENABLE(REGEXP_TRACING)
357 typedef ListHashSet<RefPtr<RegExp> > RTTraceList;
358 RTTraceList* m_rtTraceList;
359 #endif
360
361 #ifndef NDEBUG
362 ThreadIdentifier exclusiveThread;
363 #endif
364
365 CachedTranscendentalFunction<sin> cachedSin;
366
367 JS_EXPORT_PRIVATE void resetDateCache();
368
369 JS_EXPORT_PRIVATE void startSampling();
370 JS_EXPORT_PRIVATE void stopSampling();
371 JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
372 RegExpCache* regExpCache() { return m_regExpCache; }
373 #if ENABLE(REGEXP_TRACING)
374 void addRegExpToTrace(PassRefPtr<RegExp> regExp);
375 #endif
376 JS_EXPORT_PRIVATE void dumpRegExpTrace();
377
378 bool isCollectorBusy() { return heap.isBusy(); }
379 JS_EXPORT_PRIVATE void releaseExecutableMemory();
380
381 #if ENABLE(GC_VALIDATION)
382 bool isInitializingObject() const;
383 void setInitializingObjectClass(const ClassInfo*);
384 #endif
385
386 #if CPU(X86) && ENABLE(JIT)
387 unsigned m_timeoutCount;
388 #endif
389
390 #define registerTypedArrayFunction(type, capitalizedType) \
391 void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
392 { \
393 ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
394 m_##type##ArrayDescriptor = descriptor; \
395 } \
396 const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
397
398 registerTypedArrayFunction(int8, Int8);
399 registerTypedArrayFunction(int16, Int16);
400 registerTypedArrayFunction(int32, Int32);
401 registerTypedArrayFunction(uint8, Uint8);
402 registerTypedArrayFunction(uint8Clamped, Uint8Clamped);
403 registerTypedArrayFunction(uint16, Uint16);
404 registerTypedArrayFunction(uint32, Uint32);
405 registerTypedArrayFunction(float32, Float32);
406 registerTypedArrayFunction(float64, Float64);
407 #undef registerTypedArrayFunction
408
409 JSLock& apiLock() { return m_apiLock; }
410
411 private:
412 friend class LLIntOffsetsExtractor;
413
414 JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
415 static JSGlobalData*& sharedInstanceInternal();
416 void createNativeThunk();
417 #if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
418 bool m_canUseAssembler;
419 #endif
420 #if ENABLE(GC_VALIDATION)
421 const ClassInfo* m_initializingObjectClass;
422 #endif
423 bool m_inDefineOwnProperty;
424
425 TypedArrayDescriptor m_int8ArrayDescriptor;
426 TypedArrayDescriptor m_int16ArrayDescriptor;
427 TypedArrayDescriptor m_int32ArrayDescriptor;
428 TypedArrayDescriptor m_uint8ArrayDescriptor;
429 TypedArrayDescriptor m_uint8ClampedArrayDescriptor;
430 TypedArrayDescriptor m_uint16ArrayDescriptor;
431 TypedArrayDescriptor m_uint32ArrayDescriptor;
432 TypedArrayDescriptor m_float32ArrayDescriptor;
433 TypedArrayDescriptor m_float64ArrayDescriptor;
434 };
435
436 #if ENABLE(GC_VALIDATION)
437 inline bool JSGlobalData::isInitializingObject() const
438 {
439 return !!m_initializingObjectClass;
440 }
441
442 inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
443 {
444 m_initializingObjectClass = initializingObjectClass;
445 }
446 #endif
447
448 } // namespace JSC
449
450 #endif // JSGlobalData_h