Title: [246060] trunk/Source/_javascript_Core
Revision
246060
Author
[email protected]
Date
2019-06-04 04:14:10 -0700 (Tue, 04 Jun 2019)

Log Message

JSScript should not keep bytecode cache in memory
https://bugs.webkit.org/show_bug.cgi?id=198482

Reviewed by Saam Barati.

When JSScript writes to the cache, we keep the in-memory serialized bytecode alive.
Instead, we should only ever hold the memory mapped bytecode cache to avoid using
too much memory.

* API/JSScript.mm:
(-[JSScript writeCache:]):
* API/tests/testapi.mm:
(testBytecodeCacheWithSyntaxError):
* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* jsc.cpp:
* parser/SourceProvider.h:
* runtime/BytecodeCacheError.cpp: Added.
(JSC::BytecodeCacheError::StandardError::isValid const):
(JSC::BytecodeCacheError::StandardError::message const):
(JSC::BytecodeCacheError::WriteError::isValid const):
(JSC::BytecodeCacheError::WriteError::message const):
(JSC::BytecodeCacheError::operator=):
(JSC::BytecodeCacheError::isValid const):
(JSC::BytecodeCacheError::message const):
* runtime/BytecodeCacheError.h: Added.
(JSC::BytecodeCacheError::StandardError::StandardError):
(JSC::BytecodeCacheError::WriteError::WriteError):
* runtime/CachedBytecode.h:
(JSC::CachedBytecode::create):
* runtime/CachedTypes.cpp:
(JSC::Encoder::Encoder):
(JSC::Encoder::release):
(JSC::Encoder::releaseMapped):
(JSC::encodeCodeBlock):
(JSC::encodeFunctionCodeBlock):
* runtime/CachedTypes.h:
* runtime/CodeCache.cpp:
(JSC::serializeBytecode):
* runtime/CodeCache.h:
* runtime/Completion.cpp:
(JSC::generateProgramBytecode):
(JSC::generateModuleBytecode):
* runtime/Completion.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSScript.mm (246059 => 246060)


--- trunk/Source/_javascript_Core/API/JSScript.mm	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/API/JSScript.mm	2019-06-04 11:14:10 UTC (rev 246060)
@@ -27,6 +27,7 @@
 #import "JSScriptInternal.h"
 
 #import "APICast.h"
+#import "BytecodeCacheError.h"
 #import "CachedTypes.h"
 #import "CodeCache.h"
 #import "Identifier.h"
@@ -35,7 +36,6 @@
 #import "JSSourceCode.h"
 #import "JSValuePrivate.h"
 #import "JSVirtualMachineInternal.h"
-#import "ParserError.h"
 #import "Symbol.h"
 #include <sys/stat.h>
 #include <wtf/FileMetadata.h>
@@ -277,32 +277,21 @@
         close(fd);
     });
 
-    JSC::ParserError parserError;
+    JSC::BytecodeCacheError cacheError;
     JSC::SourceCode sourceCode = [self sourceCode];
     switch (m_type) {
     case kJSScriptTypeModule:
-        m_cachedBytecode = JSC::generateModuleBytecode(m_virtualMachine.vm, sourceCode, parserError);
+        m_cachedBytecode = JSC::generateModuleBytecode(m_virtualMachine.vm, sourceCode, fd, cacheError);
         break;
     case kJSScriptTypeProgram:
-        m_cachedBytecode = JSC::generateProgramBytecode(m_virtualMachine.vm, sourceCode, parserError);
+        m_cachedBytecode = JSC::generateProgramBytecode(m_virtualMachine.vm, sourceCode, fd, cacheError);
         break;
     }
 
