[JSC] Shrink UnlinkedFunctionExecutable
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Feb 2019 08:58:36 +0000 (08:58 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Feb 2019 08:58:36 +0000 (08:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194733

Reviewed by Mark Lam.

UnlinkedFunctionExecutable has sourceURLDirective and sourceMappingURLDirective. These
directives can be found in the comment of non typical function's source code (Program,
Eval code, and Global function from function constructor etc.), and tricky thing is that
SourceProvider's directives are updated by Parser. The reason why we have these fields in
UnlinkedFunctionExecutable is that we need to update the SourceProvider's directives even
if we skip parsing by using CodeCache. These fields are effective only if (1)
UnlinkedFunctionExecutable is for non typical function things, and (2) it has sourceURLDirective
or sourceMappingURLDirective. This is rare enough to purge them to a separated
UnlinkedFunctionExecutable::RareData to make UnlinkedFunctionExecutable small.
sizeof(UnlinkedFunctionExecutable) is very important since it is super frequently allocated
cell. Furthermore, the current JSC allocates two MarkedBlocks for UnlinkedFunctionExecutable
in JSGlobalObject initialization, but the usage of the second MarkedBlock is quite low (8%).
If we can reduce the size of UnlinkedFunctionExecutable, we can make them one MarkedBlock.
Since UnlinkedFunctionExecutable is allocated from IsoSubspace, we do not need to fit it to
one of size class.

This patch adds RareData to UnlinkedFunctionExecutable and move some rare datas into RareData.
And kill one MarkedBlock allocation in JSC initialization phase.

* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::ensureRareDataSlow):
* bytecode/UnlinkedFunctionExecutable.h:
* debugger/DebuggerLocation.cpp:
(JSC::DebuggerLocation::DebuggerLocation):
* inspector/ScriptDebugServer.cpp:
(Inspector::ScriptDebugServer::dispatchDidParseSource):
* parser/Lexer.h:
(JSC::Lexer::sourceURLDirective const):
(JSC::Lexer::sourceMappingURLDirective const):
(JSC::Lexer::sourceURL const): Deleted.
(JSC::Lexer::sourceMappingURL const): Deleted.
* parser/Parser.h:
(JSC::Parser<LexerType>::parse):
* parser/SourceProvider.h:
(JSC::SourceProvider::sourceURLDirective const):
(JSC::SourceProvider::sourceMappingURLDirective const):
(JSC::SourceProvider::setSourceURLDirective):
(JSC::SourceProvider::setSourceMappingURLDirective):
(JSC::SourceProvider::sourceURL const): Deleted. We rename it from sourceURL to sourceURLDirective
since it is the correct name.
(JSC::SourceProvider::sourceMappingURL const): Deleted. We rename it from sourceMappingURL to
sourceMappingURLDirective since it is the correct name.
* runtime/CachedTypes.cpp:
(JSC::CachedSourceProviderShape::encode):
(JSC::CachedFunctionExecutableRareData::encode):
(JSC::CachedFunctionExecutableRareData::decode const): CachedFunctionExecutable did not have
sourceMappingURL to sourceMappingURLDirective. So this patch keeps the same logic.
(JSC::CachedFunctionExecutable::rareData const):
(JSC::CachedFunctionExecutable::encode):
(JSC::CachedFunctionExecutable::decode const):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* runtime/CodeCache.cpp:
(JSC::CodeCache::getUnlinkedGlobalCodeBlock):
(JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
* runtime/CodeCache.h:
(JSC::generateUnlinkedCodeBlockImpl):
* runtime/FunctionExecutable.h:
* runtime/SamplingProfiler.cpp:
(JSC::SamplingProfiler::StackFrame::url):

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

13 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
Source/JavaScriptCore/debugger/DebuggerLocation.cpp
Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
Source/JavaScriptCore/parser/Lexer.h
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/SourceProvider.h
Source/JavaScriptCore/runtime/CachedTypes.cpp
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CodeCache.h
Source/JavaScriptCore/runtime/FunctionExecutable.h
Source/JavaScriptCore/runtime/SamplingProfiler.cpp

index 73a9d7c..13b3cd5 100644 (file)
@@ -1,3 +1,71 @@
+2019-02-16  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Shrink UnlinkedFunctionExecutable
+        https://bugs.webkit.org/show_bug.cgi?id=194733
+
+        Reviewed by Mark Lam.
+
+        UnlinkedFunctionExecutable has sourceURLDirective and sourceMappingURLDirective. These
+        directives can be found in the comment of non typical function's source code (Program,
+        Eval code, and Global function from function constructor etc.), and tricky thing is that
+        SourceProvider's directives are updated by Parser. The reason why we have these fields in
+        UnlinkedFunctionExecutable is that we need to update the SourceProvider's directives even
+        if we skip parsing by using CodeCache. These fields are effective only if (1)
+        UnlinkedFunctionExecutable is for non typical function things, and (2) it has sourceURLDirective
+        or sourceMappingURLDirective. This is rare enough to purge them to a separated
+        UnlinkedFunctionExecutable::RareData to make UnlinkedFunctionExecutable small.
+        sizeof(UnlinkedFunctionExecutable) is very important since it is super frequently allocated
+        cell. Furthermore, the current JSC allocates two MarkedBlocks for UnlinkedFunctionExecutable
+        in JSGlobalObject initialization, but the usage of the second MarkedBlock is quite low (8%).
+        If we can reduce the size of UnlinkedFunctionExecutable, we can make them one MarkedBlock.
+        Since UnlinkedFunctionExecutable is allocated from IsoSubspace, we do not need to fit it to
+        one of size class.
+
+        This patch adds RareData to UnlinkedFunctionExecutable and move some rare datas into RareData.
+        And kill one MarkedBlock allocation in JSC initialization phase.
+
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        (JSC::UnlinkedFunctionExecutable::ensureRareDataSlow):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * debugger/DebuggerLocation.cpp:
+        (JSC::DebuggerLocation::DebuggerLocation):
+        * inspector/ScriptDebugServer.cpp:
+        (Inspector::ScriptDebugServer::dispatchDidParseSource):
+        * parser/Lexer.h:
+        (JSC::Lexer::sourceURLDirective const):
+        (JSC::Lexer::sourceMappingURLDirective const):
+        (JSC::Lexer::sourceURL const): Deleted.
+        (JSC::Lexer::sourceMappingURL const): Deleted.
+        * parser/Parser.h:
+        (JSC::Parser<LexerType>::parse):
+        * parser/SourceProvider.h:
+        (JSC::SourceProvider::sourceURLDirective const):
+        (JSC::SourceProvider::sourceMappingURLDirective const):
+        (JSC::SourceProvider::setSourceURLDirective):
+        (JSC::SourceProvider::setSourceMappingURLDirective):
+        (JSC::SourceProvider::sourceURL const): Deleted. We rename it from sourceURL to sourceURLDirective
+        since it is the correct name.
+        (JSC::SourceProvider::sourceMappingURL const): Deleted. We rename it from sourceMappingURL to
+        sourceMappingURLDirective since it is the correct name.
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedSourceProviderShape::encode):
+        (JSC::CachedFunctionExecutableRareData::encode):
+        (JSC::CachedFunctionExecutableRareData::decode const): CachedFunctionExecutable did not have
+        sourceMappingURL to sourceMappingURLDirective. So this patch keeps the same logic.
+        (JSC::CachedFunctionExecutable::rareData const):
+        (JSC::CachedFunctionExecutable::encode):
+        (JSC::CachedFunctionExecutable::decode const):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
+        (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
+        * runtime/CodeCache.h:
+        (JSC::generateUnlinkedCodeBlockImpl):
+        * runtime/FunctionExecutable.h:
+        * runtime/SamplingProfiler.cpp:
+        (JSC::SamplingProfiler::StackFrame::url):
+
 2019-02-15  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Remove unused global private variables
index ce71c6f..a142c24 100644 (file)
@@ -42,7 +42,7 @@
 
 namespace JSC {
 
-static_assert(sizeof(UnlinkedFunctionExecutable) <= 160, "UnlinkedFunctionExecutable should fit in a 160-byte cell. If you increase the size of this class, consider making a size class that perfectly fits it.");
+static_assert(sizeof(UnlinkedFunctionExecutable) <= 128, "UnlinkedFunctionExecutable should fit in a 128-byte cell to keep allocated blocks count to only one after initializing JSGlobalObject.");
 
 const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) };
 
