[JSC] Shrink sizeof(FunctionExecutable) by 16bytes
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Mar 2019 07:14:43 +0000 (07:14 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Mar 2019 07:14:43 +0000 (07:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196122

Reviewed by Saam Barati.

This patch reduces sizeof(FunctionExecutable) by 16 bytes.

1. ScriptExecutable::m_numParametersForCall and ScriptExecutable::m_numParametersForConstruct are not used in a meaningful way. Removed them.
2. ScriptExecutable::m_lastLine and ScriptExecutable::m_endColumn can be calculated from UnlinkedFunctionExecutable. So FunctionExecutable does not need to hold it.
   This patch adds GlobalExecutable, which are non-function ScriptExecutables, and move m_lastLine and m_endColumn to this class.
3. FunctionExecutable still needs to have the feature overriding m_lastLine and m_endColumn. We move overridden data in FunctionExecutable::RareData.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::link):
* runtime/EvalExecutable.cpp:
(JSC::EvalExecutable::EvalExecutable):
* runtime/EvalExecutable.h:
* runtime/FunctionExecutable.cpp:
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::FunctionExecutable::ensureRareDataSlow):
(JSC::FunctionExecutable::overrideInfo):
* runtime/FunctionExecutable.h:
* runtime/GlobalExecutable.cpp: Copied from Source/JavaScriptCore/tools/FunctionOverrides.h.
* runtime/GlobalExecutable.h: Copied from Source/JavaScriptCore/tools/FunctionOverrides.h.
(JSC::GlobalExecutable::lastLine const):
(JSC::GlobalExecutable::endColumn const):
(JSC::GlobalExecutable::recordParse):
(JSC::GlobalExecutable::GlobalExecutable):
* runtime/ModuleProgramExecutable.cpp:
(JSC::ModuleProgramExecutable::ModuleProgramExecutable):
* runtime/ModuleProgramExecutable.h:
* runtime/ProgramExecutable.cpp:
(JSC::ProgramExecutable::ProgramExecutable):
* runtime/ProgramExecutable.h:
* runtime/ScriptExecutable.cpp:
(JSC::ScriptExecutable::clearCode):
(JSC::ScriptExecutable::installCode):
(JSC::ScriptExecutable::hasClearableCode const):
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::typeProfilingEndOffset const):
(JSC::ScriptExecutable::recordParse):
(JSC::ScriptExecutable::lastLine const):
(JSC::ScriptExecutable::endColumn const):
* runtime/ScriptExecutable.h:
(JSC::ScriptExecutable::hasJITCodeForCall const):
(JSC::ScriptExecutable::hasJITCodeForConstruct const):
(JSC::ScriptExecutable::recordParse):
(JSC::ScriptExecutable::lastLine const): Deleted.
(JSC::ScriptExecutable::endColumn const): Deleted.
* tools/FunctionOverrides.h:

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

18 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
Source/JavaScriptCore/runtime/EvalExecutable.cpp
Source/JavaScriptCore/runtime/EvalExecutable.h
Source/JavaScriptCore/runtime/FunctionExecutable.cpp
Source/JavaScriptCore/runtime/FunctionExecutable.h
Source/JavaScriptCore/runtime/GlobalExecutable.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/GlobalExecutable.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp
Source/JavaScriptCore/runtime/ModuleProgramExecutable.h
Source/JavaScriptCore/runtime/ProgramExecutable.cpp
Source/JavaScriptCore/runtime/ProgramExecutable.h
Source/JavaScriptCore/runtime/ScriptExecutable.cpp
Source/JavaScriptCore/runtime/ScriptExecutable.h
Source/JavaScriptCore/tools/FunctionOverrides.h

index 4fa0c3b..7977217 100644 (file)
@@ -803,6 +803,7 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
     runtime/GenericTypedArrayView.h
     runtime/GenericTypedArrayViewInlines.h
     runtime/GetPutInfo.h
+    runtime/GlobalExecutable.h
     runtime/HashMapImpl.h
     runtime/Identifier.h
     runtime/IdentifierInlines.h
index 0fb0780..69316df 100644 (file)
@@ -1,5 +1,61 @@
 2019-03-21  Yusuke Suzuki  <ysuzuki@apple.com>
 
