2 * Copyright (C) 2008, 2009 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.
29 #ifndef JSGlobalData_h
30 #define JSGlobalData_h
32 #include "CachedTranscendentalFunction.h"
33 #include "DateInstanceCache.h"
34 #include "ExecutableAllocator.h"
36 #include "Intrinsic.h"
40 #include "LLIntData.h"
41 #include "NumericStrings.h"
42 #include "PrivateName.h"
43 #include "SmallStrings.h"
45 #include "Terminator.h"
46 #include "TimeoutChecker.h"
47 #include "WeakRandom.h"
48 #include <wtf/BumpPointerAllocator.h>
49 #include <wtf/Forward.h>
50 #include <wtf/HashMap.h>
51 #include <wtf/SimpleStats.h>
52 #include <wtf/ThreadSafeRefCounted.h>
53 #include <wtf/ThreadSpecific.h>
54 #include <wtf/WTFThreadData.h>
55 #if ENABLE(REGEXP_TRACING)
56 #include <wtf/ListHashSet.h>
60 struct OpaqueJSClassContextData;
65 class CommonIdentifiers;
67 class IdentifierTable;
72 class LLIntOffsetsExtractor;
73 class NativeExecutable;
80 #if ENABLE(REGEXP_TRACING)
87 struct DSTOffsetCache {
107 enum ThreadStackType {
108 ThreadStackTypeLarge,
112 struct TypedArrayDescriptor {
113 TypedArrayDescriptor()
119 TypedArrayDescriptor(const ClassInfo* classInfo, size_t storageOffset, size_t lengthOffset)
120 : m_classInfo(classInfo)
121 , m_storageOffset(storageOffset)
122 , m_lengthOffset(lengthOffset)
125 const ClassInfo* m_classInfo;
126 size_t m_storageOffset;
127 size_t m_lengthOffset;
131 class ConservativeRoots;
134 #pragma warning(push)
135 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
137 struct ScratchBuffer {
143 static ScratchBuffer* create(size_t size)
145 ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer;
150 static size_t allocationSize(size_t bufferSize) { return sizeof(size_t) + bufferSize; }
151 void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
152 size_t activeLength() const { return m_activeLength; };
153 size_t* activeLengthPtr() { return &m_activeLength; };
154 void* dataBuffer() { return m_buffer; }
156 size_t m_activeLength;
164 class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {
166 // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
167 // either create() or createLeaked() should only be called once
168 // on a thread, this is the 'default' JSGlobalData (it uses the
169 // thread's default string uniquing table from wtfThreadData).
170 // API contexts created using the new context group aware interface
171 // create APIContextGroup objects which require less locking of JSC
172 // than the old singleton APIShared JSGlobalData created for use by
174 enum GlobalDataType { Default, APIContextGroup, APIShared };
177 JS_EXPORT_PRIVATE virtual ~ClientData() = 0;
180 bool isSharedInstance() { return globalDataType == APIShared; }
181 bool usingAPI() { return globalDataType != Default; }
182 static bool sharedInstanceExists();
183 JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
185 JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapType = SmallHeap);
186 JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapType = SmallHeap);
187 static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapType = SmallHeap);
188 JS_EXPORT_PRIVATE ~JSGlobalData();
190 void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
196 Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it.
198 GlobalDataType globalDataType;
199 ClientData* clientData;
200 CallFrame* topCallFrame;
202 const HashTable* arrayConstructorTable;
203 const HashTable* arrayPrototypeTable;
204 const HashTable* booleanPrototypeTable;
205 const HashTable* dateTable;
206 const HashTable* dateConstructorTable;
207 const HashTable* errorPrototypeTable;
208 const HashTable* globalObjectTable;
209 const HashTable* jsonTable;
210 const HashTable* mathTable;
211 const HashTable* numberConstructorTable;
212 const HashTable* numberPrototypeTable;
213 const HashTable* objectConstructorTable;
214 const HashTable* objectPrototypeTable;
215 const HashTable* privateNamePrototypeTable;
216 const HashTable* regExpTable;
217 const HashTable* regExpConstructorTable;
218 const HashTable* regExpPrototypeTable;
219 const HashTable* stringTable;
220 const HashTable* stringConstructorTable;
222 Strong<Structure> structureStructure;
223 Strong<Structure> debuggerActivationStructure;
224 Strong<Structure> activationStructure;
225 Strong<Structure> interruptedExecutionErrorStructure;
226 Strong<Structure> terminatedExecutionErrorStructure;
227 Strong<Structure> staticScopeStructure;
228 Strong<Structure> strictEvalActivationStructure;
229 Strong<Structure> stringStructure;
230 Strong<Structure> notAnObjectStructure;
231 Strong<Structure> propertyNameIteratorStructure;
232 Strong<Structure> getterSetterStructure;
233 Strong<Structure> apiWrapperStructure;
234 Strong<Structure> scopeChainNodeStructure;
235 Strong<Structure> executableStructure;
236 Strong<Structure> nativeExecutableStructure;
237 Strong<Structure> evalExecutableStructure;
238 Strong<Structure> programExecutableStructure;
239 Strong<Structure> functionExecutableStructure;
240 Strong<Structure> regExpStructure;
241 Strong<Structure> structureChainStructure;
243 IdentifierTable* identifierTable;
244 CommonIdentifiers* propertyNames;
245 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.
246 SmallStrings smallStrings;
247 NumericStrings numericStrings;
248 DateInstanceCache dateInstanceCache;
249 WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT;
250 Vector<CodeBlock*> codeBlocksBeingCompiled;
251 void startedCompiling(CodeBlock* codeBlock)
253 codeBlocksBeingCompiled.append(codeBlock);
256 void finishedCompiling(CodeBlock* codeBlock)
258 ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last());
259 codeBlocksBeingCompiled.removeLast();
262 void setInDefineOwnProperty(bool inDefineOwnProperty)
264 m_inDefineOwnProperty = inDefineOwnProperty;
267 bool isInDefineOwnProperty()
269 return m_inDefineOwnProperty;
272 Profiler* enabledProfiler()
274 return m_enabledProfiler;
277 #if ENABLE(ASSEMBLER)
278 ExecutableAllocator executableAllocator;
282 bool canUseJIT() { return false; } // interpreter only
283 #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
284 bool canUseJIT() { return true; } // jit only
286 bool canUseJIT() { return m_canUseAssembler; }
289 #if !ENABLE(YARR_JIT)
290 bool canUseRegExpJIT() { return false; } // interpreter only
291 #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
292 bool canUseRegExpJIT() { return true; } // jit only
294 bool canUseRegExpJIT() { return m_canUseAssembler; }
297 PrivateName m_inheritorIDKey;
299 OwnPtr<ParserArena> parserArena;
300 OwnPtr<Keywords> keywords;
301 Interpreter* interpreter;
303 OwnPtr<JITThunks> jitStubs;
304 MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator)
306 return jitStubs->ctiStub(this, generator);
308 NativeExecutable* getHostFunction(NativeFunction, Intrinsic);
310 NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
312 TimeoutChecker timeoutChecker;
313 Terminator terminator;
317 const ClassInfo* const jsArrayClassInfo;
318 const ClassInfo* const jsFinalObjectClassInfo;
320 ReturnAddressPtr exceptionLocation;
321 JSValue hostCallReturnValue;
322 CallFrame* callFrameForThrow;
323 void* targetMachinePCForThrow;
324 Instruction* targetInterpreterPCForThrow;
326 uint32_t osrExitIndex;
327 void* osrExitJumpDestination;
328 Vector<ScratchBuffer*> scratchBuffers;
329 size_t sizeOfLastScratchBuffer;
331 ScratchBuffer* scratchBufferForSize(size_t size)
336 if (size > sizeOfLastScratchBuffer) {
337 // Protect against a N^2 memory usage pathology by ensuring
338 // that at worst, we get a geometric series, meaning that the
339 // total memory usage is somewhere around
340 // max(scratch buffer size) * 4.
341 sizeOfLastScratchBuffer = size * 2;
343 scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer));
346 ScratchBuffer* result = scratchBuffers.last();
347 result->setActiveLength(0);
351 void gatherConservativeRoots(ConservativeRoots&);
354 HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
356 JSGlobalObject* dynamicGlobalObject;
358 HashSet<JSObject*> stringRecursionCheckVisitedObjects;
360 double cachedUTCOffset;
361 DSTOffsetCache dstOffsetCache;
363 UString cachedDateString;
364 double cachedDateStringValue;
368 Profiler* m_enabledProfiler;
369 RegExpCache* m_regExpCache;
370 BumpPointerAllocator m_regExpAllocator;
372 #if ENABLE(REGEXP_TRACING)
373 typedef ListHashSet<RefPtr<RegExp> > RTTraceList;
374 RTTraceList* m_rtTraceList;
378 ThreadIdentifier exclusiveThread;
381 CachedTranscendentalFunction<sin> cachedSin;
383 JS_EXPORT_PRIVATE void resetDateCache();
385 JS_EXPORT_PRIVATE void startSampling();
386 JS_EXPORT_PRIVATE void stopSampling();
387 JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
388 RegExpCache* regExpCache() { return m_regExpCache; }
389 #if ENABLE(REGEXP_TRACING)
390 void addRegExpToTrace(PassRefPtr<RegExp> regExp);
392 JS_EXPORT_PRIVATE void dumpRegExpTrace();
394 bool isCollectorBusy() { return heap.isBusy(); }
395 JS_EXPORT_PRIVATE void releaseExecutableMemory();
397 #if ENABLE(GC_VALIDATION)
398 bool isInitializingObject() const;
399 void setInitializingObjectClass(const ClassInfo*);
402 #if CPU(X86) && ENABLE(JIT)
403 unsigned m_timeoutCount;
406 unsigned m_newStringsSinceLastHashConst;
408 static const unsigned s_minNumberOfNewStringsToHashConst = 100;
410 bool haveEnoughNewStringsToHashConst() { return m_newStringsSinceLastHashConst > s_minNumberOfNewStringsToHashConst; }
411 void resetNewStringsSinceLastHashConst() { m_newStringsSinceLastHashConst = 0; }
413 #define registerTypedArrayFunction(type, capitalizedType) \
414 void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
416 ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
417 m_##type##ArrayDescriptor = descriptor; \
419 const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
421 registerTypedArrayFunction(int8, Int8);
422 registerTypedArrayFunction(int16, Int16);
423 registerTypedArrayFunction(int32, Int32);
424 registerTypedArrayFunction(uint8, Uint8);
425 registerTypedArrayFunction(uint8Clamped, Uint8Clamped);
426 registerTypedArrayFunction(uint16, Uint16);
427 registerTypedArrayFunction(uint32, Uint32);
428 registerTypedArrayFunction(float32, Float32);
429 registerTypedArrayFunction(float64, Float64);
430 #undef registerTypedArrayFunction
432 JSLock& apiLock() { return m_apiLock; }
435 friend class LLIntOffsetsExtractor;
437 JSGlobalData(GlobalDataType, ThreadStackType, HeapType);
438 static JSGlobalData*& sharedInstanceInternal();
439 void createNativeThunk();
440 #if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
441 bool m_canUseAssembler;
443 #if ENABLE(GC_VALIDATION)
444 const ClassInfo* m_initializingObjectClass;
446 bool m_inDefineOwnProperty;
448 TypedArrayDescriptor m_int8ArrayDescriptor;
449 TypedArrayDescriptor m_int16ArrayDescriptor;
450 TypedArrayDescriptor m_int32ArrayDescriptor;
451 TypedArrayDescriptor m_uint8ArrayDescriptor;
452 TypedArrayDescriptor m_uint8ClampedArrayDescriptor;
453 TypedArrayDescriptor m_uint16ArrayDescriptor;
454 TypedArrayDescriptor m_uint32ArrayDescriptor;
455 TypedArrayDescriptor m_float32ArrayDescriptor;
456 TypedArrayDescriptor m_float64ArrayDescriptor;
459 #if ENABLE(GC_VALIDATION)
460 inline bool JSGlobalData::isInitializingObject() const
462 return !!m_initializingObjectClass;
465 inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
467 m_initializingObjectClass = initializingObjectClass;
473 #endif // JSGlobalData_h