@@ -106,7 +106,6 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct
     , m_name(node->ident())
     , m_ecmaName(node->ecmaName())
     , m_inferredName(node->inferredName())
-    , m_classSource(node->classSource())
     , m_parentScopeTDZVariables(WTFMove(parentScopeTDZVariables))
 {
     // Make sure these bitfields are adequately wide.
@@ -117,6 +116,8 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct
     ASSERT(m_superBinding == static_cast<unsigned>(node->superBinding()));
     ASSERT(m_derivedContextType == static_cast<unsigned>(derivedContextType));
     ASSERT(!(m_isBuiltinDefaultClassConstructor && constructorKind() == ConstructorKind::None));
+    if (!node->classSource().isNull())
+        setClassSource(node->classSource());
 }
 
 void UnlinkedFunctionExecutable::destroy(JSCell* cell)
@@ -243,6 +244,13 @@ UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::unlinkedCodeBlockFor(
     return result;
 }
 
+UnlinkedFunctionExecutable::RareData& UnlinkedFunctionExecutable::ensureRareDataSlow()
+{
+    ASSERT(!m_rareData);
+    m_rareData = std::make_unique<RareData>();
+    return *m_rareData;
+}
+
 void UnlinkedFunctionExecutable::setInvalidTypeProfilingOffsets()
 {
     m_typeProfilingStartOffset = std::numeric_limits<unsigned>::max();
index 7738152..defd2f0 100644 (file)
@@ -56,7 +56,7 @@ class UnlinkedFunctionExecutable final : public JSCell {
 public:
     friend class CodeCache;
     friend class VM;
-    friend CachedFunctionExecutable;
+    friend class CachedFunctionExecutable;
 
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
@@ -82,8 +82,16 @@ public:
     unsigned parameterCount() const { return m_parameterCount; }; // Excluding 'this'!
     SourceParseMode parseMode() const { return static_cast<SourceParseMode>(m_sourceParseMode); };
 
-    const SourceCode& classSource() const { return m_classSource; };
-    void setClassSource(const SourceCode& source) { m_classSource = source; };
+    SourceCode classSource() const
+    {
+        if (m_rareData)
+            return m_rareData->m_classSource;
+        return SourceCode();
+    }
+    void setClassSource(const SourceCode& source)
+    {
+        ensureRareData().m_classSource = source;
+    }
 
     bool isInStrictContext() const { return m_isInStrictContext; }
     FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
@@ -140,16 +148,46 @@ public:
     ConstructAbility constructAbility() const { return static_cast<ConstructAbility>(m_constructAbility); }
     JSParserScriptMode scriptMode() const { return static_cast<JSParserScriptMode>(m_scriptMode); }
     bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; }
+    bool isClass() const
+    {
+        if (!m_rareData)
+            return false;
+        return !m_rareData->m_classSource.isNull();
+    }
     VariableEnvironment parentScopeTDZVariables() const { return m_parentScopeTDZVariables.environment().toVariableEnvironment(); }
     
     bool isArrowFunction() const { return isArrowFunctionParseMode(parseMode()); }
 
     JSC::DerivedContextType derivedContextType() const {return static_cast<JSC::DerivedContextType>(m_derivedContextType); }
 
-    const String& sourceURLDirective() const { return m_sourceURLDirective; }
-    const String& sourceMappingURLDirective() const { return m_sourceMappingURLDirective; }
-    void setSourceURLDirective(const String& sourceURL) { m_sourceURLDirective = sourceURL; }
-    void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL; }
+    String sourceURLDirective() const
+    {
+        if (m_rareData)
+            return m_rareData->m_sourceURLDirective;
+        return String();
+    }
+    String sourceMappingURLDirective() const
+    {
+        if (m_rareData)
+            return m_rareData->m_sourceMappingURLDirective;
+        return String();
+    }
+    void setSourceURLDirective(const String& sourceURL)
+    {
+        ensureRareData().m_sourceURLDirective = sourceURL;
+    }
+    void setSourceMappingURLDirective(const String& sourceMappingURL)
+    {
+        ensureRareData().m_sourceMappingURLDirective = sourceMappingURL;
+    }
+
+    struct RareData {
+        WTF_MAKE_STRUCT_FAST_ALLOCATED;
+
+        SourceCode m_classSource;
+        String m_sourceURLDirective;
+        String m_sourceMappingURLDirective;
+    };
 
 private:
     UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, CompactVariableMap::Handle,  JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