-    if (parserError.isValid()) {
+    if (cacheError.isValid()) {
         m_cachedBytecode = JSC::CachedBytecode::create();
-        error = makeString("Unable to generate bytecode for this JSScript because of a parser error: ", parserError.message());
-        return NO;
-    }
-
-    ssize_t bytesWritten = write(fd, m_cachedBytecode->data(), m_cachedBytecode->size());
-    if (bytesWritten == -1) {
-        error = makeString("Could not write cache file to disk: ", strerror(errno));
-        return NO;
-    }
-
-    if (static_cast<size_t>(bytesWritten) != m_cachedBytecode->size()) {
         ftruncate(fd, 0);
-        error = makeString("Could not write the full cache file to disk. Only wrote ", String::number(bytesWritten), " of the expected ", String::number(m_cachedBytecode->size()), " bytes.");
+        error = makeString("Unable to generate bytecode for this JSScript because: ", cacheError.message());
         return NO;
     }
 

Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (246059 => 246060)


--- trunk/Source/_javascript_Core/API/tests/testapi.mm	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm	2019-06-04 11:14:10 UTC (rev 246060)
@@ -2197,7 +2197,7 @@
         if ([script cacheBytecodeWithError:&error])
             CRASH();
         RELEASE_ASSERT(error);
-        checkResult(@"Got error when trying to cache bytecode for a script with a syntax error.", [[error description] containsString:@"Unable to generate bytecode for this JSScript because of a parser error"]);
+        checkResult(@"Got error when trying to cache bytecode for a script with a syntax error.", [[error description] containsString:@"Unable to generate bytecode for this JSScript because"]);
     }
 }
 

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (246059 => 246060)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2019-06-04 11:14:10 UTC (rev 246060)
@@ -751,6 +751,7 @@
     runtime/BooleanPrototype.h
     runtime/Butterfly.h
     runtime/ButterflyInlines.h
+    runtime/BytecodeCacheError.h
     runtime/CachePayload.h
     runtime/CacheUpdate.h
     runtime/CachedBytecode.h

Modified: trunk/Source/_javascript_Core/ChangeLog (246059 => 246060)


