diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/VM.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/VM.h | 940 |
1 files changed, 559 insertions, 381 deletions
diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h index dcd525107..759bbd97d 100644 --- a/Source/JavaScriptCore/runtime/VM.h +++ b/Source/JavaScriptCore/runtime/VM.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2013-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,500 +29,678 @@ #ifndef VM_h #define VM_h -#include "CachedTranscendentalFunction.h" +#include "ControlFlowProfiler.h" #include "DateInstanceCache.h" #include "ExecutableAllocator.h" +#include "FunctionHasExecutedCache.h" +#if ENABLE(JIT) +#include "GPRInfo.h" +#endif #include "Heap.h" #include "Intrinsic.h" #include "JITThunks.h" -#include "JITThunks.h" #include "JSCJSValue.h" #include "JSLock.h" #include "LLIntData.h" #include "MacroAssemblerCodeRef.h" +#include "Microtask.h" #include "NumericStrings.h" -#include "ProfilerDatabase.h" #include "PrivateName.h" #include "PrototypeMap.h" #include "SmallStrings.h" +#include "SourceCode.h" #include "Strong.h" #include "ThunkGenerators.h" -#include "TypedArrayDescriptor.h" -#include "Watchdog.h" -#include "WeakRandom.h" +#include "TypedArrayController.h" +#include "VMEntryRecord.h" +#include "Watchpoint.h" +#include <wtf/Bag.h> #include <wtf/BumpPointerAllocator.h> #include <wtf/DateMath.h> +#include <wtf/Deque.h> #include <wtf/Forward.h> #include <wtf/HashMap.h> -#include <wtf/RefCountedArray.h> +#include <wtf/HashSet.h> #include <wtf/SimpleStats.h> +#include <wtf/StackBounds.h> +#include <wtf/Stopwatch.h> #include <wtf/ThreadSafeRefCounted.h> #include <wtf/ThreadSpecific.h> #include <wtf/WTFThreadData.h> +#include <wtf/WeakRandom.h> +#include <wtf/text/SymbolRegistry.h> +#include <wtf/text/WTFString.h> #if ENABLE(REGEXP_TRACING) #include <wtf/ListHashSet.h> #endif namespace JSC { - class CodeBlock; - class CodeCache; - class CommonIdentifiers; - class ExecState; - class HandleStack; - class IdentifierTable; - class Interpreter; - class JSGlobalObject; - class JSObject; - class Keywords; - class LLIntOffsetsExtractor; - class LegacyProfiler; - class NativeExecutable; - class ParserArena; - class RegExpCache; - class SourceProvider; - class SourceProviderCache; - struct StackFrame; - class Stringifier; - class Structure; +class BuiltinExecutables; +class BytecodeIntrinsicRegistry; +class CodeBlock; +class CodeCache; +class CommonIdentifiers; +class CustomGetterSetter; +class ExecState; +class Exception; +class HandleStack; +class TypeProfiler; +class TypeProfilerLog; +class Identifier; +class Interpreter; +class JSBoundSlotBaseFunction; +class JSGlobalObject; +class JSObject; +class LLIntOffsetsExtractor; +class LegacyProfiler; +class NativeExecutable; +class RegExpCache; +class RegisterAtOffsetList; +#if ENABLE(SAMPLING_PROFILER) +class SamplingProfiler; +#endif +class ScriptExecutable; +class SourceProvider; +class SourceProviderCache; +struct StackFrame; +class Structure; #if ENABLE(REGEXP_TRACING) - class RegExp; +class RegExp; #endif - class UnlinkedCodeBlock; - class UnlinkedEvalCodeBlock; - class UnlinkedFunctionExecutable; - class UnlinkedProgramCodeBlock; +class UnlinkedCodeBlock; +class UnlinkedEvalCodeBlock; +class UnlinkedFunctionExecutable; +class UnlinkedProgramCodeBlock; +class UnlinkedModuleProgramCodeBlock; +class VirtualRegister; +class VMEntryScope; +class Watchdog; +class Watchpoint; +class WatchpointSet; #if ENABLE(DFG_JIT) - namespace DFG { - class LongLivedState; - } +namespace DFG { +class LongLivedState; +} #endif // ENABLE(DFG_JIT) +#if ENABLE(FTL_JIT) +namespace FTL { +class Thunks; +} +#endif // ENABLE(FTL_JIT) +namespace CommonSlowPaths { +struct ArityCheckData; +} +namespace Profiler { +class Database; +} + +struct HashTable; +struct Instruction; + +struct LocalTimeOffsetCache { + LocalTimeOffsetCache() + : start(0.0) + , end(-1.0) + , increment(0.0) + , timeType(WTF::UTCTime) + { + } - struct HashTable; - struct Instruction; + void reset() + { + offset = LocalTimeOffset(); + start = 0.0; + end = -1.0; + increment = 0.0; + timeType = WTF::UTCTime; + } - struct LocalTimeOffsetCache { - LocalTimeOffsetCache() - : start(0.0) - , end(-1.0) - , increment(0.0) - { - } - - void reset() - { - offset = LocalTimeOffset(); - start = 0.0; - end = -1.0; - increment = 0.0; - } + LocalTimeOffset offset; + double start; + double end; + double increment; + WTF::TimeType timeType; +}; + +class QueuedTask { + WTF_MAKE_NONCOPYABLE(QueuedTask); + WTF_MAKE_FAST_ALLOCATED; +public: + void run(); + + QueuedTask(VM& vm, JSGlobalObject* globalObject, PassRefPtr<Microtask> microtask) + : m_globalObject(vm, globalObject) + , m_microtask(microtask) + { + } - LocalTimeOffset offset; - double start; - double end; - double increment; - }; +private: + Strong<JSGlobalObject> m_globalObject; + RefPtr<Microtask> m_microtask; +}; -#if ENABLE(DFG_JIT) - class ConservativeRoots; +class ConservativeRoots; #if COMPILER(MSVC) #pragma warning(push) #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning #endif - struct ScratchBuffer { - ScratchBuffer() - { - u.m_activeLength = 0; - } +struct ScratchBuffer { + ScratchBuffer() + { + u.m_activeLength = 0; + } - static ScratchBuffer* create(size_t size) - { - ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer; + static ScratchBuffer* create(size_t size) + { + ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer; - return result; - } + return result; + } - static size_t allocationSize(size_t bufferSize) { return sizeof(ScratchBuffer) + bufferSize; } - void setActiveLength(size_t activeLength) { u.m_activeLength = activeLength; } - size_t activeLength() const { return u.m_activeLength; }; - size_t* activeLengthPtr() { return &u.m_activeLength; }; - void* dataBuffer() { return m_buffer; } + static size_t allocationSize(size_t bufferSize) { return sizeof(ScratchBuffer) + bufferSize; } + void setActiveLength(size_t activeLength) { u.m_activeLength = activeLength; } + size_t activeLength() const { return u.m_activeLength; }; + size_t* activeLengthPtr() { return &u.m_activeLength; }; + void* dataBuffer() { return m_buffer; } - union { - size_t m_activeLength; - double pad; // Make sure m_buffer is double aligned. - } u; + union { + size_t m_activeLength; + double pad; // Make sure m_buffer is double aligned. + } u; #if CPU(MIPS) && (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == 2) - void* m_buffer[0] __attribute__((aligned(8))); + void* m_buffer[0] __attribute__((aligned(8))); #else - void* m_buffer[0]; + void* m_buffer[0]; #endif - }; +}; #if COMPILER(MSVC) #pragma warning(pop) #endif + +class VM : public ThreadSafeRefCounted<VM> { +public: + // WebCore has a one-to-one mapping of threads to VMs; + // either create() or createLeaked() should only be called once + // on a thread, this is the 'default' VM (it uses the + // thread's default string uniquing table from wtfThreadData). + // API contexts created using the new context group aware interface + // create APIContextGroup objects which require less locking of JSC + // than the old singleton APIShared VM created for use by + // the original API. + enum VMType { Default, APIContextGroup, APIShared }; + + struct ClientData { + JS_EXPORT_PRIVATE virtual ~ClientData() = 0; + }; + + bool isSharedInstance() { return vmType == APIShared; } + bool usingAPI() { return vmType != Default; } + JS_EXPORT_PRIVATE static bool sharedInstanceExists(); + JS_EXPORT_PRIVATE static VM& sharedInstance(); + + JS_EXPORT_PRIVATE static Ref<VM> create(HeapType = SmallHeap); + JS_EXPORT_PRIVATE static Ref<VM> createLeaked(HeapType = SmallHeap); + static Ref<VM> createContextGroup(HeapType = SmallHeap); + JS_EXPORT_PRIVATE ~VM(); + + JS_EXPORT_PRIVATE Watchdog& ensureWatchdog(); + JS_EXPORT_PRIVATE Watchdog* watchdog() { return m_watchdog.get(); } + +#if ENABLE(SAMPLING_PROFILER) + JS_EXPORT_PRIVATE SamplingProfiler* samplingProfiler() { return m_samplingProfiler.get(); } + JS_EXPORT_PRIVATE void ensureSamplingProfiler(RefPtr<Stopwatch>&&); #endif - class VM : public ThreadSafeRefCounted<VM> { - public: - // WebCore has a one-to-one mapping of threads to VMs; - // either create() or createLeaked() should only be called once - // on a thread, this is the 'default' VM (it uses the - // thread's default string uniquing table from wtfThreadData). - // API contexts created using the new context group aware interface - // create APIContextGroup objects which require less locking of JSC - // than the old singleton APIShared VM created for use by - // the original API. - enum VMType { Default, APIContextGroup, APIShared }; - - struct ClientData { - JS_EXPORT_PRIVATE virtual ~ClientData() = 0; - }; - - bool isSharedInstance() { return vmType == APIShared; } - bool usingAPI() { return vmType != Default; } - static bool sharedInstanceExists(); - JS_EXPORT_PRIVATE static VM& sharedInstance(); - - JS_EXPORT_PRIVATE static PassRefPtr<VM> create(HeapType = SmallHeap); - JS_EXPORT_PRIVATE static PassRefPtr<VM> createLeaked(HeapType = SmallHeap); - static PassRefPtr<VM> createContextGroup(HeapType = SmallHeap); - JS_EXPORT_PRIVATE ~VM(); - - void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } - - private: - RefPtr<JSLock> m_apiLock; - - public: +private: + RefPtr<JSLock> m_apiLock; + +public: #if ENABLE(ASSEMBLER) - // executableAllocator should be destructed after the heap, as the heap can call executableAllocator - // in its destructor. - ExecutableAllocator executableAllocator; + // executableAllocator should be destructed after the heap, as the heap can call executableAllocator + // in its destructor. + ExecutableAllocator executableAllocator; #endif - // The heap should be just after executableAllocator and before other members to ensure that it's - // destructed after all the objects that reference it. - Heap heap; - + // The heap should be just after executableAllocator and before other members to ensure that it's + // destructed after all the objects that reference it. + Heap heap; + #if ENABLE(DFG_JIT) - OwnPtr<DFG::LongLivedState> m_dfgState; + std::unique_ptr<DFG::LongLivedState> dfgState; #endif // ENABLE(DFG_JIT) - VMType vmType; - ClientData* clientData; - ExecState* topCallFrame; - Watchdog watchdog; - - const HashTable* arrayConstructorTable; - const HashTable* arrayPrototypeTable; - const HashTable* booleanPrototypeTable; - const HashTable* dateTable; - const HashTable* dateConstructorTable; - const HashTable* errorPrototypeTable; - const HashTable* globalObjectTable; - const HashTable* jsonTable; - const HashTable* mathTable; - const HashTable* numberConstructorTable; - const HashTable* numberPrototypeTable; - const HashTable* objectConstructorTable; - const HashTable* privateNamePrototypeTable; - const HashTable* regExpTable; - const HashTable* regExpConstructorTable; - const HashTable* regExpPrototypeTable; - const HashTable* stringConstructorTable; - - Strong<Structure> structureStructure; - Strong<Structure> structureRareDataStructure; - Strong<Structure> debuggerActivationStructure; - Strong<Structure> terminatedExecutionErrorStructure; - Strong<Structure> stringStructure; - Strong<Structure> notAnObjectStructure; - Strong<Structure> propertyNameIteratorStructure; - Strong<Structure> getterSetterStructure; - Strong<Structure> apiWrapperStructure; - Strong<Structure> JSScopeStructure; - Strong<Structure> executableStructure; - Strong<Structure> nativeExecutableStructure; - Strong<Structure> evalExecutableStructure; - Strong<Structure> programExecutableStructure; - Strong<Structure> functionExecutableStructure; - Strong<Structure> regExpStructure; - Strong<Structure> sharedSymbolTableStructure; - Strong<Structure> structureChainStructure; - Strong<Structure> sparseArrayValueMapStructure; - Strong<Structure> withScopeStructure; - Strong<Structure> unlinkedFunctionExecutableStructure; - Strong<Structure> unlinkedProgramCodeBlockStructure; - Strong<Structure> unlinkedEvalCodeBlockStructure; - Strong<Structure> unlinkedFunctionCodeBlockStructure; - Strong<Structure> propertyTableStructure; - - IdentifierTable* identifierTable; - CommonIdentifiers* propertyNames; - 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. - SmallStrings smallStrings; - NumericStrings numericStrings; - DateInstanceCache dateInstanceCache; - WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT; - Vector<CodeBlock*> codeBlocksBeingCompiled; - void startedCompiling(CodeBlock* codeBlock) - { - codeBlocksBeingCompiled.append(codeBlock); - } - - void finishedCompiling(CodeBlock* codeBlock) - { - ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last()); - codeBlocksBeingCompiled.removeLast(); - } + VMType vmType; + ClientData* clientData; + VMEntryFrame* topVMEntryFrame; + ExecState* topCallFrame; + Strong<Structure> structureStructure; + Strong<Structure> structureRareDataStructure; + Strong<Structure> terminatedExecutionErrorStructure; + Strong<Structure> stringStructure; + Strong<Structure> notAnObjectStructure; + Strong<Structure> propertyNameIteratorStructure; + Strong<Structure> propertyNameEnumeratorStructure; + Strong<Structure> getterSetterStructure; + Strong<Structure> customGetterSetterStructure; + Strong<Structure> scopedArgumentsTableStructure; + Strong<Structure> apiWrapperStructure; + Strong<Structure> JSScopeStructure; + Strong<Structure> executableStructure; + Strong<Structure> nativeExecutableStructure; + Strong<Structure> evalExecutableStructure; + Strong<Structure> programExecutableStructure; + Strong<Structure> functionExecutableStructure; +#if ENABLE(WEBASSEMBLY) + Strong<Structure> webAssemblyExecutableStructure; +#endif + Strong<Structure> moduleProgramExecutableStructure; + Strong<Structure> regExpStructure; + Strong<Structure> symbolStructure; + Strong<Structure> symbolTableStructure; + Strong<Structure> structureChainStructure; + Strong<Structure> sparseArrayValueMapStructure; + Strong<Structure> templateRegistryKeyStructure; + Strong<Structure> arrayBufferNeuteringWatchpointStructure; + Strong<Structure> unlinkedFunctionExecutableStructure; + Strong<Structure> unlinkedProgramCodeBlockStructure; + Strong<Structure> unlinkedEvalCodeBlockStructure; + Strong<Structure> unlinkedFunctionCodeBlockStructure; + Strong<Structure> unlinkedModuleProgramCodeBlockStructure; + Strong<Structure> propertyTableStructure; + Strong<Structure> weakMapDataStructure; + Strong<Structure> inferredValueStructure; + Strong<Structure> inferredTypeStructure; + Strong<Structure> inferredTypeTableStructure; + Strong<Structure> functionRareDataStructure; + Strong<Structure> generatorFrameStructure; + Strong<Structure> exceptionStructure; + Strong<Structure> promiseDeferredStructure; + Strong<Structure> internalPromiseDeferredStructure; + Strong<Structure> nativeStdFunctionCellStructure; + Strong<Structure> programCodeBlockStructure; + Strong<Structure> moduleProgramCodeBlockStructure; + Strong<Structure> evalCodeBlockStructure; + Strong<Structure> functionCodeBlockStructure; + Strong<Structure> webAssemblyCodeBlockStructure; + + Strong<JSCell> iterationTerminator; + Strong<JSCell> emptyPropertyNameEnumerator; + + AtomicStringTable* m_atomicStringTable; + WTF::SymbolRegistry m_symbolRegistry; + CommonIdentifiers* propertyNames; + 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. + SmallStrings smallStrings; + NumericStrings numericStrings; + DateInstanceCache dateInstanceCache; + WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT; + WeakGCMap<std::pair<CustomGetterSetter*, int>, JSBoundSlotBaseFunction> customGetterSetterFunctionMap; + WeakGCMap<StringImpl*, JSString, PtrHash<StringImpl*>> stringCache; + Strong<JSString> lastCachedString; + + AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; } + WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; } + + void setInDefineOwnProperty(bool inDefineOwnProperty) + { + m_inDefineOwnProperty = inDefineOwnProperty; + } - void setInDefineOwnProperty(bool inDefineOwnProperty) - { - m_inDefineOwnProperty = inDefineOwnProperty; - } + bool isInDefineOwnProperty() + { + return m_inDefineOwnProperty; + } - bool isInDefineOwnProperty() - { - return m_inDefineOwnProperty; - } + LegacyProfiler* enabledProfiler() { return m_enabledProfiler; } + void setEnabledProfiler(LegacyProfiler*); - LegacyProfiler* enabledProfiler() - { - return m_enabledProfiler; - } + void* enabledProfilerAddress() { return &m_enabledProfiler; } -#if ENABLE(JIT) && ENABLE(LLINT) - bool canUseJIT() { return m_canUseJIT; } -#elif ENABLE(JIT) - bool canUseJIT() { return true; } // jit only +#if ENABLE(JIT) + bool canUseJIT() { return m_canUseJIT; } #else - bool canUseJIT() { return false; } // interpreter only + bool canUseJIT() { return false; } // interpreter only #endif #if ENABLE(YARR_JIT) - bool canUseRegExpJIT() { return m_canUseRegExpJIT; } + bool canUseRegExpJIT() { return m_canUseRegExpJIT; } #else - bool canUseRegExpJIT() { return false; } // interpreter only + bool canUseRegExpJIT() { return false; } // interpreter only #endif - SourceProviderCache* addSourceProviderCache(SourceProvider*); - void clearSourceProviderCaches(); + SourceProviderCache* addSourceProviderCache(SourceProvider*); + void clearSourceProviderCaches(); - PrototypeMap prototypeMap; + PrototypeMap prototypeMap; - OwnPtr<ParserArena> parserArena; - typedef HashMap<RefPtr<SourceProvider>, RefPtr<SourceProviderCache> > SourceProviderCacheMap; - SourceProviderCacheMap sourceProviderCacheMap; - OwnPtr<Keywords> keywords; - Interpreter* interpreter; + typedef HashMap<RefPtr<SourceProvider>, RefPtr<SourceProviderCache>> SourceProviderCacheMap; + SourceProviderCacheMap sourceProviderCacheMap; + Interpreter* interpreter; #if ENABLE(JIT) - OwnPtr<JITThunks> jitStubs; - MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator) - { - return jitStubs->ctiStub(this, generator); - } - NativeExecutable* getHostFunction(NativeFunction, Intrinsic); +#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 + intptr_t calleeSaveRegistersBuffer[NUMBER_OF_CALLEE_SAVES_REGISTERS]; + + static ptrdiff_t calleeSaveRegistersBufferOffset() + { + return OBJECT_OFFSETOF(VM, calleeSaveRegistersBuffer); + } +#endif // NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 + + std::unique_ptr<JITThunks> jitStubs; + MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator) + { + return jitStubs->ctiStub(this, generator); + } + NativeExecutable* getHostFunction(NativeFunction, Intrinsic, const String& name); + + std::unique_ptr<RegisterAtOffsetList> allCalleeSaveRegisterOffsets; + + RegisterAtOffsetList* getAllCalleeSaveRegisterOffsets() { return allCalleeSaveRegisterOffsets.get(); } + +#endif // ENABLE(JIT) + std::unique_ptr<CommonSlowPaths::ArityCheckData> arityCheckData; +#if ENABLE(FTL_JIT) + std::unique_ptr<FTL::Thunks> ftlThunks; #endif - NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor); + NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor, const String& name); - JSValue exception; - JS_EXPORT_PRIVATE void clearExceptionStack(); - RefCountedArray<StackFrame>& exceptionStack() { return m_exceptionStack; } + static ptrdiff_t exceptionOffset() + { + return OBJECT_OFFSETOF(VM, m_exception); + } - const ClassInfo* const jsArrayClassInfo; - const ClassInfo* const jsFinalObjectClassInfo; + static ptrdiff_t callFrameForCatchOffset() + { + return OBJECT_OFFSETOF(VM, callFrameForCatch); + } - ReturnAddressPtr exceptionLocation; - JSValue hostCallReturnValue; - ExecState* callFrameForThrow; - void* targetMachinePCForThrow; - Instruction* targetInterpreterPCForThrow; -#if ENABLE(DFG_JIT) - uint32_t osrExitIndex; - void* osrExitJumpDestination; - Vector<ScratchBuffer*> scratchBuffers; - size_t sizeOfLastScratchBuffer; - - ScratchBuffer* scratchBufferForSize(size_t size) - { - if (!size) - return 0; - - if (size > sizeOfLastScratchBuffer) { - // Protect against a N^2 memory usage pathology by ensuring - // that at worst, we get a geometric series, meaning that the - // total memory usage is somewhere around - // max(scratch buffer size) * 4. - sizeOfLastScratchBuffer = size * 2; - - scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer)); - } - - ScratchBuffer* result = scratchBuffers.last(); - result->setActiveLength(0); - return result; - } + static ptrdiff_t targetMachinePCForThrowOffset() + { + return OBJECT_OFFSETOF(VM, targetMachinePCForThrow); + } - void gatherConservativeRoots(ConservativeRoots&); -#endif + void restorePreviousException(Exception* exception) { setException(exception); } - JSGlobalObject* dynamicGlobalObject; + void clearException() { m_exception = nullptr; } + void clearLastException() { m_lastException = nullptr; } - HashSet<JSObject*> stringRecursionCheckVisitedObjects; + ExecState** addressOfCallFrameForCatch() { return &callFrameForCatch; } - LocalTimeOffsetCache localTimeOffsetCache; - - String cachedDateString; - double cachedDateStringValue; + Exception* exception() const { return m_exception; } + JSCell** addressOfException() { return reinterpret_cast<JSCell**>(&m_exception); } - LegacyProfiler* m_enabledProfiler; - OwnPtr<Profiler::Database> m_perBytecodeProfiler; - RegExpCache* m_regExpCache; - BumpPointerAllocator m_regExpAllocator; + Exception* lastException() const { return m_lastException; } + JSCell** addressOfLastException() { return reinterpret_cast<JSCell**>(&m_lastException); } -#if ENABLE(REGEXP_TRACING) - typedef ListHashSet<RefPtr<RegExp> > RTTraceList; - RTTraceList* m_rtTraceList; + JS_EXPORT_PRIVATE void throwException(ExecState*, Exception*); + JS_EXPORT_PRIVATE JSValue throwException(ExecState*, JSValue); + JS_EXPORT_PRIVATE JSObject* throwException(ExecState*, JSObject*); + + void setFailNextNewCodeBlock() { m_failNextNewCodeBlock = true; } + bool getAndClearFailNextNewCodeBlock() + { + bool result = m_failNextNewCodeBlock; + m_failNextNewCodeBlock = false; + return result; + } + + void* stackPointerAtVMEntry() const { return m_stackPointerAtVMEntry; } + void setStackPointerAtVMEntry(void*); + + size_t reservedZoneSize() const { return m_reservedZoneSize; } + size_t updateReservedZoneSize(size_t reservedZoneSize); + +#if ENABLE(FTL_JIT) + void updateFTLLargestStackSize(size_t); + void** addressOfFTLStackLimit() { return &m_ftlStackLimit; } #endif -#ifndef NDEBUG - ThreadIdentifier exclusiveThread; +#if !ENABLE(JIT) + void* jsStackLimit() { return m_jsStackLimit; } + void setJSStackLimit(void* limit) { m_jsStackLimit = limit; } +#endif + void* stackLimit() { return m_stackLimit; } + void** addressOfStackLimit() { return &m_stackLimit; } + + bool isSafeToRecurse(size_t neededStackInBytes = 0) const + { + ASSERT(wtfThreadData().stack().isGrowingDownward()); + int8_t* curr = reinterpret_cast<int8_t*>(&curr); + int8_t* limit = reinterpret_cast<int8_t*>(m_stackLimit); + return curr >= limit && static_cast<size_t>(curr - limit) >= neededStackInBytes; + } + + void* lastStackTop() { return m_lastStackTop; } + void setLastStackTop(void*); + + const ClassInfo* const jsArrayClassInfo; + const ClassInfo* const jsFinalObjectClassInfo; + + JSValue hostCallReturnValue; + unsigned varargsLength; + ExecState* newCallFrameReturnValue; + ExecState* callFrameForCatch; + void* targetMachinePCForThrow; + Instruction* targetInterpreterPCForThrow; + uint32_t osrExitIndex; + void* osrExitJumpDestination; + Vector<ScratchBuffer*> scratchBuffers; + size_t sizeOfLastScratchBuffer; + + bool isExecutingInRegExpJIT { false }; + + ScratchBuffer* scratchBufferForSize(size_t size) + { + if (!size) + return 0; + + if (size > sizeOfLastScratchBuffer) { + // Protect against a N^2 memory usage pathology by ensuring + // that at worst, we get a geometric series, meaning that the + // total memory usage is somewhere around + // max(scratch buffer size) * 4. + sizeOfLastScratchBuffer = size * 2; + + ScratchBuffer* newBuffer = ScratchBuffer::create(sizeOfLastScratchBuffer); + RELEASE_ASSERT(newBuffer); + scratchBuffers.append(newBuffer); + } + + ScratchBuffer* result = scratchBuffers.last(); + result->setActiveLength(0); + return result; + } + + EncodedJSValue* exceptionFuzzingBuffer(size_t size) + { + ASSERT(Options::useExceptionFuzz()); + if (!m_exceptionFuzzBuffer) + m_exceptionFuzzBuffer = MallocPtr<EncodedJSValue>::malloc(size); + return m_exceptionFuzzBuffer.get(); + } + + void gatherConservativeRoots(ConservativeRoots&); + + VMEntryScope* entryScope; + + JSObject* stringRecursionCheckFirstObject { nullptr }; + HashSet<JSObject*> stringRecursionCheckVisitedObjects; + + LocalTimeOffsetCache localTimeOffsetCache; + + String cachedDateString; + double cachedDateStringValue; + + std::unique_ptr<Profiler::Database> m_perBytecodeProfiler; + RefPtr<TypedArrayController> m_typedArrayController; + RegExpCache* m_regExpCache; + BumpPointerAllocator m_regExpAllocator; + +#if ENABLE(REGEXP_TRACING) + typedef ListHashSet<RegExp*> RTTraceList; + RTTraceList* m_rtTraceList; #endif - CachedTranscendentalFunction<std::sin> cachedSin; + bool hasExclusiveThread() const { return m_apiLock->hasExclusiveThread(); } + std::thread::id exclusiveThread() const { return m_apiLock->exclusiveThread(); } + void setExclusiveThread(std::thread::id threadId) { m_apiLock->setExclusiveThread(threadId); } - JS_EXPORT_PRIVATE void resetDateCache(); + JS_EXPORT_PRIVATE void resetDateCache(); - JS_EXPORT_PRIVATE void startSampling(); - JS_EXPORT_PRIVATE void stopSampling(); - JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec); - RegExpCache* regExpCache() { return m_regExpCache; } + JS_EXPORT_PRIVATE void startSampling(); + JS_EXPORT_PRIVATE void stopSampling(); + JS_EXPORT_PRIVATE void dumpSampleData(ExecState*); + RegExpCache* regExpCache() { return m_regExpCache; } #if ENABLE(REGEXP_TRACING) - void addRegExpToTrace(PassRefPtr<RegExp> regExp); + void addRegExpToTrace(RegExp*); #endif - JS_EXPORT_PRIVATE void dumpRegExpTrace(); + JS_EXPORT_PRIVATE void dumpRegExpTrace(); - bool isCollectorBusy() { return heap.isBusy(); } - JS_EXPORT_PRIVATE void releaseExecutableMemory(); + bool isCollectorBusy() { return heap.isBusy(); } #if ENABLE(GC_VALIDATION) - bool isInitializingObject() const; - void setInitializingObjectClass(const ClassInfo*); + bool isInitializingObject() const; + void setInitializingObjectClass(const ClassInfo*); #endif - unsigned m_newStringsSinceLastHashCons; - - static const unsigned s_minNumberOfNewStringsToHashCons = 100; - - bool haveEnoughNewStringsToHashCons() { return m_newStringsSinceLastHashCons > s_minNumberOfNewStringsToHashCons; } - void resetNewStringsSinceLastHashCons() { m_newStringsSinceLastHashCons = 0; } - -#define registerTypedArrayFunction(type, capitalizedType) \ - void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \ - { \ - ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \ - m_##type##ArrayDescriptor = descriptor; \ - ASSERT(m_##type##ArrayDescriptor.m_classInfo); \ - } \ - const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; } - - registerTypedArrayFunction(int8, Int8); - registerTypedArrayFunction(int16, Int16); - registerTypedArrayFunction(int32, Int32); - registerTypedArrayFunction(uint8, Uint8); - registerTypedArrayFunction(uint8Clamped, Uint8Clamped); - registerTypedArrayFunction(uint16, Uint16); - registerTypedArrayFunction(uint32, Uint32); - registerTypedArrayFunction(float32, Float32); - registerTypedArrayFunction(float64, Float64); -#undef registerTypedArrayFunction - - const TypedArrayDescriptor* typedArrayDescriptor(TypedArrayType type) const - { - switch (type) { - case TypedArrayNone: - return 0; - case TypedArrayInt8: - return &int8ArrayDescriptor(); - case TypedArrayInt16: - return &int16ArrayDescriptor(); - case TypedArrayInt32: - return &int32ArrayDescriptor(); - case TypedArrayUint8: - return &uint8ArrayDescriptor(); - case TypedArrayUint8Clamped: - return &uint8ClampedArrayDescriptor(); - case TypedArrayUint16: - return &uint16ArrayDescriptor(); - case TypedArrayUint32: - return &uint32ArrayDescriptor(); - case TypedArrayFloat32: - return &float32ArrayDescriptor(); - case TypedArrayFloat64: - return &float64ArrayDescriptor(); - default: - CRASH(); - return 0; - } - } + bool currentThreadIsHoldingAPILock() const { return m_apiLock->currentThreadIsHoldingLock(); } + + JSLock& apiLock() { return *m_apiLock; } + CodeCache* codeCache() { return m_codeCache.get(); } - JSLock& apiLock() { return *m_apiLock; } - CodeCache* codeCache() { return m_codeCache.get(); } + JS_EXPORT_PRIVATE void whenIdle(std::function<void()>); - JS_EXPORT_PRIVATE void discardAllCode(); + JS_EXPORT_PRIVATE void deleteAllCode(); + JS_EXPORT_PRIVATE void deleteAllLinkedCode(); + + void registerWatchpointForImpureProperty(const Identifier&, Watchpoint*); + + // FIXME: Use AtomicString once it got merged with Identifier. + JS_EXPORT_PRIVATE void addImpureProperty(const String&); + + BuiltinExecutables* builtinExecutables() { return m_builtinExecutables.get(); } + + bool enableTypeProfiler(); + bool disableTypeProfiler(); + TypeProfilerLog* typeProfilerLog() { return m_typeProfilerLog.get(); } + TypeProfiler* typeProfiler() { return m_typeProfiler.get(); } + JS_EXPORT_PRIVATE void dumpTypeProfilerData(); + + FunctionHasExecutedCache* functionHasExecutedCache() { return &m_functionHasExecutedCache; } + + ControlFlowProfiler* controlFlowProfiler() { return m_controlFlowProfiler.get(); } + bool enableControlFlowProfiler(); + bool disableControlFlowProfiler(); + + JS_EXPORT_PRIVATE void queueMicrotask(JSGlobalObject*, PassRefPtr<Microtask>); + JS_EXPORT_PRIVATE void drainMicrotasks(); + JS_EXPORT_PRIVATE void setShouldRewriteConstAsVar(bool shouldRewrite) { m_shouldRewriteConstAsVar = shouldRewrite; } + ALWAYS_INLINE bool shouldRewriteConstAsVar() { return m_shouldRewriteConstAsVar; } + + inline bool shouldTriggerTermination(ExecState*); + + void setShouldBuildPCToCodeOriginMapping() { m_shouldBuildPCToCodeOriginMapping = true; } + bool shouldBuilderPCToCodeOriginMapping() const { return m_shouldBuildPCToCodeOriginMapping; } + + BytecodeIntrinsicRegistry& bytecodeIntrinsicRegistry() { return *m_bytecodeIntrinsicRegistry; } + +private: + friend class LLIntOffsetsExtractor; + friend class ClearExceptionScope; + + VM(VMType, HeapType); + static VM*& sharedInstanceInternal(); + void createNativeThunk(); + + void updateStackLimit(); + + void setException(Exception* exception) + { + m_exception = exception; + m_lastException = exception; + } - private: - friend class LLIntOffsetsExtractor; - - VM(VMType, HeapType); - static VM*& sharedInstanceInternal(); - void createNativeThunk(); #if ENABLE(ASSEMBLER) - bool m_canUseAssembler; + bool m_canUseAssembler; #endif #if ENABLE(JIT) - bool m_canUseJIT; + bool m_canUseJIT; #endif #if ENABLE(YARR_JIT) - bool m_canUseRegExpJIT; + bool m_canUseRegExpJIT; #endif #if ENABLE(GC_VALIDATION) - const ClassInfo* m_initializingObjectClass; + const ClassInfo* m_initializingObjectClass; #endif - bool m_inDefineOwnProperty; - RefPtr<CodeCache> m_codeCache; - RefCountedArray<StackFrame> m_exceptionStack; - - TypedArrayDescriptor m_int8ArrayDescriptor; - TypedArrayDescriptor m_int16ArrayDescriptor; - TypedArrayDescriptor m_int32ArrayDescriptor; - TypedArrayDescriptor m_uint8ArrayDescriptor; - TypedArrayDescriptor m_uint8ClampedArrayDescriptor; - TypedArrayDescriptor m_uint16ArrayDescriptor; - TypedArrayDescriptor m_uint32ArrayDescriptor; - TypedArrayDescriptor m_float32ArrayDescriptor; - TypedArrayDescriptor m_float64ArrayDescriptor; + void* m_stackPointerAtVMEntry; + size_t m_reservedZoneSize; +#if !ENABLE(JIT) + struct { + void* m_stackLimit; + void* m_jsStackLimit; }; +#else + union { + void* m_stackLimit; + void* m_jsStackLimit; + }; +#if ENABLE(FTL_JIT) + void* m_ftlStackLimit; + size_t m_largestFTLStackSize; +#endif +#endif + void* m_lastStackTop; + Exception* m_exception { nullptr }; + Exception* m_lastException { nullptr }; + bool m_failNextNewCodeBlock { false }; + bool m_inDefineOwnProperty; + bool m_shouldRewriteConstAsVar { false }; + bool m_shouldBuildPCToCodeOriginMapping { false }; + std::unique_ptr<CodeCache> m_codeCache; + LegacyProfiler* m_enabledProfiler; + std::unique_ptr<BuiltinExecutables> m_builtinExecutables; + HashMap<String, RefPtr<WatchpointSet>> m_impurePropertyWatchpointSets; + std::unique_ptr<TypeProfiler> m_typeProfiler; + std::unique_ptr<TypeProfilerLog> m_typeProfilerLog; + unsigned m_typeProfilerEnabledCount; + FunctionHasExecutedCache m_functionHasExecutedCache; + std::unique_ptr<ControlFlowProfiler> m_controlFlowProfiler; + unsigned m_controlFlowProfilerEnabledCount; + Deque<std::unique_ptr<QueuedTask>> m_microtaskQueue; + MallocPtr<EncodedJSValue> m_exceptionFuzzBuffer; + RefPtr<Watchdog> m_watchdog; +#if ENABLE(SAMPLING_PROFILER) + RefPtr<SamplingProfiler> m_samplingProfiler; +#endif + std::unique_ptr<BytecodeIntrinsicRegistry> m_bytecodeIntrinsicRegistry; +}; #if ENABLE(GC_VALIDATION) - inline bool VM::isInitializingObject() const - { - return !!m_initializingObjectClass; - } +inline bool VM::isInitializingObject() const +{ + return !!m_initializingObjectClass; +} + +inline void VM::setInitializingObjectClass(const ClassInfo* initializingObjectClass) +{ + m_initializingObjectClass = initializingObjectClass; +} +#endif - inline void VM::setInitializingObjectClass(const ClassInfo* initializingObjectClass) - { - m_initializingObjectClass = initializingObjectClass; - } +inline Heap* WeakSet::heap() const +{ + return &m_vm->heap; +} + +#if ENABLE(JIT) +extern "C" void sanitizeStackForVMImpl(VM*); #endif - inline Heap* WeakSet::heap() const - { - return &m_vm->heap; - } +void sanitizeStackForVM(VM*); +void logSanitizeStack(VM*); } // namespace JSC |