+        [JSC] Shrink sizeof(FunctionExecutable) by 16bytes
+        https://bugs.webkit.org/show_bug.cgi?id=196122
+
+        Reviewed by Saam Barati.
+
+        This patch reduces sizeof(FunctionExecutable) by 16 bytes.
+
+        1. ScriptExecutable::m_numParametersForCall and ScriptExecutable::m_numParametersForConstruct are not used in a meaningful way. Removed them.
+        2. ScriptExecutable::m_lastLine and ScriptExecutable::m_endColumn can be calculated from UnlinkedFunctionExecutable. So FunctionExecutable does not need to hold it.
+           This patch adds GlobalExecutable, which are non-function ScriptExecutables, and move m_lastLine and m_endColumn to this class.
+        3. FunctionExecutable still needs to have the feature overriding m_lastLine and m_endColumn. We move overridden data in FunctionExecutable::RareData.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::link):
+        * runtime/EvalExecutable.cpp:
+        (JSC::EvalExecutable::EvalExecutable):
+        * runtime/EvalExecutable.h:
+        * runtime/FunctionExecutable.cpp:
+        (JSC::FunctionExecutable::FunctionExecutable):
+        (JSC::FunctionExecutable::ensureRareDataSlow):
+        (JSC::FunctionExecutable::overrideInfo):
+        * runtime/FunctionExecutable.h:
+        * runtime/GlobalExecutable.cpp: Copied from Source/JavaScriptCore/tools/FunctionOverrides.h.
+        * runtime/GlobalExecutable.h: Copied from Source/JavaScriptCore/tools/FunctionOverrides.h.
+        (JSC::GlobalExecutable::lastLine const):
+        (JSC::GlobalExecutable::endColumn const):
+        (JSC::GlobalExecutable::recordParse):
+        (JSC::GlobalExecutable::GlobalExecutable):
+        * runtime/ModuleProgramExecutable.cpp:
+        (JSC::ModuleProgramExecutable::ModuleProgramExecutable):
+        * runtime/ModuleProgramExecutable.h:
+        * runtime/ProgramExecutable.cpp:
+        (JSC::ProgramExecutable::ProgramExecutable):
+        * runtime/ProgramExecutable.h:
+        * runtime/ScriptExecutable.cpp:
+        (JSC::ScriptExecutable::clearCode):
+        (JSC::ScriptExecutable::installCode):
+        (JSC::ScriptExecutable::hasClearableCode const):
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        (JSC::ScriptExecutable::typeProfilingEndOffset const):
+        (JSC::ScriptExecutable::recordParse):
+        (JSC::ScriptExecutable::lastLine const):
+        (JSC::ScriptExecutable::endColumn const):
+        * runtime/ScriptExecutable.h:
+        (JSC::ScriptExecutable::hasJITCodeForCall const):
+        (JSC::ScriptExecutable::hasJITCodeForConstruct const):
+        (JSC::ScriptExecutable::recordParse):
+        (JSC::ScriptExecutable::lastLine const): Deleted.
+        (JSC::ScriptExecutable::endColumn const): Deleted.
+        * tools/FunctionOverrides.h:
+
+2019-03-21  Yusuke Suzuki  <ysuzuki@apple.com>
+
         [JSC] Shrink sizeof(RegExpObject)
         https://bugs.webkit.org/show_bug.cgi?id=196130
 
index b1fbf16..db25b72 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, ); }; };
+               E355D38F22446877008F1AD6 /* GlobalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = E355D38D2244686B008F1AD6 /* GlobalExecutable.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, ); }; };
                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>"; };
+               E355D38D2244686B008F1AD6 /* GlobalExecutable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GlobalExecutable.h; sourceTree = "<group>"; };
+               E355D38E2244686C008F1AD6 /* GlobalExecutable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalExecutable.cpp; 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>"; };
                                796465681B952FF0003059EE /* GetPutInfo.h */,
                                BC02E9B80E184545000F9297 /* GetterSetter.cpp */,
                                BC337BDE0E1AF0B80076918A /* GetterSetter.h */,
