[JSC] NativeExecutable should be smaller
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Feb 2019 19:49:04 +0000 (19:49 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Feb 2019 19:49:04 +0000 (19:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194331

Reviewed by Michael Saboff.

NativeExecutable takes 88 bytes now. Since our GC rounds the size with 16, it actually takes 96 bytes in IsoSubspaces.
Since a lot of NativeExecutable are allocated, we already has two MarkedBlocks even just after JSGlobalObject initialization.
This patch makes sizeof(NativeExecutable) 64 bytes, which is 32 bytes smaller than 96 bytes. Now our JSGlobalObject initialization
only takes one MarkedBlock for NativeExecutable.

To make NativeExecutable smaller,

1. m_numParametersForCall and m_numParametersForConstruct in ExecutableBase are only meaningful in ScriptExecutable subclasses. Since
   they are not touched from JIT, we can remove them from ExecutableBase and move them to ScriptExecutable.

2. DOMJIT::Signature* is rarely used. Rather than having it in NativeExecutable, we should put it in NativeJITCode. Since NativeExecutable
   always has JITCode, we can safely query the value from NativeExecutable. This patch creates NativeDOMJITCode, which is a subclass of
   NativeJITCode, and instantiated only when DOMJIT::Signature* is given.

3. Move Intrinsic to a member of ScriptExecutable or JITCode. Since JITCode has some paddings to put things, we can leverage this to put
   Intrinsic for NativeExecutable.

We also move "clearCode" code from ExecutableBase to ScriptExecutable since it is only valid for ScriptExecutable subclasses.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CallVariant.h:
* interpreter/Interpreter.cpp:
* jit/JITCode.cpp:
(JSC::DirectJITCode::DirectJITCode):
(JSC::NativeJITCode::NativeJITCode):
(JSC::NativeDOMJITCode::NativeDOMJITCode):
* jit/JITCode.h:
(JSC::JITCode::signature const):
(JSC::JITCode::intrinsic):
* jit/JITOperations.cpp:
* jit/JITThunks.cpp:
(JSC::JITThunks::hostFunctionStub):
* jit/Repatch.cpp:
* llint/LLIntSlowPaths.cpp:
* runtime/ExecutableBase.cpp:
(JSC::ExecutableBase::dump const):
(JSC::ExecutableBase::hashFor const):
(JSC::ExecutableBase::hasClearableCode const): Deleted.
(JSC::ExecutableBase::clearCode): Deleted.
* runtime/ExecutableBase.h:
(JSC::ExecutableBase::ExecutableBase):
(JSC::ExecutableBase::isModuleProgramExecutable):
(JSC::ExecutableBase::isHostFunction const):
(JSC::ExecutableBase::generatedJITCodeForCall const):
(JSC::ExecutableBase::generatedJITCodeForConstruct const):
(JSC::ExecutableBase::generatedJITCodeFor const):
(JSC::ExecutableBase::generatedJITCodeForCall): Deleted.
(JSC::ExecutableBase::generatedJITCodeForConstruct): Deleted.
(JSC::ExecutableBase::generatedJITCodeFor): Deleted.
(JSC::ExecutableBase::offsetOfNumParametersFor): Deleted.
(JSC::ExecutableBase::hasJITCodeForCall const): Deleted.
(JSC::ExecutableBase::hasJITCodeForConstruct const): Deleted.
(JSC::ExecutableBase::intrinsic const): Deleted.
* runtime/ExecutableBaseInlines.h: Added.
(JSC::ExecutableBase::intrinsic const):
(JSC::ExecutableBase::hasJITCodeForCall const):
(JSC::ExecutableBase::hasJITCodeForConstruct const):
* runtime/JSBoundFunction.cpp:
* runtime/JSType.cpp:
(WTF::printInternal):
* runtime/JSType.h:
* runtime/NativeExecutable.cpp:
(JSC::NativeExecutable::create):
(JSC::NativeExecutable::createStructure):
(JSC::NativeExecutable::NativeExecutable):
(JSC::NativeExecutable::signatureFor const):
(JSC::NativeExecutable::intrinsic const):
* runtime/NativeExecutable.h:
* runtime/ScriptExecutable.cpp:
(JSC::ScriptExecutable::ScriptExecutable):
(JSC::ScriptExecutable::clearCode):
(JSC::ScriptExecutable::installCode):
(JSC::ScriptExecutable::hasClearableCode const):
* runtime/ScriptExecutable.h:
(JSC::ScriptExecutable::intrinsic const):
(JSC::ScriptExecutable::hasJITCodeForCall const):
(JSC::ScriptExecutable::hasJITCodeForConstruct const):
* runtime/VM.cpp:
(JSC::VM::getHostFunction):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241037 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/CallVariant.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JITCode.cpp
Source/JavaScriptCore/jit/JITCode.h
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITThunks.cpp
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/ExecutableBase.cpp
Source/JavaScriptCore/runtime/ExecutableBase.h
Source/JavaScriptCore/runtime/ExecutableBaseInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSBoundFunction.cpp
Source/JavaScriptCore/runtime/JSType.cpp
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/NativeExecutable.cpp
Source/JavaScriptCore/runtime/NativeExecutable.h
Source/JavaScriptCore/runtime/ScriptExecutable.cpp
Source/JavaScriptCore/runtime/ScriptExecutable.h
Source/JavaScriptCore/runtime/VM.cpp

index be0c214..2cef936 100644 (file)
@@ -782,6 +782,7 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
     runtime/ExceptionHelpers.h
     runtime/ExceptionScope.h
     runtime/ExecutableBase.h
+    runtime/ExecutableBaseInlines.h
     runtime/Float32Array.h
     runtime/Float64Array.h
     runtime/FunctionConstructor.h
index f4449dc..bb3b1f8 100644 (file)
@@ -1,3 +1,91 @@
+2019-02-06  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] NativeExecutable should be smaller
+        https://bugs.webkit.org/show_bug.cgi?id=194331
+
+        Reviewed by Michael Saboff.
+
+        NativeExecutable takes 88 bytes now. Since our GC rounds the size with 16, it actually takes 96 bytes in IsoSubspaces.
+        Since a lot of NativeExecutable are allocated, we already has two MarkedBlocks even just after JSGlobalObject initialization.
+        This patch makes sizeof(NativeExecutable) 64 bytes, which is 32 bytes smaller than 96 bytes. Now our JSGlobalObject initialization
+        only takes one MarkedBlock for NativeExecutable.
+
+        To make NativeExecutable smaller,
+
+        1. m_numParametersForCall and m_numParametersForConstruct in ExecutableBase are only meaningful in ScriptExecutable subclasses. Since
+           they are not touched from JIT, we can remove them from ExecutableBase and move them to ScriptExecutable.
+
+        2. DOMJIT::Signature* is rarely used. Rather than having it in NativeExecutable, we should put it in NativeJITCode. Since NativeExecutable
+           always has JITCode, we can safely query the value from NativeExecutable. This patch creates NativeDOMJITCode, which is a subclass of
+           NativeJITCode, and instantiated only when DOMJIT::Signature* is given.
+
+        3. Move Intrinsic to a member of ScriptExecutable or JITCode. Since JITCode has some paddings to put things, we can leverage this to put
+           Intrinsic for NativeExecutable.
+
+        We also move "clearCode" code from ExecutableBase to ScriptExecutable since it is only valid for ScriptExecutable subclasses.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CallVariant.h:
+        * interpreter/Interpreter.cpp:
+        * jit/JITCode.cpp:
+        (JSC::DirectJITCode::DirectJITCode):
+        (JSC::NativeJITCode::NativeJITCode):
+        (JSC::NativeDOMJITCode::NativeDOMJITCode):
+        * jit/JITCode.h:
+        (JSC::JITCode::signature const):
+        (JSC::JITCode::intrinsic):
+        * jit/JITOperations.cpp:
+        * jit/JITThunks.cpp:
+        (JSC::JITThunks::hostFunctionStub):
+        * jit/Repatch.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        * runtime/ExecutableBase.cpp:
+        (JSC::ExecutableBase::dump const):
+        (JSC::ExecutableBase::hashFor const):
+        (JSC::ExecutableBase::hasClearableCode const): Deleted.
+        (JSC::ExecutableBase::clearCode): Deleted.
+        * runtime/ExecutableBase.h:
+        (JSC::ExecutableBase::ExecutableBase):
+        (JSC::ExecutableBase::isModuleProgramExecutable):
+        (JSC::ExecutableBase::isHostFunction const):
+        (JSC::ExecutableBase::generatedJITCodeForCall const):
+        (JSC::ExecutableBase::generatedJITCodeForConstruct const):
+        (JSC::ExecutableBase::generatedJITCodeFor const):
+        (JSC::ExecutableBase::generatedJITCodeForCall): Deleted.
+        (JSC::ExecutableBase::generatedJITCodeForConstruct): Deleted.
+        (JSC::ExecutableBase::generatedJITCodeFor): Deleted.
+        (JSC::ExecutableBase::offsetOfNumParametersFor): Deleted.
+        (JSC::ExecutableBase::hasJITCodeForCall const): Deleted.
+        (JSC::ExecutableBase::hasJITCodeForConstruct const): Deleted.
+        (JSC::ExecutableBase::intrinsic const): Deleted.
+        * runtime/ExecutableBaseInlines.h: Added.
+        (JSC::ExecutableBase::intrinsic const):
+        (JSC::ExecutableBase::hasJITCodeForCall const):
+        (JSC::ExecutableBase::hasJITCodeForConstruct const):
+        * runtime/JSBoundFunction.cpp:
+        * runtime/JSType.cpp:
+        (WTF::printInternal):
+        * runtime/JSType.h:
+        * runtime/NativeExecutable.cpp:
+        (JSC::NativeExecutable::create):
+        (JSC::NativeExecutable::createStructure):
+        (JSC::NativeExecutable::NativeExecutable):
+        (JSC::NativeExecutable::signatureFor const):
+        (JSC::NativeExecutable::intrinsic const):
+        * runtime/NativeExecutable.h:
+        * runtime/ScriptExecutable.cpp:
+        (JSC::ScriptExecutable::ScriptExecutable):
+        (JSC::ScriptExecutable::clearCode):
+        (JSC::ScriptExecutable::installCode):
+        (JSC::ScriptExecutable::hasClearableCode const):
+        * runtime/ScriptExecutable.h:
+        (JSC::ScriptExecutable::intrinsic const):
+        (JSC::ScriptExecutable::hasJITCodeForCall const):
+        (JSC::ScriptExecutable::hasJITCodeForConstruct const):
+        * runtime/VM.cpp:
+        (JSC::VM::getHostFunction):
+
 2019-02-06  Pablo Saavedra  <psaavedra@igalia.com>
 
         Build failure after r240431
index 15563fe..ecc17d3 100644 (file)
                E350708A1DC49BBF0089BCD6 /* DOMJITSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = E35070891DC49BB60089BCD6 /* DOMJITSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E354622B1B6065D100545386 /* ConstructAbility.h in Headers */ = {isa = PBXBuildFile; fileRef = E354622A1B6065D100545386 /* ConstructAbility.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3555B8A1DAE03A500F36921 /* DOMJITCallDOMGetterSnippet.h in Headers */ = {isa = PBXBuildFile; fileRef = E3555B891DAE03A200F36921 /* DOMJITCallDOMGetterSnippet.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               E35A0B9D220AD87A00AC4474 /* ExecutableBaseInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E35A0B9C220AD87A00AC4474 /* ExecutableBaseInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1521DBC3A5600F83516 /* DOMJITHeapRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35E03601B7AB43E0073AD2A /* InspectorInstrumentationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35070891DC49BB60089BCD6 /* DOMJITSignature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITSignature.h; sourceTree = "<group>"; };
                E354622A1B6065D100545386 /* ConstructAbility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstructAbility.h; sourceTree = "<group>"; };
                E3555B891DAE03A200F36921 /* DOMJITCallDOMGetterSnippet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITCallDOMGetterSnippet.h; sourceTree = "<group>"; };
+               E35A0B9C220AD87A00AC4474 /* ExecutableBaseInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableBaseInlines.h; sourceTree = "<group>"; };
                E35CA14F1DBC3A5600F83516 /* DOMJITAbstractHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITAbstractHeap.cpp; sourceTree = "<group>"; };
                E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAbstractHeap.h; sourceTree = "<group>"; };
                E35CA1511DBC3A5600F83516 /* DOMJITHeapRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITHeapRange.cpp; sourceTree = "<group>"; };
                                FE6491361D78F01300A694D4 /* ExceptionScope.h */,
                                147341E91DC2CF2500AA29BA /* ExecutableBase.cpp */,
                                147341CB1DC02D7200AA29BA /* ExecutableBase.h */,
+                               E35A0B9C220AD87A00AC4474 /* ExecutableBaseInlines.h */,
                                A7A8AF2917ADB5F3005AB174 /* Float32Array.h */,
                                A7A8AF2A17ADB5F3005AB174 /* Float64Array.h */,
                                BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */,
                                0FF054FA1AC35B4400E5BE57 /* ExecutableAllocationFuzz.h in Headers */,
                                A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */,
                                147341CC1DC02D7200AA29BA /* ExecutableBase.h in Headers */,
+                               E35A0B9D220AD87A00AC4474 /* ExecutableBaseInlines.h in Headers */,
                                14142E531B796EDD00F4BF4B /* ExecutableInfo.h in Headers */,
                                0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */,
                                0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */,
index c0d06a5..8cedae6 100644 (file)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "ExecutableBaseInlines.h"
 #include "FunctionExecutable.h"
 #include "JSCast.h"
 #include "JSFunction.h"
index 17f4a7f..06221fd 100644 (file)
@@ -37,6 +37,7 @@
 #include "CodeBlock.h"
 #include "CodeCache.h"
 #include "DirectArguments.h"
+#include "ExecutableBaseInlines.h"
 #include "Heap.h"
 #include "Debugger.h"
 #include "DebuggerCallFrame.h"
index bc28180..714ab23 100644 (file)
@@ -159,6 +159,15 @@ DirectJITCode::DirectJITCode(JITCode::CodeRef<JSEntryPtrTag> ref, JITCode::CodeP
     ASSERT(m_withArityCheck);
 }
 
+DirectJITCode::DirectJITCode(JITCode::CodeRef<JSEntryPtrTag> ref, JITCode::CodePtr<JSEntryPtrTag> withArityCheck, JITType jitType, Intrinsic intrinsic)
+    : JITCodeWithCodeRef(ref, jitType)
+    , m_withArityCheck(withArityCheck)
+{
+    m_intrinsic = intrinsic;
+    ASSERT(m_ref);
+    ASSERT(m_withArityCheck);
+}
+
 DirectJITCode::~DirectJITCode()
 {
 }
@@ -191,9 +200,10 @@ NativeJITCode::NativeJITCode(JITType jitType)
 {
 }
 
-NativeJITCode::NativeJITCode(CodeRef<JSEntryPtrTag> ref, JITType jitType)
+NativeJITCode::NativeJITCode(CodeRef<JSEntryPtrTag> ref, JITType jitType, Intrinsic intrinsic)
     : JITCodeWithCodeRef(ref, jitType)
 {
+    m_intrinsic = intrinsic;
 }
 
 NativeJITCode::~NativeJITCode()
@@ -219,6 +229,12 @@ JITCode::CodePtr<JSEntryPtrTag> NativeJITCode::addressForCall(ArityCheckMode ari
     return CodePtr<JSEntryPtrTag>();
 }
 
+NativeDOMJITCode::NativeDOMJITCode(CodeRef<JSEntryPtrTag> ref, JITType type, Intrinsic intrinsic, const DOMJIT::Signature* signature)
+    : NativeJITCode(ref, type, intrinsic)
+    , m_signature(signature)
+{
+}
+
 #if ENABLE(JIT)
 RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex)
 {
index e70647f..8474b9a 100644 (file)
@@ -43,6 +43,9 @@ namespace FTL {
 class ForOSREntryJITCode;
 class JITCode;
 }
+namespace DOMJIT {
+class Signature;
+}
 
 struct ProtoCallFrame;
 class TrackedReferences;
@@ -152,6 +155,8 @@ public:
     {
         return jitType == InterpreterThunk || jitType == BaselineJIT;
     }
+
+    virtual const DOMJIT::Signature* signature() const { return nullptr; }
     
 protected:
     JITCode(JITType);
@@ -198,8 +203,12 @@ public:
     virtual Optional<CodeOrigin> findPC(CodeBlock*, void* pc) { UNUSED_PARAM(pc); return WTF::nullopt; }
 #endif
 
+    Intrinsic intrinsic() { return m_intrinsic; }
+
 private:
     JITType m_jitType;
+protected:
+    Intrinsic m_intrinsic { NoIntrinsic }; // Effective only in NativeExecutable.
 };
 
 class JITCodeWithCodeRef : public JITCode {
@@ -224,6 +233,7 @@ class DirectJITCode : public JITCodeWithCodeRef {
 public:
     DirectJITCode(JITType);
     DirectJITCode(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck, JITType);
+    DirectJITCode(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck, JITType, Intrinsic); // For generated thunk.
     virtual ~DirectJITCode();
     
     void initializeCodeRef(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck);
@@ -237,7 +247,7 @@ private:
 class NativeJITCode : public JITCodeWithCodeRef {
 public:
     NativeJITCode(JITType);
-    NativeJITCode(CodeRef<JSEntryPtrTag>, JITType);
+    NativeJITCode(CodeRef<JSEntryPtrTag>, JITType, Intrinsic);
     virtual ~NativeJITCode();
     
     void initializeCodeRef(CodeRef<JSEntryPtrTag>);
@@ -245,6 +255,17 @@ public:
     CodePtr<JSEntryPtrTag> addressForCall(ArityCheckMode) override;
 };
 
+class NativeDOMJITCode final : public NativeJITCode {
+public:
+    NativeDOMJITCode(CodeRef<JSEntryPtrTag>, JITType, Intrinsic, const DOMJIT::Signature*);
+    virtual ~NativeDOMJITCode() = default;
+
+    const DOMJIT::Signature* signature() const override { return m_signature; }
+
+private:
+    const DOMJIT::Signature* m_signature;
+};
+
 } // namespace JSC
 
 namespace WTF {
index e8babd2..a58e5d7 100644 (file)
@@ -42,6 +42,7 @@
 #include "ErrorHandlingScope.h"
 #include "EvalCodeBlock.h"
 #include "ExceptionFuzz.h"
+#include "ExecutableBaseInlines.h"
 #include "FTLOSREntry.h"
 #include "FrameTracers.h"
 #include "FunctionCodeBlock.h"
index 5f8c02b..e1607c6 100644 (file)
@@ -124,13 +124,15 @@ NativeExecutable* JITThunks::hostFunctionStub(VM* vm, TaggedNativeFunction funct
     RefPtr<JITCode> forCall;
     if (generator) {
         MacroAssemblerCodeRef<JSEntryPtrTag> entry = generator(vm).retagged<JSEntryPtrTag>();
-        forCall = adoptRef(new DirectJITCode(entry, entry.code(), JITCode::HostCallThunk));
-    } else
-        forCall = adoptRef(new NativeJITCode(MacroAssemblerCodeRef<JSEntryPtrTag>::createSelfManagedCodeRef(ctiNativeCall(vm).retagged<JSEntryPtrTag>()), JITCode::HostCallThunk));
+        forCall = adoptRef(new DirectJITCode(entry, entry.code(), JITCode::HostCallThunk, intrinsic));
+    } else if (signature)
+        forCall = adoptRef(new NativeDOMJITCode(MacroAssemblerCodeRef<JSEntryPtrTag>::createSelfManagedCodeRef(ctiNativeCall(vm).retagged<JSEntryPtrTag>()), JITCode::HostCallThunk, intrinsic, signature));
+    else
+        forCall = adoptRef(new NativeJITCode(MacroAssemblerCodeRef<JSEntryPtrTag>::createSelfManagedCodeRef(ctiNativeCall(vm).retagged<JSEntryPtrTag>()), JITCode::HostCallThunk, intrinsic));
     
-    Ref<JITCode> forConstruct = adoptRef(*new NativeJITCode(MacroAssemblerCodeRef<JSEntryPtrTag>::createSelfManagedCodeRef(ctiNativeConstruct(vm).retagged<JSEntryPtrTag>()), JITCode::HostCallThunk));
+    Ref<JITCode> forConstruct = adoptRef(*new NativeJITCode(MacroAssemblerCodeRef<JSEntryPtrTag>::createSelfManagedCodeRef(ctiNativeConstruct(vm).retagged<JSEntryPtrTag>()), JITCode::HostCallThunk, NoIntrinsic));
     
-    NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall.releaseNonNull(), function, WTFMove(forConstruct), constructor, intrinsic, signature, name);
+    NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall.releaseNonNull(), function, WTFMove(forConstruct), constructor, name);
     weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak<NativeExecutable>(nativeExecutable, this));
     return nativeExecutable;
 }
