- Revision
- 295656
- Author
- [email protected]
- Date
- 2022-06-17 21:26:27 -0700 (Fri, 17 Jun 2022)
Log Message
Enhance Options::useOSLog to accept an os log type value.
https://bugs.webkit.org/show_bug.cgi?id=241719
Reviewed by Yusuke Suzuki.
This option only applies to OS(DARWIN).
For example, we can now use any of these:
--useOSLog=default // logs to OS_LOG_TYPE_DEFAULT
--useOSLog=info // logs to OS_LOG_TYPE_INFO
--useOSLog=debug // logs to OS_LOG_TYPE_DEBUG
--useOSLog=error // logs to OS_LOG_TYPE_ERROR
--useOSLog=fault. // logs to OS_LOG_TYPE_FAULT
We can still use --useOSLog=0 or false (which means do the normal dataLog) and
--useOSLog=1 or true (which means dataLog to OS_LOG_TYPE_ERROR).
Previously, when we specify --useOSLog=1, we will log to OS_LOG_TYPE_INFO. This
has been a source of friction in usage because no one ever remembers that we need
to enable OS_LOG_TYPE_INFO in the log stream to see this logging. Instead,
--useOSLog=1 will now log to OS_LOG_TYPE_ERROR, which ensures that logging will
show up in log stream. This is fine to do because the --useOSLog=1 option
indicates that the client really wants to see the logs. Otherwise, the client
can use one of the other os log types if they want something different.
Secondly, because --useOSLog=1 indicates that the client really wants to see the
logs, logging to OS_LOG_TYPE_ERROR ensures that the logging is flushed to the
file system instead of sitting in a memory buffer, and potentially not showing up
in the log stream.
Also made the following changes:
1. Changed Options::dumpAllOptions to use dataLog instead of printing to stderr.
This allows its output to be diverted using Options::useOSLog as well.
2. Moved the call to WTF::setDataFile from Options::initialize to
Options::recomputeDependentOptions. This allows Options::useOSLog to be
specified using the jsc shell's --useOSLog argument instead of requiring it
to be specified using the JSC_useOSLog env var in order to work.
To enable this, added a useOSLogOptionHasChanged flag that can be set in
the parser of the Options::useOSLog option. This prevents
Options::recomputeDependentOptions from calling initializeDatafileToUseOSLog()
repeatedly every time any option is set.
3. Added initializeDatafileToUseOSLog() which now instantiates the appropriate
OSLogPrintStream and sets it using WTF::setDataFile.
initializeDatafileToUseOSLog() also asserts that it is called at most once.
4. Added an assertion in WTF::setDataFile() to ensure that it is not called more
than once.
5. #if out the calls to overrideAliasedOptionWithHeuristic() on PLATFORM(COCOA).
They are not needed because, on PLATFORM(COCOA), we already iterate through
every env var starting with JSC_ and call Options::setOption() on it.
Options::setOption() will also handle aliased options.
For reference, this is an example of how we can view the logs using log stream
once --useOSLog=1 is used:
# log stream --predicate 'category == "DataLog"'
* Source/_javascript_Core/API/glib/JSCOptions.cpp:
* Source/_javascript_Core/jsc.cpp:
(CommandLine::parseArguments):
* Source/_javascript_Core/runtime/Options.cpp:
(JSC::parse):
(JSC::asDarwinOSLogType):
(JSC::initializeDatafileToUseOSLog):
(JSC::asString):
(JSC::Options::recomputeDependentOptions):
(JSC::Options::initialize):
(JSC::Options::setOptionWithoutAlias):
(JSC::Options::dumpAllOptions):
(JSC::OptionReader::Option::initValue):
(JSC::OptionReader::Option::dump const):
(JSC::OptionReader::Option::operator== const):
* Source/_javascript_Core/runtime/Options.h:
* Source/_javascript_Core/runtime/OptionsList.h:
* Source/WTF/wtf/DataLog.cpp:
(WTF::setDataFile):
Canonical link: https://commits.webkit.org/251661@main
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/API/glib/JSCOptions.cpp (295655 => 295656)
--- trunk/Source/_javascript_Core/API/glib/JSCOptions.cpp 2022-06-18 03:57:40 UTC (rev 295655)
+++ trunk/Source/_javascript_Core/API/glib/JSCOptions.cpp 2022-06-18 04:26:27 UTC (rev 295656)
@@ -164,6 +164,20 @@
}
}
+static bool valueFromGValue(const GValue* gValue, OSLogType& value)
+{
+ unsigned optionValue = g_value_get_uint(gValue);
+ if (optionValue > static_cast<unsigned>(OSLogType::Fault))
+ return false;
+ value = static_cast<OSLogType>(optionValue);
+ return true;
+}
+
+static void valueToGValue(OSLogType value, GValue* gValue)
+{
+ g_value_set_uint(gValue, static_cast<unsigned>(value));
+}
+
static gboolean jscOptionsSetValue(const char* option, const GValue* value)
{
#define SET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \
@@ -569,6 +583,11 @@
return JSC_OPTION_RANGE_STRING;
}
+static JSCOptionType jscOptionsType(const OSLogType&)
+{
+ return JSC_OPTION_UINT;
+}
+
/**
* JSCOptionType:
* @JSC_OPTION_BOOLEAN: A #gboolean option type.
Modified: trunk/Source/_javascript_Core/jsc.cpp (295655 => 295656)
--- trunk/Source/_javascript_Core/jsc.cpp 2022-06-18 03:57:40 UTC (rev 295655)
+++ trunk/Source/_javascript_Core/jsc.cpp 2022-06-18 04:26:27 UTC (rev 295656)
@@ -3684,7 +3684,7 @@
const char* optionsTitle = (dumpOptionsLevel == JSC::Options::DumpLevel::Overridden)
? "Modified JSC runtime options:"
: "All JSC runtime options:";
- JSC::Options::dumpAllOptions(stderr, dumpOptionsLevel, optionsTitle);
+ JSC::Options::dumpAllOptions(dumpOptionsLevel, optionsTitle);
}
JSC::Options::ensureOptionsAreCoherent();
if (needToExit)
Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (295655 => 295656)
--- trunk/Source/_javascript_Core/runtime/Options.cpp 2022-06-18 03:57:40 UTC (rev 295655)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp 2022-06-18 04:26:27 UTC (rev 295656)
@@ -58,6 +58,8 @@
namespace JSC {
+bool useOSLogOptionHasChanged = false;
+
template<typename T>
std::optional<T> parse(const char* string);
@@ -146,6 +148,83 @@
return std::nullopt;
}
+template<>
+std::optional<OptionsStorage::OSLogType> parse(const char* string)
+{
+ std::optional<OptionsStorage::OSLogType> result;
+
+ if (equalLettersIgnoringASCIICase(string, "false"_s) || !strcmp(string, "0"))
+ result = OSLogType::None;
+ else if (equalLettersIgnoringASCIICase(string, "true"_s) || !strcmp(string, "1"))
+ result = OSLogType::Error;
+ else if (equalLettersIgnoringASCIICase(string, "default"_s))
+ result = OSLogType::Default;
+ else if (equalLettersIgnoringASCIICase(string, "info"_s))
+ result = OSLogType::Info;
+ else if (equalLettersIgnoringASCIICase(string, "debug"_s))
+ result = OSLogType::Debug;
+ else if (equalLettersIgnoringASCIICase(string, "error"_s))
+ result = OSLogType::Error;
+ else if (equalLettersIgnoringASCIICase(string, "fault"_s))
+ result = OSLogType::Fault;
+
+ if (result && result.value() != Options::useOSLog())
+ useOSLogOptionHasChanged = true;
+ return result;
+}
+
+#if OS(DARWIN)
+static os_log_type_t asDarwinOSLogType(OSLogType type)
+{
+ switch (type) {
+ case OSLogType::None:
+ RELEASE_ASSERT_NOT_REACHED();
+ case OSLogType::Default:
+ return OS_LOG_TYPE_DEFAULT;
+ case OSLogType::Info:
+ return OS_LOG_TYPE_INFO;
+ case OSLogType::Debug:
+ return OS_LOG_TYPE_DEBUG;
+ case OSLogType::Error:
+ return OS_LOG_TYPE_ERROR;
+ case OSLogType::Fault:
+ return OS_LOG_TYPE_FAULT;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return OS_LOG_TYPE_DEFAULT;
+}
+
+static void initializeDatafileToUseOSLog()
+{
+ static bool alreadyInitialized = false;
+ RELEASE_ASSERT(!alreadyInitialized);
+ WTF::setDataFile(OSLogPrintStream::open("com.apple._javascript_Core", "DataLog", asDarwinOSLogType(Options::useOSLog())));
+ alreadyInitialized = true;
+ // Make sure no one jumped here for nefarious reasons...
+ RELEASE_ASSERT(Options::useOSLog() != OSLogType::None);
+}
+#endif // OS(DARWIN)
+
+static const char* asString(OSLogType type)
+{
+ switch (type) {
+ case OSLogType::None:
+ return "none";
+ case OSLogType::Default:
+ return "default";
+ case OSLogType::Info:
+ return "info";
+ case OSLogType::Debug:
+ return "debug";
+ case OSLogType::Error:
+ return "error";
+ case OSLogType::Fault:
+ return "fault";
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
bool Options::isAvailable(Options::ID id, Options::Availability availability)
{
if (availability == Availability::Restricted)
@@ -172,6 +251,8 @@
return false;
}
+#if !PLATFORM(COCOA)
+
template<typename T>
bool overrideOptionWithHeuristic(T& variable, Options::ID id, const char* name, Options::Availability availability)
{
@@ -208,6 +289,8 @@
return false;
}
+#endif // !PLATFORM(COCOA)
+
static unsigned computeNumberOfWorkerThreads(int maxNumberOfWorkerThreads, int minimum = 1)
{
int cpusToUse = std::min(kernTCSMAwareNumberOfProcessorCores(), maxNumberOfWorkerThreads);
@@ -575,6 +658,13 @@
FOR_EACH_JSC_EXPERIMENTAL_OPTION(DISABLE_TIERS);
}
+#if OS(DARWIN)
+ if (useOSLogOptionHasChanged) {
+ initializeDatafileToUseOSLog();
+ useOSLogOptionHasChanged = false;
+ }
+#endif
+
if (Options::verboseVerifyGC())
Options::verifyGC() = true;
}
@@ -651,7 +741,6 @@
overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);
FOR_EACH_JSC_OPTION(OVERRIDE_OPTION_WITH_HEURISTICS)
#undef OVERRIDE_OPTION_WITH_HEURISTICS
-#endif // PLATFORM(COCOA)
#define OVERRIDE_ALIASED_OPTION_WITH_HEURISTICS(aliasedName_, unaliasedName_, equivalence_) \
overrideAliasedOptionWithHeuristic("JSC_" #aliasedName_);
@@ -658,6 +747,8 @@
FOR_EACH_JSC_ALIASED_OPTION(OVERRIDE_ALIASED_OPTION_WITH_HEURISTICS)
#undef OVERRIDE_ALIASED_OPTION_WITH_HEURISTICS
+#endif // PLATFORM(COCOA)
+
#if 0
; // Deconfuse editors that do auto indentation
#endif
@@ -677,14 +768,6 @@
handleSignalsWithMach();
#endif
-#if OS(DARWIN)
- if (Options::useOSLog()) {
- WTF::setDataFile(OSLogPrintStream::open("com.apple._javascript_Core", "DataLog", OS_LOG_TYPE_INFO));
- // Make sure no one jumped here for nefarious reasons...
- RELEASE_ASSERT(useOSLog());
- }
-#endif
-
#if ASAN_ENABLED && OS(LINUX) && ENABLE(WEBASSEMBLY_SIGNALING_MEMORY)
if (Options::useWebAssemblyFastMemory() || Options::useSharedArrayBuffer()) {
const char* asanOptions = getenv("ASAN_OPTIONS");
@@ -853,7 +936,7 @@
if (Availability::availability_ != Availability::Normal \
&& !isAvailable(name_##ID, Availability::availability_)) \
return false; \
- std::optional<OptionsStorage::type_> value; \
+ std::optional<OptionsStorage::type_> value; \
value = parse<OptionsStorage::type_>(valueStr); \
if (value) { \
name_() = value.value(); \
@@ -946,11 +1029,11 @@
dumpAllOptions(builder, DumpLevel::All, nullptr, " ", nullptr, nullptr, DontDumpDefaults);
}
-void Options::dumpAllOptions(FILE* stream, DumpLevel level, const char* title)
+void Options::dumpAllOptions(DumpLevel level, const char* title)
{
StringBuilder builder;
dumpAllOptions(builder, level, title, nullptr, " ", "\n", DumpDefaults);
- fprintf(stream, "%s", builder.toString().utf8().data());
+ dataLog(builder.toString().utf8().data());
}
struct OptionReader {
@@ -986,6 +1069,7 @@
OptionRange m_optionRange;
const char* m_optionString;
GCLogging::Level m_gcLogLevel;
+ OSLogType m_osLogType;
};
friend struct OptionReader;
@@ -1087,6 +1171,9 @@
case Options::Type::GCLogLevel:
memcpy(&m_gcLogLevel, addressOfValue, sizeof(OptionsStorage::GCLogLevel));
break;
+ case Options::Type::OSLogType:
+ memcpy(&m_osLogType, addressOfValue, sizeof(OptionsStorage::OSLogType));
+ break;
}
}
@@ -1117,6 +1204,9 @@
case Options::Type::GCLogLevel:
builder.append(GCLogging::levelAsString(m_gcLogLevel));
break;
+ case Options::Type::OSLogType:
+ builder.append(asString(m_osLogType));
+ break;
}
}
@@ -1141,6 +1231,8 @@
|| (m_optionString && other.m_optionString && !strcmp(m_optionString, other.m_optionString));
case Options::Type::GCLogLevel:
return m_gcLogLevel == other.m_gcLogLevel;
+ case Options::Type::OSLogType:
+ return m_osLogType == other.m_osLogType;
}
return false;
}
Modified: trunk/Source/_javascript_Core/runtime/Options.h (295655 => 295656)
--- trunk/Source/_javascript_Core/runtime/Options.h 2022-06-18 03:57:40 UTC (rev 295655)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2022-06-18 04:26:27 UTC (rev 295656)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,7 +28,6 @@
#include "JSCConfig.h"
#include "JSExportMacros.h"
#include <stdint.h>
-#include <stdio.h>
#include <wtf/ForbidHeapAllocation.h>
#include <wtf/Noncopyable.h>
#include <wtf/PrintStream.h>
@@ -73,6 +72,7 @@
OptionRange,
OptionString,
GCLogLevel,
+ OSLogType,
};
class AllowUnfinalizedAccessScope {
@@ -113,7 +113,7 @@
// (no spaces allowed) and set the specified option if appropriate.
JS_EXPORT_PRIVATE static bool setOption(const char* arg);
- JS_EXPORT_PRIVATE static void dumpAllOptions(FILE*, DumpLevel, const char* title = nullptr);
+ JS_EXPORT_PRIVATE static void dumpAllOptions(DumpLevel, const char* title = nullptr);
JS_EXPORT_PRIVATE static void dumpAllOptionsInALine(StringBuilder&);
JS_EXPORT_PRIVATE static void ensureOptionsAreCoherent();
@@ -158,7 +158,9 @@
static bool setOptionWithoutAlias(const char* arg);
static bool setAliasedOption(const char* arg);
+#if !PLATFORM(COCOA)
static bool overrideAliasedOptionWithHeuristic(const char* name);
+#endif
inline static void* addressOfOption(Options::ID);
inline static void* addressOfOptionDefault(Options::ID);
Modified: trunk/Source/_javascript_Core/runtime/OptionsList.h (295655 => 295656)
--- trunk/Source/_javascript_Core/runtime/OptionsList.h 2022-06-18 03:57:40 UTC (rev 295655)
+++ trunk/Source/_javascript_Core/runtime/OptionsList.h 2022-06-18 04:26:27 UTC (rev 295656)
@@ -125,7 +125,7 @@
\
v(Bool, useIterationIntrinsics, true, Normal, nullptr) \
\
- v(Bool, useOSLog, false, Normal, "Log dataLog()s to os_log instead of stderr") \
+ v(OSLogType, useOSLog, OSLogType::None, Normal, "Log dataLog()s to os_log instead of stderr") \
/* dumpDisassembly implies dumpDFGDisassembly. */ \
v(Bool, needDisassemblySupport, false, Normal, nullptr) \
v(Bool, dumpDisassembly, false, Normal, "dumps disassembly of all JIT compiled code upon compilation") \
@@ -650,6 +650,16 @@
unsigned m_highLimit;
};
+enum class OSLogType : uint8_t {
+ None,
+ // These corresponds to OS_LOG_TYPE_xxx.
+ Default,
+ Info,
+ Debug,
+ Error,
+ Fault
+};
+
struct OptionsStorage {
using Bool = bool;
using Unsigned = unsigned;
@@ -659,6 +669,7 @@
using OptionRange = JSC::OptionRange;
using OptionString = const char*;
using GCLogLevel = GCLogging::Level;
+ using OSLogType = JSC::OSLogType;
bool allowUnfinalizedAccess;
bool isFinalized;
Modified: trunk/Source/WTF/wtf/DataLog.cpp (295655 => 295656)
--- trunk/Source/WTF/wtf/DataLog.cpp 2022-06-18 03:57:40 UTC (rev 295655)
+++ trunk/Source/WTF/wtf/DataLog.cpp 2022-06-18 04:26:27 UTC (rev 295656)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
#include <stdarg.h>
#include <string.h>
+#include <wtf/Assertions.h>
#include <wtf/FilePrintStream.h>
#include <wtf/LockedPrintStream.h>
#include <wtf/ProcessID.h>
@@ -160,6 +161,7 @@
void setDataFile(std::unique_ptr<PrintStream>&& file)
{
+ RELEASE_ASSERT(!s_file || reinterpret_cast<void*>(s_file) == &s_lockedFileData[0]);
s_file = file.release();
}