2 * Copyright (C) 2008, 2009, 2013, 2014 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 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.
32 #include "DateInstanceCache.h"
33 #include "ExecutableAllocator.h"
35 #include "Intrinsic.h"
36 #include "JITThunks.h"
37 #include "JSCJSValue.h"
39 #include "LLIntData.h"
40 #include "MacroAssemblerCodeRef.h"
41 #include "NumericStrings.h"
42 #include "PrivateName.h"
43 #include "PrototypeMap.h"
44 #include "SmallStrings.h"
45 #include "SourceCode.h"
47 #include "ThunkGenerators.h"
48 #include "TypedArrayController.h"
50 #include "Watchpoint.h"
51 #include "WeakRandom.h"
52 #include <wtf/BumpPointerAllocator.h>
53 #include <wtf/DateMath.h>
54 #include <wtf/Forward.h>
55 #include <wtf/HashMap.h>
56 #include <wtf/HashSet.h>
57 #include <wtf/RefCountedArray.h>
58 #include <wtf/SimpleStats.h>
59 #include <wtf/StackBounds.h>
60 #include <wtf/ThreadSafeRefCounted.h>
61 #include <wtf/ThreadSpecific.h>
62 #include <wtf/WTFThreadData.h>
63 #include <wtf/text/WTFString.h>
64 #if ENABLE(REGEXP_TRACING)
65 #include <wtf/ListHashSet.h>
70 class ArityCheckFailReturnThunks
;
71 class BuiltinExecutables
;
74 class CommonIdentifiers
;
82 class LLIntOffsetsExtractor
;
84 class NativeExecutable
;
88 class SourceProviderCache
;
92 #if ENABLE(REGEXP_TRACING)
95 class UnlinkedCodeBlock
;
96 class UnlinkedEvalCodeBlock
;
97 class UnlinkedFunctionExecutable
;
98 class UnlinkedProgramCodeBlock
;
105 class LongLivedState
;
107 #endif // ENABLE(DFG_JIT)
112 #endif // ENABLE(FTL_JIT)
113 namespace CommonSlowPaths
{
114 struct ArityCheckData
;
123 struct LocalTimeOffsetCache
{
124 LocalTimeOffsetCache()
133 offset
= LocalTimeOffset();
139 LocalTimeOffset offset
;
145 class ConservativeRoots
;
148 #pragma warning(push)
149 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
151 struct ScratchBuffer
{
154 u
.m_activeLength
= 0;
157 static ScratchBuffer
* create(size_t size
)
159 ScratchBuffer
* result
= new (fastMalloc(ScratchBuffer::allocationSize(size
))) ScratchBuffer
;
164 static size_t allocationSize(size_t bufferSize
) { return sizeof(ScratchBuffer
) + bufferSize
; }
165 void setActiveLength(size_t activeLength
) { u
.m_activeLength
= activeLength
; }
166 size_t activeLength() const { return u
.m_activeLength
; };
167 size_t* activeLengthPtr() { return &u
.m_activeLength
; };
168 void* dataBuffer() { return m_buffer
; }
171 size_t m_activeLength
;
172 double pad
; // Make sure m_buffer is double aligned.
174 #if CPU(MIPS) && (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == 2)
175 void* m_buffer
[0] __attribute__((aligned(8)));
184 class VM
: public ThreadSafeRefCounted
<VM
> {
186 // WebCore has a one-to-one mapping of threads to VMs;
187 // either create() or createLeaked() should only be called once
188 // on a thread, this is the 'default' VM (it uses the
189 // thread's default string uniquing table from wtfThreadData).
190 // API contexts created using the new context group aware interface
191 // create APIContextGroup objects which require less locking of JSC
192 // than the old singleton APIShared VM created for use by
194 enum VMType
{ Default
, APIContextGroup
, APIShared
};
197 JS_EXPORT_PRIVATE
virtual ~ClientData() = 0;
200 bool isSharedInstance() { return vmType
== APIShared
; }
201 bool usingAPI() { return vmType
!= Default
; }
202 JS_EXPORT_PRIVATE
static bool sharedInstanceExists();
203 JS_EXPORT_PRIVATE
static VM
& sharedInstance();
205 JS_EXPORT_PRIVATE
static PassRefPtr
<VM
> create(HeapType
= SmallHeap
);
206 JS_EXPORT_PRIVATE
static PassRefPtr
<VM
> createLeaked(HeapType
= SmallHeap
);
207 static PassRefPtr
<VM
> createContextGroup(HeapType
= SmallHeap
);
208 JS_EXPORT_PRIVATE
~VM();
210 void makeUsableFromMultipleThreads() { heap
.machineThreads().makeUsableFromMultipleThreads(); }
213 RefPtr
<JSLock
> m_apiLock
;
216 #if ENABLE(ASSEMBLER)
217 // executableAllocator should be destructed after the heap, as the heap can call executableAllocator
218 // in its destructor.
219 ExecutableAllocator executableAllocator
;
222 // The heap should be just after executableAllocator and before other members to ensure that it's
223 // destructed after all the objects that reference it.
227 OwnPtr
<DFG::LongLivedState
> dfgState
;
228 #endif // ENABLE(DFG_JIT)
231 ClientData
* clientData
;
232 ExecState
* topCallFrame
;
233 std::unique_ptr
<Watchdog
> watchdog
;
235 const OwnPtr
<const HashTable
> arrayConstructorTable
;
236 const OwnPtr
<const HashTable
> arrayPrototypeTable
;
237 const OwnPtr
<const HashTable
> booleanPrototypeTable
;
238 const OwnPtr
<const HashTable
> dataViewTable
;
239 const OwnPtr
<const HashTable
> dateTable
;
240 const OwnPtr
<const HashTable
> dateConstructorTable
;
241 const OwnPtr
<const HashTable
> errorPrototypeTable
;
242 const OwnPtr
<const HashTable
> globalObjectTable
;
243 const OwnPtr
<const HashTable
> jsonTable
;
244 const OwnPtr
<const HashTable
> numberConstructorTable
;
245 const OwnPtr
<const HashTable
> numberPrototypeTable
;
246 const OwnPtr
<const HashTable
> objectConstructorTable
;
247 const OwnPtr
<const HashTable
> privateNamePrototypeTable
;
248 const OwnPtr
<const HashTable
> regExpTable
;
249 const OwnPtr
<const HashTable
> regExpConstructorTable
;
250 const OwnPtr
<const HashTable
> regExpPrototypeTable
;
251 const OwnPtr
<const HashTable
> stringConstructorTable
;
253 const OwnPtr
<const HashTable
> promisePrototypeTable
;
254 const OwnPtr
<const HashTable
> promiseConstructorTable
;
257 Strong
<Structure
> structureStructure
;
258 Strong
<Structure
> structureRareDataStructure
;
259 Strong
<Structure
> debuggerActivationStructure
;
260 Strong
<Structure
> terminatedExecutionErrorStructure
;
261 Strong
<Structure
> stringStructure
;
262 Strong
<Structure
> notAnObjectStructure
;
263 Strong
<Structure
> propertyNameIteratorStructure
;
264 Strong
<Structure
> getterSetterStructure
;
265 Strong
<Structure
> customGetterSetterStructure
;
266 Strong
<Structure
> apiWrapperStructure
;
267 Strong
<Structure
> JSScopeStructure
;
268 Strong
<Structure
> executableStructure
;
269 Strong
<Structure
> nativeExecutableStructure
;
270 Strong
<Structure
> evalExecutableStructure
;
271 Strong
<Structure
> programExecutableStructure
;
272 Strong
<Structure
> functionExecutableStructure
;
273 Strong
<Structure
> regExpStructure
;
274 Strong
<Structure
> symbolTableStructure
;
275 Strong
<Structure
> structureChainStructure
;
276 Strong
<Structure
> sparseArrayValueMapStructure
;
277 Strong
<Structure
> arrayBufferNeuteringWatchpointStructure
;
278 Strong
<Structure
> withScopeStructure
;
279 Strong
<Structure
> unlinkedFunctionExecutableStructure
;
280 Strong
<Structure
> unlinkedProgramCodeBlockStructure
;
281 Strong
<Structure
> unlinkedEvalCodeBlockStructure
;
282 Strong
<Structure
> unlinkedFunctionCodeBlockStructure
;
283 Strong
<Structure
> propertyTableStructure
;
284 Strong
<Structure
> mapDataStructure
;
285 Strong
<Structure
> weakMapDataStructure
;
287 Strong
<Structure
> promiseDeferredStructure
;
288 Strong
<Structure
> promiseReactionStructure
;
290 Strong
<JSCell
> iterationTerminator
;
292 AtomicStringTable
* m_atomicStringTable
;
293 CommonIdentifiers
* propertyNames
;
294 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.
295 SmallStrings smallStrings
;
296 NumericStrings numericStrings
;
297 DateInstanceCache dateInstanceCache
;
298 WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT
;
299 WeakGCMap
<StringImpl
*, JSString
, PtrHash
<StringImpl
*>> stringCache
;
300 Strong
<JSString
> lastCachedString
;
302 AtomicStringTable
* atomicStringTable() const { return m_atomicStringTable
; }
304 void setInDefineOwnProperty(bool inDefineOwnProperty
)
306 m_inDefineOwnProperty
= inDefineOwnProperty
;
309 bool isInDefineOwnProperty()
311 return m_inDefineOwnProperty
;
314 LegacyProfiler
* enabledProfiler() { return m_enabledProfiler
; }
315 void setEnabledProfiler(LegacyProfiler
*);
317 void* enabledProfilerAddress() { return &m_enabledProfiler
; }
320 bool canUseJIT() { return m_canUseJIT
; }
322 bool canUseJIT() { return false; } // interpreter only
326 bool canUseRegExpJIT() { return m_canUseRegExpJIT
; }
328 bool canUseRegExpJIT() { return false; } // interpreter only
331 SourceProviderCache
* addSourceProviderCache(SourceProvider
*);
332 void clearSourceProviderCaches();
334 PrototypeMap prototypeMap
;
336 OwnPtr
<ParserArena
> parserArena
;
337 typedef HashMap
<RefPtr
<SourceProvider
>, RefPtr
<SourceProviderCache
>> SourceProviderCacheMap
;
338 SourceProviderCacheMap sourceProviderCacheMap
;
339 OwnPtr
<Keywords
> keywords
;
340 Interpreter
* interpreter
;
342 OwnPtr
<JITThunks
> jitStubs
;
343 MacroAssemblerCodeRef
getCTIStub(ThunkGenerator generator
)
345 return jitStubs
->ctiStub(this, generator
);
347 NativeExecutable
* getHostFunction(NativeFunction
, Intrinsic
);
349 std::unique_ptr
<ArityCheckFailReturnThunks
> arityCheckFailReturnThunks
;
350 #endif // ENABLE(JIT)
351 std::unique_ptr
<CommonSlowPaths::ArityCheckData
> arityCheckData
;
353 std::unique_ptr
<FTL::Thunks
> ftlThunks
;
355 NativeExecutable
* getHostFunction(NativeFunction
, NativeFunction constructor
);
357 static ptrdiff_t exceptionOffset()
359 return OBJECT_OFFSETOF(VM
, m_exception
);
362 static ptrdiff_t callFrameForThrowOffset()
364 return OBJECT_OFFSETOF(VM
, callFrameForThrow
);
367 static ptrdiff_t targetMachinePCForThrowOffset()
369 return OBJECT_OFFSETOF(VM
, targetMachinePCForThrow
);
372 JS_EXPORT_PRIVATE
void clearException();
373 JS_EXPORT_PRIVATE
void clearExceptionStack();
374 void getExceptionInfo(JSValue
& exception
, RefCountedArray
<StackFrame
>& exceptionStack
);
375 void setExceptionInfo(JSValue
& exception
, RefCountedArray
<StackFrame
>& exceptionStack
);
376 JSValue
exception() const { return m_exception
; }
377 JSValue
* addressOfException() { return &m_exception
; }
378 const RefCountedArray
<StackFrame
>& exceptionStack() const { return m_exceptionStack
; }
380 JS_EXPORT_PRIVATE JSValue
throwException(ExecState
*, JSValue
);
381 JS_EXPORT_PRIVATE JSObject
* throwException(ExecState
*, JSObject
*);
383 void* stackPointerAtVMEntry() const { return m_stackPointerAtVMEntry
; }
384 void setStackPointerAtVMEntry(void*);
386 size_t reservedZoneSize() const { return m_reservedZoneSize
; }
387 size_t updateReservedZoneSize(size_t reservedZoneSize
);
390 void updateFTLLargestStackSize(size_t);
391 void** addressOfFTLStackLimit() { return &m_ftlStackLimit
; }
395 void* jsStackLimit() { return m_jsStackLimit
; }
396 void setJSStackLimit(void* limit
) { m_jsStackLimit
= limit
; }
398 void* stackLimit() { return m_stackLimit
; }
399 void** addressOfStackLimit() { return &m_stackLimit
; }
401 bool isSafeToRecurse(size_t neededStackInBytes
= 0) const
403 ASSERT(wtfThreadData().stack().isGrowingDownward());
404 int8_t* curr
= reinterpret_cast<int8_t*>(&curr
);
405 int8_t* limit
= reinterpret_cast<int8_t*>(m_stackLimit
);
406 return curr
>= limit
&& static_cast<size_t>(curr
- limit
) >= neededStackInBytes
;
409 void* lastStackTop() { return m_lastStackTop
; }
410 void setLastStackTop(void* lastStackTop
) { m_lastStackTop
= lastStackTop
; }
412 const ClassInfo
* const jsArrayClassInfo
;
413 const ClassInfo
* const jsFinalObjectClassInfo
;
415 JSValue hostCallReturnValue
;
416 ExecState
* newCallFrameReturnValue
;
417 ExecState
* callFrameForThrow
;
418 void* targetMachinePCForThrow
;
419 Instruction
* targetInterpreterPCForThrow
;
420 uint32_t osrExitIndex
;
421 void* osrExitJumpDestination
;
422 Vector
<ScratchBuffer
*> scratchBuffers
;
423 size_t sizeOfLastScratchBuffer
;
425 ScratchBuffer
* scratchBufferForSize(size_t size
)
430 if (size
> sizeOfLastScratchBuffer
) {
431 // Protect against a N^2 memory usage pathology by ensuring
432 // that at worst, we get a geometric series, meaning that the
433 // total memory usage is somewhere around
434 // max(scratch buffer size) * 4.
435 sizeOfLastScratchBuffer
= size
* 2;
437 ScratchBuffer
* newBuffer
= ScratchBuffer::create(sizeOfLastScratchBuffer
);
438 RELEASE_ASSERT(newBuffer
);
439 scratchBuffers
.append(newBuffer
);
442 ScratchBuffer
* result
= scratchBuffers
.last();
443 result
->setActiveLength(0);
447 void gatherConservativeRoots(ConservativeRoots
&);
449 VMEntryScope
* entryScope
;
451 HashSet
<JSObject
*> stringRecursionCheckVisitedObjects
;
453 LocalTimeOffsetCache localTimeOffsetCache
;
455 String cachedDateString
;
456 double cachedDateStringValue
;
458 OwnPtr
<Profiler::Database
> m_perBytecodeProfiler
;
459 RefPtr
<TypedArrayController
> m_typedArrayController
;
460 RegExpCache
* m_regExpCache
;
461 BumpPointerAllocator m_regExpAllocator
;
463 #if ENABLE(REGEXP_TRACING)
464 typedef ListHashSet
<RegExp
*> RTTraceList
;
465 RTTraceList
* m_rtTraceList
;
468 bool hasExclusiveThread() const { return m_apiLock
->hasExclusiveThread(); }
469 std::thread::id
exclusiveThread() const { return m_apiLock
->exclusiveThread(); }
470 void setExclusiveThread(std::thread::id threadId
) { m_apiLock
->setExclusiveThread(threadId
); }
472 JS_EXPORT_PRIVATE
void resetDateCache();
474 JS_EXPORT_PRIVATE
void startSampling();
475 JS_EXPORT_PRIVATE
void stopSampling();
476 JS_EXPORT_PRIVATE
void dumpSampleData(ExecState
* exec
);
477 RegExpCache
* regExpCache() { return m_regExpCache
; }
478 #if ENABLE(REGEXP_TRACING)
479 void addRegExpToTrace(RegExp
*);
481 JS_EXPORT_PRIVATE
void dumpRegExpTrace();
483 bool isCollectorBusy() { return heap
.isBusy(); }
484 JS_EXPORT_PRIVATE
void releaseExecutableMemory();
486 #if ENABLE(GC_VALIDATION)
487 bool isInitializingObject() const;
488 void setInitializingObjectClass(const ClassInfo
*);
491 unsigned m_newStringsSinceLastHashCons
;
493 static const unsigned s_minNumberOfNewStringsToHashCons
= 100;
495 bool haveEnoughNewStringsToHashCons() { return m_newStringsSinceLastHashCons
> s_minNumberOfNewStringsToHashCons
; }
496 void resetNewStringsSinceLastHashCons() { m_newStringsSinceLastHashCons
= 0; }
498 bool currentThreadIsHoldingAPILock() const { return m_apiLock
->currentThreadIsHoldingLock(); }
500 JSLock
& apiLock() { return *m_apiLock
; }
501 CodeCache
* codeCache() { return m_codeCache
.get(); }
503 void waitForCompilationsToComplete();
505 JS_EXPORT_PRIVATE
void discardAllCode();
507 void registerWatchpointForImpureProperty(const Identifier
&, Watchpoint
*);
508 // FIXME: Use AtomicString once it got merged with Identifier.
509 JS_EXPORT_PRIVATE
void addImpureProperty(const String
&);
511 BuiltinExecutables
* builtinExecutables() { return m_builtinExecutables
.get(); }
514 friend class LLIntOffsetsExtractor
;
515 friend class ClearExceptionScope
;
516 friend class RecursiveAllocationScope
;
518 VM(VMType
, HeapType
);
519 static VM
*& sharedInstanceInternal();
520 void createNativeThunk();
522 void updateStackLimit();
524 #if ENABLE(ASSEMBLER)
525 bool m_canUseAssembler
;
531 bool m_canUseRegExpJIT
;
533 #if ENABLE(GC_VALIDATION)
534 const ClassInfo
* m_initializingObjectClass
;
536 void* m_stackPointerAtVMEntry
;
537 size_t m_reservedZoneSize
;
541 void* m_jsStackLimit
;
546 void* m_jsStackLimit
;
549 void* m_ftlStackLimit
;
550 size_t m_largestFTLStackSize
;
553 void* m_lastStackTop
;
555 bool m_inDefineOwnProperty
;
556 OwnPtr
<CodeCache
> m_codeCache
;
557 LegacyProfiler
* m_enabledProfiler
;
558 OwnPtr
<BuiltinExecutables
> m_builtinExecutables
;
559 RefCountedArray
<StackFrame
> m_exceptionStack
;
560 HashMap
<String
, RefPtr
<WatchpointSet
>> m_impurePropertyWatchpointSets
;
563 #if ENABLE(GC_VALIDATION)
564 inline bool VM::isInitializingObject() const
566 return !!m_initializingObjectClass
;
569 inline void VM::setInitializingObjectClass(const ClassInfo
* initializingObjectClass
)
571 m_initializingObjectClass
= initializingObjectClass
;
575 inline Heap
* WeakSet::heap() const
581 extern "C" void sanitizeStackForVMImpl(VM
*);
584 void sanitizeStackForVM(VM
*);
585 void logSanitizeStack(VM
*);