X-Git-Url: http://git.webkit.org/?p=WebKit-https.git;a=blobdiff_plain;f=Source%2FJavaScriptCore%2Fruntime%2FExecutable.h;h=b506b1c754f03d50658020768b4f69f287eee3be;hp=cf2bde88c5a6e91676036ee27d744f764539cc4c;hb=00ee9bd5f78e00eed1b5aa2a625b65d432e68894;hpb=35eb9a1fea4adb14421e4570c6280775a60a8d9e diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index cf2bde8..b506b1c 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 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 @@ -31,14 +31,11 @@ #include "CodeBlockHash.h" #include "CodeSpecializationKind.h" #include "CompilationResult.h" -#include "DFGPlan.h" #include "ExecutableInfo.h" #include "HandlerInfo.h" #include "InferredValue.h" #include "JITCode.h" #include "JSGlobalObject.h" -#include "RegisterPreservationMode.h" -#include "SamplingTool.h" #include "SourceCode.h" #include "TypeSet.h" #include "UnlinkedCodeBlock.h" @@ -50,10 +47,17 @@ 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) @@ -71,10 +75,11 @@ protected: static const int NUM_PARAMETERS_IS_HOST = 0; static const int NUM_PARAMETERS_NOT_COMPILED = -1; - ExecutableBase(VM& vm, Structure* structure, int numParameters) + ExecutableBase(VM& vm, Structure* structure, int numParameters, Intrinsic intrinsic) : JSCell(vm, structure) , m_numParametersForCall(numParameters) , m_numParametersForConstruct(numParameters) + , m_intrinsic(intrinsic) { } @@ -92,18 +97,23 @@ public: CodeBlockHash hashFor(CodeSpecializationKind) const; - bool isEvalExecutable() + bool isEvalExecutable() const { return type() == EvalExecutableType; } - bool isFunctionExecutable() + bool isFunctionExecutable() const { return type() == FunctionExecutableType; } - bool isProgramExecutable() + bool isProgramExecutable() const { return type() == ProgramExecutableType; } + bool isModuleProgramExecutable() + { + return type() == ModuleProgramExecutableType; + } + bool isHostFunction() const { @@ -111,6 +121,13 @@ public: return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; } +#if ENABLE(WEBASSEMBLY) + bool isWebAssemblyExecutable() const + { + return type() == WebAssemblyExecutableType; + } +#endif + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } void clearCode(); @@ -122,8 +139,6 @@ protected: int m_numParametersForConstruct; public: - static void clearCodeVirtual(ExecutableBase*); - PassRefPtr generatedJITCodeForCall() { ASSERT(m_jitCodeForCall); @@ -144,8 +159,7 @@ public: return generatedJITCodeForConstruct(); } - MacroAssemblerCodePtr entrypointFor( - VM& vm, CodeSpecializationKind kind, ArityCheckMode arity, RegisterPreservationMode registers) + 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 @@ -153,55 +167,25 @@ public: if (arity == MustCheckArity) { switch (kind) { case CodeForCall: - switch (registers) { - case RegisterPreservationNotRequired: - if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck) - return result; - break; - case MustPreserveRegisters: - if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheckAndPreserveRegs) - return result; - break; - } + if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck) + return result; break; case CodeForConstruct: - switch (registers) { - case RegisterPreservationNotRequired: - if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck) - return result; - break; - case MustPreserveRegisters: - if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheckAndPreserveRegs) - return result; - break; - } + if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck) + return result; break; } } MacroAssemblerCodePtr result = - generatedJITCodeFor(kind)->addressForCall(vm, this, arity, registers); + generatedJITCodeFor(kind)->addressForCall(arity); if (arity == MustCheckArity) { // Cache the result; this is necessary for the JIT's virtual call optimizations. switch (kind) { case CodeForCall: - switch (registers) { - case RegisterPreservationNotRequired: - m_jitCodeForCallWithArityCheck = result; - break; - case MustPreserveRegisters: - m_jitCodeForCallWithArityCheckAndPreserveRegs = result; - break; - } + m_jitCodeForCallWithArityCheck = result; break; case CodeForConstruct: - switch (registers) { - case RegisterPreservationNotRequired: - m_jitCodeForConstructWithArityCheck = result; - break; - case MustPreserveRegisters: - m_jitCodeForConstructWithArityCheckAndPreserveRegs = result; - break; - } + m_jitCodeForConstructWithArityCheck = result; break; } } @@ -209,23 +193,13 @@ public: } static ptrdiff_t offsetOfJITCodeWithArityCheckFor( - CodeSpecializationKind kind, RegisterPreservationMode registers) + CodeSpecializationKind kind) { switch (kind) { case CodeForCall: - switch (registers) { - case RegisterPreservationNotRequired: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); - case MustPreserveRegisters: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheckAndPreserveRegs); - } + return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); case CodeForConstruct: - switch (registers) { - case RegisterPreservationNotRequired: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); - case MustPreserveRegisters: - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheckAndPreserveRegs); - } + return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); } RELEASE_ASSERT_NOT_REACHED(); return 0; @@ -258,7 +232,7 @@ public: } // Intrinsics are only for calls, currently. - Intrinsic intrinsic() const; + Intrinsic intrinsic() const { return m_intrinsic; } Intrinsic intrinsicFor(CodeSpecializationKind kind) const { @@ -270,12 +244,11 @@ public: void dump(PrintStream&) const; protected: + Intrinsic m_intrinsic; RefPtr m_jitCodeForCall; RefPtr m_jitCodeForConstruct; MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck; MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck; - MacroAssemblerCodePtr m_jitCodeForCallWithArityCheckAndPreserveRegs; - MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheckAndPreserveRegs; }; class NativeExecutable final : public ExecutableBase { @@ -285,13 +258,7 @@ public: typedef ExecutableBase Base; static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static NativeExecutable* create(VM& vm, PassRefPtr callThunk, NativeFunction function, PassRefPtr constructThunk, NativeFunction constructor, Intrinsic intrinsic) - { - NativeExecutable* executable; - executable = new (NotNull, allocateCell(vm.heap)) NativeExecutable(vm, function, constructor); - executable->finishCreation(vm, callThunk, constructThunk, intrinsic); - return executable; - } + static NativeExecutable* create(VM& vm, PassRefPtr callThunk, NativeFunction function, PassRefPtr constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name); static void destroy(JSCell*); @@ -316,33 +283,24 @@ public: return OBJECT_OFFSETOF(NativeExecutable, m_constructor); } - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } + static Structure* createStructure(VM&, JSGlobalObject*, JSValue proto); DECLARE_INFO; - Intrinsic intrinsic() const; + const String& name() const { return m_name; } protected: - void finishCreation(VM& vm, PassRefPtr callThunk, PassRefPtr constructThunk, Intrinsic intrinsic) - { - Base::finishCreation(vm); - m_jitCodeForCall = callThunk; - m_jitCodeForConstruct = constructThunk; - m_intrinsic = intrinsic; - } + void finishCreation(VM&, PassRefPtr callThunk, PassRefPtr constructThunk, const String& name); private: - NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor) - : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) - , m_function(function) - , m_constructor(constructor) - { - } + friend class ExecutableBase; + + NativeExecutable(VM&, NativeFunction function, NativeFunction constructor, Intrinsic); NativeFunction m_function; NativeFunction m_constructor; - - Intrinsic m_intrinsic; + + String m_name; }; class ScriptExecutable : public ExecutableBase { @@ -369,23 +327,29 @@ public: 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 isArrowFunctionContext() const { return m_isArrowFunctionContext; } bool isStrictMode() const { return m_features & StrictModeFeature; } + DerivedContextType derivedContextType() const { return static_cast(m_derivedContextType); } + EvalContextType evalContextType() const { return static_cast(m_evalContextType); } + ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; } void setNeverInline(bool value) { m_neverInline = value; } + void setNeverOptimize(bool value) { m_neverOptimize = value; } + void setNeverFTLOptimize(bool value) { m_neverFTLOptimize = value; } void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; } bool neverInline() const { return m_neverInline; } + bool neverOptimize() const { return m_neverOptimize; } + bool neverFTLOptimize() const { return m_neverFTLOptimize; } bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; } bool isInliningCandidate() const { return !neverInline(); } + bool isOkToOptimize() const { return !neverOptimize(); } bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; } - void unlinkCalls(); - CodeFeatures features() const { return m_features; } - DECLARE_INFO; + DECLARE_EXPORT_INFO; void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn) { @@ -400,28 +364,32 @@ public: } void installCode(CodeBlock*); - RefPtr newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception); - PassRefPtr newReplacementCodeBlockFor(CodeSpecializationKind); - - JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind) - { - if (hasJITCodeFor(kind)) - return 0; - return prepareForExecutionImpl(exec, function, scope, kind); - } + void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind); + CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception); + CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind); + + // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock + // that is not jettisoned before this function returns. Callers are essentially asking for a strong reference + // to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in + // their CodeBlock*& reference because it's safe for CodeBlock to be jettisoned if Executable is the only thing + // to point to it. This forces callers to have a CodeBlock* in a register or on the stack that will be marked + // by conservative GC if a GC happens after we create the CodeBlock. + template + JSObject* prepareForExecution(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock); template void forEachCodeBlock(Functor&&); private: - JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind); + friend class ExecutableBase; + JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&); protected: - ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext); + ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic); void finishCreation(VM& vm) { Base::finishCreation(vm); - vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode(). + vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode(). #if ENABLE(CODEBLOCK_SAMPLING) if (SamplingTool* sampler = vm.interpreter->sampler()) @@ -429,11 +397,16 @@ protected: #endif } - SourceCode m_source; CodeFeatures m_features; - bool m_hasCapturedVariables; - bool m_neverInline; bool m_didTryToEnterInLoop; + bool m_hasCapturedVariables : 1; + bool m_neverInline : 1; + bool m_neverOptimize : 1; + bool m_neverFTLOptimize : 1; + bool m_isArrowFunctionContext : 1; + unsigned m_derivedContextType : 2; // DerivedContextType + unsigned m_evalContextType : 2; // EvalContextType + int m_overrideLineNumber; int m_firstLine; int m_lastLine; @@ -441,6 +414,7 @@ protected: unsigned m_endColumn; unsigned m_typeProfilingStartOffset; unsigned m_typeProfilingEndOffset; + SourceCode m_source; }; class EvalExecutable final : public ScriptExecutable { @@ -456,7 +430,7 @@ public: return m_evalCodeBlock.get(); } - static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, const VariableEnvironment*); + static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*); PassRefPtr generatedJITCode() { @@ -470,22 +444,20 @@ public: DECLARE_INFO; - void unlinkCalls(); - - void clearCode(); - - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); } + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); } unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); } unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); } private: + friend class ExecutableBase; friend class ScriptExecutable; - EvalExecutable(ExecState*, const SourceCode&, bool); + + EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType); static void visitChildren(JSCell*, SlotVisitor&); - RefPtr m_evalCodeBlock; + WriteBarrier m_evalCodeBlock; WriteBarrier m_unlinkedEvalCodeBlock; }; @@ -525,14 +497,11 @@ public: } DECLARE_INFO; - - void unlinkCalls(); - - void clearCode(); - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); } + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } private: + friend class ExecutableBase; friend class ScriptExecutable; ProgramExecutable(ExecState*, const SourceCode&); @@ -540,7 +509,53 @@ private: static void visitChildren(JSCell*, SlotVisitor&); WriteBarrier m_unlinkedProgramCodeBlock; - RefPtr m_programCodeBlock; + WriteBarrier m_programCodeBlock; +}; + +class ModuleProgramExecutable final : public ScriptExecutable { + friend class LLIntOffsetsExtractor; +public: + typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; + + static ModuleProgramExecutable* create(ExecState*, const SourceCode&); + + static void destroy(JSCell*); + + ModuleProgramCodeBlock* codeBlock() + { + return m_moduleProgramCodeBlock.get(); + } + + PassRefPtr generatedJITCode() + { + return generatedJITCodeForCall(); + } + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info()); + } + + DECLARE_INFO; + + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } + + UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); } + + SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); } + +private: + friend class ExecutableBase; + friend class ScriptExecutable; + + ModuleProgramExecutable(ExecState*, const SourceCode&); + + static void visitChildren(JSCell*, SlotVisitor&); + + WriteBarrier m_unlinkedModuleProgramCodeBlock; + WriteBarrier m_moduleEnvironmentSymbolTable; + WriteBarrier m_moduleProgramCodeBlock; }; class FunctionExecutable final : public ScriptExecutable { @@ -552,9 +567,9 @@ public: static FunctionExecutable* create( VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, - unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn) + unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic intrinsic) { - FunctionExecutable* executable = new (NotNull, allocateCell(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn); + FunctionExecutable* executable = new (NotNull, allocateCell(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, intrinsic); executable->finishCreation(vm); return executable; } @@ -564,7 +579,7 @@ public: static void destroy(JSCell*); - UnlinkedFunctionExecutable* unlinkedExecutable() + UnlinkedFunctionExecutable* unlinkedExecutable() const { return m_unlinkedExecutable.get(); } @@ -581,7 +596,7 @@ public: bool isGeneratedForCall() const { - return m_codeBlockForCall; + return !!m_codeBlockForCall; } FunctionCodeBlock* codeBlockForCall() @@ -591,7 +606,7 @@ public: bool isGeneratedForConstruct() const { - return m_codeBlockForConstruct; + return m_codeBlockForConstruct.get(); } FunctionCodeBlock* codeBlockForConstruct() @@ -633,14 +648,19 @@ public: FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); } bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); } ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); } - bool isArrowFunction() const { return m_unlinkedExecutable->isArrowFunction(); } + bool isClass() const { return !classSource().isNull(); } + bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; } + bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; } + bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; } + DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); } bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); } const Identifier& name() { return m_unlinkedExecutable->name(); } + const Identifier& ecmaName() { return m_unlinkedExecutable->ecmaName(); } 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(); } + const SourceCode& classSource() const { return m_unlinkedExecutable->classSource(); } - void clearUnlinkedCodeForRecompilation(); static void visitChildren(JSCell*, SlotVisitor&); static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { @@ -657,58 +677,89 @@ public: } DECLARE_INFO; - - void unlinkCalls(); - void clearCode(); - InferredValue* singletonFunction() { return m_singletonFunction.get(); } private: + friend class ExecutableBase; FunctionExecutable( VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, - unsigned lastLine, unsigned startColumn, unsigned endColumn); + unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic); void finishCreation(VM&); friend class ScriptExecutable; + unsigned m_parametersStartOffset; WriteBarrier m_unlinkedExecutable; - RefPtr m_codeBlockForCall; - RefPtr m_codeBlockForConstruct; + WriteBarrier m_codeBlockForCall; + WriteBarrier m_codeBlockForConstruct; RefPtr m_returnStatementTypeSet; - unsigned m_parametersStartOffset; WriteBarrier m_singletonFunction; }; -inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) -{ - switch (executable->type()) { - case EvalExecutableType: - return jsCast(executable)->clearCode(); - case ProgramExecutableType: - return jsCast(executable)->clearCode(); - case FunctionExecutableType: - return jsCast(executable)->clearCode(); - default: - return jsCast(executable)->clearCode(); +#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) + { + WebAssemblyExecutable* executable = new (NotNull, allocateCell(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex); + executable->finishCreation(vm); + return executable; } -} -inline void ScriptExecutable::unlinkCalls() -{ - switch (type()) { - case EvalExecutableType: - return jsCast(this)->unlinkCalls(); - case ProgramExecutableType: - return jsCast(this)->unlinkCalls(); - case FunctionExecutableType: - return jsCast(this)->unlinkCalls(); - default: - RELEASE_ASSERT_NOT_REACHED(); + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info()); } -} -} + static void destroy(JSCell*); + + DECLARE_INFO; + void prepareForExecution(ExecState*); + + WebAssemblyCodeBlock* codeBlockForCall() + { + return m_codeBlockForCall.get(); + } + +private: + friend class ExecutableBase; + WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex); + + static void visitChildren(JSCell*, SlotVisitor&); + + SourceCode m_source; + WriteBarrier m_module; + unsigned m_functionIndex; + + WriteBarrier m_codeBlockForCall; +}; #endif + +template +JSObject* ScriptExecutable::prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock) +{ + if (hasJITCodeFor(kind)) { + if (std::is_same::value) + resultCodeBlock = jsCast(jsCast(this)->codeBlock()); + else if (std::is_same::value) + resultCodeBlock = jsCast(jsCast(this)->codeBlock()); + else if (std::is_same::value) + resultCodeBlock = jsCast(jsCast(this)->codeBlock()); + else if (std::is_same::value) + resultCodeBlock = jsCast(jsCast(this)->codeBlockFor(kind)); + else + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; + } + return prepareForExecutionImpl(exec, function, scope, kind, resultCodeBlock); +} + +} // namespace JSC + +#endif // Executable_h