@@ -185,12 +223,17 @@ private:
     Identifier m_name;
     Identifier m_ecmaName;
     Identifier m_inferredName;
-    SourceCode m_classSource;
 
-    String m_sourceURLDirective;
-    String m_sourceMappingURLDirective;
+    RareData& ensureRareData()
+    {
+        if (LIKELY(m_rareData))
+            return *m_rareData;
+        return ensureRareDataSlow();
+    }
+    RareData& ensureRareDataSlow();
 
     CompactVariableMap::Handle m_parentScopeTDZVariables;
+    std::unique_ptr<RareData> m_rareData;
 
 protected:
     static void visitChildren(JSCell*, SlotVisitor&);
index b139720..c689b93 100644 (file)
@@ -40,7 +40,7 @@ DebuggerLocation::DebuggerLocation(ScriptExecutable* executable)
     column = executable->startColumn();
     url = executable->sourceURL();
     if (url.isEmpty())
-        url = executable->source().provider()->sourceURL();
+        url = executable->source().provider()->sourceURLDirective();
 }
 
 } // namespace JSC
index 35ef25b..e0a065c 100644 (file)
@@ -195,8 +195,8 @@ void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, Sou
     script.startLine = sourceProvider->startPosition().m_line.zeroBasedInt();
     script.startColumn = sourceProvider->startPosition().m_column.zeroBasedInt();
     script.isContentScript = isContentScript;
