<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[212867] trunk/Source</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/212867">212867</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2017-02-22 17:37:32 -0800 (Wed, 22 Feb 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Remove the demand executable allocator
https://bugs.webkit.org/show_bug.cgi?id=168754
Reviewed by Saam Barati.
Source/JavaScriptCore:
We currently only use the demand executable allocator for non-iOS 32-bit platforms.
Benchmark results on a MBP indicate there is no appreciable performance difference
between a the fixed and demand allocators. In a future patch I will go back through
this code and remove more of the abstractions.
* JavaScriptCore.xcodeproj/project.pbxproj:
* jit/ExecutableAllocator.cpp:
(JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator):
(JSC::FixedVMPoolExecutableAllocator::initializeSeparatedWXHeaps):
(JSC::FixedVMPoolExecutableAllocator::jitWriteThunkGenerator):
(JSC::FixedVMPoolExecutableAllocator::genericWriteToJITRegion):
(JSC::ExecutableAllocator::initializeAllocator):
(JSC::ExecutableAllocator::ExecutableAllocator):
(JSC::FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator):
(JSC::ExecutableAllocator::isValid):
(JSC::ExecutableAllocator::underMemoryPressure):
(JSC::ExecutableAllocator::memoryPressureMultiplier):
(JSC::ExecutableAllocator::allocate):
(JSC::ExecutableAllocator::isValidExecutableMemory):
(JSC::ExecutableAllocator::getLock):
(JSC::ExecutableAllocator::committedByteCount):
(JSC::ExecutableAllocator::dumpProfile):
(JSC::DemandExecutableAllocator::DemandExecutableAllocator): Deleted.
(JSC::DemandExecutableAllocator::~DemandExecutableAllocator): Deleted.
(JSC::DemandExecutableAllocator::bytesAllocatedByAllAllocators): Deleted.
(JSC::DemandExecutableAllocator::bytesCommittedByAllocactors): Deleted.
(JSC::DemandExecutableAllocator::dumpProfileFromAllAllocators): Deleted.
(JSC::DemandExecutableAllocator::allocateNewSpace): Deleted.
(JSC::DemandExecutableAllocator::notifyNeedPage): Deleted.
(JSC::DemandExecutableAllocator::notifyPageIsFree): Deleted.
(JSC::DemandExecutableAllocator::allocators): Deleted.
(JSC::DemandExecutableAllocator::allocatorsMutex): Deleted.
* jit/ExecutableAllocator.h:
* jit/ExecutableAllocatorFixedVMPool.cpp: Removed.
* jit/JITStubRoutine.h:
(JSC::JITStubRoutine::canPerformRangeFilter):
(JSC::JITStubRoutine::filteringStartAddress):
(JSC::JITStubRoutine::filteringExtentSize):
Source/WTF:
* wtf/Platform.h:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorejitExecutableAllocatorcpp">trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitExecutableAllocatorh">trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITStubRoutineh">trunk/Source/JavaScriptCore/jit/JITStubRoutine.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfPlatformh">trunk/Source/WTF/wtf/Platform.h</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorejitExecutableAllocatorFixedVMPoolcpp">trunk/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -580,7 +580,6 @@
</span><span class="cx"> jit/CallFrameShuffler64.cpp
</span><span class="cx"> jit/ExecutableAllocationFuzz.cpp
</span><span class="cx"> jit/ExecutableAllocator.cpp
</span><del>- jit/ExecutableAllocatorFixedVMPool.cpp
</del><span class="cx"> jit/GCAwareJITStubRoutine.cpp
</span><span class="cx"> jit/GPRInfo.cpp
</span><span class="cx"> jit/HostCallReturnValue.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2017-02-22 Keith Miller <keith_miller@apple.com>
+
+ Remove the demand executable allocator
+ https://bugs.webkit.org/show_bug.cgi?id=168754
+
+ Reviewed by Saam Barati.
+
+ We currently only use the demand executable allocator for non-iOS 32-bit platforms.
+ Benchmark results on a MBP indicate there is no appreciable performance difference
+ between a the fixed and demand allocators. In a future patch I will go back through
+ this code and remove more of the abstractions.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * jit/ExecutableAllocator.cpp:
+ (JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator):
+ (JSC::FixedVMPoolExecutableAllocator::initializeSeparatedWXHeaps):
+ (JSC::FixedVMPoolExecutableAllocator::jitWriteThunkGenerator):
+ (JSC::FixedVMPoolExecutableAllocator::genericWriteToJITRegion):
+ (JSC::ExecutableAllocator::initializeAllocator):
+ (JSC::ExecutableAllocator::ExecutableAllocator):
+ (JSC::FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator):
+ (JSC::ExecutableAllocator::isValid):
+ (JSC::ExecutableAllocator::underMemoryPressure):
+ (JSC::ExecutableAllocator::memoryPressureMultiplier):
+ (JSC::ExecutableAllocator::allocate):
+ (JSC::ExecutableAllocator::isValidExecutableMemory):
+ (JSC::ExecutableAllocator::getLock):
+ (JSC::ExecutableAllocator::committedByteCount):
+ (JSC::ExecutableAllocator::dumpProfile):
+ (JSC::DemandExecutableAllocator::DemandExecutableAllocator): Deleted.
+ (JSC::DemandExecutableAllocator::~DemandExecutableAllocator): Deleted.
+ (JSC::DemandExecutableAllocator::bytesAllocatedByAllAllocators): Deleted.
+ (JSC::DemandExecutableAllocator::bytesCommittedByAllocactors): Deleted.
+ (JSC::DemandExecutableAllocator::dumpProfileFromAllAllocators): Deleted.
+ (JSC::DemandExecutableAllocator::allocateNewSpace): Deleted.
+ (JSC::DemandExecutableAllocator::notifyNeedPage): Deleted.
+ (JSC::DemandExecutableAllocator::notifyPageIsFree): Deleted.
+ (JSC::DemandExecutableAllocator::allocators): Deleted.
+ (JSC::DemandExecutableAllocator::allocatorsMutex): Deleted.
+ * jit/ExecutableAllocator.h:
+ * jit/ExecutableAllocatorFixedVMPool.cpp: Removed.
+ * jit/JITStubRoutine.h:
+ (JSC::JITStubRoutine::canPerformRangeFilter):
+ (JSC::JITStubRoutine::filteringStartAddress):
+ (JSC::JITStubRoutine::filteringExtentSize):
+
</ins><span class="cx"> 2017-02-22 Saam Barati <sbarati@apple.com>
</span><span class="cx">
</span><span class="cx"> Add biased coloring to Briggs and IRC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -1553,7 +1553,6 @@
</span><span class="cx">                 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; };
</del><span class="cx">                 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 86E3C612167BABD7006D760A /* JSValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E3C606167BAB87006D760A /* JSValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
</span><span class="cx">                 86E3C613167BABD7006D760A /* JSContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E3C607167BAB87006D760A /* JSContext.h */; settings = {ATTRIBUTES = (Public, ); }; };
</span><span class="lines">@@ -4072,7 +4071,6 @@
</span><span class="cx">                 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBufferWithConstantPool.h; sourceTree = "<group>"; };
</span><span class="cx">                 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARM.h; sourceTree = "<group>"; };
</span><span class="cx">                 86D3B3C110159D7F002865E7 /* LinkBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkBuffer.h; sourceTree = "<group>"; };
</span><del>-                86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; };
</del><span class="cx">                 86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; };
</span><span class="cx">                 86E3C606167BAB87006D760A /* JSValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSValue.h; sourceTree = "<group>"; };
</span><span class="cx">                 86E3C607167BAB87006D760A /* JSContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSContext.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -5664,7 +5662,6 @@
</span><span class="cx">                                 0FF054F81AC35B4400E5BE57 /* ExecutableAllocationFuzz.h */,
</span><span class="cx">                                 A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
</span><span class="cx">                                 A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
</span><del>-                                86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */,
</del><span class="cx">                                 0F24E53E17EA9F5900ABB217 /* FPRInfo.h */,
</span><span class="cx">                                 0F766D2D15A8DCDD008F363E /* GCAwareJITStubRoutine.cpp */,
</span><span class="cx">                                 0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */,
</span><span class="lines">@@ -10151,7 +10148,6 @@
</span><span class="cx">                                 FE6491391D78F3AF00A694D4 /* ExceptionScope.cpp in Sources */,
</span><span class="cx">                                 0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
</span><span class="cx">                                 A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */,
</span><del>-                                86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */,
</del><span class="cx">                                 147341EA1DC2CF2500AA29BA /* ExecutableBase.cpp in Sources */,
</span><span class="cx">                                 0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */,
</span><span class="cx">                                 0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitExecutableAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008-2009, 2015, 2017 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -20,151 +20,299 @@
</span><span class="cx"> * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
</span><span class="cx"> * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
</span><span class="cx"> * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
</span><del>- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</del><ins>+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</ins><span class="cx"> */
</span><span class="cx">
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "ExecutableAllocator.h"
</span><span class="cx">
</span><ins>+#include "CodeProfiling.h"
+#include "ExecutableAllocationFuzz.h"
</ins><span class="cx"> #include "JSCInlines.h"
</span><del>-
-#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
-#include "CodeProfiling.h"
-#include <wtf/HashSet.h>
-#include <wtf/Lock.h>
</del><span class="cx"> #include <wtf/MetaAllocator.h>
</span><del>-#include <wtf/NeverDestroyed.h>
</del><span class="cx"> #include <wtf/PageReservation.h>
</span><del>-#include <wtf/VMTags.h>
</del><ins>+
+#if OS(DARWIN)
+#include <sys/mman.h>
</ins><span class="cx"> #endif
</span><span class="cx">
</span><del>-// Uncomment to create an artificial executable memory usage limit. This limit
-// is imperfect and is primarily useful for testing the VM's ability to handle
-// out-of-executable-memory situations.
-// #define EXECUTABLE_MEMORY_LIMIT 1000000
</del><ins>+#include "LinkBuffer.h"
+#include "MacroAssembler.h"
</ins><span class="cx">
</span><del>-#if ENABLE(ASSEMBLER)
</del><ins>+#if PLATFORM(MAC) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
+#define HAVE_REMAP_JIT 1
+#endif
</ins><span class="cx">
</span><ins>+#if HAVE(REMAP_JIT)
+#if CPU(ARM64) && PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
+#define USE_EXECUTE_ONLY_JIT_WRITE_FUNCTION 1
+#endif
+#endif
+
+#if OS(DARWIN)
+#include <mach/mach.h>
+extern "C" {
+ /* Routine mach_vm_remap */
+#ifdef mig_external
+ mig_external
+#else
+ extern
+#endif /* mig_external */
+ kern_return_t mach_vm_remap
+ (
+ vm_map_t target_task,
+ mach_vm_address_t *target_address,
+ mach_vm_size_t size,
+ mach_vm_offset_t mask,
+ int flags,
+ vm_map_t src_task,
+ mach_vm_address_t src_address,
+ boolean_t copy,
+ vm_prot_t *cur_protection,
+ vm_prot_t *max_protection,
+ vm_inherit_t inheritance
+ );
+}
+
+#endif
+
</ins><span class="cx"> using namespace WTF;
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><del>-#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
</del><ins>+JS_EXPORTDATA uintptr_t startOfFixedExecutableMemoryPool;
+JS_EXPORTDATA uintptr_t endOfFixedExecutableMemoryPool;
</ins><span class="cx">
</span><del>-class DemandExecutableAllocator : public MetaAllocator {
</del><ins>+JS_EXPORTDATA JITWriteFunction jitWriteFunction;
+
+#if !USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION) && HAVE(REMAP_JIT)
+static uintptr_t startOfFixedWritableMemoryPool;
+#endif
+
+class FixedVMPoolExecutableAllocator : public MetaAllocator {
+ WTF_MAKE_FAST_ALLOCATED;
</ins><span class="cx"> public:
</span><del>- DemandExecutableAllocator()
- : MetaAllocator(jitAllocationGranule)
</del><ins>+ FixedVMPoolExecutableAllocator()
+ : MetaAllocator(jitAllocationGranule) // round up all allocations to 32 bytes
</ins><span class="cx"> {
</span><del>- std::lock_guard<StaticLock> lock(allocatorsMutex());
- allocators().add(this);
- // Don't preallocate any memory here.
- }
-
- virtual ~DemandExecutableAllocator()
- {
- {
- std::lock_guard<StaticLock> lock(allocatorsMutex());
- allocators().remove(this);
</del><ins>+ size_t reservationSize;
+ if (Options::jitMemoryReservationSize())
+ reservationSize = Options::jitMemoryReservationSize();
+ else
+ reservationSize = fixedExecutableMemoryPoolSize;
+ reservationSize = roundUpToMultipleOf(pageSize(), reservationSize);
+ m_reservation = PageReservation::reserveWithGuardPages(reservationSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+ if (m_reservation) {
+ ASSERT(m_reservation.size() == reservationSize);
+ void* reservationBase = m_reservation.base();
+
+ if (Options::useSeparatedWXHeap()) {
+ // First page of our JIT allocation is reserved.
+ ASSERT(reservationSize >= pageSize() * 2);
+ reservationBase = (void*)((uintptr_t)reservationBase + pageSize());
+ reservationSize -= pageSize();
+ initializeSeparatedWXHeaps(m_reservation.base(), pageSize(), reservationBase, reservationSize);
+ }
+
+ addFreshFreeSpace(reservationBase, reservationSize);
+
+ startOfFixedExecutableMemoryPool = reinterpret_cast<uintptr_t>(reservationBase);
+ endOfFixedExecutableMemoryPool = startOfFixedExecutableMemoryPool + reservationSize;
</ins><span class="cx"> }
</span><del>- for (unsigned i = 0; i < reservations.size(); ++i)
- reservations.at(i).deallocate();
</del><span class="cx"> }
</span><span class="cx">
</span><del>- static size_t bytesAllocatedByAllAllocators()
</del><ins>+ virtual ~FixedVMPoolExecutableAllocator();
+
+protected:
+ void* allocateNewSpace(size_t&) override
</ins><span class="cx"> {
</span><del>- size_t total = 0;
- std::lock_guard<StaticLock> lock(allocatorsMutex());
- for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
- total += (*allocator)->bytesAllocated();
- return total;
</del><ins>+ // We're operating in a fixed pool, so new allocation is always prohibited.
+ return 0;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static size_t bytesCommittedByAllocactors()
</del><ins>+ void notifyNeedPage(void* page) override
</ins><span class="cx"> {
</span><del>- size_t total = 0;
- std::lock_guard<StaticLock> lock(allocatorsMutex());
- for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
- total += (*allocator)->bytesCommitted();
- return total;
</del><ins>+#if USE(MADV_FREE_FOR_JIT_MEMORY)
+ UNUSED_PARAM(page);
+#else
+ m_reservation.commit(page, pageSize());
+#endif
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-#if ENABLE(META_ALLOCATOR_PROFILE)
- static void dumpProfileFromAllAllocators()
</del><ins>+ void notifyPageIsFree(void* page) override
</ins><span class="cx"> {
</span><del>- std::lock_guard<StaticLock> lock(allocatorsMutex());
- for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
- (*allocator)->dumpProfile();
</del><ins>+#if USE(MADV_FREE_FOR_JIT_MEMORY)
+ for (;;) {
+ int result = madvise(page, pageSize(), MADV_FREE);
+ if (!result)
+ return;
+ ASSERT(result == -1);
+ if (errno != EAGAIN) {
+ RELEASE_ASSERT_NOT_REACHED(); // In debug mode, this should be a hard failure.
+ break; // In release mode, we should just ignore the error - not returning memory to the OS is better than crashing, especially since we _will_ be able to reuse the memory internally anyway.
+ }
+ }
+#else
+ m_reservation.decommit(page, pageSize());
+#endif
</ins><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><del>-protected:
- virtual void* allocateNewSpace(size_t& numPages)
</del><ins>+private:
+#if OS(DARWIN) && HAVE(REMAP_JIT)
+ void initializeSeparatedWXHeaps(void* stubBase, size_t stubSize, void* jitBase, size_t jitSize)
</ins><span class="cx"> {
</span><del>- size_t newNumPages = (((numPages * pageSize() + JIT_ALLOCATOR_LARGE_ALLOC_SIZE - 1) / JIT_ALLOCATOR_LARGE_ALLOC_SIZE * JIT_ALLOCATOR_LARGE_ALLOC_SIZE) + pageSize() - 1) / pageSize();
-
- ASSERT(newNumPages >= numPages);
-
- numPages = newNumPages;
-
-#ifdef EXECUTABLE_MEMORY_LIMIT
- if (bytesAllocatedByAllAllocators() >= EXECUTABLE_MEMORY_LIMIT)
- return 0;
</del><ins>+ mach_vm_address_t writableAddr = 0;
+
+ // Create a second mapping of the JIT region at a random address.
+ vm_prot_t cur, max;
+ int remapFlags = VM_FLAGS_ANYWHERE;
+#if defined(VM_FLAGS_RANDOM_ADDR)
+ remapFlags |= VM_FLAGS_RANDOM_ADDR;
</ins><span class="cx"> #endif
</span><del>-
- PageReservation reservation = PageReservation::reserve(numPages * pageSize(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
- RELEASE_ASSERT(reservation);
-
- reservations.append(reservation);
-
- return reservation.base();
</del><ins>+ kern_return_t ret = mach_vm_remap(mach_task_self(), &writableAddr, jitSize, 0,
+ remapFlags,
+ mach_task_self(), (mach_vm_address_t)jitBase, FALSE,
+ &cur, &max, VM_INHERIT_DEFAULT);
+
+ bool remapSucceeded = (ret == KERN_SUCCESS);
+ if (!remapSucceeded)
+ return;
+
+ // Assemble a thunk that will serve as the means for writing into the JIT region.
+ MacroAssemblerCodeRef writeThunk = jitWriteThunkGenerator(reinterpret_cast<void*>(writableAddr), stubBase, stubSize);
+
+ int result = 0;
+
+#if USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION)
+ // Prevent reading the write thunk code.
+ result = mprotect(stubBase, stubSize, VM_PROT_EXECUTE_ONLY);
+ RELEASE_ASSERT(!result);
+#endif
+
+ // Prevent writing into the executable JIT mapping.
+ result = mprotect(jitBase, jitSize, VM_PROT_READ | VM_PROT_EXECUTE);
+ RELEASE_ASSERT(!result);
+
+ // Prevent execution in the writable JIT mapping.
+ result = mprotect((void*)writableAddr, jitSize, VM_PROT_READ | VM_PROT_WRITE);
+ RELEASE_ASSERT(!result);
+
+ // Zero out writableAddr to avoid leaking the address of the writable mapping.
+ memset_s(&writableAddr, sizeof(writableAddr), 0, sizeof(writableAddr));
+
+ jitWriteFunction = reinterpret_cast<JITWriteFunction>(writeThunk.code().executableAddress());
</ins><span class="cx"> }
</span><del>-
- virtual void notifyNeedPage(void* page)
</del><ins>+
+#if CPU(ARM64) && USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION)
+ MacroAssemblerCodeRef jitWriteThunkGenerator(void* writableAddr, void* stubBase, size_t stubSize)
</ins><span class="cx"> {
</span><del>- OSAllocator::commit(page, pageSize(), EXECUTABLE_POOL_WRITABLE, true);
</del><ins>+ using namespace ARM64Registers;
+ using TrustedImm32 = MacroAssembler::TrustedImm32;
+
+ MacroAssembler jit;
+
+ jit.move(MacroAssembler::TrustedImmPtr(writableAddr), x7);
+ jit.addPtr(x7, x0);
+
+ jit.move(x0, x3);
+ MacroAssembler::Jump smallCopy = jit.branch64(MacroAssembler::Below, x2, MacroAssembler::TrustedImm64(64));
+
+ jit.add64(TrustedImm32(32), x3);
+ jit.and64(TrustedImm32(-32), x3);
+ jit.loadPair64(x1, x12, x13);
+ jit.loadPair64(x1, TrustedImm32(16), x14, x15);
+ jit.sub64(x3, x0, x5);
+ jit.addPtr(x5, x1);
+
+ jit.loadPair64(x1, x8, x9);
+ jit.loadPair64(x1, TrustedImm32(16), x10, x11);
+ jit.add64(TrustedImm32(32), x1);
+ jit.sub64(x5, x2);
+ jit.storePair64(x12, x13, x0);
+ jit.storePair64(x14, x15, x0, TrustedImm32(16));
+ MacroAssembler::Jump cleanup = jit.branchSub64(MacroAssembler::BelowOrEqual, TrustedImm32(64), x2);
+
+ MacroAssembler::Label copyLoop = jit.label();
+ jit.storePair64WithNonTemporalAccess(x8, x9, x3);
+ jit.storePair64WithNonTemporalAccess(x10, x11, x3, TrustedImm32(16));
+ jit.add64(TrustedImm32(32), x3);
+ jit.loadPair64WithNonTemporalAccess(x1, x8, x9);
+ jit.loadPair64WithNonTemporalAccess(x1, TrustedImm32(16), x10, x11);
+ jit.add64(TrustedImm32(32), x1);
+ jit.branchSub64(MacroAssembler::Above, TrustedImm32(32), x2).linkTo(copyLoop, &jit);
+
+ cleanup.link(&jit);
+ jit.add64(x2, x1);
+ jit.loadPair64(x1, x12, x13);
+ jit.loadPair64(x1, TrustedImm32(16), x14, x15);
+ jit.storePair64(x8, x9, x3);
+ jit.storePair64(x10, x11, x3, TrustedImm32(16));
+ jit.addPtr(x2, x3);
+ jit.storePair64(x12, x13, x3, TrustedImm32(32));
+ jit.storePair64(x14, x15, x3, TrustedImm32(48));
+ jit.ret();
+
+ MacroAssembler::Label local0 = jit.label();
+ jit.load64(x1, PostIndex(8), x6);
+ jit.store64(x6, x3, PostIndex(8));
+ smallCopy.link(&jit);
+ jit.branchSub64(MacroAssembler::AboveOrEqual, TrustedImm32(8), x2).linkTo(local0, &jit);
+ MacroAssembler::Jump local2 = jit.branchAdd64(MacroAssembler::Equal, TrustedImm32(8), x2);
+ MacroAssembler::Label local1 = jit.label();
+ jit.load8(x1, PostIndex(1), x6);
+ jit.store8(x6, x3, PostIndex(1));
+ jit.branchSub64(MacroAssembler::NotEqual, TrustedImm32(1), x2).linkTo(local1, &jit);
+ local2.link(&jit);
+ jit.ret();
+
+ LinkBuffer linkBuffer(jit, stubBase, stubSize);
+ // We don't use FINALIZE_CODE() for two reasons.
+ // The first is that we don't want the writeable address, as disassembled instructions,
+ // to appear in the console or anywhere in memory, via the PrintStream buffer.
+ // The second is we can't guarantee that the code is readable when using the
+ // asyncDisassembly option as our caller will set our pages execute only.
+ return linkBuffer.finalizeCodeWithoutDisassembly();
</ins><span class="cx"> }
</span><del>-
- virtual void notifyPageIsFree(void* page)
</del><ins>+#else // CPU(ARM64) && USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION)
+ static void genericWriteToJITRegion(off_t offset, const void* data, size_t dataSize)
</ins><span class="cx"> {
</span><del>- OSAllocator::decommit(page, pageSize());
</del><ins>+ memcpy((void*)(startOfFixedWritableMemoryPool + offset), data, dataSize);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-private:
- Vector<PageReservation, 16> reservations;
- static HashSet<DemandExecutableAllocator*>& allocators()
</del><ins>+ MacroAssemblerCodeRef jitWriteThunkGenerator(void* address, void*, size_t)
</ins><span class="cx"> {
</span><del>- static NeverDestroyed<HashSet<DemandExecutableAllocator*>> set;
- return set;
</del><ins>+ startOfFixedWritableMemoryPool = reinterpret_cast<uintptr_t>(address);
+ uintptr_t function = (uintptr_t)((void*)&genericWriteToJITRegion);
+#if CPU(ARM_THUMB2)
+ // Handle thumb offset
+ function -= 1;
+#endif
+ return MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr((void*)function));
</ins><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx">
</span><del>- static StaticLock& allocatorsMutex()
</del><ins>+#else // OS(DARWIN) && HAVE(REMAP_JIT)
+ void initializeSeparatedWXHeaps(void*, size_t, void*, size_t)
</ins><span class="cx"> {
</span><del>- static StaticLock mutex;
</del><ins>+ }
+#endif
</ins><span class="cx">
</span><del>- return mutex;
- }
</del><ins>+private:
+ PageReservation m_reservation;
</ins><span class="cx"> };
</span><span class="cx">
</span><del>-static DemandExecutableAllocator* gAllocator;
</del><ins>+static FixedVMPoolExecutableAllocator* allocator;
</ins><span class="cx">
</span><del>-namespace {
-static inline DemandExecutableAllocator* allocator()
-{
- return gAllocator;
-}
-}
-
</del><span class="cx"> void ExecutableAllocator::initializeAllocator()
</span><span class="cx"> {
</span><del>- ASSERT(!gAllocator);
- gAllocator = new DemandExecutableAllocator();
- CodeProfiling::notifyAllocator(gAllocator);
</del><ins>+ ASSERT(!allocator);
+ allocator = new FixedVMPoolExecutableAllocator();
+ CodeProfiling::notifyAllocator(allocator);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ExecutableAllocator::ExecutableAllocator(VM&)
</span><span class="cx"> {
</span><del>- ASSERT(allocator());
</del><ins>+ ASSERT(allocator);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ExecutableAllocator::~ExecutableAllocator()
</span><span class="lines">@@ -171,70 +319,97 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator()
+{
+ m_reservation.deallocate();
+}
+
</ins><span class="cx"> bool ExecutableAllocator::isValid() const
</span><span class="cx"> {
</span><del>- return true;
</del><ins>+ return !!allocator->bytesReserved();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool ExecutableAllocator::underMemoryPressure()
</span><span class="cx"> {
</span><del>-#ifdef EXECUTABLE_MEMORY_LIMIT
- return DemandExecutableAllocator::bytesAllocatedByAllAllocators() > EXECUTABLE_MEMORY_LIMIT / 2;
-#else
- return false;
-#endif
</del><ins>+ MetaAllocator::Statistics statistics = allocator->currentStatistics();
+ return statistics.bytesAllocated > statistics.bytesReserved / 2;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
</span><span class="cx"> {
</span><del>- double result;
-#ifdef EXECUTABLE_MEMORY_LIMIT
- size_t bytesAllocated = DemandExecutableAllocator::bytesAllocatedByAllAllocators() + addedMemoryUsage;
- if (bytesAllocated >= EXECUTABLE_MEMORY_LIMIT)
- bytesAllocated = EXECUTABLE_MEMORY_LIMIT;
- result = static_cast<double>(EXECUTABLE_MEMORY_LIMIT) /
- (EXECUTABLE_MEMORY_LIMIT - bytesAllocated);
-#else
- UNUSED_PARAM(addedMemoryUsage);
- result = 1.0;
-#endif
</del><ins>+ MetaAllocator::Statistics statistics = allocator->currentStatistics();
+ ASSERT(statistics.bytesAllocated <= statistics.bytesReserved);
+ size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage;
+ size_t bytesAvailable = static_cast<size_t>(
+ statistics.bytesReserved * (1 - executablePoolReservationFraction));
+ if (bytesAllocated >= bytesAvailable)
+ bytesAllocated = bytesAvailable;
+ double result = 1.0;
+ size_t divisor = bytesAvailable - bytesAllocated;
+ if (divisor)
+ result = static_cast<double>(bytesAvailable) / divisor;
</ins><span class="cx"> if (result < 1.0)
</span><span class="cx"> result = 1.0;
</span><span class="cx"> return result;
</span><del>-
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(VM&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
</span><span class="cx"> {
</span><del>- RefPtr<ExecutableMemoryHandle> result = allocator()->allocate(sizeInBytes, ownerUID);
- RELEASE_ASSERT(result || effort != JITCompilationMustSucceed);
</del><ins>+ if (Options::logExecutableAllocation()) {
+ MetaAllocator::Statistics stats = allocator->currentStatistics();
+ dataLog("Allocating ", sizeInBytes, " bytes of executable memory with ", stats.bytesAllocated, " bytes allocated, ", stats.bytesReserved, " bytes reserved, and ", stats.bytesCommitted, " committed.\n");
+ }
+
+ if (effort != JITCompilationCanFail && Options::reportMustSucceedExecutableAllocations()) {
+ dataLog("Allocating ", sizeInBytes, " bytes of executable memory with JITCompilationMustSucceed.\n");
+ WTFReportBacktrace();
+ }
+
+ if (effort == JITCompilationCanFail
+ && 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) {
+ dataLog("Ran out of executable memory while allocating ", sizeInBytes, " bytes.\n");
+ CRASH();
+ }
+ return nullptr;
+ }
</ins><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-size_t ExecutableAllocator::committedByteCount()
</del><ins>+bool ExecutableAllocator::isValidExecutableMemory(const LockHolder& locker, void* address)
</ins><span class="cx"> {
</span><del>- return DemandExecutableAllocator::bytesCommittedByAllocactors();
</del><ins>+ return allocator->isInAllocatedMemory(locker, address);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-#if ENABLE(META_ALLOCATOR_PROFILE)
-void ExecutableAllocator::dumpProfile()
</del><ins>+Lock& ExecutableAllocator::getLock() const
</ins><span class="cx"> {
</span><del>- DemandExecutableAllocator::dumpProfileFromAllAllocators();
</del><ins>+ return allocator->getLock();
</ins><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><del>-Lock& ExecutableAllocator::getLock() const
</del><ins>+size_t ExecutableAllocator::committedByteCount()
</ins><span class="cx"> {
</span><del>- return gAllocator->getLock();
</del><ins>+ return allocator->bytesCommitted();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-bool ExecutableAllocator::isValidExecutableMemory(const LockHolder& locker, void* address)
</del><ins>+#if ENABLE(META_ALLOCATOR_PROFILE)
+void ExecutableAllocator::dumpProfile()
</ins><span class="cx"> {
</span><del>- return gAllocator->isInAllocatedMemory(locker, address);
</del><ins>+ allocator->dumpProfile();
</ins><span class="cx"> }
</span><del>-
-#endif // ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
-
</del><ins>+#endif
+
</ins><span class="cx"> }
</span><del>-
-#endif // HAVE(ASSEMBLER)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorejitExecutableAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/jit/ExecutableAllocator.h        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2017 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -60,11 +60,6 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(ASSEMBLER)
</span><span class="cx">
</span><del>-#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
-class DemandExecutableAllocator;
-#endif
-
-#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
</del><span class="cx"> #if defined(FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB) && FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB > 0
</span><span class="cx"> static const size_t fixedExecutableMemoryPoolSize = FIXED_EXECUTABLE_MEMORY_POOL_SIZE_IN_MB * 1024 * 1024;
</span><span class="cx"> #elif CPU(ARM)
</span><span class="lines">@@ -102,13 +97,6 @@
</span><span class="cx"> return memcpy(dst, src, n);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#else // ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
-static inline void* performJITMemcpy(void *dst, const void *src, size_t n)
-{
- return memcpy(dst, src, n);
-}
-#endif
-
</del><span class="cx"> class ExecutableAllocator {
</span><span class="cx"> enum ProtectionSetting { Writable, Executable };
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitExecutableAllocatorFixedVMPoolcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -1,421 +0,0 @@
</span><del>-/*
- * 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
- * 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 "ExecutableAllocator.h"
-
-#include "JSCInlines.h"
-
-#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
-
-#include "CodeProfiling.h"
-#include "ExecutableAllocationFuzz.h"
-#include <wtf/MetaAllocator.h>
-#include <wtf/PageReservation.h>
-
-#if OS(DARWIN)
-#include <sys/mman.h>
-#endif
-
-#include "LinkBuffer.h"
-#include "MacroAssembler.h"
-
-#if PLATFORM(MAC) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
-#define HAVE_REMAP_JIT 1
-#endif
-
-#if HAVE(REMAP_JIT)
-#if CPU(ARM64) && PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
-#define USE_EXECUTE_ONLY_JIT_WRITE_FUNCTION 1
-#endif
-#endif
-
-#if OS(DARWIN)
-#include <mach/mach.h>
-extern "C" {
- /* Routine mach_vm_remap */
-#ifdef mig_external
- mig_external
-#else
- extern
-#endif /* mig_external */
- kern_return_t mach_vm_remap
- (
- vm_map_t target_task,
- mach_vm_address_t *target_address,
- mach_vm_size_t size,
- mach_vm_offset_t mask,
- int flags,
- vm_map_t src_task,
- mach_vm_address_t src_address,
- boolean_t copy,
- vm_prot_t *cur_protection,
- vm_prot_t *max_protection,
- vm_inherit_t inheritance
- );
-}
-
-#endif
-
-using namespace WTF;
-
-namespace JSC {
-
-JS_EXPORTDATA uintptr_t startOfFixedExecutableMemoryPool;
-JS_EXPORTDATA uintptr_t endOfFixedExecutableMemoryPool;
-
-JS_EXPORTDATA JITWriteFunction jitWriteFunction;
-
-#if !USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION) && HAVE(REMAP_JIT)
-static uintptr_t startOfFixedWritableMemoryPool;
-#endif
-
-class FixedVMPoolExecutableAllocator : public MetaAllocator {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- FixedVMPoolExecutableAllocator()
- : MetaAllocator(jitAllocationGranule) // round up all allocations to 32 bytes
- {
- size_t reservationSize;
- if (Options::jitMemoryReservationSize())
- reservationSize = Options::jitMemoryReservationSize();
- else
- reservationSize = fixedExecutableMemoryPoolSize;
- reservationSize = roundUpToMultipleOf(pageSize(), reservationSize);
- m_reservation = PageReservation::reserveWithGuardPages(reservationSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
- if (m_reservation) {
- ASSERT(m_reservation.size() == reservationSize);
- void* reservationBase = m_reservation.base();
-
- if (Options::useSeparatedWXHeap()) {
- // First page of our JIT allocation is reserved.
- ASSERT(reservationSize >= pageSize() * 2);
- reservationBase = (void*)((uintptr_t)reservationBase + pageSize());
- reservationSize -= pageSize();
- initializeSeparatedWXHeaps(m_reservation.base(), pageSize(), reservationBase, reservationSize);
- }
-
- addFreshFreeSpace(reservationBase, reservationSize);
-
- startOfFixedExecutableMemoryPool = reinterpret_cast<uintptr_t>(reservationBase);
- endOfFixedExecutableMemoryPool = startOfFixedExecutableMemoryPool + reservationSize;
- }
- }
-
- virtual ~FixedVMPoolExecutableAllocator();
-
-protected:
- void* allocateNewSpace(size_t&) override
- {
- // We're operating in a fixed pool, so new allocation is always prohibited.
- return 0;
- }
-
- void notifyNeedPage(void* page) override
- {
-#if USE(MADV_FREE_FOR_JIT_MEMORY)
- UNUSED_PARAM(page);
-#else
- m_reservation.commit(page, pageSize());
-#endif
- }
-
- void notifyPageIsFree(void* page) override
- {
-#if USE(MADV_FREE_FOR_JIT_MEMORY)
- for (;;) {
- int result = madvise(page, pageSize(), MADV_FREE);
- if (!result)
- return;
- ASSERT(result == -1);
- if (errno != EAGAIN) {
- RELEASE_ASSERT_NOT_REACHED(); // In debug mode, this should be a hard failure.
- break; // In release mode, we should just ignore the error - not returning memory to the OS is better than crashing, especially since we _will_ be able to reuse the memory internally anyway.
- }
- }
-#else
- m_reservation.decommit(page, pageSize());
-#endif
- }
-
-private:
-#if OS(DARWIN) && HAVE(REMAP_JIT)
- void initializeSeparatedWXHeaps(void* stubBase, size_t stubSize, void* jitBase, size_t jitSize)
- {
- mach_vm_address_t writableAddr = 0;
-
- // Create a second mapping of the JIT region at a random address.
- vm_prot_t cur, max;
- int remapFlags = VM_FLAGS_ANYWHERE;
-#if defined(VM_FLAGS_RANDOM_ADDR)
- remapFlags |= VM_FLAGS_RANDOM_ADDR;
-#endif
- kern_return_t ret = mach_vm_remap(mach_task_self(), &writableAddr, jitSize, 0,
- remapFlags,
- mach_task_self(), (mach_vm_address_t)jitBase, FALSE,
- &cur, &max, VM_INHERIT_DEFAULT);
-
- bool remapSucceeded = (ret == KERN_SUCCESS);
- if (!remapSucceeded)
- return;
-
- // Assemble a thunk that will serve as the means for writing into the JIT region.
- MacroAssemblerCodeRef writeThunk = jitWriteThunkGenerator(reinterpret_cast<void*>(writableAddr), stubBase, stubSize);
-
- int result = 0;
-
-#if USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION)
- // Prevent reading the write thunk code.
- result = mprotect(stubBase, stubSize, VM_PROT_EXECUTE_ONLY);
- RELEASE_ASSERT(!result);
-#endif
-
- // Prevent writing into the executable JIT mapping.
- result = mprotect(jitBase, jitSize, VM_PROT_READ | VM_PROT_EXECUTE);
- RELEASE_ASSERT(!result);
-
- // Prevent execution in the writable JIT mapping.
- result = mprotect((void*)writableAddr, jitSize, VM_PROT_READ | VM_PROT_WRITE);
- RELEASE_ASSERT(!result);
-
- // Zero out writableAddr to avoid leaking the address of the writable mapping.
- memset_s(&writableAddr, sizeof(writableAddr), 0, sizeof(writableAddr));
-
- jitWriteFunction = reinterpret_cast<JITWriteFunction>(writeThunk.code().executableAddress());
- }
-
-#if CPU(ARM64) && USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION)
- MacroAssemblerCodeRef jitWriteThunkGenerator(void* writableAddr, void* stubBase, size_t stubSize)
- {
- using namespace ARM64Registers;
- using TrustedImm32 = MacroAssembler::TrustedImm32;
-
- MacroAssembler jit;
-
- jit.move(MacroAssembler::TrustedImmPtr(writableAddr), x7);
- jit.addPtr(x7, x0);
-
- jit.move(x0, x3);
- MacroAssembler::Jump smallCopy = jit.branch64(MacroAssembler::Below, x2, MacroAssembler::TrustedImm64(64));
-
- jit.add64(TrustedImm32(32), x3);
- jit.and64(TrustedImm32(-32), x3);
- jit.loadPair64(x1, x12, x13);
- jit.loadPair64(x1, TrustedImm32(16), x14, x15);
- jit.sub64(x3, x0, x5);
- jit.addPtr(x5, x1);
-
- jit.loadPair64(x1, x8, x9);
- jit.loadPair64(x1, TrustedImm32(16), x10, x11);
- jit.add64(TrustedImm32(32), x1);
- jit.sub64(x5, x2);
- jit.storePair64(x12, x13, x0);
- jit.storePair64(x14, x15, x0, TrustedImm32(16));
- MacroAssembler::Jump cleanup = jit.branchSub64(MacroAssembler::BelowOrEqual, TrustedImm32(64), x2);
-
- MacroAssembler::Label copyLoop = jit.label();
- jit.storePair64WithNonTemporalAccess(x8, x9, x3);
- jit.storePair64WithNonTemporalAccess(x10, x11, x3, TrustedImm32(16));
- jit.add64(TrustedImm32(32), x3);
- jit.loadPair64WithNonTemporalAccess(x1, x8, x9);
- jit.loadPair64WithNonTemporalAccess(x1, TrustedImm32(16), x10, x11);
- jit.add64(TrustedImm32(32), x1);
- jit.branchSub64(MacroAssembler::Above, TrustedImm32(32), x2).linkTo(copyLoop, &jit);
-
- cleanup.link(&jit);
- jit.add64(x2, x1);
- jit.loadPair64(x1, x12, x13);
- jit.loadPair64(x1, TrustedImm32(16), x14, x15);
- jit.storePair64(x8, x9, x3);
- jit.storePair64(x10, x11, x3, TrustedImm32(16));
- jit.addPtr(x2, x3);
- jit.storePair64(x12, x13, x3, TrustedImm32(32));
- jit.storePair64(x14, x15, x3, TrustedImm32(48));
- jit.ret();
-
- MacroAssembler::Label local0 = jit.label();
- jit.load64(x1, PostIndex(8), x6);
- jit.store64(x6, x3, PostIndex(8));
- smallCopy.link(&jit);
- jit.branchSub64(MacroAssembler::AboveOrEqual, TrustedImm32(8), x2).linkTo(local0, &jit);
- MacroAssembler::Jump local2 = jit.branchAdd64(MacroAssembler::Equal, TrustedImm32(8), x2);
- MacroAssembler::Label local1 = jit.label();
- jit.load8(x1, PostIndex(1), x6);
- jit.store8(x6, x3, PostIndex(1));
- jit.branchSub64(MacroAssembler::NotEqual, TrustedImm32(1), x2).linkTo(local1, &jit);
- local2.link(&jit);
- jit.ret();
-
- LinkBuffer linkBuffer(jit, stubBase, stubSize);
- // We don't use FINALIZE_CODE() for two reasons.
- // The first is that we don't want the writeable address, as disassembled instructions,
- // to appear in the console or anywhere in memory, via the PrintStream buffer.
- // The second is we can't guarantee that the code is readable when using the
- // asyncDisassembly option as our caller will set our pages execute only.
- return linkBuffer.finalizeCodeWithoutDisassembly();
- }
-#else // CPU(ARM64) && USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION)
- static void genericWriteToJITRegion(off_t offset, const void* data, size_t dataSize)
- {
- memcpy((void*)(startOfFixedWritableMemoryPool + offset), data, dataSize);
- }
-
- MacroAssemblerCodeRef jitWriteThunkGenerator(void* address, void*, size_t)
- {
- startOfFixedWritableMemoryPool = reinterpret_cast<uintptr_t>(address);
- uintptr_t function = (uintptr_t)((void*)&genericWriteToJITRegion);
-#if CPU(ARM_THUMB2)
- // Handle thumb offset
- function -= 1;
-#endif
- return MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr((void*)function));
- }
-#endif
-
-#else // OS(DARWIN) && HAVE(REMAP_JIT)
- void initializeSeparatedWXHeaps(void*, size_t, void*, size_t)
- {
- }
-#endif
-
-private:
- PageReservation m_reservation;
-};
-
-static FixedVMPoolExecutableAllocator* allocator;
-
-void ExecutableAllocator::initializeAllocator()
-{
- ASSERT(!allocator);
- allocator = new FixedVMPoolExecutableAllocator();
- CodeProfiling::notifyAllocator(allocator);
-}
-
-ExecutableAllocator::ExecutableAllocator(VM&)
-{
- ASSERT(allocator);
-}
-
-ExecutableAllocator::~ExecutableAllocator()
-{
-}
-
-FixedVMPoolExecutableAllocator::~FixedVMPoolExecutableAllocator()
-{
- m_reservation.deallocate();
-}
-
-bool ExecutableAllocator::isValid() const
-{
- return !!allocator->bytesReserved();
-}
-
-bool ExecutableAllocator::underMemoryPressure()
-{
- MetaAllocator::Statistics statistics = allocator->currentStatistics();
- return statistics.bytesAllocated > statistics.bytesReserved / 2;
-}
-
-double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
-{
- MetaAllocator::Statistics statistics = allocator->currentStatistics();
- ASSERT(statistics.bytesAllocated <= statistics.bytesReserved);
- size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage;
- size_t bytesAvailable = static_cast<size_t>(
- statistics.bytesReserved * (1 - executablePoolReservationFraction));
- if (bytesAllocated >= bytesAvailable)
- bytesAllocated = bytesAvailable;
- double result = 1.0;
- size_t divisor = bytesAvailable - bytesAllocated;
- if (divisor)
- result = static_cast<double>(bytesAvailable) / divisor;
- if (result < 1.0)
- result = 1.0;
- return result;
-}
-
-RefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(VM&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
-{
- if (Options::logExecutableAllocation()) {
- MetaAllocator::Statistics stats = allocator->currentStatistics();
- dataLog("Allocating ", sizeInBytes, " bytes of executable memory with ", stats.bytesAllocated, " bytes allocated, ", stats.bytesReserved, " bytes reserved, and ", stats.bytesCommitted, " committed.\n");
- }
-
- if (effort != JITCompilationCanFail && Options::reportMustSucceedExecutableAllocations()) {
- dataLog("Allocating ", sizeInBytes, " bytes of executable memory with JITCompilationMustSucceed.\n");
- WTFReportBacktrace();
- }
-
- if (effort == JITCompilationCanFail
- && 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) {
- dataLog("Ran out of executable memory while allocating ", sizeInBytes, " bytes.\n");
- CRASH();
- }
- return nullptr;
- }
- return result;
-}
-
-bool ExecutableAllocator::isValidExecutableMemory(const LockHolder& locker, void* address)
-{
- return allocator->isInAllocatedMemory(locker, address);
-}
-
-Lock& ExecutableAllocator::getLock() const
-{
- return allocator->getLock();
-}
-
-size_t ExecutableAllocator::committedByteCount()
-{
- return allocator->bytesCommitted();
-}
-
-#if ENABLE(META_ALLOCATOR_PROFILE)
-void ExecutableAllocator::dumpProfile()
-{
- allocator->dumpProfile();
-}
-#endif
-
-}
-
-
-#endif // ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITStubRoutineh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITStubRoutine.h (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITStubRoutine.h        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/JavaScriptCore/jit/JITStubRoutine.h        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -97,29 +97,15 @@
</span><span class="cx">
</span><span class="cx"> static bool canPerformRangeFilter()
</span><span class="cx"> {
</span><del>-#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
</del><span class="cx"> return true;
</span><del>-#else
- return false;
-#endif
</del><span class="cx"> }
</span><span class="cx"> static uintptr_t filteringStartAddress()
</span><span class="cx"> {
</span><del>-#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
</del><span class="cx"> return startOfFixedExecutableMemoryPool;
</span><del>-#else
- UNREACHABLE_FOR_PLATFORM();
- return 0;
-#endif
</del><span class="cx"> }
</span><span class="cx"> static size_t filteringExtentSize()
</span><span class="cx"> {
</span><del>-#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
</del><span class="cx"> return fixedExecutableMemoryPoolSize;
</span><del>-#else
- UNREACHABLE_FOR_PLATFORM();
- return 0;
-#endif
</del><span class="cx"> }
</span><span class="cx"> static bool passesFilter(uintptr_t address)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/WTF/ChangeLog        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2017-02-22 Keith Miller <keith_miller@apple.com>
+
+ Remove the demand executable allocator
+ https://bugs.webkit.org/show_bug.cgi?id=168754
+
+ Reviewed by Saam Barati.
+
+ * wtf/Platform.h:
+
</ins><span class="cx"> 2017-02-22 Alex Christensen <achristensen@webkit.org>
</span><span class="cx">
</span><span class="cx"> Re-commit part of r212812 accidentally rolled out with r212841.
</span></span></pre></div>
<a id="trunkSourceWTFwtfPlatformh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Platform.h (212866 => 212867)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Platform.h        2017-02-23 01:18:31 UTC (rev 212866)
+++ trunk/Source/WTF/wtf/Platform.h        2017-02-23 01:37:32 UTC (rev 212867)
</span><span class="lines">@@ -909,16 +909,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>-/* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in.
- On non-Windows x86-64, iOS, and ARM64 we use a single fixed mmap, on other platforms we mmap on demand. */
-#if ENABLE(ASSEMBLER)
-#if CPU(X86_64) || PLATFORM(IOS) || CPU(ARM64)
-#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1
-#else
-#define ENABLE_EXECUTABLE_ALLOCATOR_DEMAND 1
-#endif
-#endif
-
</del><span class="cx"> /* CSS Selector JIT Compiler */
</span><span class="cx"> #if !defined(ENABLE_CSS_SELECTOR_JIT)
</span><span class="cx"> #if (CPU(X86_64) || CPU(ARM64) || (CPU(ARM_THUMB2) && PLATFORM(IOS))) && ENABLE(JIT) && (OS(DARWIN) || PLATFORM(GTK))
</span></span></pre>
</div>
</div>
</body>
</html>