Title: [213151] trunk/Source
Revision
213151
Author
msab...@apple.com
Date
2017-02-28 10:50:00 -0800 (Tue, 28 Feb 2017)

Log Message

Add ability to configure JSC options from a file
https://bugs.webkit.org/show_bug.cgi?id=168914

Reviewed by Filip Pizlo.

Added the ability to set options and DataLog file location via a configuration file.
Source/_javascript_Core:

The configuration file is specified with the --configFile option to JSC or the
JSC_configFile environment variable.

The file format allows for options conditionally dependent on various attributes.
Currently those attributes are the process name, parent process name and build
type (Release or Debug).  In this patch, the parent process type is not set.
That will be set up in WebKit code with a follow up patch.

Here is an example config file:

    logFile = "/tmp/jscLog.%pid.txt"

    jscOptions {
        dumpOptions = 2
    }

    build == "Debug" {
        jscOptions {
            useConcurrentJIT = false
            dumpDisassembly = true
        }
    }

    build == "Release" && processName == "jsc" {
        jscOptions {
            asyncDisassembly = true
        }
    }

Eliminated the prior options file code.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* jsc.cpp:
(jscmain):
* runtime/ConfigFile.cpp: Added.
(JSC::ConfigFileScanner::ConfigFileScanner):
(JSC::ConfigFileScanner::start):
(JSC::ConfigFileScanner::lineNumber):
(JSC::ConfigFileScanner::currentBuffer):
(JSC::ConfigFileScanner::atFileEnd):
(JSC::ConfigFileScanner::tryConsume):
(JSC::ConfigFileScanner::tryConsumeString):
(JSC::ConfigFileScanner::tryConsumeUpto):
(JSC::ConfigFileScanner::fillBufferIfNeeded):
(JSC::ConfigFileScanner::fillBuffer):
(JSC::ConfigFile::ConfigFile):
(JSC::ConfigFile::setProcessName):
(JSC::ConfigFile::setParentProcessName):
(JSC::ConfigFile::parse):
* runtime/ConfigFile.h: Added.
* runtime/Options.cpp:
(JSC::Options::initialize):
(JSC::Options::setOptions):
* runtime/Options.h:

Source/WTF:

The pathname can include the printf style "%pid", which will be replaced with the
current process id.

* wtf/DataLog.cpp:
(WTF::initializeLogFileOnce):
(WTF::setDataFile):
* wtf/DataLog.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (213150 => 213151)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2017-02-28 18:50:00 UTC (rev 213151)
@@ -690,6 +690,7 @@
     runtime/CommonSlowPathsExceptions.cpp
     runtime/CompilationResult.cpp
     runtime/Completion.cpp
+    runtime/ConfigFile.cpp
     runtime/ConsoleClient.cpp
     runtime/ConsoleObject.cpp
     runtime/ConstantMode.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (213150 => 213151)


