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 "Heap.h"
34 #include "DateInstanceCache.h"
35 #include "ExecutableAllocator.h"
36 #include "Strong.h"
37 #include "JITStubs.h"
38 #include "JSValue.h"
39 #include "NumericStrings.h"
40 #include "SmallStrings.h"
41 #include "Terminator.h"
42 #include "TimeoutChecker.h"
43 #include "WeakRandom.h"
44 #include <wtf/BumpPointerAllocator.h>
45 #include <wtf/DateMath.h>
46 #include <wtf/Forward.h>
47 #include <wtf/HashMap.h>
48 #include <wtf/RefCounted.h>
49 #include <wtf/ThreadSpecific.h>
50 #include <wtf/WTFThreadData.h>
51 #if ENABLE(REGEXP_TRACING)
52 #include <wtf/ListHashSet.h>
53 #endif
54 
55 struct OpaqueJSClass;
56 struct OpaqueJSClassContextData;
57 
58 namespace JSC {
59 
60     class CodeBlock;
61     class CommonIdentifiers;
62     class HandleStack;
63     class IdentifierTable;
64     class Interpreter;
65     class JSGlobalObject;
66     class JSObject;
67     class Lexer;
68     class NativeExecutable;
69     class Parser;
70     class RegExpCache;
71     class Stringifier;
72     class Structure;
73     class UString;
74 #if ENABLE(REGEXP_TRACING)
75     class RegExp;
76 #endif
77 
78     struct HashTable;
79     struct Instruction;
80 
81     struct LocalTimeOffsetCache {
LocalTimeOffsetCacheLocalTimeOffsetCache82         LocalTimeOffsetCache()
83             : start(0.0)
84             , end(-1.0)
85             , increment(0.0)
86         {
87         }
88 
resetLocalTimeOffsetCache89         void reset()
90         {
91             offset = LocalTimeOffset();
92             start = 0.0;
93             end = -1.0;
94             increment = 0.0;
95         }
96 
97         LocalTimeOffset offset;
98         double start;
99         double end;
100         double increment;
101     };
102 
103     enum ThreadStackType {
104         ThreadStackTypeLarge,
105         ThreadStackTypeSmall
106     };
107 
108     class JSGlobalData : public RefCounted<JSGlobalData> {
109     public:
110         // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
111         // either create() or createLeaked() should only be called once
112         // on a thread, this is the 'default' JSGlobalData (it uses the
113         // thread's default string uniquing table from wtfThreadData).
114         // API contexts created using the new context group aware interface
115         // create APIContextGroup objects which require less locking of JSC
116         // than the old singleton APIShared JSGlobalData created for use by
117         // the original API.
118         enum GlobalDataType { Default, APIContextGroup, APIShared };
119 
120         struct ClientData {
121             virtual ~ClientData() = 0;
122         };
123 
isSharedInstance()124         bool isSharedInstance() { return globalDataType == APIShared; }
usingAPI()125         bool usingAPI() { return globalDataType != Default; }
126         static bool sharedInstanceExists();
127         static JSGlobalData& sharedInstance();
128 
129         static PassRefPtr<JSGlobalData> create(ThreadStackType);
130         static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType);
131         static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType);
132         ~JSGlobalData();
133 
134 #if ENABLE(JSC_MULTIPLE_THREADS)
135         // Will start tracking threads that use the heap, which is resource-heavy.
makeUsableFromMultipleThreads()136         void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
137 #endif
138 
139         GlobalDataType globalDataType;
140         ClientData* clientData;
141 
142         const HashTable* arrayTable;
143         const HashTable* dateTable;
144         const HashTable* jsonTable;
145         const HashTable* mathTable;
146         const HashTable* numberTable;
147         const HashTable* objectConstructorTable;
148         const HashTable* regExpTable;
149         const HashTable* regExpConstructorTable;
150         const HashTable* stringTable;
151 
152         Strong<Structure> structureStructure;
153         Strong<Structure> debuggerActivationStructure;
154         Strong<Structure> activationStructure;
155         Strong<Structure> interruptedExecutionErrorStructure;
156         Strong<Structure> terminatedExecutionErrorStructure;
157         Strong<Structure> staticScopeStructure;
158         Strong<Structure> strictEvalActivationStructure;
159         Strong<Structure> stringStructure;
160         Strong<Structure> notAnObjectStructure;
161         Strong<Structure> propertyNameIteratorStructure;
162         Strong<Structure> getterSetterStructure;
163         Strong<Structure> apiWrapperStructure;
164         Strong<Structure> scopeChainNodeStructure;
165         Strong<Structure> executableStructure;
166         Strong<Structure> nativeExecutableStructure;
167         Strong<Structure> evalExecutableStructure;
168         Strong<Structure> programExecutableStructure;
169         Strong<Structure> functionExecutableStructure;
170         Strong<Structure> dummyMarkableCellStructure;
171         Strong<Structure> structureChainStructure;
172 
173 #if ENABLE(JSC_ZOMBIES)
174         Strong<Structure> zombieStructure;
175 #endif
176 
177         static void storeVPtrs();
178         static JS_EXPORTDATA void* jsArrayVPtr;
179         static JS_EXPORTDATA void* jsByteArrayVPtr;
180         static JS_EXPORTDATA void* jsStringVPtr;
181         static JS_EXPORTDATA void* jsFunctionVPtr;
182 
183         IdentifierTable* identifierTable;
184         CommonIdentifiers* propertyNames;
185         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.
186         SmallStrings smallStrings;
187         NumericStrings numericStrings;
188         DateInstanceCache dateInstanceCache;
189 
190 #if ENABLE(ASSEMBLER)
191         ExecutableAllocator executableAllocator;
192         ExecutableAllocator regexAllocator;
193 #endif
194 
195 #if !ENABLE(JIT)
canUseJIT()196         bool canUseJIT() { return false; } // interpreter only
197 #elif !ENABLE(INTERPRETER)
canUseJIT()198         bool canUseJIT() { return true; } // jit only
199 #else
canUseJIT()200         bool canUseJIT() { return m_canUseJIT; }
201 #endif
202 
stack()203         const StackBounds& stack()
204         {
205             return (globalDataType == Default)
206                 ? m_stack
207                 : wtfThreadData().stack();
208         }
209 
210         Lexer* lexer;
211         Parser* parser;
212         Interpreter* interpreter;
213 #if ENABLE(JIT)
214         OwnPtr<JITThunks> jitStubs;
getCTIStub(ThunkGenerator generator)215         MacroAssemblerCodePtr getCTIStub(ThunkGenerator generator)
216         {
217             return jitStubs->ctiStub(this, generator);
218         }
219         NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator);
220 #endif
221         NativeExecutable* getHostFunction(NativeFunction);
222 
223         TimeoutChecker timeoutChecker;
224         Terminator terminator;
225         Heap heap;
226 
227         JSValue exception;
228 #if ENABLE(JIT)
229         ReturnAddressPtr exceptionLocation;
230 #endif
231 
232         HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
233 
234         unsigned globalObjectCount;
235         JSGlobalObject* dynamicGlobalObject;
236 
237         HashSet<JSObject*> stringRecursionCheckVisitedObjects;
238 
239         LocalTimeOffsetCache localTimeOffsetCache;
240 
241         UString cachedDateString;
242         double cachedDateStringValue;
243 
244         int maxReentryDepth;
245 
246         RegExpCache* m_regExpCache;
247         BumpPointerAllocator m_regExpAllocator;
248 
249 #if ENABLE(REGEXP_TRACING)
250         typedef ListHashSet<RefPtr<RegExp> > RTTraceList;
251         RTTraceList* m_rtTraceList;
252 #endif
253 
254 #ifndef NDEBUG
255         ThreadIdentifier exclusiveThread;
256 #endif
257 
258         CachedTranscendentalFunction<sin> cachedSin;
259 
260         void resetDateCache();
261 
262         void startSampling();
263         void stopSampling();
264         void dumpSampleData(ExecState* exec);
265         void recompileAllJSFunctions();
regExpCache()266         RegExpCache* regExpCache() { return m_regExpCache; }
267 #if ENABLE(REGEXP_TRACING)
268         void addRegExpToTrace(PassRefPtr<RegExp> regExp);
269 #endif
270         void dumpRegExpTrace();
allocateGlobalHandle()271         HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); }
allocateLocalHandle()272         HandleSlot allocateLocalHandle() { return heap.allocateLocalHandle(); }
273         void clearBuiltinStructures();
274 
275     private:
276         JSGlobalData(GlobalDataType, ThreadStackType);
277         static JSGlobalData*& sharedInstanceInternal();
278         void createNativeThunk();
279 #if ENABLE(JIT) && ENABLE(INTERPRETER)
280         bool m_canUseJIT;
281 #endif
282         StackBounds m_stack;
283     };
284 
allocateGlobalHandle(JSGlobalData & globalData)285     inline HandleSlot allocateGlobalHandle(JSGlobalData& globalData)
286     {
287         return globalData.allocateGlobalHandle();
288     }
289 
290 } // namespace JSC
291 
292 #endif // JSGlobalData_h
293