From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- Source/JavaScriptCore/runtime/VM.h | 1041 ++++++++++++++++++++++-------------- 1 file changed, 653 insertions(+), 388 deletions(-) (limited to 'Source/JavaScriptCore/runtime/VM.h') diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h index 1de423e0e..732b26e4e 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-2017 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. * @@ -26,527 +26,792 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef VM_h -#define VM_h +#pragma once +#include "CallData.h" +#include "ConcurrentJSLock.h" +#include "ControlFlowProfiler.h" #include "DateInstanceCache.h" +#include "DeleteAllCodeEffort.h" +#include "ExceptionEventLocation.h" #include "ExecutableAllocator.h" -#include "GPRInfo.h" +#include "FunctionHasExecutedCache.h" #include "Heap.h" #include "Intrinsic.h" #include "JITThunks.h" #include "JSCJSValue.h" +#include "JSDestructibleObjectSubspace.h" #include "JSLock.h" -#include "LLIntData.h" +#include "JSSegmentedVariableObjectSubspace.h" +#include "JSStringSubspace.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 "Subspace.h" +#include "TemplateRegistryKeyTable.h" #include "ThunkGenerators.h" -#include "TypedArrayController.h" -#include "Watchdog.h" +#include "VMEntryRecord.h" #include "Watchpoint.h" -#include "WeakRandom.h" +#include #include #include +#include +#include #include #include #include -#include -#include #include +#include #include #include #include +#include #include #if ENABLE(REGEXP_TRACING) #include #endif +namespace WTF { +class SimpleStats; +} // namespace WTF +using WTF::SimpleStats; + namespace JSC { - class CodeBlock; - class CodeCache; - class CommonIdentifiers; - class ExecState; - class HandleStack; - class Identifier; - 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 ExceptionScope; +class HandleStack; +class TypeProfiler; +class TypeProfilerLog; +class HasOwnPropertyCache; +class HeapProfiler; +class Identifier; +class Interpreter; +class JSCustomGetterSetterFunction; +class JSGlobalObject; +class JSObject; +class JSWebAssemblyInstance; +class LLIntOffsetsExtractor; +class NativeExecutable; +class RegExpCache; +class Register; +class RegisterAtOffsetList; +#if ENABLE(SAMPLING_PROFILER) +class SamplingProfiler; +#endif +class ShadowChicken; +class ScriptExecutable; +class SourceProvider; +class SourceProviderCache; +class StackFrame; +class Structure; #if ENABLE(REGEXP_TRACING) - class RegExp; +class RegExp; #endif - class UnlinkedCodeBlock; - class UnlinkedEvalCodeBlock; - class UnlinkedFunctionExecutable; - class UnlinkedProgramCodeBlock; - class VMEntryScope; - class Watchpoint; - class WatchpointSet; +class Symbol; +class TypedArrayController; +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; - class Worklist; - } +namespace DFG { +class LongLivedState; +} #endif // ENABLE(DFG_JIT) #if ENABLE(FTL_JIT) - namespace FTL { - class Thunks; - } +namespace FTL { +class Thunks; +} #endif // ENABLE(FTL_JIT) +namespace CommonSlowPaths { +struct ArityCheckData; +} +namespace Profiler { +class Database; +} +namespace DOMJIT { +class Signature; +} +#if ENABLE(WEBASSEMBLY) +namespace Wasm { +class SignatureInformation; +} +#endif - struct HashTable; - struct Instruction; +struct HashTable; +struct Instruction; - struct LocalTimeOffsetCache { - LocalTimeOffsetCache() - : start(0.0) - , end(-1.0) - , increment(0.0) - , timeType(WTF::UTCTime) - { - } - - 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) + , timeType(WTF::UTCTime) + { + } - LocalTimeOffset offset; - double start; - double end; - double increment; - WTF::TimeType timeType; - }; + void reset() + { + offset = LocalTimeOffset(); + start = 0.0; + end = -1.0; + increment = 0.0; + timeType = WTF::UTCTime; + } + + 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, Ref&& microtask) + : m_globalObject(vm, globalObject) + , m_microtask(WTFMove(microtask)) + { + } + +private: + Strong m_globalObject; + Ref m_microtask; +}; - 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 { - 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 PassRefPtr create(HeapType = SmallHeap); - JS_EXPORT_PRIVATE static PassRefPtr createLeaked(HeapType = SmallHeap); - static PassRefPtr createContextGroup(HeapType = SmallHeap); - JS_EXPORT_PRIVATE ~VM(); - - void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } - -#if ENABLE(DFG_JIT) - DFG::Worklist* ensureWorklist(); -#endif // ENABLE(DFG_JIT) +class VM : public ThreadSafeRefCounted, public DoublyLinkedListNode { +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; + }; - private: - RefPtr m_apiLock; + bool isSharedInstance() { return vmType == APIShared; } + bool usingAPI() { return vmType != Default; } + JS_EXPORT_PRIVATE static bool sharedInstanceExists(); + JS_EXPORT_PRIVATE static VM& sharedInstance(); - public: + JS_EXPORT_PRIVATE static Ref create(HeapType = SmallHeap); + JS_EXPORT_PRIVATE static Ref createLeaked(HeapType = SmallHeap); + static Ref createContextGroup(HeapType = SmallHeap); + JS_EXPORT_PRIVATE ~VM(); + + JS_EXPORT_PRIVATE Watchdog& ensureWatchdog(); + Watchdog* watchdog() { return m_watchdog.get(); } + + HeapProfiler* heapProfiler() const { return m_heapProfiler.get(); } + JS_EXPORT_PRIVATE HeapProfiler& ensureHeapProfiler(); + +#if ENABLE(SAMPLING_PROFILER) + SamplingProfiler* samplingProfiler() { return m_samplingProfiler.get(); } + JS_EXPORT_PRIVATE SamplingProfiler& ensureSamplingProfiler(RefPtr&&); +#endif + +private: + RefPtr 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; + + Subspace auxiliarySpace; + + // Whenever possible, use subspaceFor(vm) to get one of these subspaces. + Subspace cellSpace; + Subspace destructibleCellSpace; + JSStringSubspace stringSpace; + JSDestructibleObjectSubspace destructibleObjectSpace; + JSSegmentedVariableObjectSubspace segmentedVariableObjectSpace; + #if ENABLE(DFG_JIT) - OwnPtr dfgState; - RefPtr worklist; + std::unique_ptr dfgState; #endif // ENABLE(DFG_JIT) - VMType vmType; - ClientData* clientData; - ExecState* topCallFrame; - Watchdog watchdog; - - const OwnPtr arrayConstructorTable; - const OwnPtr arrayPrototypeTable; - const OwnPtr booleanPrototypeTable; - const OwnPtr dataViewTable; - const OwnPtr dateTable; - const OwnPtr dateConstructorTable; - const OwnPtr errorPrototypeTable; - const OwnPtr globalObjectTable; - const OwnPtr jsonTable; - const OwnPtr numberConstructorTable; - const OwnPtr numberPrototypeTable; - const OwnPtr objectConstructorTable; - const OwnPtr privateNamePrototypeTable; - const OwnPtr regExpTable; - const OwnPtr regExpConstructorTable; - const OwnPtr regExpPrototypeTable; - const OwnPtr stringConstructorTable; -#if ENABLE(PROMISES) - const OwnPtr promisePrototypeTable; - const OwnPtr promiseConstructorTable; + VMType vmType; + ClientData* clientData; + VMEntryFrame* topVMEntryFrame; + // NOTE: When throwing an exception while rolling back the call frame, this may be equal to + // topVMEntryFrame. + // FIXME: This should be a void*, because it might not point to a CallFrame. + // https://bugs.webkit.org/show_bug.cgi?id=160441 + ExecState* topCallFrame; + JSWebAssemblyInstance* topJSWebAssemblyInstance; + Strong structureStructure; + Strong structureRareDataStructure; + Strong terminatedExecutionErrorStructure; + Strong stringStructure; + Strong propertyNameIteratorStructure; + Strong propertyNameEnumeratorStructure; + Strong customGetterSetterStructure; + Strong scopedArgumentsTableStructure; + Strong apiWrapperStructure; + Strong JSScopeStructure; + Strong executableStructure; + Strong nativeExecutableStructure; + Strong evalExecutableStructure; + Strong programExecutableStructure; + Strong functionExecutableStructure; +#if ENABLE(WEBASSEMBLY) + Strong webAssemblyCalleeStructure; + Strong webAssemblyToJSCalleeStructure; + Strong webAssemblyToJSCallee; #endif + Strong moduleProgramExecutableStructure; + Strong regExpStructure; + Strong symbolStructure; + Strong symbolTableStructure; + Strong fixedArrayStructure; + Strong sourceCodeStructure; + Strong scriptFetcherStructure; + Strong structureChainStructure; + Strong sparseArrayValueMapStructure; + Strong templateRegistryKeyStructure; + Strong arrayBufferNeuteringWatchpointStructure; + Strong unlinkedFunctionExecutableStructure; + Strong unlinkedProgramCodeBlockStructure; + Strong unlinkedEvalCodeBlockStructure; + Strong unlinkedFunctionCodeBlockStructure; + Strong unlinkedModuleProgramCodeBlockStructure; + Strong propertyTableStructure; + Strong weakMapDataStructure; + Strong inferredValueStructure; + Strong inferredTypeStructure; + Strong inferredTypeTableStructure; + Strong functionRareDataStructure; + Strong exceptionStructure; + Strong promiseDeferredStructure; + Strong internalPromiseDeferredStructure; + Strong nativeStdFunctionCellStructure; + Strong programCodeBlockStructure; + Strong moduleProgramCodeBlockStructure; + Strong evalCodeBlockStructure; + Strong functionCodeBlockStructure; + Strong hashMapBucketSetStructure; + Strong hashMapBucketMapStructure; + Strong hashMapImplSetStructure; + Strong hashMapImplMapStructure; + + Strong iterationTerminator; + Strong emptyPropertyNameEnumerator; + +#if ENABLE(WEBASSEMBLY) + std::once_flag m_wasmSignatureInformationOnceFlag; + std::unique_ptr m_wasmSignatureInformation; +#endif + + JSCell* currentlyDestructingCallbackObject; + const ClassInfo* currentlyDestructingCallbackObjectClassInfo; + + AtomicStringTable* m_atomicStringTable; + WTF::SymbolRegistry m_symbolRegistry; + TemplateRegistryKeyTable m_templateRegistryKeytable; + CommonIdentifiers* propertyNames; + const ArgList* emptyList; + SmallStrings smallStrings; + NumericStrings numericStrings; + DateInstanceCache dateInstanceCache; + std::unique_ptr machineCodeBytesPerBytecodeWordForBaselineJIT; + WeakGCMap, JSCustomGetterSetterFunction> customGetterSetterFunctionMap; + WeakGCMap> stringCache; + Strong lastCachedString; + + AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; } + WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; } + + TemplateRegistryKeyTable& templateRegistryKeyTable() { return m_templateRegistryKeytable; } + + WeakGCMap> symbolImplToSymbolMap; + + enum class DeletePropertyMode { + // Default behaviour of deleteProperty, matching the spec. + Default, + // This setting causes deleteProperty to force deletion of all + // properties including those that are non-configurable (DontDelete). + IgnoreConfigurable + }; + + DeletePropertyMode deletePropertyMode() + { + return m_deletePropertyMode; + } - Strong structureStructure; - Strong structureRareDataStructure; - Strong debuggerActivationStructure; - Strong terminatedExecutionErrorStructure; - Strong stringStructure; - Strong notAnObjectStructure; - Strong propertyNameIteratorStructure; - Strong getterSetterStructure; - Strong apiWrapperStructure; - Strong JSScopeStructure; - Strong executableStructure; - Strong nativeExecutableStructure; - Strong evalExecutableStructure; - Strong programExecutableStructure; - Strong functionExecutableStructure; - Strong regExpStructure; - Strong symbolTableStructure; - Strong structureChainStructure; - Strong sparseArrayValueMapStructure; - Strong arrayBufferNeuteringWatchpointStructure; - Strong withScopeStructure; - Strong unlinkedFunctionExecutableStructure; - Strong unlinkedProgramCodeBlockStructure; - Strong unlinkedEvalCodeBlockStructure; - Strong unlinkedFunctionCodeBlockStructure; - Strong propertyTableStructure; - Strong mapDataStructure; - Strong weakMapDataStructure; - Strong promiseDeferredStructure; - Strong promiseReactionStructure; - Strong iterationTerminator; - - 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; - - void setInDefineOwnProperty(bool inDefineOwnProperty) + class DeletePropertyModeScope { + public: + DeletePropertyModeScope(VM& vm, DeletePropertyMode mode) + : m_vm(vm) + , m_previousMode(vm.m_deletePropertyMode) { - m_inDefineOwnProperty = inDefineOwnProperty; + m_vm.m_deletePropertyMode = mode; } - bool isInDefineOwnProperty() + ~DeletePropertyModeScope() { - return m_inDefineOwnProperty; + m_vm.m_deletePropertyMode = m_previousMode; } - LegacyProfiler* enabledProfiler() { return m_enabledProfiler; } - void setEnabledProfiler(LegacyProfiler*); - - void* enabledProfilerAddress() { return &m_enabledProfiler; } + private: + VM& m_vm; + DeletePropertyMode m_previousMode; + }; -#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; - typedef HashMap, RefPtr> SourceProviderCacheMap; - SourceProviderCacheMap sourceProviderCacheMap; - OwnPtr keywords; - Interpreter* interpreter; + typedef HashMap, RefPtr> SourceProviderCacheMap; + SourceProviderCacheMap sourceProviderCacheMap; + Interpreter* interpreter; #if ENABLE(JIT) - OwnPtr jitStubs; - MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator) - { - return jitStubs->ctiStub(this, generator); - } - NativeExecutable* getHostFunction(NativeFunction, Intrinsic); -#endif + std::unique_ptr jitStubs; + MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator) + { + return jitStubs->ctiStub(this, generator); + } + + std::unique_ptr allCalleeSaveRegisterOffsets; + + RegisterAtOffsetList* getAllCalleeSaveRegisterOffsets() { return allCalleeSaveRegisterOffsets.get(); } + +#endif // ENABLE(JIT) + std::unique_ptr arityCheckData; #if ENABLE(FTL_JIT) - std::unique_ptr ftlThunks; + std::unique_ptr ftlThunks; #endif - NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor); + NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor, const String& name); + NativeExecutable* getHostFunction(NativeFunction, Intrinsic, NativeFunction constructor, const DOMJIT::Signature*, const String& name); - static ptrdiff_t exceptionOffset() - { - return OBJECT_OFFSETOF(VM, m_exception); - } + static ptrdiff_t exceptionOffset() + { + return OBJECT_OFFSETOF(VM, m_exception); + } - static ptrdiff_t callFrameForThrowOffset() - { - return OBJECT_OFFSETOF(VM, callFrameForThrow); - } + static ptrdiff_t callFrameForCatchOffset() + { + return OBJECT_OFFSETOF(VM, callFrameForCatch); + } - static ptrdiff_t targetMachinePCForThrowOffset() - { - return OBJECT_OFFSETOF(VM, targetMachinePCForThrow); - } + static ptrdiff_t targetMachinePCForThrowOffset() + { + return OBJECT_OFFSETOF(VM, targetMachinePCForThrow); + } - JS_EXPORT_PRIVATE void clearException(); - JS_EXPORT_PRIVATE void clearExceptionStack(); - void getExceptionInfo(JSValue& exception, RefCountedArray& exceptionStack); - void setExceptionInfo(JSValue& exception, RefCountedArray& exceptionStack); - JSValue exception() const { return m_exception; } - JSValue* addressOfException() { return &m_exception; } - const RefCountedArray& exceptionStack() const { return m_exceptionStack; } - - JS_EXPORT_PRIVATE JSValue throwException(ExecState*, JSValue); - JS_EXPORT_PRIVATE JSObject* throwException(ExecState*, JSObject*); - - void** addressOfJSStackLimit() { return &m_jsStackLimit; } - void* jsStackLimit() { return m_jsStackLimit; } - void setJSStackLimit(void* limit) { m_jsStackLimit = limit; } - - void* stackLimit() { return m_stackLimit; } - void setStackLimit(void* limit) { m_stackLimit = limit; } - bool isSafeToRecurse(size_t neededStackInBytes = 0) const - { - ASSERT(wtfThreadData().stack().isGrowingDownward()); - int8_t* curr = reinterpret_cast(&curr); - int8_t* limit = reinterpret_cast(m_stackLimit); - return curr >= limit && static_cast(curr - limit) >= neededStackInBytes; - } + void restorePreviousException(Exception* exception) { setException(exception); } - const ClassInfo* const jsArrayClassInfo; - const ClassInfo* const jsFinalObjectClassInfo; - - ReturnAddressPtr exceptionLocation; - JSValue hostCallReturnValue; - ExecState* newCallFrameReturnValue; - ExecState* callFrameForThrow; - void* targetMachinePCForThrow; - Instruction* targetInterpreterPCForThrow; - uint32_t osrExitIndex; - void* osrExitJumpDestination; - Vector 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; + void clearLastException() { m_lastException = nullptr; } + + ExecState** addressOfCallFrameForCatch() { return &callFrameForCatch; } + + JSCell** addressOfException() { return reinterpret_cast(&m_exception); } + + Exception* lastException() const { return m_lastException; } + JSCell** addressOfLastException() { return reinterpret_cast(&m_lastException); } + + void setFailNextNewCodeBlock() { m_failNextNewCodeBlock = true; } + bool getAndClearFailNextNewCodeBlock() + { + bool result = m_failNextNewCodeBlock; + m_failNextNewCodeBlock = false; + return result; + } + + ALWAYS_INLINE Structure* getStructure(StructureID id) + { + return heap.structureIDTable().get(decontaminate(id)); + } + + void* stackPointerAtVMEntry() const { return m_stackPointerAtVMEntry; } + void setStackPointerAtVMEntry(void*); + + size_t softReservedZoneSize() const { return m_currentSoftReservedZoneSize; } + size_t updateSoftReservedZoneSize(size_t softReservedZoneSize); + + static size_t committedStackByteCount(); + inline bool ensureStackCapacityFor(Register* newTopOfStack); + + void* stackLimit() { return m_stackLimit; } + void* softStackLimit() { return m_softStackLimit; } + void** addressOfSoftStackLimit() { return &m_softStackLimit; } +#if !ENABLE(JIT) + void* cloopStackLimit() { return m_cloopStackLimit; } + void setCLoopStackLimit(void* limit) { m_cloopStackLimit = limit; } +#endif + + inline bool isSafeToRecurseSoft() const; + bool isSafeToRecurse() const + { + return isSafeToRecurse(m_stackLimit); + } + + 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 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); } - void gatherConservativeRoots(ConservativeRoots&); + ScratchBuffer* result = scratchBuffers.last(); + result->setActiveLength(0); + return result; + } + + EncodedJSValue* exceptionFuzzingBuffer(size_t size) + { + ASSERT(Options::useExceptionFuzz()); + if (!m_exceptionFuzzBuffer) + m_exceptionFuzzBuffer = MallocPtr::malloc(size); + return m_exceptionFuzzBuffer.get(); + } - VMEntryScope* entryScope; + void gatherConservativeRoots(ConservativeRoots&); - HashSet stringRecursionCheckVisitedObjects; + VMEntryScope* entryScope; - LocalTimeOffsetCache localTimeOffsetCache; - - String cachedDateString; - double cachedDateStringValue; + JSObject* stringRecursionCheckFirstObject { nullptr }; + HashSet stringRecursionCheckVisitedObjects; - OwnPtr m_perBytecodeProfiler; - RefPtr m_typedArrayController; - RegExpCache* m_regExpCache; - BumpPointerAllocator m_regExpAllocator; + LocalTimeOffsetCache localTimeOffsetCache; + + String cachedDateString; + double cachedDateStringValue; + + std::unique_ptr m_perBytecodeProfiler; + RefPtr m_typedArrayController; + RegExpCache* m_regExpCache; + BumpPointerAllocator m_regExpAllocator; + ConcurrentJSLock m_regExpAllocatorLock; + + std::unique_ptr m_hasOwnPropertyCache; + ALWAYS_INLINE HasOwnPropertyCache* hasOwnPropertyCache() { return m_hasOwnPropertyCache.get(); } + HasOwnPropertyCache* ensureHasOwnPropertyCache(); #if ENABLE(REGEXP_TRACING) - typedef ListHashSet> RTTraceList; - RTTraceList* m_rtTraceList; + typedef ListHashSet RTTraceList; + RTTraceList* m_rtTraceList; #endif - ThreadIdentifier exclusiveThread; + 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; } + RegExpCache* regExpCache() { return m_regExpCache; } #if ENABLE(REGEXP_TRACING) - void addRegExpToTrace(PassRefPtr 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 isCollectorBusyOnCurrentThread() { return heap.isCurrentThreadBusy(); } #if ENABLE(GC_VALIDATION) - bool isInitializingObject() const; - void setInitializingObjectClass(const ClassInfo*); + bool isInitializingObject() const; + void setInitializingObjectClass(const ClassInfo*); #endif - unsigned m_newStringsSinceLastHashCons; + bool currentThreadIsHoldingAPILock() const { return m_apiLock->currentThreadIsHoldingLock(); } - static const unsigned s_minNumberOfNewStringsToHashCons = 100; + JSLock& apiLock() { return *m_apiLock; } + CodeCache* codeCache() { return m_codeCache.get(); } - bool haveEnoughNewStringsToHashCons() { return m_newStringsSinceLastHashCons > s_minNumberOfNewStringsToHashCons; } - void resetNewStringsSinceLastHashCons() { m_newStringsSinceLastHashCons = 0; } + JS_EXPORT_PRIVATE void whenIdle(std::function); - bool currentThreadIsHoldingAPILock() const - { - return m_apiLock->currentThreadIsHoldingLock() || exclusiveThread == currentThread(); - } + JS_EXPORT_PRIVATE void deleteAllCode(DeleteAllCodeEffort); + JS_EXPORT_PRIVATE void deleteAllLinkedCode(DeleteAllCodeEffort); - JSLock& apiLock() { return *m_apiLock; } - CodeCache* codeCache() { return m_codeCache.get(); } + WatchpointSet* ensureWatchpointSetForImpureProperty(const Identifier&); + void registerWatchpointForImpureProperty(const Identifier&, Watchpoint*); + + // FIXME: Use AtomicString once it got merged with Identifier. + JS_EXPORT_PRIVATE void addImpureProperty(const String&); - void prepareToDiscardCode(); - - JS_EXPORT_PRIVATE void discardAllCode(); + BuiltinExecutables* builtinExecutables() { return m_builtinExecutables.get(); } - void registerWatchpointForImpureProperty(const Identifier&, Watchpoint*); - // FIXME: Use AtomicString once it got merged with Identifier. - JS_EXPORT_PRIVATE void addImpureProperty(const String&); + 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*, Ref&&); + JS_EXPORT_PRIVATE void drainMicrotasks(); + void setGlobalConstRedeclarationShouldThrow(bool globalConstRedeclarationThrow) { m_globalConstRedeclarationShouldThrow = globalConstRedeclarationThrow; } + ALWAYS_INLINE bool globalConstRedeclarationShouldThrow() const { return m_globalConstRedeclarationShouldThrow; } + + inline bool shouldTriggerTermination(ExecState*); + + void setShouldBuildPCToCodeOriginMapping() { m_shouldBuildPCToCodeOriginMapping = true; } + bool shouldBuilderPCToCodeOriginMapping() const { return m_shouldBuildPCToCodeOriginMapping; } + + BytecodeIntrinsicRegistry& bytecodeIntrinsicRegistry() { return *m_bytecodeIntrinsicRegistry; } + + ShadowChicken& shadowChicken() { return *m_shadowChicken; } + + template + void logEvent(CodeBlock*, const char* summary, const Func& func); + +private: + friend class LLIntOffsetsExtractor; + + VM(VMType, HeapType); + static VM*& sharedInstanceInternal(); + void createNativeThunk(); + + void updateStackLimits(); + + bool isSafeToRecurse(void* stackLimit) const + { + ASSERT(wtfThreadData().stack().isGrowingDownward()); + void* curr = reinterpret_cast(&curr); + return curr >= stackLimit; + } + + void setException(Exception* exception) + { + m_exception = exception; + m_lastException = exception; + } + Exception* exception() const + { +#if ENABLE(EXCEPTION_SCOPE_VERIFICATION) + m_needExceptionCheck = false; +#endif + return m_exception; + } + void clearException() + { +#if ENABLE(EXCEPTION_SCOPE_VERIFICATION) + m_needExceptionCheck = false; +#endif + m_exception = nullptr; + } + +#if !ENABLE(JIT) + bool ensureStackCapacityForCLoop(Register* newTopOfStack); + bool isSafeToRecurseSoftCLoop() const; +#endif // !ENABLE(JIT) + + JS_EXPORT_PRIVATE void throwException(ExecState*, Exception*); + JS_EXPORT_PRIVATE JSValue throwException(ExecState*, JSValue); + JS_EXPORT_PRIVATE JSObject* throwException(ExecState*, JSObject*); + +#if ENABLE(EXCEPTION_SCOPE_VERIFICATION) + void verifyExceptionCheckNeedIsSatisfied(unsigned depth, ExceptionEventLocation&); +#endif - private: - friend class LLIntOffsetsExtractor; - friend class ClearExceptionScope; - friend class RecursiveAllocationScope; - - 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 -#if USE(SEPARATE_C_AND_JS_STACK) - struct { - void* m_stackLimit; - void* m_jsStackLimit; - }; -#else - union { - void* m_stackLimit; - void* m_jsStackLimit; - }; + void* m_stackPointerAtVMEntry; + size_t m_currentSoftReservedZoneSize; + void* m_stackLimit { nullptr }; + void* m_softStackLimit { nullptr }; +#if !ENABLE(JIT) + void* m_cloopStackLimit { nullptr }; +#endif + void* m_lastStackTop; + + Exception* m_exception { nullptr }; + Exception* m_lastException { nullptr }; +#if ENABLE(EXCEPTION_SCOPE_VERIFICATION) + ExceptionScope* m_topExceptionScope { nullptr }; + ExceptionEventLocation m_simulatedThrowPointLocation; + unsigned m_simulatedThrowPointRecursionDepth { 0 }; + mutable bool m_needExceptionCheck { false }; #endif - JSValue m_exception; - bool m_inDefineOwnProperty; - OwnPtr m_codeCache; - RefCountedArray m_exceptionStack; - LegacyProfiler* m_enabledProfiler; + bool m_failNextNewCodeBlock { false }; + DeletePropertyMode m_deletePropertyMode { DeletePropertyMode::Default }; + bool m_globalConstRedeclarationShouldThrow { true }; + bool m_shouldBuildPCToCodeOriginMapping { false }; + std::unique_ptr m_codeCache; + std::unique_ptr m_builtinExecutables; + HashMap> m_impurePropertyWatchpointSets; + std::unique_ptr m_typeProfiler; + std::unique_ptr m_typeProfilerLog; + unsigned m_typeProfilerEnabledCount; + FunctionHasExecutedCache m_functionHasExecutedCache; + std::unique_ptr m_controlFlowProfiler; + unsigned m_controlFlowProfilerEnabledCount; + Deque> m_microtaskQueue; + MallocPtr m_exceptionFuzzBuffer; + RefPtr m_watchdog; + std::unique_ptr m_heapProfiler; +#if ENABLE(SAMPLING_PROFILER) + RefPtr m_samplingProfiler; +#endif + std::unique_ptr m_shadowChicken; + std::unique_ptr m_bytecodeIntrinsicRegistry; - HashMap> m_impurePropertyWatchpointSets; - }; + VM* m_prev; // Required by DoublyLinkedListNode. + VM* m_next; // Required by DoublyLinkedListNode. + + // Friends for exception checking purpose only. + friend class Heap; + friend class CatchScope; + friend class ExceptionScope; + friend class ThrowScope; + friend class WTF::DoublyLinkedListNode; +}; #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 - -#endif // VM_h -- cgit v1.2.1