Diff
Modified: trunk/Source/_javascript_Core/API/JSVirtualMachine.mm (231588 => 231589)
--- trunk/Source/_javascript_Core/API/JSVirtualMachine.mm 2018-05-09 19:59:46 UTC (rev 231588)
+++ trunk/Source/_javascript_Core/API/JSVirtualMachine.mm 2018-05-09 20:11:31 UTC (rev 231589)
@@ -268,6 +268,13 @@
return m_externalRememberedSet;
}
+- (void)shrinkFootprint
+{
+ JSC::VM* vm = toJS(m_group);
+ JSC::JSLockHolder locker(vm);
+ vm->shrinkFootprint();
+}
+
@end
static void scanExternalObjectGraph(JSC::VM& vm, JSC::SlotVisitor& visitor, void* root, bool lockAcquired)
Added: trunk/Source/_javascript_Core/API/JSVirtualMachinePrivate.h (0 => 231589)
--- trunk/Source/_javascript_Core/API/JSVirtualMachinePrivate.h (rev 0)
+++ trunk/Source/_javascript_Core/API/JSVirtualMachinePrivate.h 2018-05-09 20:11:31 UTC (rev 231589)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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 <_javascript_Core/_javascript_.h>
+
+#if JSC_OBJC_API_ENABLED
+
+#import <_javascript_Core/JSVirtualMachine.h>
+
+@interface JSVirtualMachine(JSPrivate)
+
+/*!
+@method
+@discussion Shrinks the memory footprint of the VM by deleting various internal caches,
+ running synchronous garbage collection, and releasing memory back to the OS. For this
+ to free as much memory as possible, do not call this when _javascript_ is running on the stack.
+*/
+
+- (void)shrinkFootprint; // FIXME: Annotate this with NS_AVAILABLE: <rdar://problem/40071332>.
+
+@end
+
+#endif // JSC_OBJC_API_ENABLED
Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (231588 => 231589)
--- trunk/Source/_javascript_Core/API/tests/testapi.mm 2018-05-09 19:59:46 UTC (rev 231588)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm 2018-05-09 20:11:31 UTC (rev 231589)
@@ -28,11 +28,14 @@
#import "CurrentThisInsideBlockGetterTest.h"
#import "DateTests.h"
#import "JSExportTests.h"
+#import "JSVirtualMachinePrivate.h"
#import "Regress141275.h"
#import "Regress141809.h"
#import <pthread.h>
#import <vector>
+#import <wtf/MemoryFootprint.h>
+#import <wtf/Optional.h>
extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef);
extern "C" void JSSynchronousEdenCollectForDebugging(JSContextRef);
@@ -1469,6 +1472,33 @@
checkResult(@"Ran code in five concurrent VMs that GC'd", ok);
}
+ @autoreleasepool {
+ JSContext *context = [[JSContext alloc] init];
+ JSVirtualMachine *vm = [context virtualMachine];
+ [vm shrinkFootprint]; // Make sure that when we allocate a ton of memory below we reuse at little as possible.
+
+ std::optional<size_t> footprintBefore = WTF::memoryFootprint();
+ RELEASE_ASSERT(footprintBefore);
+
+ [context evaluateScript:@"for (let i = 0; i < 10000; ++i) { eval(`myVariable_${i} = [i]`); }"];
+
+ static constexpr size_t approximateBytes = 10000 * sizeof(int);
+ std::optional<size_t> footprintMiddle = WTF::memoryFootprint();
+ RELEASE_ASSERT(footprintMiddle);
+ checkResult(@"Footprint is larger than what we allocated", *footprintMiddle > approximateBytes);
+ checkResult(@"Footprint got larger as we allocated a ton of stuff", *footprintMiddle > *footprintBefore);
+ size_t allocationDelta = *footprintMiddle - *footprintBefore;
+ checkResult(@"We allocated as much or more memory than what we expected to", allocationDelta >= approximateBytes);
+
+ [context evaluateScript:@"for (let i = 0; i < 10000; ++i) { eval(`myVariable_${i} = null`); }"];
+ [vm shrinkFootprint];
+ std::optional<size_t> footprintAfter = WTF::memoryFootprint();
+ RELEASE_ASSERT(footprintAfter);
+ checkResult(@"Footprint got smaller after we shrank the VM", *footprintAfter < *footprintMiddle);
+ size_t freeDelta = *footprintMiddle - *footprintAfter;
+ checkResult(@"Shrinking the footprint of the VM actually freed memory", freeDelta > (approximateBytes / 2));
+ }
+
currentThisInsideBlockGetterTest();
runDateTests();
runJSExportTests();
Modified: trunk/Source/_javascript_Core/ChangeLog (231588 => 231589)
--- trunk/Source/_javascript_Core/ChangeLog 2018-05-09 19:59:46 UTC (rev 231588)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-05-09 20:11:31 UTC (rev 231589)
@@ -1,3 +1,27 @@
+2018-05-09 Saam Barati <[email protected]>
+
+ Add JSVirtualMachine SPI to shrink the memory footprint of the VM
+ https://bugs.webkit.org/show_bug.cgi?id=185441
+ <rdar://problem/39999414>
+
+ Reviewed by Keith Miller.
+
+ This patch adds JSVirtualMachine SPI to release as much memory as possible.
+ The SPI does:
+ - Deletes all code caches.
+ - Synchronous GC.
+ - Run the scavenger.
+
+ * API/JSVirtualMachine.mm:
+ (-[JSVirtualMachine shrinkFootprint]):
+ * API/JSVirtualMachinePrivate.h: Added.
+ * API/tests/testapi.mm:
+ (testObjectiveCAPIMain):
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * runtime/VM.cpp:
+ (JSC::VM::shrinkFootprint):
+ * runtime/VM.h:
+
2018-05-09 Leo Balter <[email protected]>
[JSC] Fix ArraySpeciesCreate to return a new Array when the given object is not an array
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (231588 => 231589)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2018-05-09 19:59:46 UTC (rev 231588)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2018-05-09 20:11:31 UTC (rev 231589)
@@ -1099,6 +1099,7 @@
7919B7801E03559C005BEED8 /* B3Compile.h in Headers */ = {isa = PBXBuildFile; fileRef = 7919B77F1E03559C005BEED8 /* B3Compile.h */; settings = {ATTRIBUTES = (Private, ); }; };
79233C2B1D34715700C5A834 /* JITMathIC.h in Headers */ = {isa = PBXBuildFile; fileRef = 79233C291D34715700C5A834 /* JITMathIC.h */; settings = {ATTRIBUTES = (Private, ); }; };
792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 795AC61820A2355E0052C76C /* JSVirtualMachinePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 795AC61720A2354B0052C76C /* JSVirtualMachinePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
7965C2171E5D799600B7591D /* AirAllocateRegistersByGraphColoring.h in Headers */ = {isa = PBXBuildFile; fileRef = 7965C2151E5D799600B7591D /* AirAllocateRegistersByGraphColoring.h */; settings = {ATTRIBUTES = (Private, ); }; };
796DAA2B1E89CCD6005DF24A /* CalleeBits.h in Headers */ = {isa = PBXBuildFile; fileRef = 796DAA2A1E89CCD6005DF24A /* CalleeBits.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3611,6 +3612,7 @@
79233C291D34715700C5A834 /* JITMathIC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMathIC.h; sourceTree = "<group>"; };
792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCToCodeOriginMap.cpp; sourceTree = "<group>"; };
792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCToCodeOriginMap.h; sourceTree = "<group>"; };
+ 795AC61720A2354B0052C76C /* JSVirtualMachinePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSVirtualMachinePrivate.h; sourceTree = "<group>"; };
795F099C1E03600500BBE37F /* B3Compile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Compile.cpp; path = b3/B3Compile.cpp; sourceTree = "<group>"; };
796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = "<group>"; };
7965C2141E5D799600B7591D /* AirAllocateRegistersByGraphColoring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateRegistersByGraphColoring.cpp; path = b3/air/AirAllocateRegistersByGraphColoring.cpp; sourceTree = "<group>"; };
@@ -5848,6 +5850,7 @@
14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */,
1482B6EA0A4300B300517CFC /* JSValueRef.h */,
86E3C60F167BAB87006D760A /* JSVirtualMachine.h */,
+ 795AC61720A2354B0052C76C /* JSVirtualMachinePrivate.h */,
86E3C610167BAB87006D760A /* JSVirtualMachine.mm */,
86E3C611167BAB87006D760A /* JSVirtualMachineInternal.h */,
A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */,
@@ -8594,6 +8597,7 @@
0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */,
0F392C8A1B46188400844728 /* DFGOSRExitFuzz.h in Headers */,
+ 795AC61820A2355E0052C76C /* JSVirtualMachinePrivate.h in Headers */,
0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */,
0F235BEE17178E7300690C7F /* DFGOSRExitPreparation.h in Headers */,
0F6237981AE45CA700D402EA /* DFGPhantomInsertionPhase.h in Headers */,
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (231588 => 231589)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2018-05-09 19:59:46 UTC (rev 231588)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2018-05-09 20:11:31 UTC (rev 231589)
@@ -771,6 +771,16 @@
});
}
+void VM::shrinkFootprint()
+{
+ sanitizeStackForVM(this);
+ deleteAllCode(DeleteAllCodeIfNotCollecting);
+ heap.collectSync();
+ WTF::releaseFastMallocFreeMemory();
+ // FIXME: Consider stopping various automatic threads here.
+ // https://bugs.webkit.org/show_bug.cgi?id=185447
+}
+
SourceProviderCache* VM::addSourceProviderCache(SourceProvider* sourceProvider)
{
auto addResult = sourceProviderCacheMap.add(sourceProvider, nullptr);
Modified: trunk/Source/_javascript_Core/runtime/VM.h (231588 => 231589)
--- trunk/Source/_javascript_Core/runtime/VM.h 2018-05-09 19:59:46 UTC (rev 231588)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2018-05-09 20:11:31 UTC (rev 231589)
@@ -746,6 +746,8 @@
JS_EXPORT_PRIVATE void deleteAllCode(DeleteAllCodeEffort);
JS_EXPORT_PRIVATE void deleteAllLinkedCode(DeleteAllCodeEffort);
+ void shrinkFootprint();
+
WatchpointSet* ensureWatchpointSetForImpureProperty(const Identifier&);
void registerWatchpointForImpureProperty(const Identifier&, Watchpoint*);