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 "SmallStrings.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>
59 struct OpaqueJSClassContextData
;
64 class CommonIdentifiers
;
66 class IdentifierTable
;
71 class LLIntOffsetsExtractor
;
72 class NativeExecutable
;
78 #if ENABLE(REGEXP_TRACING)
85 struct DSTOffsetCache
{
105 enum ThreadStackType
{
106 ThreadStackTypeLarge
,
110 struct TypedArrayDescriptor
{
111 TypedArrayDescriptor()
117 TypedArrayDescriptor(const ClassInfo
* classInfo
, size_t storageOffset
, size_t lengthOffset
)
118 : m_classInfo(classInfo
)
119 , m_storageOffset(storageOffset
)
120 , m_lengthOffset(lengthOffset
)
123 const ClassInfo
* m_classInfo
;
124 size_t m_storageOffset
;
125 size_t m_lengthOffset
;
129 class ConservativeRoots
;
131 struct ScratchBuffer
{
137 static ScratchBuffer
* create(size_t size
)
139 ScratchBuffer
* result
= new (fastMalloc(ScratchBuffer::allocationSize(size
))) ScratchBuffer
;
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
; }
150 size_t m_activeLength
;
155 class JSGlobalData
: public ThreadSafeRefCounted
<JSGlobalData
> {
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
165 enum GlobalDataType
{ Default
, APIContextGroup
, APIShared
};
168 JS_EXPORT_PRIVATE
virtual ~ClientData() = 0;
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();
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();
181 void makeUsableFromMultipleThreads() { heap
.machineThreads().makeUsableFromMultipleThreads(); }
187 Heap heap
; // The heap is our first data member to ensure that it's destructed after all the objects that reference it.
189 GlobalDataType globalDataType
;
190 ClientData
* clientData
;
191 CallFrame
* topCallFrame
;
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
;
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
;
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
)
243 codeBlocksBeingCompiled
.append(codeBlock
);
246 void finishedCompiling(CodeBlock
* codeBlock
)
248 ASSERT_UNUSED(codeBlock
, codeBlock
== codeBlocksBeingCompiled
.last());
249 codeBlocksBeingCompiled
.removeLast();
252 void setInDefineOwnProperty(bool inDefineOwnProperty
)
254 m_inDefineOwnProperty
= inDefineOwnProperty
;
257 bool isInDefineOwnProperty()
259 return m_inDefineOwnProperty
;
262 #if ENABLE(ASSEMBLER)
263 ExecutableAllocator executableAllocator
;
267 bool canUseJIT() { return false; } // interpreter only
268 #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
269 bool canUseJIT() { return true; } // jit only
271 bool canUseJIT() { return m_canUseAssembler
; }
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
279 bool canUseRegExpJIT() { return m_canUseAssembler
; }
282 OwnPtr
<ParserArena
> parserArena
;
283 OwnPtr
<Keywords
> keywords
;
284 Interpreter
* interpreter
;
286 OwnPtr
<JITThunks
> jitStubs
;
287 MacroAssemblerCodeRef
getCTIStub(ThunkGenerator generator
)
289 return jitStubs
->ctiStub(this, generator
);
291 NativeExecutable
* getHostFunction(NativeFunction
, Intrinsic
);
293 NativeExecutable
* getHostFunction(NativeFunction
, NativeFunction constructor
);
295 TimeoutChecker timeoutChecker
;
296 Terminator terminator
;
300 const ClassInfo
* const jsArrayClassInfo
;
301 const ClassInfo
* const jsFinalObjectClassInfo
;
303 LLInt::Data llintData
;
305 ReturnAddressPtr exceptionLocation
;
306 JSValue hostCallReturnValue
;
307 CallFrame
* callFrameForThrow
;
308 void* targetMachinePCForThrow
;
309 Instruction
* targetInterpreterPCForThrow
;
311 uint32_t osrExitIndex
;
312 void* osrExitJumpDestination
;
313 Vector
<ScratchBuffer
*> scratchBuffers
;
314 size_t sizeOfLastScratchBuffer
;
316 ScratchBuffer
* scratchBufferForSize(size_t size
)
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;
328 scratchBuffers
.append(ScratchBuffer::create(sizeOfLastScratchBuffer
));
331 ScratchBuffer
* result
= scratchBuffers
.last();
332 result
->setActiveLength(0);
336 void gatherConservativeRoots(ConservativeRoots
&);
339 HashMap
<OpaqueJSClass
*, OwnPtr
<OpaqueJSClassContextData
> > opaqueJSClassData
;
341 JSGlobalObject
* dynamicGlobalObject
;
343 HashSet
<JSObject
*> stringRecursionCheckVisitedObjects
;
345 double cachedUTCOffset
;
346 DSTOffsetCache dstOffsetCache
;
348 UString cachedDateString
;
349 double cachedDateStringValue
;
353 RegExpCache
* m_regExpCache
;
354 BumpPointerAllocator m_regExpAllocator
;
356 #if ENABLE(REGEXP_TRACING)
357 typedef ListHashSet
<RefPtr
<RegExp
> > RTTraceList
;
358 RTTraceList
* m_rtTraceList
;
362 ThreadIdentifier exclusiveThread
;
365 CachedTranscendentalFunction
<sin
> cachedSin
;
367 JS_EXPORT_PRIVATE
void resetDateCache();
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
);
376 JS_EXPORT_PRIVATE
void dumpRegExpTrace();
378 bool isCollectorBusy() { return heap
.isBusy(); }
379 JS_EXPORT_PRIVATE
void releaseExecutableMemory();
381 #if ENABLE(GC_VALIDATION)
382 bool isInitializingObject() const;
383 void setInitializingObjectClass(const ClassInfo
*);
386 #if CPU(X86) && ENABLE(JIT)
387 unsigned m_timeoutCount
;
390 #define registerTypedArrayFunction(type, capitalizedType) \
391 void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
393 ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
394 m_##type##ArrayDescriptor = descriptor; \
396 const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
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
409 JSLock
& apiLock() { return m_apiLock
; }
412 friend class LLIntOffsetsExtractor
;
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
;
420 #if ENABLE(GC_VALIDATION)
421 const ClassInfo
* m_initializingObjectClass
;
423 bool m_inDefineOwnProperty
;
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
;
436 #if ENABLE(GC_VALIDATION)
437 inline bool JSGlobalData::isInitializingObject() const
439 return !!m_initializingObjectClass
;
442 inline void JSGlobalData::setInitializingObjectClass(const ClassInfo
* initializingObjectClass
)
444 m_initializingObjectClass
= initializingObjectClass
;
450 #endif // JSGlobalData_h