Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (187124 => 187125)
--- trunk/Source/_javascript_Core/ChangeLog 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-07-21 21:41:30 UTC (rev 187125)
@@ -1,3 +1,37 @@
+2015-07-21 Filip Pizlo <fpi...@apple.com>
+
+ Fixed VM pool allocation should have a reserve for allocations that cannot fail
+ https://bugs.webkit.org/show_bug.cgi?id=147154
+ rdar://problem/21847618
+
+ Reviewed by Geoffrey Garen.
+
+ This adds the notion of a JIT pool reserve fraction. Some fraction, currently 1/4, of
+ the JIT pool is reserved for allocations that cannot fail. It makes sense to make this
+ a fraction rather than a constant because each allocation that can fail may cause some
+ number of allocations that cannot fail (for example, the OSR exit thunks that we
+ compile when we exit from some CodeBlock cannot fail).
+
+ I've tested this by adding a test mode where we artificially limit the JIT pool size.
+ Prior to the fix, we had >20 failures. Now we have none.
+
+ * heap/GCLogging.cpp:
+ (WTF::printInternal): I needed a dump method on Options members when debugging this.
+ * heap/GCLogging.h:
+ * jit/ExecutableAllocator.h: Raise the ARM64 limit to 32MB because 16MB is cutting it too close.
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator): Add the ability to artificially limit JIT pool size for testing.
+ (JSC::ExecutableAllocator::memoryPressureMultiplier): Implement the reserve when computing memory pressure for JIT tier-up heuristics.
+ (JSC::ExecutableAllocator::allocate): Implement the reserve when allocating can-fail things.
+ * jsc.cpp: Rewire some options parsing so that CommandLine happens before we create the JIT pool.
+ (main):
+ (CommandLine::parseArguments):
+ (jscmain):
+ * runtime/Options.cpp:
+ (JSC::OptionRange::dump): I needed a dump method on Options members when debugging this.
+ (JSC::Options::initialize): This can now be called more than once.
+ * runtime/Options.h:
+
2015-07-21 Saam barati <saambara...@gmail.com>
ObjectPatternNode's entry should use "const Identifier&" instead of "Identifier"
Modified: trunk/Source/_javascript_Core/heap/GCLogging.cpp (187124 => 187125)
--- trunk/Source/_javascript_Core/heap/GCLogging.cpp 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/heap/GCLogging.cpp 2015-07-21 21:41:30 UTC (rev 187125)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
#include "HeapIterationScope.h"
#include "JSCell.h"
#include "JSCellInlines.h"
+#include <wtf/PrintStream.h>
namespace JSC {
@@ -113,3 +114,26 @@
}
} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream& out, JSC::GCLogging::Level level)
+{
+ switch (level) {
+ case JSC::GCLogging::Level::None:
+ out.print("None");
+ return;
+ case JSC::GCLogging::Level::Basic:
+ out.print("Basic");
+ return;
+ case JSC::GCLogging::Level::Verbose:
+ out.print("Verbose");
+ return;
+ default:
+ out.print("Level=", level - JSC::GCLogging::Level::None);
+ return;
+ }
+}
+
+} // namespace WTF
+
Modified: trunk/Source/_javascript_Core/heap/GCLogging.h (187124 => 187125)
--- trunk/Source/_javascript_Core/heap/GCLogging.h 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/heap/GCLogging.h 2015-07-21 21:41:30 UTC (rev 187125)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -48,4 +48,12 @@
} // namespace JSC
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::GCLogging::Level);
+
+} // namespace WTF
+
#endif // GCLogging_h
Modified: trunk/Source/_javascript_Core/jit/ExecutableAllocator.h (187124 => 187125)
--- trunk/Source/_javascript_Core/jit/ExecutableAllocator.h 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/jit/ExecutableAllocator.h 2015-07-21 21:41:30 UTC (rev 187125)
@@ -80,13 +80,16 @@
#endif
#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
-#if CPU(ARM) || CPU(ARM64)
+#if CPU(ARM)
static const size_t fixedExecutableMemoryPoolSize = 16 * 1024 * 1024;
+#elif CPU(ARM64)
+static const size_t fixedExecutableMemoryPoolSize = 32 * 1024 * 1024;
#elif CPU(X86_64)
static const size_t fixedExecutableMemoryPoolSize = 1024 * 1024 * 1024;
#else
static const size_t fixedExecutableMemoryPoolSize = 32 * 1024 * 1024;
#endif
+static const double executablePoolReservationFraction = 0.25;
extern uintptr_t startOfFixedExecutableMemoryPool;
#endif
Modified: trunk/Source/_javascript_Core/jit/ExecutableAllocatorFixedVMPool.cpp (187124 => 187125)
--- trunk/Source/_javascript_Core/jit/ExecutableAllocatorFixedVMPool.cpp 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/jit/ExecutableAllocatorFixedVMPool.cpp 2015-07-21 21:41:30 UTC (rev 187125)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,9 +60,14 @@
FixedVMPoolExecutableAllocator()
: MetaAllocator(jitAllocationGranule) // round up all allocations to 32 bytes
{
- m_reservation = PageReservation::reserveWithGuardPages(fixedExecutableMemoryPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+ size_t reservationSize;
+ if (Options::jitMemoryReservationSize())
+ reservationSize = Options::jitMemoryReservationSize();
+ else
+ reservationSize = fixedExecutableMemoryPoolSize;
+ m_reservation = PageReservation::reserveWithGuardPages(reservationSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
if (m_reservation) {
- ASSERT(m_reservation.size() == fixedExecutableMemoryPoolSize);
+ ASSERT(m_reservation.size() == reservationSize);
addFreshFreeSpace(m_reservation.base(), m_reservation.size());
startOfFixedExecutableMemoryPool = reinterpret_cast<uintptr_t>(m_reservation.base());
@@ -148,12 +153,14 @@
MetaAllocator::Statistics statistics = allocator->currentStatistics();
ASSERT(statistics.bytesAllocated <= statistics.bytesReserved);
size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage;
- if (bytesAllocated >= statistics.bytesReserved)
- bytesAllocated = statistics.bytesReserved;
+ size_t bytesAvailable = static_cast<size_t>(
+ statistics.bytesReserved * (1 - executablePoolReservationFraction));
+ if (bytesAllocated >= bytesAvailable)
+ bytesAllocated = bytesAvailable;
double result = 1.0;
- size_t divisor = statistics.bytesReserved - bytesAllocated;
+ size_t divisor = bytesAvailable - bytesAllocated;
if (divisor)
- result = static_cast<double>(statistics.bytesReserved) / divisor;
+ result = static_cast<double>(bytesAvailable) / divisor;
if (result < 1.0)
result = 1.0;
return result;
@@ -170,6 +177,16 @@
&& doExecutableAllocationFuzzingIfEnabled() == PretendToFailExecutableAllocation)
return nullptr;
+ if (effort == JITCompilationCanFail) {
+ // Don't allow allocations if we are down to reserve.
+ MetaAllocator::Statistics statistics = allocator->currentStatistics();
+ size_t bytesAllocated = statistics.bytesAllocated + sizeInBytes;
+ size_t bytesAvailable = static_cast<size_t>(
+ statistics.bytesReserved * (1 - executablePoolReservationFraction));
+ if (bytesAllocated > bytesAvailable)
+ return nullptr;
+ }
+
RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
if (!result) {
if (effort != JITCompilationCanFail) {
Modified: trunk/Source/_javascript_Core/jsc.cpp (187124 => 187125)
--- trunk/Source/_javascript_Core/jsc.cpp 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/jsc.cpp 2015-07-21 21:41:30 UTC (rev 187125)
@@ -1248,12 +1248,6 @@
ecore_init();
#endif
- // Initialize JSC before getting VM.
-#if ENABLE(SAMPLING_REGIONS)
- WTF::initializeMainThread();
-#endif
- JSC::initializeThreading();
-
if (char* timeoutString = getenv("JSC_timeout")) {
if (sscanf(timeoutString, "%lf", &s_desiredTimeout) != 1) {
dataLog(
@@ -1430,6 +1424,8 @@
void CommandLine::parseArguments(int argc, char** argv)
{
+ Options::initialize();
+
int i = 1;
bool needToDumpOptions = false;
bool needToExit = false;
@@ -1494,8 +1490,7 @@
}
// See if the -- option is a JSC VM option.
- // NOTE: At this point, we know that the arg starts with "--". Skip it.
- if (JSC::Options::setOption(&arg[2])) {
+ if (strstr(arg, "--") == arg && JSC::Options::setOption(&arg[2])) {
// The arg was recognized as a VM option and has been parsed.
continue; // Just continue with the next arg.
}
@@ -1523,6 +1518,13 @@
// Note that the options parsing can affect VM creation, and thus
// comes first.
CommandLine options(argc, argv);
+
+ // Initialize JSC before getting VM.
+#if ENABLE(SAMPLING_REGIONS)
+ WTF::initializeMainThread();
+#endif
+ JSC::initializeThreading();
+
VM* vm = &VM::create(LargeHeap).leakRef();
int result;
{
Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (187124 => 187125)
--- trunk/Source/_javascript_Core/runtime/Options.cpp 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp 2015-07-21 21:41:30 UTC (rev 187125)
@@ -30,6 +30,7 @@
#include <algorithm>
#include <limits>
#include <math.h>
+#include <mutex>
#include <stdlib.h>
#include <string.h>
#include <wtf/DataLog.h>
@@ -201,6 +202,11 @@
return m_state == Normal ? false : true;
}
+void OptionRange::dump(PrintStream& out) const
+{
+ out.print(m_rangeString);
+}
+
Options::Entry Options::s_options[Options::numberOfOptions];
Options::Entry Options::s_defaultOptions[Options::numberOfOptions];
@@ -318,60 +324,66 @@
void Options::initialize()
{
- // Initialize each of the options with their default values:
-#define FOR_EACH_OPTION(type_, name_, defaultValue_, description_) \
- name_() = defaultValue_; \
- name_##Default() = defaultValue_;
- JSC_OPTIONS(FOR_EACH_OPTION)
+ static std::once_flag initializeOptionsOnceFlag;
+
+ std::call_once(
+ initializeOptionsOnceFlag,
+ [] {
+ // Initialize each of the options with their default values:
+#define FOR_EACH_OPTION(type_, name_, defaultValue_, description_) \
+ name_() = defaultValue_; \
+ name_##Default() = defaultValue_;
+ JSC_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION
- // It *probably* makes sense for other platforms to enable this.
+ // It *probably* makes sense for other platforms to enable this.
#if PLATFORM(IOS) && CPU(ARM64)
- enableLLVMFastISel() = true;
+ enableLLVMFastISel() = true;
#endif
- // Allow environment vars to override options if applicable.
- // The evn var should be the name of the option prefixed with
- // "JSC_".
-#define FOR_EACH_OPTION(type_, name_, defaultValue_, description_) \
- overrideOptionWithHeuristic(name_(), "JSC_" #name_);
- JSC_OPTIONS(FOR_EACH_OPTION)
+ // Allow environment vars to override options if applicable.
+ // The evn var should be the name of the option prefixed with
+ // "JSC_".
+#define FOR_EACH_OPTION(type_, name_, defaultValue_, description_) \
+ overrideOptionWithHeuristic(name_(), "JSC_" #name_);
+ JSC_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION
#if 0
- ; // Deconfuse editors that do auto indentation
+ ; // Deconfuse editors that do auto indentation
#endif
- recomputeDependentOptions();
+ recomputeDependentOptions();
- // Do range checks where needed and make corrections to the options:
- ASSERT(Options::thresholdForOptimizeAfterLongWarmUp() >= Options::thresholdForOptimizeAfterWarmUp());
- ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= Options::thresholdForOptimizeSoon());
- ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= 0);
+ // Do range checks where needed and make corrections to the options:
+ ASSERT(Options::thresholdForOptimizeAfterLongWarmUp() >= Options::thresholdForOptimizeAfterWarmUp());
+ ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= Options::thresholdForOptimizeSoon());
+ ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= 0);
- if (Options::showOptions()) {
- DumpLevel level = static_cast<DumpLevel>(Options::showOptions());
- if (level > DumpLevel::Verbose)
- level = DumpLevel::Verbose;
+ if (Options::showOptions()) {
+ DumpLevel level = static_cast<DumpLevel>(Options::showOptions());
+ if (level > DumpLevel::Verbose)
+ level = DumpLevel::Verbose;
- const char* title = nullptr;
- switch (level) {
- case DumpLevel::None:
- break;
- case DumpLevel::Overridden:
- title = "Overridden JSC options:";
- break;
- case DumpLevel::All:
- title = "All JSC options:";
- break;
- case DumpLevel::Verbose:
- title = "All JSC options with descriptions:";
- break;
- }
- dumpAllOptions(level, title);
- }
+ const char* title = nullptr;
+ switch (level) {
+ case DumpLevel::None:
+ break;
+ case DumpLevel::Overridden:
+ title = "Overridden JSC options:";
+ break;
+ case DumpLevel::All:
+ title = "All JSC options:";
+ break;
+ case DumpLevel::Verbose:
+ title = "All JSC options with descriptions:";
+ break;
+ }
+ dumpAllOptions(level, title);
+ }
- ensureOptionsAreCoherent();
+ ensureOptionsAreCoherent();
+ });
}
// Parses a single command line option in the format "<optionName>=<value>"
Modified: trunk/Source/_javascript_Core/runtime/Options.h (187124 => 187125)
--- trunk/Source/_javascript_Core/runtime/Options.h 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2015-07-21 21:41:30 UTC (rev 187125)
@@ -30,6 +30,7 @@
#include "JSExportMacros.h"
#include <stdint.h>
#include <stdio.h>
+#include <wtf/PrintStream.h>
#include <wtf/StdLibExtras.h>
namespace JSC {
@@ -80,6 +81,8 @@
bool init(const char*);
bool isInRange(unsigned);
const char* rangeString() const { return (m_state > InitError) ? m_rangeString : "<null>"; }
+
+ void dump(PrintStream& out) const;
private:
RangeState m_state;
@@ -106,6 +109,7 @@
v(unsigned, errorModeReservedZoneSize, 64 * KB, nullptr) \
\
v(bool, crashIfCantAllocateJITMemory, false, nullptr) \
+ v(unsigned, jitMemoryReservationSize, 0, nullptr) \
\
v(bool, forceDFGCodeBlockLiveness, false, nullptr) \
v(bool, forceICFailure, false, nullptr) \
@@ -350,7 +354,7 @@
gcLogLevelType,
};
- static void initialize();
+ JS_EXPORT_PRIVATE static void initialize();
// Parses a single command line option in the format "<optionName>=<value>"
// (no spaces allowed) and set the specified option if appropriate.
Modified: trunk/Tools/ChangeLog (187124 => 187125)
--- trunk/Tools/ChangeLog 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Tools/ChangeLog 2015-07-21 21:41:30 UTC (rev 187125)
@@ -1,3 +1,16 @@
+2015-07-21 Filip Pizlo <fpi...@apple.com>
+
+ Fixed VM pool allocation should have a reserve for allocations that cannot fail
+ https://bugs.webkit.org/show_bug.cgi?id=147154
+ rdar://problem/21847618
+
+ Reviewed by Geoffrey Garen.
+
+ Add a new test mode where we artificially limit JIT memory to 50KB. If our JIT OOM
+ mitigations work, these should all pass. Prior to this patch there were >20 failures.
+
+ * Scripts/run-jsc-stress-tests:
+
2015-07-20 Carlos Garcia Campos <cgar...@igalia.com>
[GTK] Add API to be notified about editor state changes
Modified: trunk/Tools/Scripts/run-jsc-stress-tests (187124 => 187125)
--- trunk/Tools/Scripts/run-jsc-stress-tests 2015-07-21 21:39:58 UTC (rev 187124)
+++ trunk/Tools/Scripts/run-jsc-stress-tests 2015-07-21 21:41:30 UTC (rev 187125)
@@ -758,6 +758,10 @@
run("ftl-no-cjit-no-access-inlining", "--enableAccessInlining=false", *(FTL_OPTIONS + NO_CJIT_OPTIONS)) if $enableFTL
end
+def runFTLNoCJITSmallPool
+ run("ftl-no-cjit-small-pool", "--jitMemoryReservationSize=50000", *(FTL_OPTIONS + NO_CJIT_OPTIONS)) if $enableFTL
+end
+
def defaultRun
runDefault
runAlwaysTriggerCopyPhase
@@ -771,6 +775,7 @@
runFTLNoCJITNoInlineValidate
runFTLEager
runFTLEagerNoCJITValidate
+ runFTLNoCJITSmallPool
end
end