+                               E355D38E2244686C008F1AD6 /* GlobalExecutable.cpp */,
+                               E355D38D2244686B008F1AD6 /* GlobalExecutable.h */,
                                79A0907D1D768465008B889B /* HashMapImpl.cpp */,
                                79A0907E1D768465008B889B /* HashMapImpl.h */,
                                79DFCBDA1D88C59600527D03 /* HasOwnPropertyCache.h */,
                                534E03581E53BF2F00213F64 /* GetterSetterAccessCase.h in Headers */,
                                0FEC3C5B1F33A48900F59B6C /* GigacageAlignedMemoryAllocator.h in Headers */,
                                14AD910E1DCA92940014F9FE /* GlobalCodeBlock.h in Headers */,
+                               E355D38F22446877008F1AD6 /* GlobalExecutable.h in Headers */,
                                0F24E54417EA9F5900ABB217 /* GPRInfo.h in Headers */,
                                142E3134134FF0A600AFADB5 /* Handle.h in Headers */,
                                C283190016FE4B7D00157BFD /* HandleBlock.h in Headers */,
index 8b3dd5e..f05a3fe 100644 (file)
@@ -768,6 +768,7 @@ runtime/GeneratorFunctionPrototype.cpp
 runtime/GeneratorPrototype.cpp
 runtime/GetPutInfo.cpp
 runtime/GetterSetter.cpp
+runtime/GlobalExecutable.cpp
 runtime/HashMapImpl.cpp
 runtime/Identifier.cpp
 runtime/IndexingType.cpp
index 9629c46..58ae6c5 100644 (file)
@@ -158,31 +158,17 @@ SourceCode UnlinkedFunctionExecutable::linkedSourceCode(const SourceCode& passed
 FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& passedParentSource, Optional<int> overrideLineNumber, Intrinsic intrinsic)
 {
     SourceCode source = linkedSourceCode(passedParentSource);
-    unsigned firstLine = source.firstLine().oneBasedInt();
-    unsigned lineCount = m_lineCount;
-    unsigned endColumn = linkedEndColumn(source.startColumn().oneBasedInt());
     FunctionOverrides::OverrideInfo overrideInfo;
     bool hasFunctionOverride = false;
-    if (UNLIKELY(Options::functionOverrides())) {
+    if (UNLIKELY(Options::functionOverrides()))
         hasFunctionOverride = FunctionOverrides::initializeOverrideFor(source, overrideInfo);
-        if (UNLIKELY(hasFunctionOverride)) {
-            firstLine = overrideInfo.firstLine;
-            lineCount = overrideInfo.lineCount;
-            endColumn = overrideInfo.endColumn;
-            source = overrideInfo.sourceCode;
-        }
-    }
 
-    FunctionExecutable* result = FunctionExecutable::create(vm, source, this, firstLine + lineCount, endColumn, intrinsic);
+    FunctionExecutable* result = FunctionExecutable::create(vm, source, this, intrinsic);
     if (overrideLineNumber)
         result->setOverrideLineNumber(*overrideLineNumber);
 
-    if (UNLIKELY(hasFunctionOverride)) {
-        result->overrideParameterAndTypeProfilingStartEndOffsets(
-            overrideInfo.parametersStartOffset,
-            overrideInfo.typeProfilingStartOffset,
-            overrideInfo.typeProfilingEndOffset);
-    }
+    if (UNLIKELY(hasFunctionOverride))
+        result->overrideInfo(overrideInfo);
 
     return result;
 }
index 6ed8ccc..28c7f76 100644 (file)
 
 namespace JSC {
 
-const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(EvalExecutable) };
+const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(EvalExecutable) };
 
 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
-    : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, NoIntrinsic)
+    : Base(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, NoIntrinsic)
 {
     ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Program);
 }
index f98b644..b9cb74d 100644 (file)
 #pragma once
 
 #include "ExecutableToCodeBlockEdge.h"