-    script.sourceURL = sourceProvider->sourceURL();
-    script.sourceMappingURL = sourceProvider->sourceMappingURL();
+    script.sourceURL = sourceProvider->sourceURLDirective();
+    script.sourceMappingURL = sourceProvider->sourceMappingURLDirective();
 
     int sourceLength = script.source.length();
     int lineCount = 1;
index 80189d0..700d1a7 100644 (file)
@@ -87,8 +87,8 @@ public:
     void setSawError(bool sawError) { m_error = sawError; }
     String getErrorMessage() const { return m_lexErrorMessage; }
     void setErrorMessage(const String& errorMessage) { m_lexErrorMessage = errorMessage; }
-    String sourceURL() const { return m_sourceURLDirective; }
-    String sourceMappingURL() const { return m_sourceMappingURLDirective; }
+    String sourceURLDirective() const { return m_sourceURLDirective; }
+    String sourceMappingURLDirective() const { return m_sourceMappingURLDirective; }
     void clear();
     void setOffset(int offset, int lineStartOffset)
     {
index 1c1a8d9..d1f9434 100644 (file)
@@ -1938,8 +1938,8 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I
         result->setEndOffset(m_lexer->currentOffset());
 
         if (!isFunctionParseMode(parseMode)) {
-            m_source->provider()->setSourceURLDirective(m_lexer->sourceURL());
-            m_source->provider()->setSourceMappingURLDirective(m_lexer->sourceMappingURL());
+            m_source->provider()->setSourceURLDirective(m_lexer->sourceURLDirective());
+            m_source->provider()->setSourceMappingURLDirective(m_lexer->sourceMappingURLDirective());
         }
     } else {
         // We can never see a syntax error when reparsing a function, since we should have
index b3c9c46..bff521c 100644 (file)
@@ -125,8 +125,8 @@ namespace JSC {
 
         const SourceOrigin& sourceOrigin() const { return m_sourceOrigin; }
         const URL& url() const { return m_url; }
-        const String& sourceURL() const { return m_sourceURLDirective; }
-        const String& sourceMappingURL() const { return m_sourceMappingURLDirective; }
+        const String& sourceURLDirective() const { return m_sourceURLDirective; }
+        const String& sourceMappingURLDirective() const { return m_sourceMappingURLDirective; }
 
         TextPosition startPosition() const { return m_startPosition; }
         SourceProviderSourceType sourceType() const { return m_sourceType; }
@@ -138,8 +138,8 @@ namespace JSC {
             return m_id;
         }
 
-        void setSourceURLDirective(const String& sourceURL) { m_sourceURLDirective = sourceURL; }
-        void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL; }
+        void setSourceURLDirective(const String& sourceURLDirective) { m_sourceURLDirective = sourceURLDirective; }
+        void setSourceMappingURLDirective(const String& sourceMappingURLDirective) { m_sourceMappingURLDirective = sourceMappingURLDirective; }
 
     private:
         JS_EXPORT_PRIVATE void getID();
index 610a83b..8a1dde3 100644 (file)
@@ -1266,8 +1266,8 @@ public:
     {
         m_sourceOrigin.encode(encoder, sourceProvider.sourceOrigin());
         m_url.encode(encoder, sourceProvider.url());
-        m_sourceURLDirective.encode(encoder, sourceProvider.sourceURL());
-        m_sourceMappingURLDirective.encode(encoder, sourceProvider.sourceMappingURL());
+        m_sourceURLDirective.encode(encoder, sourceProvider.sourceURLDirective());
+        m_sourceMappingURLDirective.encode(encoder, sourceProvider.sourceMappingURLDirective());
         m_startPosition.encode(encoder, sourceProvider.startPosition());
     }
 
@@ -1429,6 +1429,24 @@ private:
     int m_startColumn;
 };
 