index ad572c4..fba76da 100644 (file)
@@ -35,6 +35,7 @@
 #include "DFGSpeculativeJIT.h"
 #include "DOMJITGetterSetter.h"
 #include "DirectArguments.h"
+#include "ExecutableBaseInlines.h"
 #include "FTLThunks.h"
 #include "FullCodeOrigin.h"
 #include "FunctionCodeBlock.h"
index 2b3c7cb..a9a8550 100644 (file)
@@ -34,6 +34,7 @@
 #include "EvalCodeBlock.h"
 #include "Exception.h"
 #include "ExceptionFuzz.h"
+#include "ExecutableBaseInlines.h"
 #include "FrameTracers.h"
 #include "FunctionCodeBlock.h"
 #include "FunctionWhitelist.h"
index df43130..2989b1d 100644 (file)
@@ -49,100 +49,17 @@ void ExecutableBase::destroy(JSCell* cell)
     static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
 }
 
-bool ExecutableBase::hasClearableCode() const
-{
-    VM& vm = *this->vm();
-
-#if ENABLE(JIT)
-    if (m_jitCodeForCall
-        || m_jitCodeForConstruct
-        || m_jitCodeForCallWithArityCheck
-        || m_jitCodeForConstructWithArityCheck)
-        return true;
-#endif
-
-    if (structure(vm)->classInfo() == FunctionExecutable::info()) {
-        auto* executable = static_cast<const FunctionExecutable*>(this);
-        if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
-            return true;
-
-    } else if (structure(vm)->classInfo() == EvalExecutable::info()) {
-        auto* executable = static_cast<const EvalExecutable*>(this);
-        if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
-            return true;
-
-    } else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
-        auto* executable = static_cast<const ProgramExecutable*>(this);
-        if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
-            return true;
-
-    } else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
-        auto* executable = static_cast<const ModuleProgramExecutable*>(this);
-        if (executable->m_moduleProgramCodeBlock
-            || executable->m_unlinkedModuleProgramCodeBlock
-            || executable->m_moduleEnvironmentSymbolTable)
-            return true;
-    }
-    return false;
-}
-
-void ExecutableBase::clearCode()
-{
-#if ENABLE(JIT)
-    m_jitCodeForCall = nullptr;
-    m_jitCodeForConstruct = nullptr;
-    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
-    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
-#endif
-    m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
-    m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
-    VM& vm = *this->vm();
-
-
-    if (structure(vm)->classInfo() == FunctionExecutable::info()) {
-        FunctionExecutable* executable = static_cast<FunctionExecutable*>(this);
-        executable->m_codeBlockForCall.clear();
-        executable->m_codeBlockForConstruct.clear();
-        return;
-    }
-
-    if (structure(vm)->classInfo() == EvalExecutable::info()) {
-        EvalExecutable* executable = static_cast<EvalExecutable*>(this);
-        executable->m_evalCodeBlock.clear();
-        executable->m_unlinkedEvalCodeBlock.clear();
-        return;
-    }
-    
-    if (structure(vm)->classInfo() == ProgramExecutable::info()) {
-        ProgramExecutable* executable = static_cast<ProgramExecutable*>(this);
-        executable->m_programCodeBlock.clear();
-        executable->m_unlinkedProgramCodeBlock.clear();
-        return;
-    }
-
-    if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
-        ModuleProgramExecutable* executable = static_cast<ModuleProgramExecutable*>(this);
-        executable->m_moduleProgramCodeBlock.clear();
-        executable->m_unlinkedModuleProgramCodeBlock.clear();
-        executable->m_moduleEnvironmentSymbolTable.clear();
-        return;
-    }
-    
-    ASSERT(structure(vm)->classInfo() == NativeExecutable::info());
-}
-
 void ExecutableBase::dump(PrintStream& out) const
 {
-    VM& vm = *this->vm();
     ExecutableBase* realThis = const_cast<ExecutableBase*>(this);
 
-    if (classInfo(vm) == NativeExecutable::info()) {
+    switch (type()) {
+    case NativeExecutableType: {
         NativeExecutable* native = jsCast<NativeExecutable*>(realThis);
         out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));
         return;
     }
-    
-    if (classInfo(vm) == EvalExecutable::info()) {
+    case EvalExecutableType: {
         EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);
         if (CodeBlock* codeBlock = eval->codeBlock())
             out.print(*codeBlock);
@@ -150,8 +67,7 @@ void ExecutableBase::dump(PrintStream& out) const
             out.print("EvalExecutable w/o CodeBlock");
         return;
     }
-    
-    if (classInfo(vm) == ProgramExecutable::info()) {
+    case ProgramExecutableType: {
         ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);
         if (CodeBlock* codeBlock = eval->codeBlock())
             out.print(*codeBlock);
@@ -159,8 +75,7 @@ void ExecutableBase::dump(PrintStream& out) const
             out.print("ProgramExecutable w/o CodeBlock");
         return;
     }
-
-    if (classInfo(vm) == ModuleProgramExecutable::info()) {
+    case ModuleProgramExecutableType: {
         ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(realThis);
         if (CodeBlock* codeBlock = executable->codeBlock())
             out.print(*codeBlock);
@@ -168,22 +83,27 @@ void ExecutableBase::dump(PrintStream& out) const
             out.print("ModuleProgramExecutable w/o CodeBlock");
         return;
     }
-    
-    FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
-    if (!function->eitherCodeBlock())
-        out.print("FunctionExecutable w/o CodeBlock");
-    else {
-        CommaPrinter comma("/");
-        if (function->codeBlockForCall())
-            out.print(comma, *function->codeBlockForCall());
-        if (function->codeBlockForConstruct())
-            out.print(comma, *function->codeBlockForConstruct());
+    case FunctionExecutableType: {
+        FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);
+        if (!function->eitherCodeBlock())
+            out.print("FunctionExecutable w/o CodeBlock");
+        else {
+            CommaPrinter comma("/");
+            if (function->codeBlockForCall())
+                out.print(comma, *function->codeBlockForCall());
+            if (function->codeBlockForConstruct())
+                out.print(comma, *function->codeBlockForConstruct());
+        }
+        return;
+    }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
     }
 }
 
 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
 {
-    if (this->classInfo(*this->vm()) == NativeExecutable::info())
+    if (type() == NativeExecutableType)
         return jsCast<const NativeExecutable*>(this)->hashFor(kind);
     
     return jsCast<const ScriptExecutable*>(this)->hashFor(kind);
index 4ba9896..339e2d4 100644 (file)
@@ -60,14 +60,8 @@ class ExecutableBase : public JSCell {
     friend MacroAssemblerCodeRef<JITThunkPtrTag> boundThisNoArgsFunctionCallGenerator(VM*);
 
 protected:
-    static const int NUM_PARAMETERS_IS_HOST = 0;
-    static const int NUM_PARAMETERS_NOT_COMPILED = -1;
-
-    ExecutableBase(VM& vm, Structure* structure, int numParameters, Intrinsic intrinsic)
+    ExecutableBase(VM& vm, Structure* structure)
         : JSCell(vm, structure)
-        , m_numParametersForCall(numParameters)
-        , m_numParametersForConstruct(numParameters)
-        , m_intrinsic(intrinsic)
     {
     }
 
@@ -105,39 +99,29 @@ public:
     {
         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;
+        return type() == NativeExecutableType;
     }
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
 
-    bool hasClearableCode() const;
-    void clearCode();
-
     DECLARE_EXPORT_INFO;
 
-protected:
-    int m_numParametersForCall;
-    int m_numParametersForConstruct;
-
 public:
-    Ref<JITCode> generatedJITCodeForCall()
+    Ref<JITCode> generatedJITCodeForCall() const
     {
         ASSERT(m_jitCodeForCall);
         return *m_jitCodeForCall;
     }
 
-    Ref<JITCode> generatedJITCodeForConstruct()
+    Ref<JITCode> generatedJITCodeForConstruct() const
     {
         ASSERT(m_jitCodeForConstruct);
         return *m_jitCodeForConstruct;
     }
         
-    Ref<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
+    Ref<JITCode> generatedJITCodeFor(CodeSpecializationKind kind) const
     {
         if (kind == CodeForCall)
             return generatedJITCodeForCall();
@@ -190,24 +174,9 @@ public:
         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);
-    }
+    bool hasJITCodeForCall() const;
+    bool hasJITCodeForConstruct() const;
 
-    bool hasJITCodeForCall() const
-    {
-        return m_numParametersForCall >= 0;
-    }
-        
-    bool hasJITCodeForConstruct() const
-    {
-        return m_numParametersForConstruct >= 0;
-    }
-        
     bool hasJITCodeFor(CodeSpecializationKind kind) const
     {
         if (kind == CodeForCall)
@@ -217,7 +186,7 @@ public:
     }
 
     // Intrinsics are only for calls, currently.
-    Intrinsic intrinsic() const { return m_intrinsic; }
+    Intrinsic intrinsic() const;
         
     Intrinsic intrinsicFor(CodeSpecializationKind kind) const
     {
@@ -233,7 +202,6 @@ protected:
     RefPtr<JITCode> m_jitCodeForConstruct;
     MacroAssemblerCodePtr<JSEntryPtrTag> m_jitCodeForCallWithArityCheck;
     MacroAssemblerCodePtr<JSEntryPtrTag> m_jitCodeForConstructWithArityCheck;
-    Intrinsic m_intrinsic;
 };
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ExecutableBaseInlines.h b/Source/JavaScriptCore/runtime/ExecutableBaseInlines.h
new file mode 100644 (file)
index 0000000..e9de48a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ExecutableBase.h"
+#include "NativeExecutable.h"
+#include "ScriptExecutable.h"
+
+namespace JSC {
+
+inline Intrinsic ExecutableBase::intrinsic() const
+{
+    if (isHostFunction())
+        return jsCast<const NativeExecutable*>(this)->intrinsic();
+    return jsCast<const ScriptExecutable*>(this)->intrinsic();
+}
+
+inline bool ExecutableBase::hasJITCodeForCall() const
+{
+    if (isHostFunction())
+        return true;
+    return jsCast<const ScriptExecutable*>(this)->hasJITCodeForCall();
+}
+
+inline bool ExecutableBase::hasJITCodeForConstruct() const
+{
+    if (isHostFunction())
+        return true;
+    return jsCast<const ScriptExecutable*>(this)->hasJITCodeForConstruct();
+}
+
+} // namespace JSC
index ff49eaf..29d727e 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "JSBoundFunction.h"
 
+#include "ExecutableBaseInlines.h"
 #include "GetterSetter.h"
 #include "JSGlobalObject.h"
 #include "JSCInlines.h"
index 054df78..780dabd 100644 (file)
@@ -46,6 +46,7 @@ void printInternal(PrintStream& out, JSC::JSType type)
     CASE(BigIntType)
     CASE(CustomGetterSetterType)
     CASE(APIValueWrapperType)
+    CASE(NativeExecutableType)
     CASE(ProgramExecutableType)
     CASE(ModuleProgramExecutableType)
     CASE(EvalExecutableType)
index 38aaf51..c62ec6d 100644 (file)
@@ -32,6 +32,8 @@ enum JSType : uint8_t {
     CustomGetterSetterType,
     APIValueWrapperType,
 
+    NativeExecutableType,
+
     ProgramExecutableType,
     ModuleProgramExecutableType,
     EvalExecutableType,
index 51cfcc8..63dd2ec 100644 (file)
@@ -40,10 +40,10 @@ namespace JSC {
 
 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(NativeExecutable) };
 
-NativeExecutable* NativeExecutable::create(VM& vm, Ref<JITCode>&& callThunk, TaggedNativeFunction function, Ref<JITCode>&& constructThunk, TaggedNativeFunction constructor, Intrinsic intrinsic, const DOMJIT::Signature* signature, const String& name)
+NativeExecutable* NativeExecutable::create(VM& vm, Ref<JITCode>&& callThunk, TaggedNativeFunction function, Ref<JITCode>&& constructThunk, TaggedNativeFunction constructor, const String& name)
 {
     NativeExecutable* executable;
-    executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor, intrinsic, signature);
+    executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
     executable->finishCreation(vm, WTFMove(callThunk), WTFMove(constructThunk), name);
     return executable;
 }
@@ -55,7 +55,7 @@ void NativeExecutable::destroy(JSCell* cell)
 
 Structure* NativeExecutable::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
 {
-    return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info());
+    return Structure::create(vm, globalObject, proto, TypeInfo(NativeExecutableType, StructureFlags), info());
 }
 
 void NativeExecutable::finishCreation(VM& vm, Ref<JITCode>&& callThunk, Ref<JITCode>&& constructThunk, const String& name)