--- trunk/Source/_javascript_Core/ChangeLog	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-02-28 18:50:00 UTC (rev 213151)
@@ -1,3 +1,67 @@
+2017-02-28  Michael Saboff  <msab...@apple.com>
+
+        Add ability to configure JSC options from a file
+        https://bugs.webkit.org/show_bug.cgi?id=168914
+
+        Reviewed by Filip Pizlo.
+
+        Added the ability to set options and DataLog file location via a configuration file.
+        The configuration file is specified with the --configFile option to JSC or the
+        JSC_configFile environment variable.
+
+        The file format allows for options conditionally dependent on various attributes.
+        Currently those attributes are the process name, parent process name and build
+        type (Release or Debug).  In this patch, the parent process type is not set.
+        That will be set up in WebKit code with a follow up patch.
+
+        Here is an example config file:
+
+            logFile = "/tmp/jscLog.%pid.txt"
+
+            jscOptions {
+                dumpOptions = 2
+            }
+
+            build == "Debug" {
+                jscOptions {
+                    useConcurrentJIT = false
+                    dumpDisassembly = true
+                }
+            }
+
+            build == "Release" && processName == "jsc" {
+                jscOptions {
+                    asyncDisassembly = true
+                }
+            }
+
+        Eliminated the prior options file code.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * jsc.cpp:
+        (jscmain):
+        * runtime/ConfigFile.cpp: Added.
+        (JSC::ConfigFileScanner::ConfigFileScanner):
+        (JSC::ConfigFileScanner::start):
+        (JSC::ConfigFileScanner::lineNumber):
+        (JSC::ConfigFileScanner::currentBuffer):
+        (JSC::ConfigFileScanner::atFileEnd):
+        (JSC::ConfigFileScanner::tryConsume):
+        (JSC::ConfigFileScanner::tryConsumeString):
+        (JSC::ConfigFileScanner::tryConsumeUpto):
+        (JSC::ConfigFileScanner::fillBufferIfNeeded):
+        (JSC::ConfigFileScanner::fillBuffer):
+        (JSC::ConfigFile::ConfigFile):
+        (JSC::ConfigFile::setProcessName):
+        (JSC::ConfigFile::setParentProcessName):
+        (JSC::ConfigFile::parse):
+        * runtime/ConfigFile.h: Added.
+        * runtime/Options.cpp:
+        (JSC::Options::initialize):
+        (JSC::Options::setOptions):
+        * runtime/Options.h:
+
 2017-02-27  Alex Christensen  <achristen...@webkit.org>
 
         Begin enabling WebRTC on 64-bit

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (213150 => 213151)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-02-28 18:50:00 UTC (rev 213151)
@@ -1386,6 +1386,8 @@
 		655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 655EB29A10CE2581001A990E /* NodesCodegen.cpp */; };
 		657CF45819BF6662004ACBF2 /* JSCallee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 657CF45619BF6662004ACBF2 /* JSCallee.cpp */; };
 		657CF45919BF6662004ACBF2 /* JSCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = 657CF45719BF6662004ACBF2 /* JSCallee.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		658824AF1E5CFDB000FB7359 /* ConfigFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 658824AE1E5CFDB000FB7359 /* ConfigFile.h */; };
+		658824B11E5CFDF400FB7359 /* ConfigFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 658824B01E5CFDF400FB7359 /* ConfigFile.cpp */; };
 		658D3A5619638268003C45D6 /* VMEntryRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 658D3A5519638268003C45D6 /* VMEntryRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		65B8392E1BACAD360044E824 /* CachedRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B8392C1BACA92A0044E824 /* CachedRecovery.h */; };
 		65B8392F1BACAD6A0044E824 /* CachedRecovery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65B8392D1BACA9D30044E824 /* CachedRecovery.cpp */; };
@@ -3870,6 +3872,8 @@
 		657CF45619BF6662004ACBF2 /* JSCallee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCallee.cpp; sourceTree = "<group>"; };
 		657CF45719BF6662004ACBF2 /* JSCallee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallee.h; sourceTree = "<group>"; };
 		65860177185A8F5E00030EEE /* MaxFrameExtentForSlowPathCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MaxFrameExtentForSlowPathCall.h; sourceTree = "<group>"; };
+		658824AE1E5CFDB000FB7359 /* ConfigFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigFile.h; sourceTree = "<group>"; };
+		658824B01E5CFDF400FB7359 /* ConfigFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConfigFile.cpp; sourceTree = "<group>"; };
 		658D3A5519638268003C45D6 /* VMEntryRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VMEntryRecord.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilationInfo.h; path = dfg/DFGOSRExitCompilationInfo.h; sourceTree = "<group>"; };
 		65987F2F16828A7E003C2F8D /* UnusedPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnusedPointer.h; sourceTree = "<group>"; };
@@ -6354,6 +6358,8 @@
 				A7E5A3A61797432D00E893C0 /* CompilationResult.h */,
 				969A09220ED1E09C00F1F681 /* Completion.cpp */,
 				F5BB2BC5030F772101FCFE1D /* Completion.h */,
+				658824B01E5CFDF400FB7359 /* ConfigFile.cpp */,
+				658824AE1E5CFDB000FB7359 /* ConfigFile.h */,
 				0FDB2CE9174896C7007B3C1B /* ConcurrentJSLock.h */,
 				A5B6A74C18C6DBA600F11E91 /* ConsoleClient.cpp */,
 				A53CE08918BC21C300BEDF76 /* ConsoleClient.h */,
