d185e18653cf7a2b6df995a1d3f48fd4ad3b91fd
[framework/web/webkit-efl.git] / Source / JavaScriptCore / 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 "PrivateName.h"
43 #include "SmallStrings.h"
44 #include "Strong.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>
57 #endif
58
59 struct OpaqueJSClass;
60 struct OpaqueJSClassContextData;
61
62 namespace JSC {
63
64     class CodeBlock;
65     class CommonIdentifiers;
66     class HandleStack;
67     class IdentifierTable;
68     class Interpreter;
69     class JSGlobalObject;
70     class JSObject;
71     class Keywords;
72     class LLIntOffsetsExtractor;
73     class NativeExecutable;
74     class ParserArena;
75     class Profiler;
76     class RegExpCache;
77     class Stringifier;
78     class Structure;
79     class UString;
80 #if ENABLE(REGEXP_TRACING)
81     class RegExp;
82 #endif
83
84     struct HashTable;
85     struct Instruction;
86
87     struct DSTOffsetCache {
88         DSTOffsetCache()
89         {
90             reset();
91         }
92         
93         void reset()
94         {
95             offset = 0.0;
96             start = 0.0;
97             end = -1.0;
98             increment = 0.0;
99         }
100
101         double offset;
102         double start;
103         double end;
104         double increment;
105     };
106
107     enum ThreadStackType {
108         ThreadStackTypeLarge,
109         ThreadStackTypeSmall
110     };
111
112     struct TypedArrayDescriptor {
113         TypedArrayDescriptor()
114             : m_classInfo(0)
115             , m_storageOffset(0)
116             , m_lengthOffset(0)
117         {
118         }
119         TypedArrayDescriptor(const ClassInfo* classInfo, size_t storageOffset, size_t lengthOffset)
120             : m_classInfo(classInfo)
121             , m_storageOffset(storageOffset)
122             , m_lengthOffset(lengthOffset)
123         {
124         }
125         const ClassInfo* m_classInfo;
126         size_t m_storageOffset;
127         size_t m_lengthOffset;
128     };
129
130 #if ENABLE(DFG_JIT)
131     class ConservativeRoots;
132
133 #if COMPILER(MSVC)
134 #pragma warning(push)
135 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
136 #endif
137     struct ScratchBuffer {
138         ScratchBuffer()
139             : m_activeLength(0)
140         {
141         }
142
143         static ScratchBuffer* create(size_t size)
144         {
145             ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer;
146
147             return result;
148         }
149
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; }
155
156         size_t m_activeLength;
157         void* m_buffer[0];
158     };
159 #if COMPILER(MSVC)
160 #pragma warning(pop)
161 #endif
162 #endif
163
164     class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {
165     public:
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
173         // the original API.
174         enum GlobalDataType { Default, APIContextGroup, APIShared };
175         
176         struct ClientData {
177             JS_EXPORT_PRIVATE virtual ~ClientData() = 0;
178         };
179
180         bool isSharedInstance() { return globalDataType == APIShared; }
181         bool usingAPI() { return globalDataType != Default; }
182         static bool sharedInstanceExists();
183         JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
184
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();
189
190         void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
191
192     private:
193         JSLock m_apiLock;
194
195     public:
196         Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it.
197
198         GlobalDataType globalDataType;
199         ClientData* clientData;
200         CallFrame* topCallFrame;
201
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;
221         
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;
242
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)
252         {
253             codeBlocksBeingCompiled.append(codeBlock);
254         }
255
256         void finishedCompiling(CodeBlock* codeBlock)
257         {
258             ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last());
259             codeBlocksBeingCompiled.removeLast();
260         }
261
262         void setInDefineOwnProperty(bool inDefineOwnProperty)
263         {
264             m_inDefineOwnProperty = inDefineOwnProperty;
265         }
266
267         bool isInDefineOwnProperty()
268         {
269             return m_inDefineOwnProperty;
270         }
271
272         Profiler* enabledProfiler()
273         {
274             return m_enabledProfiler;
275         }
276
277 #if ENABLE(ASSEMBLER)
278         ExecutableAllocator executableAllocator;
279 #endif
280
281 #if !ENABLE(JIT)
282         bool canUseJIT() { return false; } // interpreter only
283 #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
284         bool canUseJIT() { return true; } // jit only
285 #else
286         bool canUseJIT() { return m_canUseAssembler; }
287 #endif
288
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
293 #else
294         bool canUseRegExpJIT() { return m_canUseAssembler; }
295 #endif
296
297         PrivateName m_inheritorIDKey;
298
299         OwnPtr<ParserArena> parserArena;
300         OwnPtr<Keywords> keywords;
301         Interpreter* interpreter;
302 #if ENABLE(JIT)
303         OwnPtr<JITThunks> jitStubs;
304         MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator)
305         {
306             return jitStubs->ctiStub(this, generator);
307         }
308         NativeExecutable* getHostFunction(NativeFunction, Intrinsic);
309 #endif
310         NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
311
312         TimeoutChecker timeoutChecker;
313         Terminator terminator;
314
315         JSValue exception;
316
317         const ClassInfo* const jsArrayClassInfo;
318         const ClassInfo* const jsFinalObjectClassInfo;
319
320         ReturnAddressPtr exceptionLocation;
321         JSValue hostCallReturnValue;
322         CallFrame* callFrameForThrow;
323         void* targetMachinePCForThrow;
324         Instruction* targetInterpreterPCForThrow;
325 #if ENABLE(DFG_JIT)
326         uint32_t osrExitIndex;
327         void* osrExitJumpDestination;
328         Vector<ScratchBuffer*> scratchBuffers;
329         size_t sizeOfLastScratchBuffer;
330         
331         ScratchBuffer* scratchBufferForSize(size_t size)
332         {
333             if (!size)
334                 return 0;
335             
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;
342
343                 scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer));
344             }
345
346             ScratchBuffer* result = scratchBuffers.last();
347             result->setActiveLength(0);
348             return result;
349         }
350
351         void gatherConservativeRoots(ConservativeRoots&);
352 #endif
353
354         HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
355
356         JSGlobalObject* dynamicGlobalObject;
357
358         HashSet<JSObject*> stringRecursionCheckVisitedObjects;
359
360         double cachedUTCOffset;
361         DSTOffsetCache dstOffsetCache;
362         
363         UString cachedDateString;
364         double cachedDateStringValue;
365
366         int maxReentryDepth;
367
368         Profiler* m_enabledProfiler;
369         RegExpCache* m_regExpCache;
370         BumpPointerAllocator m_regExpAllocator;
371
372 #if ENABLE(REGEXP_TRACING)
373         typedef ListHashSet<RefPtr<RegExp> > RTTraceList;
374         RTTraceList* m_rtTraceList;
375 #endif
376
377 #ifndef NDEBUG
378         ThreadIdentifier exclusiveThread;
379 #endif
380
381         CachedTranscendentalFunction<sin> cachedSin;
382
383         JS_EXPORT_PRIVATE void resetDateCache();
384
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);
391 #endif
392         JS_EXPORT_PRIVATE void dumpRegExpTrace();
393
394         bool isCollectorBusy() { return heap.isBusy(); }
395         JS_EXPORT_PRIVATE void releaseExecutableMemory();
396
397 #if ENABLE(GC_VALIDATION)
398         bool isInitializingObject() const; 
399         void setInitializingObjectClass(const ClassInfo*);
400 #endif
401
402 #if CPU(X86) && ENABLE(JIT)
403         unsigned m_timeoutCount;
404 #endif
405
406         unsigned m_newStringsSinceLastHashConst;
407
408         static const unsigned s_minNumberOfNewStringsToHashConst = 100;
409
410         bool haveEnoughNewStringsToHashConst() { return m_newStringsSinceLastHashConst > s_minNumberOfNewStringsToHashConst; }
411         void resetNewStringsSinceLastHashConst() { m_newStringsSinceLastHashConst = 0; }
412
413 #define registerTypedArrayFunction(type, capitalizedType) \
414         void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
415         { \
416             ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
417             m_##type##ArrayDescriptor = descriptor; \
418         } \
419         const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
420
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
431
432         JSLock& apiLock() { return m_apiLock; }
433
434     private:
435         friend class LLIntOffsetsExtractor;
436         
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;
442 #endif
443 #if ENABLE(GC_VALIDATION)
444         const ClassInfo* m_initializingObjectClass;
445 #endif
446         bool m_inDefineOwnProperty;
447
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;
457     };
458
459 #if ENABLE(GC_VALIDATION)
460     inline bool JSGlobalData::isInitializingObject() const
461     {
462         return !!m_initializingObjectClass;
463     }
464
465     inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
466     {
467         m_initializingObjectClass = initializingObjectClass;
468     }
469 #endif
470
471 } // namespace JSC
472
473 #endif // JSGlobalData_h