@@ -73,14 +73,24 @@ void NativeExecutable::finishCreation(VM& vm, Ref<JITCode>&& callThunk, Ref<JITC
     assertIsTaggedWith(m_jitCodeForConstructWithArityCheck.executableAddress(), JSEntryPtrTag);
 }
 
-NativeExecutable::NativeExecutable(VM& vm, TaggedNativeFunction function, TaggedNativeFunction constructor, Intrinsic intrinsic, const DOMJIT::Signature* signature)
-    : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST, intrinsic)
+NativeExecutable::NativeExecutable(VM& vm, TaggedNativeFunction function, TaggedNativeFunction constructor)
+    : ExecutableBase(vm, vm.nativeExecutableStructure.get())
     , m_function(function)
     , m_constructor(constructor)
-    , m_signature(signature)
 {
 }
 
+const DOMJIT::Signature* NativeExecutable::signatureFor(CodeSpecializationKind kind) const
+{
+    ASSERT(hasJITCodeFor(kind));
+    return generatedJITCodeFor(kind)->signature();
+}
+
+Intrinsic NativeExecutable::intrinsic() const
+{
+    return generatedJITCodeFor(CodeForCall)->intrinsic();
+}
+
 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
 {
     if (kind == CodeForCall)
index 91fb35b..b9ab65a 100644 (file)
@@ -29,9 +29,6 @@
 #include "JSCPoison.h"
 
 namespace JSC {
-namespace DOMJIT {
-class Signature;
-}
 
 class NativeExecutable final : public ExecutableBase {
     friend class JIT;
@@ -40,7 +37,7 @@ public:
     typedef ExecutableBase Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-    static NativeExecutable* create(VM&, Ref<JITCode>&& callThunk, TaggedNativeFunction, Ref<JITCode>&& constructThunk, TaggedNativeFunction constructor, Intrinsic, const DOMJIT::Signature*, const String& name);
+    static NativeExecutable* create(VM&, Ref<JITCode>&& callThunk, TaggedNativeFunction, Ref<JITCode>&& constructThunk, TaggedNativeFunction constructor, const String& name);
 
     static void destroy(JSCell*);
     
@@ -76,14 +73,9 @@ public:
     DECLARE_INFO;
 
     const String& name() const { return m_name; }
-    const DOMJIT::Signature* signature() const { return m_signature; }
 
-    const DOMJIT::Signature* signatureFor(CodeSpecializationKind kind) const
-    {
-        if (isCall(kind))
-            return signature();
-        return nullptr;
-    }
+    const DOMJIT::Signature* signatureFor(CodeSpecializationKind) const;
+    Intrinsic intrinsic() const;
 
 protected:
     void finishCreation(VM&, Ref<JITCode>&& callThunk, Ref<JITCode>&& constructThunk, const String& name);
@@ -92,11 +84,10 @@ private:
     friend class ExecutableBase;
     using PoisonedTaggedNativeFunction = Poisoned<NativeCodePoison, TaggedNativeFunction>;
 
-    NativeExecutable(VM&, TaggedNativeFunction, TaggedNativeFunction constructor, Intrinsic, const DOMJIT::Signature*);
+    NativeExecutable(VM&, TaggedNativeFunction, TaggedNativeFunction constructor);
 
     PoisonedTaggedNativeFunction m_function;
     PoisonedTaggedNativeFunction m_constructor;
-    const DOMJIT::Signature* m_signature;
 
     String m_name;
 };
index 3251a79..b882b98 100644 (file)
@@ -46,7 +46,9 @@ namespace JSC {
 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ScriptExecutable) };
 
 ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, EvalContextType evalContextType, Intrinsic intrinsic)