+class CachedFunctionExecutableRareData : public CachedObject<UnlinkedFunctionExecutable::RareData> {
+public:
+    void encode(Encoder& encoder, const UnlinkedFunctionExecutable::RareData& rareData)
+    {
+        m_classSource.encode(encoder, rareData.m_classSource);
+    }
+
+    UnlinkedFunctionExecutable::RareData* decode(Decoder& decoder) const
+    {
+        UnlinkedFunctionExecutable::RareData* rareData = new UnlinkedFunctionExecutable::RareData { };
+        m_classSource.decode(decoder, rareData->m_classSource);
+        return rareData;
+    }
+
+private:
+    CachedSourceCode m_classSource;
+};
+
 class CachedFunctionExecutable : public CachedObject<UnlinkedFunctionExecutable> {
 public:
     void encode(Encoder&, const UnlinkedFunctionExecutable&);
@@ -1464,6 +1482,8 @@ public:
     Identifier ecmaName(Decoder& decoder) const { return m_ecmaName.decode(decoder); }
     Identifier inferredName(Decoder& decoder) const { return m_inferredName.decode(decoder); }
 
+    UnlinkedFunctionExecutable::RareData* rareData(Decoder& decoder) const { return m_rareData.decodeAsPtr(decoder); }
+
 private:
     unsigned m_firstLineOffset;
     unsigned m_lineCount;
@@ -1489,7 +1509,7 @@ private:
     unsigned m_superBinding : 1;
     unsigned m_derivedContextType: 2;
 
-    CachedSourceCode m_classSource;
+    CachedOptional<CachedFunctionExecutableRareData> m_rareData;
 
     CachedIdentifier m_name;
     CachedIdentifier m_ecmaName;
@@ -1824,7 +1844,7 @@ ALWAYS_INLINE void CachedFunctionExecutable::encode(Encoder& encoder, const Unli
     m_superBinding = executable.m_superBinding;
     m_derivedContextType = executable.m_derivedContextType;
 
-    m_classSource.encode(encoder, executable.m_classSource);
+    m_rareData.encode(encoder, executable.m_rareData);
 
     m_name.encode(encoder, executable.name());
     m_ecmaName.encode(encoder, executable.ecmaName());
@@ -1844,7 +1864,6 @@ ALWAYS_INLINE UnlinkedFunctionExecutable* CachedFunctionExecutable::decode(Decod
     UnlinkedFunctionExecutable* executable = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(decoder.vm().heap)) UnlinkedFunctionExecutable(decoder, env, *this);
     executable->finishCreation(decoder.vm());
 
-    m_classSource.decode(decoder, executable->m_classSource);
     m_unlinkedCodeBlockForCall.decode(decoder, executable->m_unlinkedCodeBlockForCall, executable);
     m_unlinkedCodeBlockForConstruct.decode(decoder, executable->m_unlinkedCodeBlockForConstruct, executable);
 
@@ -1882,6 +1901,8 @@ ALWAYS_INLINE UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(Decoder& de
     , m_inferredName(cachedExecutable.inferredName(decoder))
 
     , m_parentScopeTDZVariables(decoder.vm().m_compactVariableMap->get(parentScopeTDZVariables))
+
+    , m_rareData(cachedExecutable.rareData(decoder))
 {
 }
 
index f1ea777..6fc02f8 100644 (file)
@@ -70,8 +70,10 @@ UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableT
         bool endColumnIsOnStartLine = !lineCount;
         unsigned endColumn = unlinkedCodeBlock->endColumn() + (endColumnIsOnStartLine ? startColumn : 1);
         executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), source.firstLine().oneBasedInt() + lineCount, endColumn);
-        source.provider()->setSourceURLDirective(unlinkedCodeBlock->sourceURLDirective());
-        source.provider()->setSourceMappingURLDirective(unlinkedCodeBlock->sourceMappingURLDirective());
+        if (!unlinkedCodeBlock->sourceURLDirective().isNull())
+            source.provider()->setSourceURLDirective(unlinkedCodeBlock->sourceURLDirective());
+        if (!unlinkedCodeBlock->sourceMappingURLDirective().isNull())
+            source.provider()->setSourceMappingURLDirective(unlinkedCodeBlock->sourceMappingURLDirective());
         return unlinkedCodeBlock;
     }
 