-#include "ScriptExecutable.h"
+#include "GlobalExecutable.h"
 #include "UnlinkedEvalCodeBlock.h"
 
 namespace JSC {
 
-class EvalExecutable : public ScriptExecutable {
+class EvalExecutable : public GlobalExecutable {
     friend class LLIntOffsetsExtractor;
 public:
-    typedef ScriptExecutable Base;
+    using Base = GlobalExecutable;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
     static void destroy(JSCell*);
index 4c91ca2..b1b77f4 100644 (file)
@@ -29,6 +29,7 @@
 #include "CodeBlock.h"
 #include "Debugger.h"
 #include "FunctionCodeBlock.h"
+#include "FunctionOverrides.h"
 #include "JIT.h"
 #include "JSCInlines.h"
 #include "LLIntEntrypoint.h"
@@ -41,15 +42,14 @@ namespace JSC {
 
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(FunctionExecutable) };
 
-FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned lastLine, unsigned endColumn, Intrinsic intrinsic)
+static_assert(sizeof(FunctionExecutable) <= 128, "FunctionExecutable should fit in a 128-byte cell since it is so frequently allocated.");
+
+FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic)
     : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext(), unlinkedExecutable->derivedContextType(), false, EvalContextType::None, intrinsic)
     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
 {
     RELEASE_ASSERT(!source.isNull());
     ASSERT(source.length());
-    m_lastLine = lastLine;
-    ASSERT(endColumn != UINT_MAX);
-    m_endColumn = endColumn;
     if (VM::canUseJIT())
         new (&m_singletonFunction) WriteBarrier<InferredValue>();
     else
@@ -111,11 +111,25 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(
 FunctionExecutable::RareData& FunctionExecutable::ensureRareDataSlow()
 {
     ASSERT(!m_rareData);
-    m_rareData = std::make_unique<RareData>();
-    m_rareData->m_parametersStartOffset = m_unlinkedExecutable->parametersStartOffset();
-    m_rareData->m_typeProfilingStartOffset = m_unlinkedExecutable->typeProfilingStartOffset();
-    m_rareData->m_typeProfilingEndOffset = m_unlinkedExecutable->typeProfilingEndOffset();
+    auto rareData = std::make_unique<RareData>();
+    rareData->m_lineCount = lineCount();
+    rareData->m_endColumn = endColumn();
+    rareData->m_parametersStartOffset = parametersStartOffset();
+    rareData->m_typeProfilingStartOffset = typeProfilingStartOffset();
+    rareData->m_typeProfilingEndOffset = typeProfilingEndOffset();
+    m_rareData = WTFMove(rareData);
     return *m_rareData;
 }
 
+void FunctionExecutable::overrideInfo(const FunctionOverrideInfo& overrideInfo)
+{
+    auto& rareData = ensureRareData();
+    m_source = overrideInfo.sourceCode;
+    rareData.m_lineCount = overrideInfo.lineCount;
+    rareData.m_endColumn = overrideInfo.endColumn;
+    rareData.m_parametersStartOffset = overrideInfo.parametersStartOffset;
+    rareData.m_typeProfilingStartOffset = overrideInfo.typeProfilingStartOffset;
+    rareData.m_typeProfilingEndOffset = overrideInfo.typeProfilingEndOffset;
+}
+
 } // namespace JSC
index 3cd1588..7cfedbd 100644 (file)
@@ -33,6 +33,8 @@
 
 namespace JSC {
 
+struct FunctionOverrideInfo;
+
 class FunctionExecutable final : public ScriptExecutable {
     friend class JIT;
     friend class LLIntOffsetsExtractor;
@@ -46,11 +48,9 @@ public:
         return &vm.functionExecutableSpace.space;
     }
 
-    static FunctionExecutable* create(
-        VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, 
-        unsigned lastLine, unsigned endColumn, Intrinsic intrinsic)
+    static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, Intrinsic intrinsic)
     {
-        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, lastLine, endColumn, intrinsic);
+        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, intrinsic);
         executable->finishCreation(vm);
         return executable;
     }
@@ -190,8 +190,37 @@ public:
         return WTF::nullopt;
     }
 