@@ -8364,6 +8370,7 @@
 				A7D89CFE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h in Headers */,
 				0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
 				0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
+				658824AF1E5CFDB000FB7359 /* ConfigFile.h in Headers */,
 				0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
 				0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
 				0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
@@ -10377,6 +10384,7 @@
 				140B7D1D0DC69AF7009C42B8 /* JSLexicalEnvironment.cpp in Sources */,
 				14280875107EC13E0013E7B2 /* JSLock.cpp in Sources */,
 				C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */,
+				658824B11E5CFDF400FB7359 /* ConfigFile.cpp in Sources */,
 				A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */,
 				A74DEF95182D991400522C22 /* JSMapIterator.cpp in Sources */,
 				E3D239C81B829C1C00BBEF67 /* JSModuleEnvironment.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/jsc.cpp (213150 => 213151)


--- trunk/Source/_javascript_Core/jsc.cpp	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/_javascript_Core/jsc.cpp	2017-02-28 18:50:00 UTC (rev 213151)
@@ -29,6 +29,7 @@
 #include "ButterflyInlines.h"
 #include "CodeBlock.h"
 #include "Completion.h"
+#include "ConfigFile.h"
 #include "DOMJITGetterSetter.h"
 #include "DOMJITPatchpoint.h"
 #include "DOMJITPatchpointParams.h"
@@ -3762,6 +3763,12 @@
     // comes first.
     CommandLine options(argc, argv);
 
+    if (Options::configFile()) {
+        ConfigFile configFile(Options::configFile());
+        configFile.setProcessName("jsc");
+        configFile.parse();
+    }
+
     // Initialize JSC before getting VM.
     WTF::initializeMainThread();
     JSC::initializeThreading();

Added: trunk/Source/_javascript_Core/runtime/ConfigFile.cpp (0 => 213151)


--- trunk/Source/_javascript_Core/runtime/ConfigFile.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ConfigFile.cpp	2017-02-28 18:50:00 UTC (rev 213151)
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2017 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 "ConfigFile.h"
+
+#include "Options.h"
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/DataLog.h>
+#include <wtf/StringExtras.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace JSC {
+
+static const size_t s_processNameMax = 128;
+#if PLATFORM(WIN)
+static const size_t s_maxPathLength = 260; // Windows value for "MAX_PATH"
+#else
+static const size_t s_maxPathLength = PATH_MAX;
+#endif
+char ConfigFile::s_processName[s_processNameMax + 1] = { 0 };
+char ConfigFile::s_parentProcessName[s_processNameMax + 1] = { 0 };
+
+class ConfigFileScanner {
+public:
+    ConfigFileScanner(const char* filename)
+        : m_filename(filename)
+        , m_lineNumber(0)
+    {
+        m_srcPtr = &m_buffer[0];
+        m_bufferEnd = &m_buffer[0];
+    }
+
+    bool start()
+    {
+        m_file = fopen(m_filename, "r");
+        if (!m_file) {
+            dataLogF("Failed to open file JSC Config file '%s'.\n", m_filename);
+            return false;
+        }
+
+        return true;
+    }
+
+    unsigned lineNumber()
+    {
+        return m_lineNumber;
+    }
+
+    const char* currentBuffer()
+    {
+        if (!m_srcPtr || m_srcPtr == m_bufferEnd)
+            return "";
+
+        return m_srcPtr;
+    }
+
+    bool atFileEnd()
+    {
+        if (!fillBufferIfNeeded())
+            return true;
+
+        return false;
+    }
+
+    bool tryConsume(char c)
+    {
+        if (!fillBufferIfNeeded())
+            return false;
+
+        if (c == *m_srcPtr) {
+            m_srcPtr++;
+            return true;
+        }
+
+        return false;
+    }
+
+    template <size_t length>
+    bool tryConsume(const char (&token) [length])
+    {
+        if (!fillBufferIfNeeded())
+            return false;
+
+        size_t tokenLength = length - 1;
+        if (!strncmp(m_srcPtr, token, tokenLength)) {
+            m_srcPtr += tokenLength;
+            return true;
+        }
+
+        return false;
+    }
+
+    char* tryConsumeString()
+    {
+        if (!fillBufferIfNeeded())
+            return nullptr;
+
+        if (*m_srcPtr != '"')
+            return nullptr;
+
+        char* stringStart = ++m_srcPtr;
+
+        char* stringEnd = strchr(m_srcPtr, '"');
+        if (stringEnd) {
+            *stringEnd = '\0';
+            m_srcPtr = stringEnd + 1;
+            return stringStart;
+        }
+
+        return nullptr;
+    }
+
+    char* tryConsumeUpto(bool& foundChar, char c)
+    {
+        if (!fillBufferIfNeeded())
+            return nullptr;
+
+        char* start = m_srcPtr;
+        foundChar = false;
+
+        char* cPosition = strchr(m_srcPtr, c);
+        if (cPosition) {
+            *cPosition = '\0';
+            m_srcPtr = cPosition + 1;
+            foundChar = true;
+        } else
+            m_srcPtr = m_bufferEnd;
+
+        return start;
+    }
+
+private:
+    bool fillBufferIfNeeded()
+    {
+        if (!m_srcPtr)
+            return false;
+
+        while (true) {
+            while (m_srcPtr != m_bufferEnd && isASCIISpace(*m_srcPtr))
+                m_srcPtr++;
+
+            if (m_srcPtr != m_bufferEnd)
+                break;
+
+            if (!fillBuffer())
+                return false;
+        }
+
+        return true;
+    }
+
+    bool fillBuffer()
+    {
+        do {
+            m_srcPtr = fgets(m_buffer, sizeof(m_buffer), m_file);
+            if (!m_srcPtr) {
+                fclose(m_file);
+                return false;
+            }
+
+            m_lineNumber++;
+
+            m_bufferEnd = strchr(m_srcPtr, '#');
+
+            if (m_bufferEnd)
+                *m_bufferEnd = '\0';
+            else {
+                m_bufferEnd = m_srcPtr + strlen(m_srcPtr);
+                if (m_bufferEnd > m_srcPtr && m_bufferEnd[-1] == '\n') {
+                    m_bufferEnd--;
+                    *m_bufferEnd = '\0';
+                }
+            }
+        } while (m_bufferEnd == m_srcPtr);
+
+        return true;
+    }
+
+    const char* m_filename;
+    unsigned m_lineNumber;
+    FILE* m_file;
+    char m_buffer[BUFSIZ];
+    char* m_srcPtr;
+    char* m_bufferEnd;
+};
+
+ConfigFile::ConfigFile(const char* filename)
+    : m_filename(filename)
+{
+}
+
+void ConfigFile::setProcessName(const char* processName)
+{
+    strncpy(s_processName, processName, s_processNameMax);
+}
+
+void ConfigFile::setParentProcessName(const char* parentProcessName)
+{
+    strncpy(s_parentProcessName, parentProcessName, s_processNameMax);
+}
+
+void ConfigFile::parse()
+{
+    enum StatementNesting { TopLevelStatment, NestedStatement, NestedStatementFailedCriteria };
+    enum ParseResult { ParseOK, ParseError, NestedStatementDone };
+
+    ConfigFileScanner scanner(m_filename);
+
+    if (!scanner.start())
+        return;
+
+    char logPathname[s_maxPathLength + 1] = { 0 };
+
+    StringBuilder jscOptionsBuilder;
+
+    auto parseLogFile = [&](StatementNesting statementNesting) {
+        char* filename = nullptr;
+        if (scanner.tryConsume('=') && (filename = scanner.tryConsumeString())) {
+            if (statementNesting != NestedStatementFailedCriteria)
+                strncpy(logPathname, filename, s_maxPathLength);
+
+            return ParseOK;
+        }
+
+        return ParseError;
+    };
+
+    auto parseJSCOptions = [&](StatementNesting statementNesting) {
+        if (scanner.tryConsume('{')) {
+            StringBuilder builder;
+
+            bool foundClosingBrace = false;
+            char* currentLine = nullptr;
+
+            while ((currentLine = scanner.tryConsumeUpto(foundClosingBrace, '}'))) {
+                char* p = currentLine;
+
+                do {
+                    if (foundClosingBrace && !*p)
+                        break;
+
+                    char* optionNameStart = p;
+
+                    while (*p && !isASCIISpace(*p) && *p != '=')
+                        p++;
+
+                    builder.append(optionNameStart, p - optionNameStart);
+
+                    while (*p && isASCIISpace(*p) && *p != '=')
+                        p++;
+
+                    if (!*p)
+                        return ParseError;
+                    p++; // Advance past the '='
+
+                    builder.append('=');
+
+                    while (*p && isASCIISpace(*p))
+                        p++;
+
+                    if (!*p)
+                        return ParseError;
+
+                    char* optionValueStart = p;
+
+                    while (*p && !isASCIISpace(*p))
+                        p++;
+
+                    builder.append(optionValueStart, p - optionValueStart);
+                    builder.append('\n');
+
+                    while (*p && isASCIISpace(*p))
+                        p++;
+                } while (*p);
+
+                if (foundClosingBrace)
+                    break;
+            }
+
+            if (statementNesting != NestedStatementFailedCriteria)
+                jscOptionsBuilder.append(builder);
+
+            return ParseOK;
+        }
+
+        return ParseError;
+    };
+
+    auto parseNestedStatement = [&](StatementNesting statementNesting) {
+        if (scanner.tryConsume("jscOptions"))
+            return parseJSCOptions(statementNesting);
+
+        if (scanner.tryConsume("logFile"))
+            return parseLogFile(statementNesting);
+
+        if (scanner.tryConsume('}'))
+            return NestedStatementDone;
+
+        return ParseError;
+    };
+
+    auto parsePredicate = [&](bool& predicateMatches, const char* matchValue) {
+        char* predicateValue = nullptr;
+        if (scanner.tryConsume("==")
+            && (predicateValue = scanner.tryConsumeString()) && matchValue) {
+                predicateMatches = !strcmp(predicateValue, matchValue);
+                return true;
+        }
+
+        return false;
+    };
+
+    auto parseConditionalBlock = [&](StatementNesting statementNesting) {
+        if (statementNesting == NestedStatement) {
+            StatementNesting subNesting = NestedStatement;
+
+            while (true) {
+                bool predicateMatches;
+                const char* actualValue = nullptr;
+
+                if (scanner.tryConsume("processName"))
+                    actualValue = s_processName;
+                else if (scanner.tryConsume("parentProcessName"))
+                    actualValue = s_parentProcessName;
+                else if (scanner.tryConsume("build"))
+#ifndef NDEBUG
+                    actualValue = "Debug";
+#else
+                    actualValue = "Release";
+#endif
+                else
+                    return ParseError;
+
+                if (parsePredicate(predicateMatches, actualValue)) {
+                    if (!predicateMatches)
+                        subNesting = NestedStatementFailedCriteria;
+
+                    if (!scanner.tryConsume("&&"))
+                        break;
+                }
+            }
+
+            if (!scanner.tryConsume('{'))
+                return ParseError;
+
+            ParseResult parseResult = ParseOK;
+            while (parseResult == ParseOK && !scanner.atFileEnd())
+                parseResult = parseNestedStatement(subNesting);
+
+            if (parseResult == NestedStatementDone)
+                return ParseOK;
+        }
+
+        return ParseError;
+    };
+
+    auto parseStatement = [&](StatementNesting statementNesting) {
+        if (scanner.tryConsume("jscOptions"))
+            return parseJSCOptions(statementNesting);
+
+        if (scanner.tryConsume("logFile"))
+            return parseLogFile(statementNesting);
+
+        if (statementNesting == TopLevelStatment)
+            return parseConditionalBlock(NestedStatement);
+
+        return ParseError;
+    };
+
+    ParseResult parseResult = ParseOK;
+
+    while (parseResult == ParseOK && !scanner.atFileEnd())
+        parseResult = parseStatement(TopLevelStatment);
+
+    if (parseResult == ParseOK) {
+        if (strlen(logPathname))
+            WTF::setDataFile(logPathname);
+
+        if (!jscOptionsBuilder.isEmpty()) {
+            const char* optionsStr = jscOptionsBuilder.toString().utf8().data();
+            Options::setOptions(optionsStr);
+        }
+    } else
+        WTF::dataLogF("Error in JSC Config file on or near line %u, parsing '%s'\n", scanner.lineNumber(), scanner.currentBuffer());
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ConfigFile.h (0 => 213151)


--- trunk/Source/_javascript_Core/runtime/ConfigFile.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ConfigFile.h	2017-02-28 18:50:00 UTC (rev 213151)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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
+
+namespace JSC {
+
+class ConfigFile {
+public:
+    JS_EXPORT_PRIVATE ConfigFile(const char*);
+
+    JS_EXPORT_PRIVATE static void setProcessName(const char*);
+    JS_EXPORT_PRIVATE static void setParentProcessName(const char*);
+    JS_EXPORT_PRIVATE void parse();
+
+private:
+    static char s_processName[];
+    static char s_parentProcessName[];
+
+    const char* m_filename;
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (213150 => 213151)


--- trunk/Source/_javascript_Core/runtime/Options.cpp	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp	2017-02-28 18:50:00 UTC (rev 213151)
@@ -51,9 +51,6 @@
 #include "MacroAssemblerX86.h"
 #endif
 
-#define USE_OPTIONS_FILE 0
-#define OPTIONS_FILENAME "/tmp/jsc.options"
-
 namespace JSC {
 
 namespace {
@@ -496,31 +493,6 @@
                 ; // Deconfuse editors that do auto indentation
 #endif
     
-#if USE(OPTIONS_FILE)
-            {
-                const char* filename = OPTIONS_FILENAME;
-                FILE* optionsFile = fopen(filename, "r");
-                if (!optionsFile) {
-                    dataLogF("Failed to open file %s. Did you add the file-read-data entitlement to WebProcess.sb?\n", filename);
-                    return;
-                }
-                
-                StringBuilder builder;
-                char* line;
-                char buffer[BUFSIZ];
-                while ((line = fgets(buffer, sizeof(buffer), optionsFile)))
-                    builder.append(buffer);
-                
-                const char* optionsStr = builder.toString().utf8().data();
-                dataLogF("Setting options: %s\n", optionsStr);
-                setOptions(optionsStr);
-                
-                int result = fclose(optionsFile);
-                if (result)
-                    dataLogF("Failed to close file %s: %s\n", filename, strerror(errno));
-            }
-#endif
-
             recomputeDependentOptions();
 
             // Do range checks where needed and make corrections to the options:
@@ -628,7 +600,12 @@
         }
     }
 
+    recomputeDependentOptions();
+
     dumpOptionsIfNeeded();
+
+    ensureOptionsAreCoherent();
+
     return success;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/Options.h (213150 => 213151)


--- trunk/Source/_javascript_Core/runtime/Options.h	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2017-02-28 18:50:00 UTC (rev 213151)
@@ -103,6 +103,7 @@
 #define JSC_OPTIONS(v) \
     v(bool, validateOptions, false, Normal, "crashes if mis-typed JSC options were passed to the VM") \
     v(unsigned, dumpOptions, 0, Normal, "dumps JSC options (0 = None, 1 = Overridden only, 2 = All, 3 = Verbose)") \
+    v(optionString, configFile, nullptr, Normal, "file to configure JSC options and logging location") \
     \
     v(bool, useLLInt,  true, Normal, "allows the LLINT to be used if true") \
     v(bool, useJIT,    true, Normal, "allows the baseline JIT to be used if true") \

Modified: trunk/Source/WTF/ChangeLog (213150 => 213151)


--- trunk/Source/WTF/ChangeLog	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/WTF/ChangeLog	2017-02-28 18:50:00 UTC (rev 213151)
@@ -1,3 +1,19 @@
+2017-02-28  Michael Saboff  <msab...@apple.com>
+
+        Add ability to configure JSC options from a file
+        https://bugs.webkit.org/show_bug.cgi?id=168914
+
+        Reviewed by Filip Pizlo.
+
+        Added the ability to set options and DataLog file location via a configuration file.
+        The pathname can include the printf style "%pid", which will be replaced with the
+        current process id.
+
+        * wtf/DataLog.cpp:
+        (WTF::initializeLogFileOnce):
+        (WTF::setDataFile):
+        * wtf/DataLog.h:
+
 2017-02-27  Andy Estes  <aes...@apple.com>
 
         [iOS] Enable file replacement

Modified: trunk/Source/WTF/wtf/DataLog.cpp (213150 => 213151)


--- trunk/Source/WTF/wtf/DataLog.cpp	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/WTF/wtf/DataLog.cpp	2017-02-28 18:50:00 UTC (rev 213151)
@@ -50,30 +50,22 @@
 
 namespace WTF {
 
+static const size_t maxPathLength = 1024;
+
 static PrintStream* s_file;
-
 static uint64_t s_fileData[(sizeof(FilePrintStream) + 7) / 8];
 static uint64_t s_lockedFileData[(sizeof(LockedPrintStream) + 7) / 8];
 
 static void initializeLogFileOnce()
 {
-    FilePrintStream* file = nullptr;
-    
-#if DATA_LOG_TO_FILE
-    const long maxPathLength = 1024;
+    const char* filename = nullptr;
 
-    char filenameSuffix[maxPathLength + 1];
+    if (s_file)
+        return;
 
-#if PLATFORM(WIN)
-    _snprintf(filenameSuffix, sizeof(filenameSuffix), ".%d.txt", GetCurrentProcessId());
-#else
-    snprintf(filenameSuffix, sizeof(filenameSuffix), ".%d.txt", getpid());
-#endif
-
+#if DATA_LOG_TO_FILE
 #if DATA_LOG_TO_DARWIN_TEMP_DIR
     char filenameBuffer[maxPathLength + 1];
-    unsigned suffixLength = strlen(filenameSuffix);
-
 #if defined(DATA_LOG_FILENAME)
     char* logBasename = strrchr(DATA_LOG_FILENAME, '/');
     if (!logBasename)
@@ -82,13 +74,11 @@
     const char* logBasename = "WTFLog";
 #endif
 
-    const char* filename = nullptr;
-
     bool success = confstr(_CS_DARWIN_USER_TEMP_DIR, filenameBuffer, sizeof(filenameBuffer));
     if (success) {
         // FIXME: Assert that the path ends with a slash instead of adding a slash if it does not exist
         // once <rdar://problem/23579077> is fixed in all iOS Simulator versions that we use.
-        size_t lastComponentLength = strlen(logBasename) + suffixLength;
+        size_t lastComponentLength = strlen(logBasename) + 20; // More than enough for ".<pid>.txt"
         size_t dirnameLength = strlen(filenameBuffer);
         bool shouldAddPathSeparator = filenameBuffer[dirnameLength - 1] != '/' && logBasename[0] != '/';
         if (lastComponentLength + shouldAddPathSeparator <= sizeof(filenameBuffer) - dirnameLength - 1) {
@@ -99,36 +89,23 @@
         }
     }
 #elif defined(DATA_LOG_FILENAME)
-    const char* filename = DATA_LOG_FILENAME;
+    filename = DATA_LOG_FILENAME;
 #else
-    const char* filename = getenv("WTF_DATA_LOG_FILENAME");
+    filename = getenv("WTF_DATA_LOG_FILENAME");
 #endif
     char actualFilename[maxPathLength + 1];
 
-    if (filename) {
+    if (filename && !strstr(filename, "%pid")) {
 #if PLATFORM(WIN)
-        _snprintf(actualFilename, sizeof(actualFilename), "%s%s", filename, filenameSuffix);
+        _snprintf(actualFilename, sizeof(actualFilename), "%s.%%pid.txt", filename);
 #else
-        snprintf(actualFilename, sizeof(actualFilename), "%s%s", filename, filenameSuffix);
+        snprintf(actualFilename, sizeof(actualFilename), "%s.%%pid.txt", filename);
 #endif
-        
-        file = FilePrintStream::open(actualFilename, "w").release();
-        if (file)
-            WTFLogAlways("*** DataLog output to \"%s\" ***\n", actualFilename);
-        else
-            WTFLogAlways("Warning: Could not open DataLog file %s for writing.\n", actualFilename);
+        filename = actualFilename;
     }
 #endif // DATA_LOG_TO_FILE
-    
-    if (!file) {
-        // Use placement new; this makes it easier to use dataLog() to debug
-        // fastMalloc.
-        file = new (s_fileData) FilePrintStream(stderr, FilePrintStream::Borrow);
-    }
-    
-    setvbuf(file->file(), 0, _IONBF, 0); // Prefer unbuffered output, so that we get a full log upon crash or deadlock.
-    
-    s_file = new (s_lockedFileData) LockedPrintStream(std::unique_ptr<FilePrintStream>(file));
+
+    setDataFile(filename);
 }
 
 static void initializeLogFile()
@@ -141,6 +118,60 @@
         });
 }
 
+void setDataFile(const char* path)
+{
+    FilePrintStream* file = nullptr;
+    char formattedPath[maxPathLength + 1];
+    const char* pathToOpen = path;
+
+    if (path) {
+        const char* pidFormat = strstr(path, "%pid");
+        if (pidFormat) {
+            size_t leadingPathLength = pidFormat - path;
+            size_t pathCharactersAvailable = std::min(maxPathLength, leadingPathLength);
+            strncpy(formattedPath, path, pathCharactersAvailable);
+            char* nextDest = formattedPath + pathCharactersAvailable;
+            pathCharactersAvailable = maxPathLength - pathCharactersAvailable;
+            if (pathCharactersAvailable) {
+                int pidTextLength;
+#if PLATFORM(WIN)
+                pidTextLength = _snprintf(nextDest, pathCharactersAvailable, "%d", GetCurrentProcessId());
+#else
+                pidTextLength = snprintf(nextDest, pathCharactersAvailable, "%d", getpid());
+#endif
+                if (pidTextLength < 0 || static_cast<size_t>(pidTextLength) >= pathCharactersAvailable)
+                    pathCharactersAvailable = 0;
+                else {
+                    pathCharactersAvailable -= static_cast<size_t>(pidTextLength);
+                    nextDest += pidTextLength;
+                    strncpy(nextDest, pidFormat + 4, pathCharactersAvailable);
+                }
+            }
+            formattedPath[maxPathLength] = '\0';
+            pathToOpen = formattedPath;
+        }
+
+        file = FilePrintStream::open(pathToOpen, "w").release();
+        if (file)
+            WTFLogAlways("*** DataLog output to \"%s\" ***\n", pathToOpen);
+        else
+            WTFLogAlways("Warning: Could not open DataLog file %s for writing.\n", pathToOpen);
+    }
+
+    if (!file) {
+        // Use placement new; this makes it easier to use dataLog() to debug
+        // fastMalloc.
+        file = new (s_fileData) FilePrintStream(stderr, FilePrintStream::Borrow);
+    }
+
+    setvbuf(file->file(), 0, _IONBF, 0); // Prefer unbuffered output, so that we get a full log upon crash or deadlock.
+
+    if (s_file)
+        s_file->flush();
+
+    s_file = new (s_lockedFileData) LockedPrintStream(std::unique_ptr<FilePrintStream>(file));
+}
+
 PrintStream& dataFile()
 {
     initializeLogFile();

Modified: trunk/Source/WTF/wtf/DataLog.h (213150 => 213151)


--- trunk/Source/WTF/wtf/DataLog.h	2017-02-28 16:43:27 UTC (rev 213150)
+++ trunk/Source/WTF/wtf/DataLog.h	2017-02-28 18:50:00 UTC (rev 213151)
@@ -34,6 +34,7 @@
 namespace WTF {
 
 WTF_EXPORT_PRIVATE PrintStream& dataFile();
+WTF_EXPORT_PRIVATE void setDataFile(const char* path);
 
 WTF_EXPORT_PRIVATE void dataLogFV(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(1, 0);
 WTF_EXPORT_PRIVATE void dataLogF(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to