summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/Executable.h
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/runtime/Executable.h
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-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.h1287
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