--- trunk/Source/_javascript_Core/ChangeLog	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-06-04 11:14:10 UTC (rev 246060)
@@ -1,3 +1,51 @@
+2019-06-04  Tadeu Zagallo  <[email protected]>
+
+        JSScript should not keep bytecode cache in memory
+        https://bugs.webkit.org/show_bug.cgi?id=198482
+
+        Reviewed by Saam Barati.
+
+        When JSScript writes to the cache, we keep the in-memory serialized bytecode alive.
+        Instead, we should only ever hold the memory mapped bytecode cache to avoid using
+        too much memory.
+
+        * API/JSScript.mm:
+        (-[JSScript writeCache:]):
+        * API/tests/testapi.mm:
+        (testBytecodeCacheWithSyntaxError):
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * jsc.cpp:
+        * parser/SourceProvider.h:
+        * runtime/BytecodeCacheError.cpp: Added.
+        (JSC::BytecodeCacheError::StandardError::isValid const):
+        (JSC::BytecodeCacheError::StandardError::message const):
+        (JSC::BytecodeCacheError::WriteError::isValid const):
+        (JSC::BytecodeCacheError::WriteError::message const):
+        (JSC::BytecodeCacheError::operator=):
+        (JSC::BytecodeCacheError::isValid const):
+        (JSC::BytecodeCacheError::message const):
+        * runtime/BytecodeCacheError.h: Added.
+        (JSC::BytecodeCacheError::StandardError::StandardError):
+        (JSC::BytecodeCacheError::WriteError::WriteError):
+        * runtime/CachedBytecode.h:
+        (JSC::CachedBytecode::create):
+        * runtime/CachedTypes.cpp:
+        (JSC::Encoder::Encoder):
+        (JSC::Encoder::release):
+        (JSC::Encoder::releaseMapped):
+        (JSC::encodeCodeBlock):
+        (JSC::encodeFunctionCodeBlock):
+        * runtime/CachedTypes.h:
+        * runtime/CodeCache.cpp:
+        (JSC::serializeBytecode):
+        * runtime/CodeCache.h:
+        * runtime/Completion.cpp:
+        (JSC::generateProgramBytecode):
+        (JSC::generateModuleBytecode):
+        * runtime/Completion.h:
+
 2019-06-03  Caio Lima  <[email protected]>
 
         [ESNext][BigInt] Implement support for "**"

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (246059 => 246060)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-06-04 11:14:10 UTC (rev 246060)
@@ -772,6 +772,7 @@
 		142E313B134FF0A600AFADB5 /* Strong.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3132134FF0A600AFADB5 /* Strong.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		142E313C134FF0A600AFADB5 /* Weak.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3133134FF0A600AFADB5 /* Weak.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		142F16E021558802003D49C9 /* MetadataTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 142F16DF215585C8003D49C9 /* MetadataTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		1435952122A521CD00E8086D /* BytecodeCacheError.h in Headers */ = {isa = PBXBuildFile; fileRef = 1435951F22A521CA00E8086D /* BytecodeCacheError.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		14386A751DD69895008652C4 /* DirectEvalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14386A731DD69895008652C4 /* DirectEvalExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		14386A791DD6989C008652C4 /* IndirectEvalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1440057F0A5335640005F061 /* JSNode.c in Sources */ = {isa = PBXBuildFile; fileRef = 1440F6420A4F8B6A0005F061 /* JSNode.c */; };
@@ -3190,6 +3191,8 @@
 		142E3133134FF0A600AFADB5 /* Weak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Weak.h; sourceTree = "<group>"; };
 		142F16DF215585C8003D49C9 /* MetadataTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetadataTable.h; sourceTree = "<group>"; };
 		142F16E921583B5E003D49C9 /* CodeBlockInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockInlines.h; sourceTree = "<group>"; };
+		1435951F22A521CA00E8086D /* BytecodeCacheError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BytecodeCacheError.h; sourceTree = "<group>"; };
+		1435952022A521CA00E8086D /* BytecodeCacheError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeCacheError.cpp; sourceTree = "<group>"; };
 		14386A721DD69895008652C4 /* DirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectEvalExecutable.cpp; sourceTree = "<group>"; };
 		14386A731DD69895008652C4 /* DirectEvalExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectEvalExecutable.h; sourceTree = "<group>"; };
 		14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndirectEvalExecutable.cpp; sourceTree = "<group>"; };
@@ -6755,6 +6758,8 @@
 				9E729409190F0306001A91B5 /* BundlePath.mm */,
 				0FB7F38B15ED8E3800F167B2 /* Butterfly.h */,
 				0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
+				1435952022A521CA00E8086D /* BytecodeCacheError.cpp */,
+				1435951F22A521CA00E8086D /* BytecodeCacheError.h */,
 				148B1419225DD1E900D6E998 /* CachedBytecode.cpp */,
 				144CA34F221F037900817789 /* CachedBytecode.h */,
 				14DAFA4521E3B871004B68F7 /* CachedTypes.cpp */,
@@ -8776,6 +8781,7 @@
 				0FB7F39715ED8E4600F167B2 /* Butterfly.h in Headers */,
 				0FB7F39815ED8E4600F167B2 /* ButterflyInlines.h in Headers */,
 				C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */,
+				1435952122A521CD00E8086D /* BytecodeCacheError.h in Headers */,
 				0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */,
 				E3D877741E65C0A000BE945A /* BytecodeDumper.h in Headers */,
 				969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (246059 => 246060)


--- trunk/Source/_javascript_Core/Sources.txt	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-06-04 11:14:10 UTC (rev 246060)
@@ -718,6 +718,7 @@
 runtime/BooleanConstructor.cpp
 runtime/BooleanObject.cpp
 runtime/BooleanPrototype.cpp
+runtime/BytecodeCacheError.cpp
 runtime/CallData.cpp
 runtime/CachePayload.cpp
 runtime/CacheUpdate.cpp

Modified: trunk/Source/_javascript_Core/jsc.cpp (246059 => 246060)


--- trunk/Source/_javascript_Core/jsc.cpp	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/jsc.cpp	2019-06-04 11:14:10 UTC (rev 246060)
@@ -26,6 +26,7 @@
 #include "ArrayPrototype.h"
 #include "BuiltinNames.h"
 #include "ButterflyInlines.h"
+#include "BytecodeCacheError.h"
 #include "CatchScope.h"
 #include "CodeBlock.h"
 #include "CodeCache.h"
@@ -981,8 +982,10 @@
     {
         if (!cacheEnabled() || !m_cachedBytecode)
             return;
-        Ref<CachedBytecode> cachedBytecode = encodeFunctionCodeBlock(*executable->vm(), codeBlock);
-        m_cachedBytecode->addFunctionUpdate(executable, kind, WTFMove(cachedBytecode));
+        BytecodeCacheError error;
+        RefPtr<CachedBytecode> cachedBytecode = encodeFunctionCodeBlock(*executable->vm(), codeBlock, error);
+        if (cachedBytecode && !error.isValid())
+            m_cachedBytecode->addFunctionUpdate(executable, kind, *cachedBytecode);
     }
 
     void cacheBytecode(const BytecodeCacheGenerator& generator) const override
@@ -991,7 +994,9 @@
             return;
         if (!m_cachedBytecode)
             m_cachedBytecode = CachedBytecode::create();
-        m_cachedBytecode->addGlobalUpdate(generator());
+        auto update = generator();
+        if (update)
+            m_cachedBytecode->addGlobalUpdate(*update);
     }
 
     void commitCachedBytecode() const override

