diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/runtime/Executable.h | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/runtime/Executable.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/Executable.h | 1287 |
1 files changed, 607 insertions, 680 deletions
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 28e823ca4..3a3fd8f42 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2013-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,804 +26,731 @@ #ifndef Executable_h #define Executable_h +#include "ArityCheckMode.h" #include "CallData.h" #include "CodeBlockHash.h" #include "CodeSpecializationKind.h" +#include "CompilationResult.h" +#include "ExecutableInfo.h" #include "HandlerInfo.h" -#include "JSFunction.h" -#include "Interpreter.h" +#include "InferredValue.h" #include "JITCode.h" #include "JSGlobalObject.h" -#include "LLIntCLoop.h" #include "SamplingTool.h" #include "SourceCode.h" +#include "TypeSet.h" #include "UnlinkedCodeBlock.h" -#include <wtf/PassOwnPtr.h> +#include "UnlinkedFunctionExecutable.h" namespace JSC { - class CodeBlock; - class Debugger; - class EvalCodeBlock; - class FunctionCodeBlock; - class LLIntOffsetsExtractor; - class ProgramCodeBlock; - class JSScope; - - enum CompilationKind { FirstCompilation, OptimizingCompilation }; - - inline bool isCall(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return true; - ASSERT(kind == CodeForConstruct); - return false; - } +class CodeBlock; +class Debugger; +class EvalCodeBlock; +class FunctionCodeBlock; +class JSScope; +class JSWASMModule; +class LLIntOffsetsExtractor; +class ProgramCodeBlock; +class ModuleProgramCodeBlock; +class JSScope; +class WebAssemblyCodeBlock; +class ModuleProgramCodeBlock; +class JSModuleRecord; +class JSScope; + +enum CompilationKind { FirstCompilation, OptimizingCompilation }; + +inline bool isCall(CodeSpecializationKind kind) +{ + if (kind == CodeForCall) + return true; + ASSERT(kind == CodeForConstruct); + return false; +} - class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> { - friend class WTF::DoublyLinkedListNode<ExecutableBase>; - friend class JIT; +class ExecutableBase : public JSCell { + friend class JIT; - protected: - static const int NUM_PARAMETERS_IS_HOST = 0; - static const int NUM_PARAMETERS_NOT_COMPILED = -1; +protected: + static const int NUM_PARAMETERS_IS_HOST = 0; + static const int NUM_PARAMETERS_NOT_COMPILED = -1; - ExecutableBase(VM& vm, Structure* structure, int numParameters) - : JSCell(vm, structure) - , m_numParametersForCall(numParameters) - , m_numParametersForConstruct(numParameters) - { - } + ExecutableBase(VM& vm, Structure* structure, int numParameters) + : JSCell(vm, structure) + , m_numParametersForCall(numParameters) + , m_numParametersForConstruct(numParameters) + { + } - void finishCreation(VM& vm) - { - Base::finishCreation(vm); - } + void finishCreation(VM& vm) + { + Base::finishCreation(vm); + } - public: - typedef JSCell Base; +public: + typedef JSCell Base; + static const unsigned StructureFlags = Base::StructureFlags; -#if ENABLE(JIT) - static const bool needsDestruction = true; - static const bool hasImmortalStructure = true; - static void destroy(JSCell*); -#endif + static const bool needsDestruction = true; + static void destroy(JSCell*); - CodeBlockHash hashFor(CodeSpecializationKind) const; + CodeBlockHash hashFor(CodeSpecializationKind) const; - bool isFunctionExecutable() - { - return structure()->typeInfo().type() == FunctionExecutableType; - } + bool isEvalExecutable() const + { + return type() == EvalExecutableType; + } + bool isFunctionExecutable() const + { + return type() == FunctionExecutableType; + } + bool isProgramExecutable() const + { + return type() == ProgramExecutableType; + } + bool isModuleProgramExecutable() + { + return type() == ModuleProgramExecutableType; + } - bool isHostFunction() const - { - ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST)); - return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; - } - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); } - - void clearCode(); + bool isHostFunction() const + { + ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST)); + return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; + } - static JS_EXPORTDATA const ClassInfo s_info; +#if ENABLE(WEBASSEMBLY) + bool isWebAssemblyExecutable() const + { + return type() == WebAssemblyExecutableType; + } +#endif - protected: - static const unsigned StructureFlags = 0; - int m_numParametersForCall; - int m_numParametersForConstruct; + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } + + void clearCode(); - public: - static void clearCodeVirtual(ExecutableBase*); + DECLARE_EXPORT_INFO; -#if ENABLE(JIT) - JITCode& generatedJITCodeForCall() - { - ASSERT(m_jitCodeForCall); - return m_jitCodeForCall; - } +protected: + int m_numParametersForCall; + int m_numParametersForConstruct; - JITCode& generatedJITCodeForConstruct() - { - ASSERT(m_jitCodeForConstruct); - return m_jitCodeForConstruct; - } - - JITCode& generatedJITCodeFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return generatedJITCodeForCall(); - ASSERT(kind == CodeForConstruct); - return generatedJITCodeForConstruct(); - } - - MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck() - { - ASSERT(m_jitCodeForCall); - ASSERT(m_jitCodeForCallWithArityCheck); - return m_jitCodeForCallWithArityCheck; - } +public: + PassRefPtr<JITCode> generatedJITCodeForCall() + { + ASSERT(m_jitCodeForCall); + return m_jitCodeForCall; + } - MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck() - { - ASSERT(m_jitCodeForConstruct); - ASSERT(m_jitCodeForConstructWithArityCheck); - return m_jitCodeForConstructWithArityCheck; - } - - MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return generatedJITCodeForCallWithArityCheck(); - ASSERT(kind == CodeForConstruct); - return generatedJITCodeForConstructWithArityCheck(); - } - - bool hasJITCodeForCall() const - { - return m_numParametersForCall >= 0; - } + PassRefPtr<JITCode> generatedJITCodeForConstruct() + { + ASSERT(m_jitCodeForConstruct); + return m_jitCodeForConstruct; + } - bool hasJITCodeForConstruct() const - { - return m_numParametersForConstruct >= 0; + PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return generatedJITCodeForCall(); + ASSERT(kind == CodeForConstruct); + return generatedJITCodeForConstruct(); + } + + MacroAssemblerCodePtr entrypointFor(CodeSpecializationKind kind, ArityCheckMode arity) + { + // Check if we have a cached result. We only have it for arity check because we use the + // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in + // machine code. + if (arity == MustCheckArity) { + switch (kind) { + case CodeForCall: + if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck) + return result; + break; + case CodeForConstruct: + if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck) + return result; + break; + } } - - bool hasJITCodeFor(CodeSpecializationKind kind) const - { - if (kind == CodeForCall) - return hasJITCodeForCall(); - ASSERT(kind == CodeForConstruct); - return hasJITCodeForConstruct(); + MacroAssemblerCodePtr result = + generatedJITCodeFor(kind)->addressForCall(arity); + if (arity == MustCheckArity) { + // Cache the result; this is necessary for the JIT's virtual call optimizations. + switch (kind) { + case CodeForCall: + m_jitCodeForCallWithArityCheck = result; + break; + case CodeForConstruct: + m_jitCodeForConstructWithArityCheck = result; + break; + } } + return result; + } - static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCall); - ASSERT(kind == CodeForConstruct); - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstruct); - } - - static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); - ASSERT(kind == CodeForConstruct); + static ptrdiff_t offsetOfJITCodeWithArityCheckFor( + CodeSpecializationKind kind) + { + switch (kind) { + case CodeForCall: + return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); + case CodeForConstruct: return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); } - - static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall); - ASSERT(kind == CodeForConstruct); - return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct); - } -#endif // ENABLE(JIT) + RELEASE_ASSERT_NOT_REACHED(); + return 0; + } + + static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall); + ASSERT(kind == CodeForConstruct); + return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct); + } - // Intrinsics are only for calls, currently. - Intrinsic intrinsic() const; + bool hasJITCodeForCall() const + { + return m_numParametersForCall >= 0; + } - Intrinsic intrinsicFor(CodeSpecializationKind kind) const - { - if (isCall(kind)) - return intrinsic(); - return NoIntrinsic; - } + bool hasJITCodeForConstruct() const + { + return m_numParametersForConstruct >= 0; + } -#if ENABLE(JIT) || ENABLE(LLINT_C_LOOP) - MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind) - { - #if ENABLE(JIT) - return generatedJITCodeFor(kind).addressForCall(); - #else - return LLInt::CLoop::hostCodeEntryFor(kind); - #endif - } + bool hasJITCodeFor(CodeSpecializationKind kind) const + { + if (kind == CodeForCall) + return hasJITCodeForCall(); + ASSERT(kind == CodeForConstruct); + return hasJITCodeForConstruct(); + } - MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind) - { - #if ENABLE(JIT) - return generatedJITCodeFor(kind).addressForCall(); - #else - return LLInt::CLoop::jsCodeEntryFor(kind); - #endif - } + // Intrinsics are only for calls, currently. + Intrinsic intrinsic() const; + + Intrinsic intrinsicFor(CodeSpecializationKind kind) const + { + if (isCall(kind)) + return intrinsic(); + return NoIntrinsic; + } + + void dump(PrintStream&) const; + +protected: + RefPtr<JITCode> m_jitCodeForCall; + RefPtr<JITCode> m_jitCodeForConstruct; + MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck; + MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck; +}; + +class NativeExecutable final : public ExecutableBase { + friend class JIT; + friend class LLIntOffsetsExtractor; +public: + typedef ExecutableBase Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; + + static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name) + { + NativeExecutable* executable; + executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor); + executable->finishCreation(vm, callThunk, constructThunk, intrinsic, name); + return executable; + } - MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind) - { - #if ENABLE(JIT) - return generatedJITCodeWithArityCheckFor(kind); - #else - return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind); - #endif - } + static void destroy(JSCell*); - static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter) - { - #if ENABLE(JIT) - UNUSED_PARAM(catchPCForInterpreter); - return handler->nativeCode.executableAddress(); - #else - UNUSED_PARAM(handler); - return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter); - #endif - } -#endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP) + CodeBlockHash hashFor(CodeSpecializationKind) const; - protected: - ExecutableBase* m_prev; - ExecutableBase* m_next; + NativeFunction function() { return m_function; } + NativeFunction constructor() { return m_constructor; } + + NativeFunction nativeFunctionFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return function(); + ASSERT(kind == CodeForConstruct); + return constructor(); + } + + static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return OBJECT_OFFSETOF(NativeExecutable, m_function); + ASSERT(kind == CodeForConstruct); + return OBJECT_OFFSETOF(NativeExecutable, m_constructor); + } -#if ENABLE(JIT) - JITCode m_jitCodeForCall; - JITCode m_jitCodeForConstruct; - MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck; - MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck; -#endif - }; - - class NativeExecutable : public ExecutableBase { - friend class JIT; - friend class LLIntOffsetsExtractor; - public: - typedef ExecutableBase Base; - -#if ENABLE(JIT) - static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic) - { - NativeExecutable* executable; - if (!callThunk) { - executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor); - executable->finishCreation(vm, JITCode(), JITCode(), intrinsic); - } else { - executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor); - executable->finishCreation(vm, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic); - } - return executable; - } -#endif + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } + + DECLARE_INFO; -#if ENABLE(LLINT_C_LOOP) - static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor) - { - ASSERT(!vm.canUseJIT()); - NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor); - executable->finishCreation(vm); - return executable; - } -#endif + Intrinsic intrinsic() const; -#if ENABLE(JIT) - static void destroy(JSCell*); -#endif + const String& name() const { return m_name; } - CodeBlockHash hashFor(CodeSpecializationKind) const; +protected: + void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic, const String& name) + { + Base::finishCreation(vm); + m_jitCodeForCall = callThunk; + m_jitCodeForConstruct = constructThunk; + m_intrinsic = intrinsic; + m_name = name; + } - NativeFunction function() { return m_function; } - NativeFunction constructor() { return m_constructor; } - - NativeFunction nativeFunctionFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return function(); - ASSERT(kind == CodeForConstruct); - return constructor(); - } - - static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return OBJECT_OFFSETOF(NativeExecutable, m_function); - ASSERT(kind == CodeForConstruct); - return OBJECT_OFFSETOF(NativeExecutable, m_constructor); - } +private: + friend class ExecutableBase; - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); } - - static const ClassInfo s_info; - - Intrinsic intrinsic() const; - - protected: -#if ENABLE(JIT) - void finishCreation(VM& vm, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic) - { - Base::finishCreation(vm); - m_jitCodeForCall = callThunk; - m_jitCodeForConstruct = constructThunk; - m_jitCodeForCallWithArityCheck = callThunk.addressForCall(); - m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall(); - m_intrinsic = intrinsic; - } -#endif + NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor) + : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) + , m_function(function) + , m_constructor(constructor) + { + } - private: - NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor) - : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) - , m_function(function) - , m_constructor(constructor) - { - } + NativeFunction m_function; + NativeFunction m_constructor; + + Intrinsic m_intrinsic; + + String m_name; +}; + +class ScriptExecutable : public ExecutableBase { +public: + typedef ExecutableBase Base; + static const unsigned StructureFlags = Base::StructureFlags; + + static void destroy(JSCell*); + + CodeBlockHash hashFor(CodeSpecializationKind) const; + + const SourceCode& source() const { return m_source; } + intptr_t sourceID() const { return m_source.providerID(); } + const String& sourceURL() const { return m_source.provider()->url(); } + int firstLine() const { return m_firstLine; } + void setOverrideLineNumber(int overrideLineNumber) { m_overrideLineNumber = overrideLineNumber; } + bool hasOverrideLineNumber() const { return m_overrideLineNumber != -1; } + int overrideLineNumber() const { return m_overrideLineNumber; } + int lastLine() const { return m_lastLine; } + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } + unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; } + unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; } + + bool usesEval() const { return m_features & EvalFeature; } + bool usesArguments() const { return m_features & ArgumentsFeature; } + bool isArrowFunctionContext() const { return m_isArrowFunctionContext; } + bool isStrictMode() const { return m_features & StrictModeFeature; } + DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); } + + ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; } + + void setNeverInline(bool value) { m_neverInline = value; } + void setNeverOptimize(bool value) { m_neverOptimize = value; } + void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; } + bool neverInline() const { return m_neverInline; } + bool neverOptimize() const { return m_neverOptimize; } + bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; } + bool isInliningCandidate() const { return !neverInline(); } + bool isOkToOptimize() const { return !neverOptimize(); } + + bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; } - NativeFunction m_function; - NativeFunction m_constructor; + CodeFeatures features() const { return m_features; } - Intrinsic m_intrinsic; - }; - - class ScriptExecutable : public ExecutableBase { - public: - typedef ExecutableBase Base; - - ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED) - , m_source(source) - , m_features(isInStrictContext ? StrictModeFeature : 0) - , m_neverInline(false) - { - } + DECLARE_EXPORT_INFO; - ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED) - , m_source(source) - , m_features(isInStrictContext ? StrictModeFeature : 0) - , m_neverInline(false) - { - } + void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn) + { + m_features = features; + m_hasCapturedVariables = hasCapturedVariables; + m_firstLine = firstLine; + m_lastLine = lastLine; + ASSERT(startColumn != UINT_MAX); + m_startColumn = startColumn; + ASSERT(endColumn != UINT_MAX); + m_endColumn = endColumn; + } -#if ENABLE(JIT) - static void destroy(JSCell*); -#endif - - CodeBlockHash hashFor(CodeSpecializationKind) const; - - const SourceCode& source() const { return m_source; } - intptr_t sourceID() const { return m_source.providerID(); } - const String& sourceURL() const { return m_source.provider()->url(); } - int lineNo() const { return m_firstLine; } - int lastLine() const { return m_lastLine; } - unsigned startColumn() const { return m_startColumn; } - - bool usesEval() const { return m_features & EvalFeature; } - bool usesArguments() const { return m_features & ArgumentsFeature; } - bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); } - bool isStrictMode() const { return m_features & StrictModeFeature; } - - void setNeverInline(bool value) { m_neverInline = value; } - bool neverInline() const { return m_neverInline; } - bool isInliningCandidate() const { return !neverInline(); } + void installCode(CodeBlock*); + void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind); + CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception); + CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind); + + JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind) + { + if (hasJITCodeFor(kind)) + return 0; + return prepareForExecutionImpl(exec, function, scope, kind); + } - void unlinkCalls(); + template <typename Functor> void forEachCodeBlock(Functor&&); - CodeFeatures features() const { return m_features; } - - static const ClassInfo s_info; - - void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn) - { - m_features = features; - m_hasCapturedVariables = hasCapturedVariables; - m_firstLine = firstLine; - m_lastLine = lastLine; - m_startColumn = startColumn; - } +private: + friend class ExecutableBase; + JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind); - protected: - void finishCreation(VM& vm) - { - Base::finishCreation(vm); - vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode(). +protected: + ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext); + + void finishCreation(VM& vm) + { + Base::finishCreation(vm); + vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode(). #if ENABLE(CODEBLOCK_SAMPLING) - if (SamplingTool* sampler = vm.interpreter->sampler()) - sampler->notifyOfScope(vm, this); + if (SamplingTool* sampler = vm.interpreter->sampler()) + sampler->notifyOfScope(vm, this); #endif - } + } - SourceCode m_source; - CodeFeatures m_features; - bool m_hasCapturedVariables; - bool m_neverInline; - int m_firstLine; - int m_lastLine; - unsigned m_startColumn; - }; - - class EvalExecutable : public ScriptExecutable { - friend class LLIntOffsetsExtractor; - public: - typedef ScriptExecutable Base; - - static void destroy(JSCell*); - - JSObject* compile(ExecState* exec, JSScope* scope) - { - RELEASE_ASSERT(exec->vm().dynamicGlobalObject); - JSObject* error = 0; - if (!m_evalCodeBlock) - error = compileInternal(exec, scope, JITCode::bottomTierJIT()); - ASSERT(!error == !!m_evalCodeBlock); - return error; - } - - JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex); - -#if ENABLE(JIT) - void jettisonOptimizedCode(VM&); - bool jitCompile(ExecState*); -#endif + CodeFeatures m_features; + bool m_didTryToEnterInLoop; + bool m_hasCapturedVariables : 1; + bool m_neverInline : 1; + bool m_neverOptimize : 1; + bool m_isArrowFunctionContext : 1; + unsigned m_derivedContextType : 2; // DerivedContextType + + int m_overrideLineNumber; + int m_firstLine; + int m_lastLine; + unsigned m_startColumn; + unsigned m_endColumn; + unsigned m_typeProfilingStartOffset; + unsigned m_typeProfilingEndOffset; + SourceCode m_source; +}; + +class EvalExecutable final : public ScriptExecutable { + friend class LLIntOffsetsExtractor; +public: + typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; + + static void destroy(JSCell*); + + EvalCodeBlock* codeBlock() + { + return m_evalCodeBlock.get(); + } - EvalCodeBlock& generatedBytecode() - { - ASSERT(m_evalCodeBlock); - return *m_evalCodeBlock; - } + static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, DerivedContextType, bool isArrowFunctionContext, const VariableEnvironment*); - static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext) - { - EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext); - executable->finishCreation(exec->vm()); - return executable; - } + PassRefPtr<JITCode> generatedJITCode() + { + return generatedJITCodeForCall(); + } -#if ENABLE(JIT) - JITCode& generatedJITCode() - { - return generatedJITCodeForCall(); - } -#endif - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) - { - return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info); - } + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info()); + } - static const ClassInfo s_info; + DECLARE_INFO; - void unlinkCalls(); + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext() , false); } - void clearCode(); + unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); } + unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); } - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); } +private: + friend class ExecutableBase; + friend class ScriptExecutable; - private: - static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; - EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool); + EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext); - JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX); - static void visitChildren(JSCell*, SlotVisitor&); + static void visitChildren(JSCell*, SlotVisitor&); - OwnPtr<EvalCodeBlock> m_evalCodeBlock; - WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock; - RefPtr<CodeCache> m_codeCache; - }; + WriteBarrier<EvalCodeBlock> m_evalCodeBlock; + WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock; +}; - class ProgramExecutable : public ScriptExecutable { - friend class LLIntOffsetsExtractor; - public: - typedef ScriptExecutable Base; +class ProgramExecutable final : public ScriptExecutable { + friend class LLIntOffsetsExtractor; +public: + typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static ProgramExecutable* create(ExecState* exec, const SourceCode& source) - { - ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source); - executable->finishCreation(exec->vm()); - return executable; - } + static ProgramExecutable* create(ExecState* exec, const SourceCode& source) + { + ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source); + executable->finishCreation(exec->vm()); + return executable; + } - JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*); + JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*); - static void destroy(JSCell*); + static void destroy(JSCell*); - JSObject* compile(ExecState* exec, JSScope* scope) - { - RELEASE_ASSERT(exec->vm().dynamicGlobalObject); - JSObject* error = 0; - if (!m_programCodeBlock) - error = compileInternal(exec, scope, JITCode::bottomTierJIT()); - ASSERT(!error == !!m_programCodeBlock); - return error; - } + ProgramCodeBlock* codeBlock() + { + return m_programCodeBlock.get(); + } + + JSObject* checkSyntax(ExecState*); - JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex); + PassRefPtr<JITCode> generatedJITCode() + { + return generatedJITCodeForCall(); + } -#if ENABLE(JIT) - void jettisonOptimizedCode(VM&); - bool jitCompile(ExecState*); -#endif + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info()); + } + + DECLARE_INFO; - ProgramCodeBlock& generatedBytecode() - { - ASSERT(m_programCodeBlock); - return *m_programCodeBlock; - } + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false); } - JSObject* checkSyntax(ExecState*); +private: + friend class ExecutableBase; + friend class ScriptExecutable; -#if ENABLE(JIT) - JITCode& generatedJITCode() - { - return generatedJITCodeForCall(); - } -#endif - - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) - { - return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info); - } - - static const ClassInfo s_info; - - void unlinkCalls(); + ProgramExecutable(ExecState*, const SourceCode&); - void clearCode(); + static void visitChildren(JSCell*, SlotVisitor&); - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); } + WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock; + WriteBarrier<ProgramCodeBlock> m_programCodeBlock; +}; - private: - static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; +class ModuleProgramExecutable final : public ScriptExecutable { + friend class LLIntOffsetsExtractor; +public: + typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - ProgramExecutable(ExecState*, const SourceCode&); + static ModuleProgramExecutable* create(ExecState*, const SourceCode&); - enum ConstantMode { IsConstant, IsVariable }; - enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable }; - int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode); + static void destroy(JSCell*); - JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX); - static void visitChildren(JSCell*, SlotVisitor&); + ModuleProgramCodeBlock* codeBlock() + { + return m_moduleProgramCodeBlock.get(); + } - WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock; - OwnPtr<ProgramCodeBlock> m_programCodeBlock; - }; + PassRefPtr<JITCode> generatedJITCode() + { + return generatedJITCodeForCall(); + } - class FunctionExecutable : public ScriptExecutable { - friend class JIT; - friend class LLIntOffsetsExtractor; - public: - typedef ScriptExecutable Base; + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info()); + } - static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn) - { - FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn); - executable->finishCreation(vm); - return executable; - } - static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception); + DECLARE_INFO; - static void destroy(JSCell*); - - UnlinkedFunctionExecutable* unlinkedExecutable() - { - return m_unlinkedExecutable.get(); - } + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false); } - // Returns either call or construct bytecode. This can be appropriate - // for answering questions that that don't vary between call and construct -- - // for example, argumentsRegister(). - FunctionCodeBlock& generatedBytecode() - { - if (m_codeBlockForCall) - return *m_codeBlockForCall; - ASSERT(m_codeBlockForConstruct); - return *m_codeBlockForConstruct; - } - - PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception); - - JSObject* compileForCall(ExecState* exec, JSScope* scope) - { - RELEASE_ASSERT(exec->vm().dynamicGlobalObject); - JSObject* error = 0; - if (!m_codeBlockForCall) - error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT()); - ASSERT(!error == !!m_codeBlockForCall); - return error; - } + UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); } - JSObject* compileOptimizedForCall(ExecState*, JSScope*, unsigned bytecodeIndex); - -#if ENABLE(JIT) - void jettisonOptimizedCodeForCall(VM&); - bool jitCompileForCall(ExecState*); -#endif + SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); } - bool isGeneratedForCall() const - { - return m_codeBlockForCall; - } +private: + friend class ExecutableBase; + friend class ScriptExecutable; - FunctionCodeBlock& generatedBytecodeForCall() - { - ASSERT(m_codeBlockForCall); - return *m_codeBlockForCall; - } + ModuleProgramExecutable(ExecState*, const SourceCode&); - JSObject* compileForConstruct(ExecState* exec, JSScope* scope) - { - RELEASE_ASSERT(exec->vm().dynamicGlobalObject); - JSObject* error = 0; - if (!m_codeBlockForConstruct) - error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT()); - ASSERT(!error == !!m_codeBlockForConstruct); - return error; - } + static void visitChildren(JSCell*, SlotVisitor&); - JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, unsigned bytecodeIndex); - -#if ENABLE(JIT) - void jettisonOptimizedCodeForConstruct(VM&); - bool jitCompileForConstruct(ExecState*); -#endif + WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock; + WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable; + WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock; +}; - bool isGeneratedForConstruct() const - { - return m_codeBlockForConstruct; - } +class FunctionExecutable final : public ScriptExecutable { + friend class JIT; + friend class LLIntOffsetsExtractor; +public: + typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - FunctionCodeBlock& generatedBytecodeForConstruct() - { - ASSERT(m_codeBlockForConstruct); - return *m_codeBlockForConstruct; - } - - JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind) - { - ASSERT(exec->callee()); - ASSERT(exec->callee()->inherits(&JSFunction::s_info)); - ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this); - - if (kind == CodeForCall) - return compileForCall(exec, scope); - ASSERT(kind == CodeForConstruct); - return compileForConstruct(exec, scope); - } - - JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, unsigned bytecodeIndex, CodeSpecializationKind kind) - { - ASSERT(exec->callee()); - ASSERT(exec->callee()->inherits(&JSFunction::s_info)); - ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this); - - if (kind == CodeForCall) - return compileOptimizedForCall(exec, scope, bytecodeIndex); - ASSERT(kind == CodeForConstruct); - return compileOptimizedForConstruct(exec, scope, bytecodeIndex); - } - -#if ENABLE(JIT) - void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind) - { - if (kind == CodeForCall) - jettisonOptimizedCodeForCall(vm); - else { - ASSERT(kind == CodeForConstruct); - jettisonOptimizedCodeForConstruct(vm); - } - } - - bool jitCompileFor(ExecState* exec, CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return jitCompileForCall(exec); - ASSERT(kind == CodeForConstruct); - return jitCompileForConstruct(exec); - } -#endif + static FunctionExecutable* create( + VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, + unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn) + { + FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn); + executable->finishCreation(vm); + return executable; + } + static FunctionExecutable* fromGlobalCode( + const Identifier& name, ExecState&, const SourceCode&, + JSObject*& exception, int overrideLineNumber); + + static void destroy(JSCell*); - bool isGeneratedFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return isGeneratedForCall(); - ASSERT(kind == CodeForConstruct); - return isGeneratedForConstruct(); - } + UnlinkedFunctionExecutable* unlinkedExecutable() const + { + return m_unlinkedExecutable.get(); + } + + // Returns either call or construct bytecode. This can be appropriate + // for answering questions that that don't vary between call and construct -- + // for example, argumentsRegister(). + FunctionCodeBlock* eitherCodeBlock() + { + if (m_codeBlockForCall) + return m_codeBlockForCall.get(); + return m_codeBlockForConstruct.get(); + } - FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return generatedBytecodeForCall(); - ASSERT(kind == CodeForConstruct); - return generatedBytecodeForConstruct(); - } + bool isGeneratedForCall() const + { + return !!m_codeBlockForCall; + } + + FunctionCodeBlock* codeBlockForCall() + { + return m_codeBlockForCall.get(); + } + + bool isGeneratedForConstruct() const + { + return m_codeBlockForConstruct.get(); + } - FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind); + FunctionCodeBlock* codeBlockForConstruct() + { + return m_codeBlockForConstruct.get(); + } - FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind) - { - return baselineCodeBlockFor(kind); - } + bool isGeneratedFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return isGeneratedForCall(); + ASSERT(kind == CodeForConstruct); + return isGeneratedForConstruct(); + } - const Identifier& name() { return m_unlinkedExecutable->name(); } - const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); } - JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); } - size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'! - String paramString() const; - SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); } - - void clearCodeIfNotCompiling(); - void clearUnlinkedCodeForRecompilationIfNotCompiling(); - static void visitChildren(JSCell*, SlotVisitor&); - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) - { - return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info); - } + FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return codeBlockForCall(); + ASSERT(kind == CodeForConstruct); + return codeBlockForConstruct(); + } + + FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind); - static const ClassInfo s_info; + FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind) + { + return baselineCodeBlockFor(kind); + } + + RefPtr<TypeSet> returnStatementTypeSet() + { + if (!m_returnStatementTypeSet) + m_returnStatementTypeSet = TypeSet::create(); + + return m_returnStatementTypeSet; + } - void unlinkCalls(); + FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); } + bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); } + ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); } + bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; } + DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); } + bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); } + const Identifier& name() { return m_unlinkedExecutable->name(); } + const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); } + JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); } + size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'! + SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); } + + static void visitChildren(JSCell*, SlotVisitor&); + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info()); + } - void clearCode(); + unsigned parametersStartOffset() const { return m_parametersStartOffset; } + + void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset) + { + m_parametersStartOffset = parametersStartOffset; + m_typeProfilingStartOffset = typeProfilingStartOffset; + m_typeProfilingEndOffset = typeProfilingEndOffset; + } - private: - FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn); + DECLARE_INFO; - JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX); - JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX); - - OwnPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) - return m_codeBlockForCall; - ASSERT(kind == CodeForConstruct); - return m_codeBlockForConstruct; - } - - bool isCompiling() - { -#if ENABLE(JIT) - if (!m_jitCodeForCall && m_codeBlockForCall) - return true; - if (!m_jitCodeForConstruct && m_codeBlockForConstruct) - return true; -#endif - return false; - } + InferredValue* singletonFunction() { return m_singletonFunction.get(); } - static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; - WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; - OwnPtr<FunctionCodeBlock> m_codeBlockForCall; - OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct; - }; +private: + friend class ExecutableBase; + FunctionExecutable( + VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, + unsigned lastLine, unsigned startColumn, unsigned endColumn); + + void finishCreation(VM&); - inline bool isHostFunction(JSValue value, NativeFunction nativeFunction) + friend class ScriptExecutable; + + unsigned m_parametersStartOffset; + WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; + WriteBarrier<FunctionCodeBlock> m_codeBlockForCall; + WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct; + RefPtr<TypeSet> m_returnStatementTypeSet; + WriteBarrier<InferredValue> m_singletonFunction; +}; + +#if ENABLE(WEBASSEMBLY) +class WebAssemblyExecutable final : public ExecutableBase { +public: + typedef ExecutableBase Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; + + static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex) { - JSFunction* function = jsCast<JSFunction*>(getJSFunction(value)); - if (!function || !function->isHostFunction()) - return false; - return function->nativeFunction() == nativeFunction; + WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex); + executable->finishCreation(vm); + return executable; } - inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { - switch (executable->structure()->typeInfo().type()) { - case EvalExecutableType: - return jsCast<EvalExecutable*>(executable)->clearCode(); - case ProgramExecutableType: - return jsCast<ProgramExecutable*>(executable)->clearCode(); - case FunctionExecutableType: - return jsCast<FunctionExecutable*>(executable)->clearCode(); - default: - return jsCast<NativeExecutable*>(executable)->clearCode(); - } + return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info()); } - inline void ScriptExecutable::unlinkCalls() + static void destroy(JSCell*); + + DECLARE_INFO; + + void prepareForExecution(ExecState*); + + WebAssemblyCodeBlock* codeBlockForCall() { - switch (structure()->typeInfo().type()) { - case EvalExecutableType: - return jsCast<EvalExecutable*>(this)->unlinkCalls(); - case ProgramExecutableType: - return jsCast<ProgramExecutable*>(this)->unlinkCalls(); - case FunctionExecutableType: - return jsCast<FunctionExecutable*>(this)->unlinkCalls(); - default: - RELEASE_ASSERT_NOT_REACHED(); - } + return m_codeBlockForCall.get(); } -} +private: + friend class ExecutableBase; + WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex); + + static void visitChildren(JSCell*, SlotVisitor&); -#include "JSFunctionInlines.h" + SourceCode m_source; + WriteBarrier<JSWASMModule> m_module; + unsigned m_functionIndex; + WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall; +}; #endif + +} // namespace JSC + +#endif // Executable_h |