Unreviewed, rolling out r144074.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSGlobalData.h
1 /*
2  * Copyright (C) 2008, 2009, 2013 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 "JITThunks.h"
38 #include "JITThunks.h"
39 #include "JSCJSValue.h"
40 #include "JSLock.h"
41 #include "LLIntData.h"
42 #include "MacroAssemblerCodeRef.h"
43 #include "NumericStrings.h"
44 #include "ProfilerDatabase.h"
45 #include "PrivateName.h"
46 #include "PrototypeMap.h"
47 #include "SmallStrings.h"
48 #include "Strong.h"
49 #include "Terminator.h"
50 #include "ThunkGenerators.h"
51 #include "TimeoutChecker.h"
52 #include "TypedArrayDescriptor.h"
53 #include "WeakRandom.h"
54 #include <wtf/BumpPointerAllocator.h>
55 #include <wtf/Forward.h>
56 #include <wtf/HashMap.h>
57 #include <wtf/SimpleStats.h>
58 #include <wtf/ThreadSafeRefCounted.h>
59 #include <wtf/ThreadSpecific.h>
60 #include <wtf/WTFThreadData.h>
61 #if ENABLE(REGEXP_TRACING)
62 #include <wtf/ListHashSet.h>
63 #endif
64
65 struct OpaqueJSClass;
66 struct OpaqueJSClassContextData;
67
68 namespace JSC {
69
70     class CodeBlock;
71     class CodeCache;
72     class CommonIdentifiers;
73     class ExecState;
74     class HandleStack;
75     class IdentifierTable;
76     class Interpreter;
77     class JSGlobalObject;
78     class JSObject;
79     class Keywords;
80     class LLIntOffsetsExtractor;
81     class LegacyProfiler;
82     class NativeExecutable;
83     class ParserArena;
84     class RegExpCache;
85     class SourceProvider;
86     class SourceProviderCache;
87     class Stringifier;
88     class Structure;
89 #if ENABLE(REGEXP_TRACING)
90     class RegExp;
91 #endif
92     class UnlinkedCodeBlock;
93     class UnlinkedEvalCodeBlock;
94     class UnlinkedFunctionExecutable;
95     class UnlinkedProgramCodeBlock;
96
97 #if ENABLE(DFG_JIT)
98     namespace DFG {
99     class LongLivedState;
100     }
101 #endif // ENABLE(DFG_JIT)
102
103     struct HashTable;
104     struct Instruction;
105
106     struct DSTOffsetCache {
107         DSTOffsetCache()
108         {
109             reset();
110         }
111         
112         void reset()
113         {
114             offset = 0.0;
115             start = 0.0;
116             end = -1.0;
117             increment = 0.0;
118         }
119
120         double offset;
121         double start;
122         double end;
123         double increment;
124     };
125
126 #if ENABLE(DFG_JIT)
127     class ConservativeRoots;
128
129 #if COMPILER(MSVC)
130 #pragma warning(push)
131 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
132 #endif
133     struct ScratchBuffer {
134         ScratchBuffer()
135             : m_activeLength(0)
136         {
137         }
138
139         static ScratchBuffer* create(size_t size)
140         {
141             ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer;
142
143             return result;
144         }
145
146         static size_t allocationSize(size_t bufferSize) { return sizeof(ScratchBuffer) + bufferSize; }
147         void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
148         size_t activeLength() const { return m_activeLength; };
149         size_t* activeLengthPtr() { return &m_activeLength; };
150         void* dataBuffer() { return m_buffer; }
151
152         size_t m_activeLength;
153 #if CPU(MIPS) && (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == 2)
154         void* m_buffer[0] __attribute__((aligned(8)));
155 #else
156         void* m_buffer[0];
157 #endif
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(HeapType = SmallHeap);
186         JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(HeapType = SmallHeap);
187         static PassRefPtr<JSGlobalData> createContextGroup(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 #if ENABLE(ASSEMBLER)
197         // executableAllocator should be destructed after the heap, as the heap can call executableAllocator
198         // in its destructor.
199         ExecutableAllocator executableAllocator;
200 #endif
201
202         // The heap should be just after executableAllocator and before other members to ensure that it's
203         // destructed after all the objects that reference it.
204         Heap heap;
205         
206 #if ENABLE(DFG_JIT)
207         OwnPtr<DFG::LongLivedState> m_dfgState;
208 #endif // ENABLE(DFG_JIT)
209
210         GlobalDataType globalDataType;
211         ClientData* clientData;
212         ExecState* topCallFrame;
213
214         const HashTable* arrayConstructorTable;
215         const HashTable* arrayPrototypeTable;
216         const HashTable* booleanPrototypeTable;
217         const HashTable* dateTable;
218         const HashTable* dateConstructorTable;
219         const HashTable* errorPrototypeTable;
220         const HashTable* globalObjectTable;
221         const HashTable* jsonTable;
222         const HashTable* mathTable;
223         const HashTable* numberConstructorTable;
224         const HashTable* numberPrototypeTable;
225         const HashTable* objectConstructorTable;
226         const HashTable* objectPrototypeTable;
227         const HashTable* privateNamePrototypeTable;
228         const HashTable* regExpTable;
229         const HashTable* regExpConstructorTable;
230         const HashTable* regExpPrototypeTable;
231         const HashTable* stringTable;
232         const HashTable* stringConstructorTable;
233         
234         Strong<Structure> structureStructure;
235         Strong<Structure> structureRareDataStructure;
236         Strong<Structure> debuggerActivationStructure;
237         Strong<Structure> interruptedExecutionErrorStructure;
238         Strong<Structure> terminatedExecutionErrorStructure;
239         Strong<Structure> stringStructure;
240         Strong<Structure> notAnObjectStructure;
241         Strong<Structure> propertyNameIteratorStructure;
242         Strong<Structure> getterSetterStructure;
243         Strong<Structure> apiWrapperStructure;
244         Strong<Structure> JSScopeStructure;
245         Strong<Structure> executableStructure;
246         Strong<Structure> nativeExecutableStructure;
247         Strong<Structure> evalExecutableStructure;
248         Strong<Structure> programExecutableStructure;
249         Strong<Structure> functionExecutableStructure;
250         Strong<Structure> regExpStructure;
251         Strong<Structure> sharedSymbolTableStructure;
252         Strong<Structure> structureChainStructure;
253         Strong<Structure> sparseArrayValueMapStructure;
254         Strong<Structure> withScopeStructure;
255         Strong<Structure> unlinkedFunctionExecutableStructure;
256         Strong<Structure> unlinkedProgramCodeBlockStructure;
257         Strong<Structure> unlinkedEvalCodeBlockStructure;
258         Strong<Structure> unlinkedFunctionCodeBlockStructure;
259
260         IdentifierTable* identifierTable;
261         CommonIdentifiers* propertyNames;
262         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.
263         SmallStrings smallStrings;
264         NumericStrings numericStrings;
265         DateInstanceCache dateInstanceCache;
266         WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT;
267         Vector<CodeBlock*> codeBlocksBeingCompiled;
268         void startedCompiling(CodeBlock* codeBlock)
269         {
270             codeBlocksBeingCompiled.append(codeBlock);
271         }
272
273         void finishedCompiling(CodeBlock* codeBlock)
274         {
275             ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last());
276             codeBlocksBeingCompiled.removeLast();
277         }
278
279         void setInDefineOwnProperty(bool inDefineOwnProperty)
280         {
281             m_inDefineOwnProperty = inDefineOwnProperty;
282         }
283
284         bool isInDefineOwnProperty()
285         {
286             return m_inDefineOwnProperty;
287         }
288
289         LegacyProfiler* enabledProfiler()
290         {
291             return m_enabledProfiler;
292         }
293
294 #if ENABLE(JIT) && ENABLE(LLINT)
295         bool canUseJIT() { return m_canUseJIT; }
296 #elif ENABLE(JIT)
297         bool canUseJIT() { return true; } // jit only
298 #else
299         bool canUseJIT() { return false; } // interpreter only
300 #endif
301
302 #if ENABLE(YARR_JIT)
303         bool canUseRegExpJIT() { return m_canUseRegExpJIT; }
304 #else
305         bool canUseRegExpJIT() { return false; } // interpreter only
306 #endif
307
308         SourceProviderCache* addSourceProviderCache(SourceProvider*);
309         void clearSourceProviderCaches();
310
311         PrototypeMap prototypeMap;
312
313         OwnPtr<ParserArena> parserArena;
314         typedef HashMap<RefPtr<SourceProvider>, RefPtr<SourceProviderCache> > SourceProviderCacheMap;
315         SourceProviderCacheMap sourceProviderCacheMap;
316         OwnPtr<Keywords> keywords;
317         Interpreter* interpreter;
318 #if ENABLE(JIT)
319         OwnPtr<JITThunks> jitStubs;
320         MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator)
321         {
322             return jitStubs->ctiStub(this, generator);
323         }
324         NativeExecutable* getHostFunction(NativeFunction, Intrinsic);
325 #endif
326         NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
327
328         TimeoutChecker timeoutChecker;
329         Terminator terminator;
330
331         JSValue exception;
332
333         const ClassInfo* const jsArrayClassInfo;
334         const ClassInfo* const jsFinalObjectClassInfo;
335
336         ReturnAddressPtr exceptionLocation;
337         JSValue hostCallReturnValue;
338         ExecState* callFrameForThrow;
339         void* targetMachinePCForThrow;
340         Instruction* targetInterpreterPCForThrow;
341 #if ENABLE(DFG_JIT)
342         uint32_t osrExitIndex;
343         void* osrExitJumpDestination;
344         Vector<ScratchBuffer*> scratchBuffers;
345         size_t sizeOfLastScratchBuffer;
346         
347         ScratchBuffer* scratchBufferForSize(size_t size)
348         {
349             if (!size)
350                 return 0;
351             
352             if (size > sizeOfLastScratchBuffer) {
353                 // Protect against a N^2 memory usage pathology by ensuring
354                 // that at worst, we get a geometric series, meaning that the
355                 // total memory usage is somewhere around
356                 // max(scratch buffer size) * 4.
357                 sizeOfLastScratchBuffer = size * 2;
358
359                 scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer));
360             }
361
362             ScratchBuffer* result = scratchBuffers.last();
363             result->setActiveLength(0);
364             return result;
365         }
366
367         void gatherConservativeRoots(ConservativeRoots&);
368 #endif
369
370         HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
371
372         JSGlobalObject* dynamicGlobalObject;
373
374         HashSet<JSObject*> stringRecursionCheckVisitedObjects;
375
376         double cachedUTCOffset;
377         DSTOffsetCache dstOffsetCache;
378         
379         String cachedDateString;
380         double cachedDateStringValue;
381
382         LegacyProfiler* m_enabledProfiler;
383         OwnPtr<Profiler::Database> m_perBytecodeProfiler;
384         RegExpCache* m_regExpCache;
385         BumpPointerAllocator m_regExpAllocator;
386
387 #if ENABLE(REGEXP_TRACING)
388         typedef ListHashSet<RefPtr<RegExp> > RTTraceList;
389         RTTraceList* m_rtTraceList;
390 #endif
391
392 #ifndef NDEBUG
393         ThreadIdentifier exclusiveThread;
394 #endif
395
396         CachedTranscendentalFunction<sin> cachedSin;
397
398         JS_EXPORT_PRIVATE void resetDateCache();
399
400         JS_EXPORT_PRIVATE void startSampling();
401         JS_EXPORT_PRIVATE void stopSampling();
402         JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
403         RegExpCache* regExpCache() { return m_regExpCache; }
404 #if ENABLE(REGEXP_TRACING)
405         void addRegExpToTrace(PassRefPtr<RegExp> regExp);
406 #endif
407         JS_EXPORT_PRIVATE void dumpRegExpTrace();
408
409         bool isCollectorBusy() { return heap.isBusy(); }
410         JS_EXPORT_PRIVATE void releaseExecutableMemory();
411
412 #if ENABLE(GC_VALIDATION)
413         bool isInitializingObject() const; 
414         void setInitializingObjectClass(const ClassInfo*);
415 #endif
416
417 #if CPU(X86) && ENABLE(JIT)
418         unsigned m_timeoutCount;
419 #endif
420
421         unsigned m_newStringsSinceLastHashConst;
422
423         static const unsigned s_minNumberOfNewStringsToHashConst = 100;
424
425         bool haveEnoughNewStringsToHashConst() { return m_newStringsSinceLastHashConst > s_minNumberOfNewStringsToHashConst; }
426         void resetNewStringsSinceLastHashConst() { m_newStringsSinceLastHashConst = 0; }
427
428 #define registerTypedArrayFunction(type, capitalizedType) \
429         void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
430         { \
431             ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
432             m_##type##ArrayDescriptor = descriptor; \
433             ASSERT(m_##type##ArrayDescriptor.m_classInfo); \
434         } \
435         const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
436
437         registerTypedArrayFunction(int8, Int8);
438         registerTypedArrayFunction(int16, Int16);
439         registerTypedArrayFunction(int32, Int32);
440         registerTypedArrayFunction(uint8, Uint8);
441         registerTypedArrayFunction(uint8Clamped, Uint8Clamped);
442         registerTypedArrayFunction(uint16, Uint16);
443         registerTypedArrayFunction(uint32, Uint32);
444         registerTypedArrayFunction(float32, Float32);
445         registerTypedArrayFunction(float64, Float64);
446 #undef registerTypedArrayFunction
447         
448         const TypedArrayDescriptor* typedArrayDescriptor(TypedArrayType type) const
449         {
450             switch (type) {
451             case TypedArrayNone:
452                 return 0;
453             case TypedArrayInt8:
454                 return &int8ArrayDescriptor();
455             case TypedArrayInt16:
456                 return &int16ArrayDescriptor();
457             case TypedArrayInt32:
458                 return &int32ArrayDescriptor();
459             case TypedArrayUint8:
460                 return &uint8ArrayDescriptor();
461             case TypedArrayUint8Clamped:
462                 return &uint8ClampedArrayDescriptor();
463             case TypedArrayUint16:
464                 return &uint16ArrayDescriptor();
465             case TypedArrayUint32:
466                 return &uint32ArrayDescriptor();
467             case TypedArrayFloat32:
468                 return &float32ArrayDescriptor();
469             case TypedArrayFloat64:
470                 return &float64ArrayDescriptor();
471             default:
472                 CRASH();
473                 return 0;
474             }
475         }
476
477         JSLock& apiLock() { return m_apiLock; }
478         CodeCache* codeCache() { return m_codeCache.get(); }
479
480         JS_EXPORT_PRIVATE void discardAllCode();
481
482     private:
483         friend class LLIntOffsetsExtractor;
484         
485         JSGlobalData(GlobalDataType, HeapType);
486         static JSGlobalData*& sharedInstanceInternal();
487         void createNativeThunk();
488 #if ENABLE(ASSEMBLER)
489         bool m_canUseAssembler;
490 #endif
491 #if ENABLE(JIT)
492         bool m_canUseJIT;
493 #endif
494 #if ENABLE(YARR_JIT)
495         bool m_canUseRegExpJIT;
496 #endif
497 #if ENABLE(GC_VALIDATION)
498         const ClassInfo* m_initializingObjectClass;
499 #endif
500         bool m_inDefineOwnProperty;
501         OwnPtr<CodeCache> m_codeCache;
502
503         TypedArrayDescriptor m_int8ArrayDescriptor;
504         TypedArrayDescriptor m_int16ArrayDescriptor;
505         TypedArrayDescriptor m_int32ArrayDescriptor;
506         TypedArrayDescriptor m_uint8ArrayDescriptor;
507         TypedArrayDescriptor m_uint8ClampedArrayDescriptor;
508         TypedArrayDescriptor m_uint16ArrayDescriptor;
509         TypedArrayDescriptor m_uint32ArrayDescriptor;
510         TypedArrayDescriptor m_float32ArrayDescriptor;
511         TypedArrayDescriptor m_float64ArrayDescriptor;
512     };
513
514 #if ENABLE(GC_VALIDATION)
515     inline bool JSGlobalData::isInitializingObject() const
516     {
517         return !!m_initializingObjectClass;
518     }
519
520     inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
521     {
522         m_initializingObjectClass = initializingObjectClass;
523     }
524 #endif
525
526     inline Heap* WeakSet::heap() const
527     {
528         return &m_globalData->heap;
529     }
530
531 } // namespace JSC
532
533 #endif // JSGlobalData_h