Modified: trunk/Source/_javascript_Core/parser/SourceProvider.h (246059 => 246060)


--- trunk/Source/_javascript_Core/parser/SourceProvider.h	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/parser/SourceProvider.h	2019-06-04 11:14:10 UTC (rev 246060)
@@ -48,7 +48,7 @@
         WebAssembly,
     };
 
-    using BytecodeCacheGenerator = Function<Ref<CachedBytecode>()>;
+    using BytecodeCacheGenerator = Function<RefPtr<CachedBytecode>()>;
 
     class SourceProvider : public RefCounted<SourceProvider> {
     public:

Added: trunk/Source/_javascript_Core/runtime/BytecodeCacheError.cpp (0 => 246060)


--- trunk/Source/_javascript_Core/runtime/BytecodeCacheError.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/BytecodeCacheError.cpp	2019-06-04 11:14:10 UTC (rev 246060)
@@ -0,0 +1,83 @@
+/*
+ * 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 "BytecodeCacheError.h"
+
+namespace JSC {
+
+bool BytecodeCacheError::StandardError::isValid() const
+{
+    return true;
+}
+
+String BytecodeCacheError::StandardError::message() const
+{
+    return strerror(m_errno);
+}
+
+bool BytecodeCacheError::WriteError::isValid() const
+{
+    return true;
+}
+
+String BytecodeCacheError::WriteError::message() const
+{
+    return makeString("Could not write the full cache file to disk. Only wrote ", String::number(m_written), " of the expected ", String::number(m_expected), " bytes.");
+}
+
+BytecodeCacheError& BytecodeCacheError::operator=(const ParserError& error)
+{
+    m_error = error;
+    return *this;
+}
+
+BytecodeCacheError& BytecodeCacheError::operator=(const StandardError& error)
+{
+    m_error = error;
+    return *this;
+}
+
+BytecodeCacheError& BytecodeCacheError::operator=(const WriteError& error)
+{
+    m_error = error;
+    return *this;
+}
+
+bool BytecodeCacheError::isValid() const
+{
+    return WTF::switchOn(m_error, [](const auto& error) {
+        return error.isValid();
+    });
+}
+
+String BytecodeCacheError::message() const
+{
+    return WTF::switchOn(m_error, [](const auto& error) {
+        return error.message();
+    });
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/BytecodeCacheError.h (0 => 246060)


--- trunk/Source/_javascript_Core/runtime/BytecodeCacheError.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/BytecodeCacheError.h	2019-06-04 11:14:10 UTC (rev 246060)
@@ -0,0 +1,79 @@
+/*
+ * 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 "JSGlobalObject.h"
+#include "JSSourceCode.h"
+#include "ParserError.h"
+#include <wtf/Variant.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class BytecodeCacheError {
+public:
+    class StandardError {
+    public:
+        StandardError(int error)
+            : m_errno(error)
+        {
+        }
+
+        bool isValid() const;
+        String message() const;
+
+    private:
+        int m_errno;
+    };
+
+    class WriteError {
+    public:
+        WriteError(size_t written, size_t expected)
+            : m_written(written)
+            , m_expected(expected)
+        {
+        }
+
+        bool isValid() const;
+        String message() const;
+
+    private:
+        size_t m_written;
+        size_t m_expected;
+    };
+
+    JS_EXPORT_PRIVATE BytecodeCacheError& operator=(const ParserError&);
+    JS_EXPORT_PRIVATE BytecodeCacheError& operator=(const StandardError&);
+    JS_EXPORT_PRIVATE BytecodeCacheError& operator=(const WriteError&);
+
+    JS_EXPORT_PRIVATE bool isValid() const;
+    JS_EXPORT_PRIVATE String message() const;
+
+private:
+    Variant<ParserError, StandardError, WriteError> m_error;
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/CachedBytecode.h (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/CachedBytecode.h	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/CachedBytecode.h	2019-06-04 11:14:10 UTC (rev 246060)
@@ -47,9 +47,9 @@
     }
 
 #if !OS(WINDOWS)
-    static Ref<CachedBytecode> create(void* data, size_t size)
+    static Ref<CachedBytecode> create(void* data, size_t size, LeafExecutableMap&& leafExecutables = { })
     {
-        return adoptRef(*new CachedBytecode(CachePayload::makeMappedPayload(data, size)));
+        return adoptRef(*new CachedBytecode(CachePayload::makeMappedPayload(data, size), WTFMove(leafExecutables)));
     }
 #endif
 

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.cpp (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2019-06-04 11:14:10 UTC (rev 246060)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "CachedTypes.h"
 
+#include "BytecodeCacheError.h"
 #include "BytecodeCacheVersion.h"
 #include "BytecodeLivenessAnalysis.h"
 #include "JSCInlines.h"
@@ -87,8 +88,9 @@
         ptrdiff_t m_offset;
     };
 
-    Encoder(VM& vm)
+    Encoder(VM& vm, int fd = -1)
         : m_vm(vm)
+        , m_fd(fd)
         , m_baseOffset(0)
         , m_currentPage(nullptr)
     {
@@ -144,12 +146,20 @@
         m_leafExecutables.add(executable, offset);
     }
 
-    Ref<CachedBytecode> release()
+    RefPtr<CachedBytecode> release(BytecodeCacheError& error)
     {
         if (!m_currentPage)
-            return CachedBytecode::create();
+            return nullptr;
+        m_currentPage->alignEnd();
 
-        m_currentPage->alignEnd();
+        if (m_fd != -1) {
+#if !OS(WINDOWS)
+            return releaseMapped(error);
+#else
+            RELEASE_ASSERT_NOT_REACHED();
+#endif
+        }
+
         size_t size = m_baseOffset + m_currentPage->size();
         MallocPtr<uint8_t> buffer = MallocPtr<uint8_t>::malloc(size);
         unsigned offset = 0;
@@ -162,6 +172,38 @@
     }
 
 private:
+#if !OS(WINDOWS)
+    RefPtr<CachedBytecode> releaseMapped(BytecodeCacheError& error)
+    {
+        size_t size = m_baseOffset + m_currentPage->size();
+        if (ftruncate(m_fd, size)) {
+            error = BytecodeCacheError::StandardError(errno);
+            return nullptr;
+        }
+
+        for (const auto& page : m_pages) {
+            ssize_t bytesWritten = write(m_fd, page.buffer(), page.size());
+            if (bytesWritten == -1) {
+                error = BytecodeCacheError::StandardError(errno);
+                return nullptr;
+            }
+
+            if (static_cast<size_t>(bytesWritten) != page.size()) {
+                error = BytecodeCacheError::WriteError(bytesWritten, page.size());
+                return nullptr;
+            }
+        }
+
+        void* buffer = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, m_fd, 0);
+        if (buffer == MAP_FAILED) {
+            error = BytecodeCacheError::StandardError(errno);
+            return nullptr;
+        }
+
+        return CachedBytecode::create(buffer, size, WTFMove(m_leafExecutables));
+    }
+#endif
+
     class Page {
     public:
         Page(size_t size)
@@ -228,6 +270,7 @@
     }
 
     VM& m_vm;
+    int m_fd;
     ptrdiff_t m_baseOffset;
     Page* m_currentPage;
     Vector<Page> m_pages;
@@ -2342,11 +2385,11 @@
     entry->encode(encoder, { key, jsCast<const UnlinkedCodeBlockType*>(codeBlock) });
 }
 
-Ref<CachedBytecode> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock)
+RefPtr<CachedBytecode> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock, int fd, BytecodeCacheError& error)
 {
     const ClassInfo* classInfo = codeBlock->classInfo(vm);
 
-    Encoder encoder(vm);
+    Encoder encoder(vm, fd);
     if (classInfo == UnlinkedProgramCodeBlock::info())
         encodeCodeBlock<UnlinkedProgramCodeBlock>(encoder, key, codeBlock);
     else if (classInfo == UnlinkedModuleProgramCodeBlock::info())
@@ -2354,14 +2397,20 @@
     else
         ASSERT(classInfo == UnlinkedEvalCodeBlock::info());
 
-    return encoder.release();
+    return encoder.release(error);
 }
 
-Ref<CachedBytecode> encodeFunctionCodeBlock(VM& vm, const UnlinkedFunctionCodeBlock* codeBlock)
+RefPtr<CachedBytecode> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock)
 {
+    BytecodeCacheError error;
+    return encodeCodeBlock(vm, key, codeBlock, -1, error);
+}
+
+RefPtr<CachedBytecode> encodeFunctionCodeBlock(VM& vm, const UnlinkedFunctionCodeBlock* codeBlock, BytecodeCacheError& error)
+{
     Encoder encoder(vm);
     encoder.malloc<CachedFunctionCodeBlock>()->encode(encoder, *codeBlock);
-    return encoder.release();
+    return encoder.release(error);
 }
 
 UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, Ref<CachedBytecode> cachedBytecode)

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.h (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.h	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.h	2019-06-04 11:14:10 UTC (rev 246060)
@@ -33,6 +33,7 @@
 
 namespace JSC {
 
+class BytecodeCacheError;
 class CachedBytecode;
 class SourceCodeKey;
 class UnlinkedCodeBlock;
@@ -107,7 +108,8 @@
     RefPtr<SourceProvider> m_provider;
 };
 
-JS_EXPORT_PRIVATE Ref<CachedBytecode> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*);
+JS_EXPORT_PRIVATE RefPtr<CachedBytecode> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*);
+JS_EXPORT_PRIVATE RefPtr<CachedBytecode> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*, int fd, BytecodeCacheError&);
 
 UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, Ref<CachedBytecode>);
 
@@ -117,7 +119,7 @@
     return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, WTFMove(cachedBytecode)));
 }
 
-JS_EXPORT_PRIVATE Ref<CachedBytecode> encodeFunctionCodeBlock(VM&, const UnlinkedFunctionCodeBlock*);
+JS_EXPORT_PRIVATE RefPtr<CachedBytecode> encodeFunctionCodeBlock(VM&, const UnlinkedFunctionCodeBlock*, BytecodeCacheError&);
 
 JS_EXPORT_PRIVATE void decodeFunctionCodeBlock(Decoder&, int32_t cachedFunctionCodeBlockOffset, WriteBarrier<UnlinkedFunctionCodeBlock>&, const JSCell*);
 

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2019-06-04 11:14:10 UTC (rev 246060)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012-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
@@ -225,10 +225,10 @@
     return sourceCodeKeyForSerializedBytecode(vm, sourceCode, SourceCodeType::ModuleType, strictMode, scriptMode, { });
 }
 
-Ref<CachedBytecode> serializeBytecode(VM& vm, UnlinkedCodeBlock* codeBlock, const SourceCode& source, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode)
+RefPtr<CachedBytecode> serializeBytecode(VM& vm, UnlinkedCodeBlock* codeBlock, const SourceCode& source, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, int fd, BytecodeCacheError& error, OptionSet<CodeGenerationMode> codeGenerationMode)
 {
     return encodeCodeBlock(vm,
-        sourceCodeKeyForSerializedBytecode(vm, source, codeType, strictMode, scriptMode, codeGenerationMode), codeBlock);
+        sourceCodeKeyForSerializedBytecode(vm, source, codeType, strictMode, scriptMode, codeGenerationMode), codeBlock, fd, error);
 }
 
 }

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.h (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/CodeCache.h	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.h	2019-06-04 11:14:10 UTC (rev 246060)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012-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
@@ -318,7 +318,7 @@
 }
 
 void writeCodeBlock(VM&, const SourceCodeKey&, const SourceCodeValue&);
-Ref<CachedBytecode> serializeBytecode(VM&, UnlinkedCodeBlock*, const SourceCode&, SourceCodeType, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>);
+RefPtr<CachedBytecode> serializeBytecode(VM&, UnlinkedCodeBlock*, const SourceCode&, SourceCodeType, JSParserStrictMode, JSParserScriptMode, int fd, BytecodeCacheError&, OptionSet<CodeGenerationMode>);
 SourceCodeKey sourceCodeKeyForSerializedProgram(VM&, const SourceCode&);
 SourceCodeKey sourceCodeKeyForSerializedModule(VM&, const SourceCode&);
 

Modified: trunk/Source/_javascript_Core/runtime/Completion.cpp (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/Completion.cpp	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/Completion.cpp	2019-06-04 11:14:10 UTC (rev 246060)
@@ -23,6 +23,7 @@
 #include "config.h"
 #include "Completion.h"
 
+#include "BytecodeCacheError.h"
 #include "CallFrame.h"
 #include "CatchScope.h"
 #include "CodeCache.h"
@@ -91,7 +92,7 @@
     return true;
 }
 
-Ref<CachedBytecode> generateProgramBytecode(VM& vm, const SourceCode& source, ParserError& error)
+RefPtr<CachedBytecode> generateProgramBytecode(VM& vm, const SourceCode& source, int fd, BytecodeCacheError& error)
 {
     JSLockHolder lock(vm);
     RELEASE_ASSERT(vm.atomicStringTable() == Thread::current().atomicStringTable());
@@ -101,13 +102,17 @@
     JSParserScriptMode scriptMode = JSParserScriptMode::Classic;
     EvalContextType evalContextType = EvalContextType::None;
 
-    UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlock<UnlinkedProgramCodeBlock>(vm, source, strictMode, scriptMode, { }, error, evalContextType, &variablesUnderTDZ);
+    ParserError parserError;
+    UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlock<UnlinkedProgramCodeBlock>(vm, source, strictMode, scriptMode, { }, parserError, evalContextType, &variablesUnderTDZ);
+    if (parserError.isValid())
+        error = parserError;
     if (!unlinkedCodeBlock)
-        return CachedBytecode::create();
-    return serializeBytecode(vm, unlinkedCodeBlock, source, SourceCodeType::ProgramType, strictMode, scriptMode, { });
+        return nullptr;
+
+    return serializeBytecode(vm, unlinkedCodeBlock, source, SourceCodeType::ProgramType, strictMode, scriptMode, fd, error, { });
 }
 
-Ref<CachedBytecode> generateModuleBytecode(VM& vm, const SourceCode& source, ParserError& error)
+RefPtr<CachedBytecode> generateModuleBytecode(VM& vm, const SourceCode& source, int fd, BytecodeCacheError& error)
 {
     JSLockHolder lock(vm);
     RELEASE_ASSERT(vm.atomicStringTable() == Thread::current().atomicStringTable());
@@ -117,10 +122,13 @@
     JSParserScriptMode scriptMode = JSParserScriptMode::Module;
     EvalContextType evalContextType = EvalContextType::None;
 
-    UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, source, strictMode, scriptMode, { }, error, evalContextType, &variablesUnderTDZ);
+    ParserError parserError;
+    UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, source, strictMode, scriptMode, { }, parserError, evalContextType, &variablesUnderTDZ);
+    if (parserError.isValid())
+        error = parserError;
     if (!unlinkedCodeBlock)
-        return CachedBytecode::create();
-    return serializeBytecode(vm, unlinkedCodeBlock, source, SourceCodeType::ModuleType, strictMode, scriptMode, { });
+        return nullptr;
+    return serializeBytecode(vm, unlinkedCodeBlock, source, SourceCodeType::ModuleType, strictMode, scriptMode, fd, error, { });
 }
 
 JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, NakedPtr<Exception>& returnedException)

Modified: trunk/Source/_javascript_Core/runtime/Completion.h (246059 => 246060)


--- trunk/Source/_javascript_Core/runtime/Completion.h	2019-06-04 10:37:58 UTC (rev 246059)
+++ trunk/Source/_javascript_Core/runtime/Completion.h	2019-06-04 11:14:10 UTC (rev 246060)
@@ -28,6 +28,7 @@
 
 namespace JSC {
 
+class BytecodeCacheError;
 class CachedBytecode;
 class Exception;
 class ExecState;
@@ -42,8 +43,8 @@
 JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0);
 JS_EXPORT_PRIVATE bool checkModuleSyntax(ExecState*, const SourceCode&, ParserError&);
 
-JS_EXPORT_PRIVATE Ref<CachedBytecode> generateProgramBytecode(VM&, const SourceCode&, ParserError&);
-JS_EXPORT_PRIVATE Ref<CachedBytecode> generateModuleBytecode(VM&, const SourceCode&, ParserError&);
+JS_EXPORT_PRIVATE RefPtr<CachedBytecode> generateProgramBytecode(VM&, const SourceCode&, int fd, BytecodeCacheError&);
+JS_EXPORT_PRIVATE RefPtr<CachedBytecode> generateModuleBytecode(VM&, const SourceCode&, int fd, BytecodeCacheError&);
 
 JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, const SourceCode&, JSValue thisValue, NakedPtr<Exception>& returnedException);
 inline JSValue evaluate(ExecState* exec, const SourceCode& sourceCode, JSValue thisValue = JSValue())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to