-    : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED, intrinsic)
+    : ExecutableBase(vm, structure)
+    , m_source(source)
+    , m_intrinsic(intrinsic)
     , m_features(isInStrictContext ? StrictModeFeature : 0)
     , m_hasCapturedVariables(false)
     , m_neverInline(false)
@@ -56,7 +58,6 @@ ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCod
     , m_canUseOSRExitFuzzing(true)
     , m_derivedContextType(static_cast<unsigned>(derivedContextType))
     , m_evalContextType(static_cast<unsigned>(evalContextType))
-    , m_source(source)
 {
 }
 
@@ -67,7 +68,46 @@ void ScriptExecutable::destroy(JSCell* cell)
 
 void ScriptExecutable::clearCode(IsoCellSet& clearableCodeSet)
 {
-    Base::clearCode();
+#if ENABLE(JIT)
+    m_jitCodeForCall = nullptr;
+    m_jitCodeForConstruct = nullptr;
+    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
+    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
+#endif
+    m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
+    m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
+
+    switch (type()) {
+    case FunctionExecutableType: {
+        FunctionExecutable* executable = static_cast<FunctionExecutable*>(this);
+        executable->m_codeBlockForCall.clear();
+        executable->m_codeBlockForConstruct.clear();
+        break;
+    }
+    case EvalExecutableType: {
+        EvalExecutable* executable = static_cast<EvalExecutable*>(this);
+        executable->m_evalCodeBlock.clear();
+        executable->m_unlinkedEvalCodeBlock.clear();
+        break;
+    }
+    case ProgramExecutableType: {
+        ProgramExecutable* executable = static_cast<ProgramExecutable*>(this);
+        executable->m_programCodeBlock.clear();
+        executable->m_unlinkedProgramCodeBlock.clear();
+        break;
+    }
+    case ModuleProgramExecutableType: {
+        ModuleProgramExecutable* executable = static_cast<ModuleProgramExecutable*>(this);
+        executable->m_moduleProgramCodeBlock.clear();
+        executable->m_unlinkedModuleProgramCodeBlock.clear();
+        executable->m_moduleEnvironmentSymbolTable.clear();
+        break;
+    }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
+
     ASSERT(&VM::SpaceAndSet::setFor(*subspace()) == &clearableCodeSet);
     clearableCodeSet.remove(this);
 }
@@ -150,7 +190,7 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
     }
 
     auto& clearableCodeSet = VM::SpaceAndSet::setFor(*subspace());