@@ -115,8 +117,10 @@ UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v
         functionConstructorParametersEndPosition);
     UnlinkedFunctionExecutable* executable = m_sourceCode.findCacheAndUpdateAge<UnlinkedFunctionExecutable>(vm, key);
     if (executable && Options::useCodeCache()) {
-        source.provider()->setSourceURLDirective(executable->sourceURLDirective());
-        source.provider()->setSourceMappingURLDirective(executable->sourceMappingURLDirective());
+        if (!executable->sourceURLDirective().isNull())
+            source.provider()->setSourceURLDirective(executable->sourceURLDirective());
+        if (!executable->sourceMappingURLDirective().isNull())
+            source.provider()->setSourceMappingURLDirective(executable->sourceMappingURLDirective());
         return executable;
     }
 
@@ -149,8 +153,10 @@ UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v
     ConstructAbility constructAbility = constructAbilityForParseMode(metadata->parseMode());
     UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, vm.m_compactVariableMap->get(emptyTDZVariables), DerivedContextType::None);
 
-    functionExecutable->setSourceURLDirective(source.provider()->sourceURL());
-    functionExecutable->setSourceMappingURLDirective(source.provider()->sourceMappingURL());
+    if (!source.provider()->sourceURLDirective().isNull())
+        functionExecutable->setSourceURLDirective(source.provider()->sourceURLDirective());
+    if (!source.provider()->sourceMappingURLDirective().isNull())
+        functionExecutable->setSourceMappingURLDirective(source.provider()->sourceMappingURLDirective());
 
     if (Options::useCodeCache())
         m_sourceCode.addCache(key, SourceCodeValue(vm, functionExecutable, m_sourceCode.age()));
index 45938e6..2befc63 100644 (file)
@@ -297,8 +297,10 @@ UnlinkedCodeBlockType* generateUnlinkedCodeBlockImpl(VM& vm, const SourceCode& s
 
     UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executableInfo, debuggerMode);
     unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), lineCount, unlinkedEndColumn);
-    unlinkedCodeBlock->setSourceURLDirective(source.provider()->sourceURL());
-    unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURL());
+    if (!source.provider()->sourceURLDirective().isNull())
+        unlinkedCodeBlock->setSourceURLDirective(source.provider()->sourceURLDirective());
+    if (!source.provider()->sourceMappingURLDirective().isNull())
+        unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURLDirective());
 
     error = BytecodeGenerator::generate(vm, rootNode.get(), source, unlinkedCodeBlock, debuggerMode, variablesUnderTDZ);
 
index 0e18829..3cd1588 100644 (file)
@@ -132,7 +132,7 @@ public:
     FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
     bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
     ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
-    bool isClass() const { return !classSource().isNull(); }
+    bool isClass() const { return m_unlinkedExecutable->isClass(); }
     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
     bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
     bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
@@ -165,7 +165,7 @@ public:
     unsigned parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
     SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
     JSParserScriptMode scriptMode() const { return m_unlinkedExecutable->scriptMode(); }
-    const SourceCode& classSource() const { return m_unlinkedExecutable->classSource(); }
+    SourceCode classSource() const { return m_unlinkedExecutable->classSource(); }
 
     static void visitChildren(JSCell*, SlotVisitor&);
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
index 4588df5..372e059 100644 (file)
@@ -863,7 +863,7 @@ String SamplingProfiler::StackFrame::url()
 
     String url = static_cast<ScriptExecutable*>(executable)->sourceURL();
     if (url.isEmpty())
-        return static_cast<ScriptExecutable*>(executable)->source().provider()->sourceURL(); // Fall back to sourceURL directive.
+        return static_cast<ScriptExecutable*>(executable)->source().provider()->sourceURLDirective(); // Fall back to sourceURL directive.
     return url;
 }