+    int lineCount() const
+    {
+        if (UNLIKELY(m_rareData))
+            return m_rareData->m_lineCount;
+        return m_unlinkedExecutable->lineCount();
+    }
+
+    int endColumn() const
+    {
+        if (UNLIKELY(m_rareData))
+            return m_rareData->m_endColumn;
+        return m_unlinkedExecutable->linkedEndColumn(m_source.startColumn().oneBasedInt());
+    }
+
+    int firstLine() const
+    {
+        return source().firstLine().oneBasedInt();
+    }
+
+    int lastLine() const
+    {
+        return firstLine() + lineCount();
+    }
+
     unsigned typeProfilingStartOffset(VM&) const
     {
+        return typeProfilingStartOffset();
+    }
+
+    unsigned typeProfilingStartOffset() const
+    {
         if (UNLIKELY(m_rareData))
             return m_rareData->m_typeProfilingStartOffset;
         return m_unlinkedExecutable->typeProfilingStartOffset();
@@ -199,6 +228,11 @@ public:
 
     unsigned typeProfilingEndOffset(VM&) const
     {
+        return typeProfilingEndOffset();
+    }
+
+    unsigned typeProfilingEndOffset() const
+    {
         if (UNLIKELY(m_rareData))
             return m_rareData->m_typeProfilingEndOffset;
         return m_unlinkedExecutable->typeProfilingEndOffset();
@@ -211,13 +245,7 @@ public:
         return m_unlinkedExecutable->parametersStartOffset();
     }
 
-    void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
-    {
-        auto& rareData = ensureRareData();
-        rareData.m_parametersStartOffset = parametersStartOffset;
-        rareData.m_typeProfilingStartOffset = typeProfilingStartOffset;
-        rareData.m_typeProfilingEndOffset = typeProfilingEndOffset;
-    }
+    void overrideInfo(const FunctionOverrideInfo&);
 
     DECLARE_INFO;
 
@@ -268,9 +296,7 @@ public:
 
 private:
     friend class ExecutableBase;
-    FunctionExecutable(
-        VM&, const SourceCode&, UnlinkedFunctionExecutable*,
-        unsigned lastLine, unsigned endColumn, Intrinsic);
+    FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic);
     
     void finishCreation(VM&);
 
@@ -278,11 +304,13 @@ private:
 
     struct RareData {
         WTF_MAKE_STRUCT_FAST_ALLOCATED;
+        RefPtr<TypeSet> m_returnStatementTypeSet;
+        unsigned m_lineCount;
+        unsigned m_endColumn;
         Markable<int, IntegralMarkableTraits<int, -1>> m_overrideLineNumber;
         unsigned m_parametersStartOffset { 0 };
         unsigned m_typeProfilingStartOffset { UINT_MAX };
         unsigned m_typeProfilingEndOffset { UINT_MAX };
-        RefPtr<TypeSet> m_returnStatementTypeSet;
     };
 
     RareData& ensureRareData()
diff --git a/Source/JavaScriptCore/runtime/GlobalExecutable.cpp b/Source/JavaScriptCore/runtime/GlobalExecutable.cpp
new file mode 100644 (file)
index 0000000..a0dfe76
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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. 
+ */
+
+#include "config.h"
+#include "GlobalExecutable.h"
+
+namespace JSC {
+
+const ClassInfo GlobalExecutable::s_info = { "GlobalExecutable", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(GlobalExecutable) };
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/GlobalExecutable.h b/Source/JavaScriptCore/runtime/GlobalExecutable.h
new file mode 100644 (file)
index 0000000..0240470
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 "ExecutableToCodeBlockEdge.h"
+#include "ScriptExecutable.h"
+
+namespace JSC {
+
+class GlobalExecutable : public ScriptExecutable {
+public:
+    using Base = ScriptExecutable;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
+    DECLARE_INFO;
+
+    unsigned lastLine() const { return m_lastLine; }
+    unsigned endColumn() const { return m_endColumn; }
+
+    void recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
+    {
+        Base::recordParse(features, hasCapturedVariables);
+        m_lastLine = lastLine;
+        m_endColumn = endColumn;
+        ASSERT(endColumn != UINT_MAX);
+    }
+
+protected:
+    GlobalExecutable(Structure* structure, VM& vm, const SourceCode& sourceCode, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, EvalContextType evalContextType, Intrinsic intrinsic)
+        : Base(structure, vm, sourceCode, isInStrictContext, derivedContextType, isInArrowFunctionContext, evalContextType, intrinsic)
+    {
+    }
+
+    int m_lastLine { -1 };
+    unsigned m_endColumn { UINT_MAX };
+};
+
+} // namespace JSC
index aef3fab..232b418 100644 (file)
 
 namespace JSC {
 
-const ClassInfo ModuleProgramExecutable::s_info = { "ModuleProgramExecutable", &ScriptExecutable::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ModuleProgramExecutable) };
+const ClassInfo ModuleProgramExecutable::s_info = { "ModuleProgramExecutable", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ModuleProgramExecutable) };
 
 ModuleProgramExecutable::ModuleProgramExecutable(ExecState* exec, const SourceCode& source)