-    if (hasClearableCode())
+    if (hasClearableCode(vm))
         clearableCodeSet.add(this);
     else
         clearableCodeSet.remove(this);
@@ -176,6 +216,41 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
     vm.heap.writeBarrier(this);
 }
 
+bool ScriptExecutable::hasClearableCode(VM& vm) const
+{
+#if ENABLE(JIT)
+    if (m_jitCodeForCall
+        || m_jitCodeForConstruct
+        || m_jitCodeForCallWithArityCheck
+        || m_jitCodeForConstructWithArityCheck)
+        return true;
+#endif
+
+    if (structure(vm)->classInfo() == FunctionExecutable::info()) {
+        auto* executable = static_cast<const FunctionExecutable*>(this);
+        if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
+            return true;
+
+    } else if (structure(vm)->classInfo() == EvalExecutable::info()) {
+        auto* executable = static_cast<const EvalExecutable*>(this);
+        if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
+            return true;
+
+    } else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
+        auto* executable = static_cast<const ProgramExecutable*>(this);
+        if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
+            return true;
+
+    } else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
+        auto* executable = static_cast<const ModuleProgramExecutable*>(this);
+        if (executable->m_moduleProgramCodeBlock
+            || executable->m_unlinkedModuleProgramCodeBlock
+            || executable->m_moduleEnvironmentSymbolTable)
+            return true;
+    }
+    return false;
+}
+
 CodeBlock* ScriptExecutable::newCodeBlockFor(
     CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)
 {
index 5b85393..115f883 100644 (file)
@@ -97,6 +97,22 @@ public:
 
     void clearCode(IsoCellSet&);
 
+    Intrinsic intrinsic() const
+    {
+        return m_intrinsic;
+    }
+
+    static constexpr int NUM_PARAMETERS_NOT_COMPILED = -1;
+
+    bool hasJITCodeForCall() const
+    {
+        return m_numParametersForCall >= 0;
+    }
+    bool hasJITCodeForConstruct() const
+    {
+        return m_numParametersForConstruct >= 0;
+    }
+
     // 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
@@ -110,6 +126,8 @@ private:
     friend class ExecutableBase;
     JSObject* prepareForExecutionImpl(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&);
 
+    bool hasClearableCode(VM&) const;
+
 protected:
     ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic);
 
