diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/JavaScriptCore/runtime/Executable.h | |
parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/JavaScriptCore/runtime/Executable.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/Executable.h | 485 |
1 files changed, 284 insertions, 201 deletions
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 6ff27aee9..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,20 +26,21 @@ #ifndef Executable_h #define Executable_h +#include "ArityCheckMode.h" #include "CallData.h" #include "CodeBlockHash.h" #include "CodeSpecializationKind.h" #include "CompilationResult.h" -#include "DFGPlan.h" +#include "ExecutableInfo.h" #include "HandlerInfo.h" -#include "JSFunction.h" -#include "Interpreter.h" +#include "InferredValue.h" #include "JITCode.h" #include "JSGlobalObject.h" #include "SamplingTool.h" #include "SourceCode.h" +#include "TypeSet.h" #include "UnlinkedCodeBlock.h" -#include <wtf/PassOwnPtr.h> +#include "UnlinkedFunctionExecutable.h" namespace JSC { @@ -47,10 +48,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) @@ -61,8 +69,7 @@ inline bool isCall(CodeSpecializationKind kind) return false; } -class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> { - friend class WTF::DoublyLinkedListNode<ExecutableBase>; +class ExecutableBase : public JSCell { friend class JIT; protected: @@ -83,27 +90,30 @@ protected: 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 CodeBlockHash hashFor(CodeSpecializationKind) const; - bool isEvalExecutable() + bool isEvalExecutable() const { - return structure()->typeInfo().type() == EvalExecutableType; + return type() == EvalExecutableType; } - bool isFunctionExecutable() + bool isFunctionExecutable() const { - return structure()->typeInfo().type() == FunctionExecutableType; + return type() == FunctionExecutableType; } - bool isProgramExecutable() + bool isProgramExecutable() const { - return structure()->typeInfo().type() == ProgramExecutableType; + return type() == ProgramExecutableType; } + bool isModuleProgramExecutable() + { + return type() == ModuleProgramExecutableType; + } + bool isHostFunction() const { @@ -111,20 +121,24 @@ public: 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), info()); } +#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(); DECLARE_EXPORT_INFO; protected: - static const unsigned StructureFlags = 0; int m_numParametersForCall; int m_numParametersForConstruct; public: - static void clearCodeVirtual(ExecutableBase*); - PassRefPtr<JITCode> generatedJITCodeForCall() { ASSERT(m_jitCodeForCall); @@ -144,37 +158,53 @@ public: ASSERT(kind == CodeForConstruct); return generatedJITCodeForConstruct(); } - - MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck() - { - ASSERT(m_jitCodeForCall); - ASSERT(m_jitCodeForCallWithArityCheck); - return m_jitCodeForCallWithArityCheck; - } - - 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(); - } - - static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind) - { - if (kind == CodeForCall) + + 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; + } + } + 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 offsetOfJITCodeWithArityCheckFor( + CodeSpecializationKind kind) + { + switch (kind) { + case CodeForCall: return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); - ASSERT(kind == CodeForConstruct); - return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); + case CodeForConstruct: + return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); + } + RELEASE_ASSERT_NOT_REACHED(); + return 0; } - + static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind) { if (kind == CodeForCall) @@ -210,52 +240,32 @@ public: return intrinsic(); return NoIntrinsic; } + + void dump(PrintStream&) const; - MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind) - { - return generatedJITCodeFor(kind)->addressForCall(); - } - - MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind) - { - return generatedJITCodeFor(kind)->addressForCall(); - } - - MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind) - { - return generatedJITCodeWithArityCheckFor(kind); - } - protected: - ExecutableBase* m_prev; - ExecutableBase* m_next; - RefPtr<JITCode> m_jitCodeForCall; RefPtr<JITCode> m_jitCodeForConstruct; MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck; MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck; }; -class NativeExecutable : public ExecutableBase { +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, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic) + 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); - if (!callThunk) - executable->finishCreation(vm, 0, 0, intrinsic); - else - executable->finishCreation(vm, JITCode::hostFunction(callThunk), JITCode::hostFunction(constructThunk), intrinsic); + executable->finishCreation(vm, callThunk, constructThunk, intrinsic, name); return executable; } -#if ENABLE(JIT) static void destroy(JSCell*); -#endif CodeBlockHash hashFor(CodeSpecializationKind) const; @@ -278,24 +288,27 @@ public: return OBJECT_OFFSETOF(NativeExecutable, m_constructor); } - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), info()); } + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } DECLARE_INFO; Intrinsic intrinsic() const; + const String& name() const { return m_name; } + protected: - void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic) + void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic, const String& name) { Base::finishCreation(vm); - m_jitCodeForCallWithArityCheck = callThunk ? callThunk->addressForCall() : MacroAssemblerCodePtr(); - m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk->addressForCall() : MacroAssemblerCodePtr(); m_jitCodeForCall = callThunk; m_jitCodeForConstruct = constructThunk; m_intrinsic = intrinsic; + m_name = name; } private: + friend class ExecutableBase; + NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor) : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) @@ -307,61 +320,54 @@ private: NativeFunction m_constructor; Intrinsic m_intrinsic; + + String m_name; }; class ScriptExecutable : public ExecutableBase { public: typedef ExecutableBase Base; + static const unsigned StructureFlags = Base::StructureFlags; - 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) - , m_startColumn(UINT_MAX) - , m_endColumn(UINT_MAX) - { - } - - 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) - , m_startColumn(UINT_MAX) - , m_endColumn(UINT_MAX) - { - } - -#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 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 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<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; } - 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) { @@ -376,24 +382,30 @@ public: } void installCode(CodeBlock*); - PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSScope*, JSObject*& exception); - PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind); + void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind); + CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception); + CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind); - JSObject* prepareForExecution(ExecState* exec, JSScope* scope, CodeSpecializationKind kind) + JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind) { if (hasJITCodeFor(kind)) return 0; - return prepareForExecutionImpl(exec, scope, kind); + return prepareForExecutionImpl(exec, function, scope, kind); } + template <typename Functor> void forEachCodeBlock(Functor&&); + private: - JSObject* prepareForExecutionImpl(ExecState*, JSScope*, CodeSpecializationKind); + friend class ExecutableBase; + JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind); protected: + ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext); + 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()) @@ -401,20 +413,29 @@ 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_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 : public ScriptExecutable { +class EvalExecutable final : public ScriptExecutable { friend class LLIntOffsetsExtractor; public: typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; static void destroy(JSCell*); @@ -423,7 +444,7 @@ public: return m_evalCodeBlock.get(); } - static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext); + static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, DerivedContextType, bool isArrowFunctionContext, const VariableEnvironment*); PassRefPtr<JITCode> generatedJITCode() { @@ -437,30 +458,28 @@ public: DECLARE_INFO; - void unlinkCalls(); - - void clearCode(); - - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); } + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext() , false); } unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); } unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); } private: + friend class ExecutableBase; friend class ScriptExecutable; - static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; - EvalExecutable(ExecState*, const SourceCode&, bool); + + EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext); static void visitChildren(JSCell*, SlotVisitor&); - RefPtr<EvalCodeBlock> m_evalCodeBlock; + WriteBarrier<EvalCodeBlock> m_evalCodeBlock; WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock; }; -class ProgramExecutable : public ScriptExecutable { +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) { @@ -492,43 +511,89 @@ public: } DECLARE_INFO; - - void unlinkCalls(); - void clearCode(); - - ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); } + ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false); } private: + friend class ExecutableBase; friend class ScriptExecutable; - - static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; ProgramExecutable(ExecState*, const SourceCode&); static void visitChildren(JSCell*, SlotVisitor&); WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock; - RefPtr<ProgramCodeBlock> m_programCodeBlock; + WriteBarrier<ProgramCodeBlock> 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<JITCode> 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); } + + 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<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock; + WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable; + WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock; }; -class FunctionExecutable : public ScriptExecutable { +class FunctionExecutable final : public ScriptExecutable { friend class JIT; friend class LLIntOffsetsExtractor; public: typedef ScriptExecutable Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces = true) + 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, bodyIncludesBraces); + 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*, Debugger*, const SourceCode&, JSObject** exception); + static FunctionExecutable* fromGlobalCode( + const Identifier& name, ExecState&, const SourceCode&, + JSObject*& exception, int overrideLineNumber); static void destroy(JSCell*); - UnlinkedFunctionExecutable* unlinkedExecutable() + UnlinkedFunctionExecutable* unlinkedExecutable() const { return m_unlinkedExecutable.get(); } @@ -545,7 +610,7 @@ public: bool isGeneratedForCall() const { - return m_codeBlockForCall; + return !!m_codeBlockForCall; } FunctionCodeBlock* codeBlockForCall() @@ -555,7 +620,7 @@ public: bool isGeneratedForConstruct() const { - return m_codeBlockForConstruct; + return m_codeBlockForConstruct.get(); } FunctionCodeBlock* codeBlockForConstruct() @@ -585,89 +650,107 @@ public: { return baselineCodeBlockFor(kind); } + + RefPtr<TypeSet> returnStatementTypeSet() + { + if (!m_returnStatementTypeSet) + m_returnStatementTypeSet = TypeSet::create(); + + return m_returnStatementTypeSet; + } + 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'! - String paramString() const; - SymbolTable* symbolTable(CodeSpecializationKind); + SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); } - 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), info()); } - - DECLARE_INFO; - - void unlinkCalls(); - - void clearCode(); - - bool bodyIncludesBraces() const { return m_bodyIncludesBraces; } -private: - FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces); + unsigned parametersStartOffset() const { return m_parametersStartOffset; } - bool isCompiling() + void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset) { -#if ENABLE(JIT) - if (!m_jitCodeForCall && m_codeBlockForCall) - return true; - if (!m_jitCodeForConstruct && m_codeBlockForConstruct) - return true; -#endif - return false; + m_parametersStartOffset = parametersStartOffset; + m_typeProfilingStartOffset = typeProfilingStartOffset; + m_typeProfilingEndOffset = typeProfilingEndOffset; } - friend class ScriptExecutable; + DECLARE_INFO; + + InferredValue* singletonFunction() { return m_singletonFunction.get(); } + +private: + friend class ExecutableBase; + FunctionExecutable( + VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, + unsigned lastLine, unsigned startColumn, unsigned endColumn); + + void finishCreation(VM&); - static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; + friend class ScriptExecutable; + + unsigned m_parametersStartOffset; WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; - RefPtr<FunctionCodeBlock> m_codeBlockForCall; - RefPtr<FunctionCodeBlock> m_codeBlockForConstruct; - bool m_bodyIncludesBraces; + WriteBarrier<FunctionCodeBlock> m_codeBlockForCall; + WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct; + RefPtr<TypeSet> m_returnStatementTypeSet; + WriteBarrier<InferredValue> m_singletonFunction; }; -inline bool isHostFunction(JSValue value, NativeFunction nativeFunction) -{ - JSFunction* function = jsCast<JSFunction*>(getJSFunction(value)); - if (!function || !function->isHostFunction()) - return false; - return function->nativeFunction() == nativeFunction; -} +#if ENABLE(WEBASSEMBLY) +class WebAssemblyExecutable final : public ExecutableBase { +public: + typedef ExecutableBase Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; -inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) -{ - 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(); + static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex) + { + WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex); + executable->finishCreation(vm); + return executable; } -} -inline void ScriptExecutable::unlinkCalls() -{ - 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(); + 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<JSWASMModule> m_module; + unsigned m_functionIndex; + + WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall; +}; #endif + +} // namespace JSC + +#endif // Executable_h |