-    : ScriptExecutable(exec->vm().moduleProgramExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false, EvalContextType::None, NoIntrinsic)
+    : Base(exec->vm().moduleProgramExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false, EvalContextType::None, NoIntrinsic)
 {
     ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Module);
     VM& vm = exec->vm();
index ff82c28..6d355b7 100644 (file)
 #pragma once
 
 #include "ExecutableToCodeBlockEdge.h"
-#include "ScriptExecutable.h"
+#include "GlobalExecutable.h"
 
 namespace JSC {
 
-class ModuleProgramExecutable final : public ScriptExecutable {
+class ModuleProgramExecutable final : public GlobalExecutable {
     friend class LLIntOffsetsExtractor;
 public:
-    typedef ScriptExecutable Base;
+    using Base = GlobalExecutable;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
     template<typename CellType, SubspaceAccess mode>
index 3578d2a..21623bb 100644 (file)
 
 namespace JSC {
 
-const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ProgramExecutable) };
+const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ProgramExecutable) };
 
 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
-    : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false, EvalContextType::None, NoIntrinsic)
+    : Base(exec->vm().programExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false, EvalContextType::None, NoIntrinsic)
 {
     ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Program);
     VM& vm = exec->vm();
index a1ecd21..6051167 100644 (file)
 #pragma once
 
 #include "ExecutableToCodeBlockEdge.h"
-#include "ScriptExecutable.h"
+#include "GlobalExecutable.h"
 
 namespace JSC {
 
-class ProgramExecutable final : public ScriptExecutable {
+class ProgramExecutable final : public GlobalExecutable {
     friend class LLIntOffsetsExtractor;
 public:
-    typedef ScriptExecutable Base;
+    using Base = GlobalExecutable;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
     template<typename CellType, SubspaceAccess>
index 4e1ef9a..0aae2ee 100644 (file)
@@ -30,6 +30,7 @@
 #include "Debugger.h"
 #include "EvalCodeBlock.h"
 #include "FunctionCodeBlock.h"
+#include "GlobalExecutable.h"
 #include "IsoCellSetInlines.h"
 #include "JIT.h"
 #include "JSCInlines.h"
@@ -68,14 +69,10 @@ void ScriptExecutable::destroy(JSCell* cell)
 
 void ScriptExecutable::clearCode(IsoCellSet& clearableCodeSet)
 {
-#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: {
@@ -180,12 +177,10 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
     case CodeForCall:
         m_jitCodeForCall = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
         m_jitCodeForCallWithArityCheck = nullptr;
-        m_numParametersForCall = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;
         break;
     case CodeForConstruct:
         m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
         m_jitCodeForConstructWithArityCheck = nullptr;
-        m_numParametersForConstruct = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;
         break;
     }
 
@@ -218,13 +213,11 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
 
 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);
@@ -322,7 +315,7 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
     DebuggerMode debuggerMode = globalObject->hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = 
         executable->m_unlinkedExecutable->unlinkedCodeBlockFor(
-            *vm, executable->m_source, kind, debuggerMode, error, 
+            *vm, executable->source(), kind, debuggerMode, error, 
             executable->parseMode());
     recordParse(
         executable->m_unlinkedExecutable->features(), 
@@ -331,7 +324,7 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
     if (!unlinkedCodeBlock) {
         exception = throwException(
             globalObject->globalExec(), throwScope,
-            error.toErrorObject(globalObject, executable->m_source));
+            error.toErrorObject(globalObject, executable->source()));
         return nullptr;
     }
 
@@ -459,7 +452,42 @@ unsigned ScriptExecutable::typeProfilingEndOffset(VM& vm) const
         return jsCast<const FunctionExecutable*>(this)->typeProfilingEndOffset(vm);
     if (inherits<EvalExecutable>(vm))
         return UINT_MAX;
-    return m_source.length() - 1;
+    return source().length() - 1;
+}
+
+void ScriptExecutable::recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
+{
+    switch (type()) {
+    case FunctionExecutableType:
+        // Since UnlinkedFunctionExecutable holds the information to calculate lastLine and endColumn, we do not need to remember them in ScriptExecutable's fields.
+        jsCast<FunctionExecutable*>(this)->recordParse(features, hasCapturedVariables);
+        return;
+    default:
+        jsCast<GlobalExecutable*>(this)->recordParse(features, hasCapturedVariables, lastLine, endColumn);
+        return;
+    }
+}
+
+int ScriptExecutable::lastLine() const
+{
+    switch (type()) {
+    case FunctionExecutableType:
+        return jsCast<const FunctionExecutable*>(this)->lastLine();
+    default:
+        return jsCast<const GlobalExecutable*>(this)->lastLine();
+    }
+    return 0;
+}
+
+unsigned ScriptExecutable::endColumn() const
+{
+    switch (type()) {
+    case FunctionExecutableType:
+        return jsCast<const FunctionExecutable*>(this)->endColumn();
+    default:
+        return jsCast<const GlobalExecutable*>(this)->endColumn();
+    }
+    return 0;
 }
 
 } // namespace JSC