@@ -123,6 +141,15 @@ protected:
 #endif
     }
 
+    SourceCode m_source;
+
+    int m_numParametersForCall { NUM_PARAMETERS_NOT_COMPILED };
+    int m_numParametersForConstruct { NUM_PARAMETERS_NOT_COMPILED };
+
+    int m_lastLine { -1 };
+    unsigned m_endColumn { UINT_MAX };
+
+    Intrinsic m_intrinsic { NoIntrinsic };
     bool m_didTryToEnterInLoop { false };
     CodeFeatures m_features;
     bool m_hasCapturedVariables : 1;
@@ -133,10 +160,6 @@ protected:
     bool m_canUseOSRExitFuzzing : 1;
     unsigned m_derivedContextType : 2; // DerivedContextType
     unsigned m_evalContextType : 2; // EvalContextType
-
-    int m_lastLine { -1 };
-    unsigned m_endColumn { UINT_MAX };
-    SourceCode m_source;
 };
 
 } // namespace JSC
index 4ef7baa..763b0d6 100644 (file)
@@ -699,10 +699,12 @@ NativeExecutable* VM::getHostFunction(NativeFunction function, Intrinsic intrins
     }
 #endif // ENABLE(JIT)
     UNUSED_PARAM(intrinsic);
+    UNUSED_PARAM(signature);
+
     return NativeExecutable::create(*this,
-        adoptRef(*new NativeJITCode(LLInt::getCodeRef<JSEntryPtrTag>(llint_native_call_trampoline), JITCode::HostCallThunk)), function,
-        adoptRef(*new NativeJITCode(LLInt::getCodeRef<JSEntryPtrTag>(llint_native_construct_trampoline), JITCode::HostCallThunk)), constructor,
-        NoIntrinsic, signature, name);
+        adoptRef(*new NativeJITCode(LLInt::getCodeRef<JSEntryPtrTag>(llint_native_call_trampoline), JITCode::HostCallThunk, NoIntrinsic)), function,
+        adoptRef(*new NativeJITCode(LLInt::getCodeRef<JSEntryPtrTag>(llint_native_construct_trampoline), JITCode::HostCallThunk, NoIntrinsic)), constructor,
+        name);
 }
 
 MacroAssemblerCodePtr<JSEntryPtrTag> VM::getCTIInternalFunctionTrampolineFor(CodeSpecializationKind kind)