index bc33924..462db80 100644 (file)
@@ -45,9 +45,9 @@ public:
     const SourceOrigin& sourceOrigin() const { return m_source.provider()->sourceOrigin(); }
     const String& sourceURL() const { return m_source.provider()->url(); }
     int firstLine() const { return m_source.firstLine().oneBasedInt(); }
-    int lastLine() const { return m_lastLine; }
+    JS_EXPORT_PRIVATE int lastLine() const;
     unsigned startColumn() const { return m_source.startColumn().oneBasedInt(); }
-    unsigned endColumn() const { return m_endColumn; }
+    JS_EXPORT_PRIVATE unsigned endColumn() const;
 
     Optional<int> overrideLineNumber(VM&) const;
     unsigned typeProfilingStartOffset(VM&) const;
@@ -81,15 +81,7 @@ public:
         
     DECLARE_EXPORT_INFO;
 
-    void recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
-    {
-        m_features = features;
-        m_hasCapturedVariables = hasCapturedVariables;
-        m_lastLine = lastLine;
-        ASSERT(endColumn != UINT_MAX);
-        m_endColumn = endColumn;
-    }
-
+    void recordParse(CodeFeatures, bool hasCapturedVariables, int lastLine, unsigned endColumn);
     void installCode(CodeBlock*);
     void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
     CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, Exception*&);
@@ -102,15 +94,13 @@ public:
         return m_intrinsic;
     }
 
-    static constexpr int NUM_PARAMETERS_NOT_COMPILED = -1;
-
     bool hasJITCodeForCall() const
     {
-        return m_numParametersForCall >= 0;
+        return m_jitCodeForCall;
     }
     bool hasJITCodeForConstruct() const
     {
-        return m_numParametersForConstruct >= 0;
+        return m_jitCodeForConstruct;
     }
 
     // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
@@ -141,14 +131,13 @@ 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 };
+    void recordParse(CodeFeatures features, bool hasCapturedVariables)
+    {
+        m_features = features;
+        m_hasCapturedVariables = hasCapturedVariables;
+    }
 
+    SourceCode m_source;
     Intrinsic m_intrinsic { NoIntrinsic };
     bool m_didTryToEnterInLoop { false };
     CodeFeatures m_features;
index f9790e8..4a42bbc 100644 (file)
@@ -33,18 +33,20 @@ namespace JSC {
 
 class ScriptExecutable;
 
+struct FunctionOverrideInfo {
+    SourceCode sourceCode;
+    unsigned firstLine;
+    unsigned lineCount;
+    unsigned startColumn;
+    unsigned endColumn;
+    unsigned parametersStartOffset;
+    unsigned typeProfilingStartOffset;
+    unsigned typeProfilingEndOffset;
+};
+
 class FunctionOverrides {
 public:
-    struct OverrideInfo {
-        SourceCode sourceCode;
-        unsigned firstLine;
-        unsigned lineCount;
-        unsigned startColumn;
-        unsigned endColumn;
-        unsigned parametersStartOffset;
-        unsigned typeProfilingStartOffset;
-        unsigned typeProfilingEndOffset;
-    };
+    using OverrideInfo = FunctionOverrideInfo;
 
     static FunctionOverrides& overrides();
     FunctionOverrides(const char* functionOverridesFileName);