GC allocation trigger should be tuned to system RAM
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 May 2012 19:17:57 +0000 (19:17 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 May 2012 19:17:57 +0000 (19:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=87039

Reviewed by Darin Adler.

../JavaScriptCore:

This helps avoid OOM crashes on small platforms, and helps avoid "too much GC"
performance issues on big platforms.

* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::collect):
* heap/Heap.h:
(Heap): GC balances between a fixed minimum and a proportional multiplier,
which are limited based on system RAM.

* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::createContextGroup):
(JSC::JSGlobalData::create):
(JSC::JSGlobalData::createLeaked):
* runtime/JSGlobalData.h:
(JSGlobalData): Renamed HeapSize to HeapType because the exact size is
influenced by the heap type, but not determined by it.

../WTF:

Added a helper function for measuring system RAM.

* GNUmakefile.list.am:
* WTF.gypi:
* WTF.pro:
* WTF.vcproj/WTF.vcproj:
* WTF.xcodeproj/project.pbxproj:
* wtf/AmountOfRAM.cpp: Added.
(WTF):
(WTF::computeAmountOfRAM):
(WTF::amountOfRAM):
* wtf/AmountOfRAM.h: Added.
(WTF):
* wtf/CMakeLists.txt:
* wtf/StdLibExtras.h:
(WTF):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@118019 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/runtime/JSGlobalData.cpp
Source/JavaScriptCore/runtime/JSGlobalData.h
Source/WTF/ChangeLog
Source/WTF/GNUmakefile.list.am
Source/WTF/WTF.gypi
Source/WTF/WTF.pro
Source/WTF/WTF.vcproj/WTF.vcproj
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/RAMSize.cpp [new file with mode: 0644]
Source/WTF/wtf/RAMSize.h [new file with mode: 0644]
Source/WTF/wtf/StdLibExtras.h

index c2c86e196000a562f81d83f77027fb80c871217f..b424fb12abf661d6b3456b74377704225476507c 100644 (file)
@@ -1,3 +1,29 @@
+2011-05-21  Geoffrey Garen  <ggaren@apple.com>
+
+        GC allocation trigger should be tuned to system RAM
+        https://bugs.webkit.org/show_bug.cgi?id=87039
+
+        Reviewed by Darin Adler.
+
+        This helps avoid OOM crashes on small platforms, and helps avoid "too much GC"
+        performance issues on big platforms.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::collect):
+        * heap/Heap.h:
+        (Heap): GC balances between a fixed minimum and a proportional multiplier,
+        which are limited based on system RAM.
+
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::JSGlobalData):
+        (JSC::JSGlobalData::createContextGroup):
+        (JSC::JSGlobalData::create):
+        (JSC::JSGlobalData::createLeaked):
+        * runtime/JSGlobalData.h:
+        (JSGlobalData): Renamed HeapSize to HeapType because the exact size is
+        influenced by the heap type, but not determined by it.
+
 2012-05-21  Gavin Barraclough  <barraclough@apple.com>
 
         Disable private names by default in WebCore
index 347db83f1ea9c0b7ca80e97faca9579cde9a2489..6d5828c4462efe331846d93d5595a46acd8b7844 100755 (executable)
@@ -102,13 +102,13 @@ EXPORTS
     ?convertUTF16ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPB_WPB_WPAPADPAD_N@Z
     ?convertUTF8ToUTF16@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBDPBDPAPA_WPA_W_N@Z
     ?create@JSFunction@JSC@@SAPAV12@PAVExecState@2@PAVJSGlobalObject@2@HABVUString@2@P6I_J0@ZW4Intrinsic@2@3@Z
-    ?create@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@W4HeapSize@2@@Z
+    ?create@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@W4HeapType@2@@Z
     ?create@OpaqueJSString@@SA?AV?$PassRefPtr@UOpaqueJSString@@@WTF@@ABVUString@JSC@@@Z
     ?create@RegExp@JSC@@SAPAV12@AAVJSGlobalData@2@ABVUString@2@W4RegExpFlags@2@@Z
     ?createEmptyString@SmallStrings@JSC@@AAEXPAVJSGlobalData@2@@Z
     ?createError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z
     ?createInterruptedExecutionException@JSC@@YAPAVJSObject@1@PAVJSGlobalData@1@@Z
-    ?createLeaked@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@W4HeapSize@2@@Z
+    ?createLeaked@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@W4HeapType@2@@Z
     ?createNotEnoughArgumentsError@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z
     ?createRangeError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z
     ?createReferenceError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z
index 2ee02ae31160d7fcc39477247056a562c89cb92e..182858774b056b666668e4484efc365a3b5f023c 100644 (file)
@@ -35,9 +35,9 @@
 #include "Tracing.h"
 #include "WeakSetInlines.h"
 #include <algorithm>
+#include <wtf/RAMSize.h>
 #include <wtf/CurrentTime.h>
 
-
 using namespace std;
 using namespace JSC;
 
@@ -45,14 +45,8 @@ namespace JSC {
 
 namespace { 
 
-#if CPU(X86) || CPU(X86_64)
-static const size_t largeHeapSize = 16 * 1024 * 1024;
-#elif PLATFORM(IOS)
-static const size_t largeHeapSize = 8 * 1024 * 1024;
-#else
-static const size_t largeHeapSize = 512 * 1024;
-#endif
-static const size_t smallHeapSize = 512 * 1024;
+static const size_t largeHeapSize = 32 * MB; // About 1.5X the average webpage.
+static const size_t smallHeapSize = 1 * MB; // Matches the FastMalloc per-thread cache.
 
 #if ENABLE(GC_LOGGING)
 #if COMPILER(CLANG)
@@ -148,14 +142,23 @@ struct GCCounter {
 #define GCCOUNTER(name, value) do { } while (false)
 #endif
 
-static size_t heapSizeForHint(HeapSize heapSize)
+static inline size_t minHeapSize(HeapType heapType, size_t ramSize)
 {
-    if (heapSize == LargeHeap)
-        return largeHeapSize;
-    ASSERT(heapSize == SmallHeap);
+    if (heapType == LargeHeap)
+        return min(largeHeapSize, ramSize / 4);
     return smallHeapSize;
 }
 
+static inline size_t proportionalHeapSize(size_t heapSize, size_t ramSize)
+{
+    // Try to stay under 1/2 RAM size to leave room for the DOM, rendering, networking, etc.
+    if (heapSize < ramSize / 4)
+        return 2 * heapSize;
+    if (heapSize < ramSize / 2)
+        return 1.5 * heapSize;
+    return 1.25 * heapSize;
+}
+
 static inline bool isValidSharedInstanceThreadState()
 {
     if (!JSLock::lockCount())
@@ -230,9 +233,10 @@ inline PassOwnPtr<TypeCountSet> RecordType::returnValue()
 
 } // anonymous namespace
 
-Heap::Heap(JSGlobalData* globalData, HeapSize heapSize)
-    : m_heapSize(heapSize)
-    , m_minBytesPerCycle(heapSizeForHint(heapSize))
+Heap::Heap(JSGlobalData* globalData, HeapType heapType)
+    : m_heapType(heapType)
+    , m_ramSize(ramSize())
+    , m_minBytesPerCycle(minHeapSize(m_heapType, m_ramSize))
     , m_sizeAfterLastCollect(0)
     , m_bytesAllocatedLimit(m_minBytesPerCycle)
     , m_bytesAllocated(0)
@@ -722,15 +726,15 @@ void Heap::collect(SweepToggle sweepToggle)
         m_bytesAbandoned = 0;
     }
 
-    // To avoid pathological GC churn in large heaps, we set the new allocation 
-    // limit to be the current size of the heap. This heuristic 
-    // is a bit arbitrary. Using the current size of the heap after this 
-    // collection gives us a 2X multiplier, which is a 1:1 (heap size :
-    // new bytes allocated) proportion, and seems to work well in benchmarks.
-    size_t newSize = size();
+    size_t currentHeapSize = size();
     if (fullGC) {
-        m_sizeAfterLastCollect = newSize;
-        m_bytesAllocatedLimit = max(newSize, m_minBytesPerCycle);
+        m_sizeAfterLastCollect = currentHeapSize;
+
+        // To avoid pathological GC churn in very small and very large heaps, we set
+        // the new allocation limit based on the current size of the heap, with a
+        // fixed minimum.
+        size_t maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize));
+        m_bytesAllocatedLimit = maxHeapSize - currentHeapSize;
     }
     m_bytesAllocated = 0;
     double lastGCEndTime = WTF::currentTime();
index 6bf82e4a578eecdc3facbf62518ebca9ad3d1fbf..dc681e894804927d409de711de81dd07533d78e2 100644 (file)
@@ -65,8 +65,7 @@ namespace JSC {
 
     enum OperationInProgress { NoOperation, Allocation, Collection };
 
-    // Heap size hint.
-    enum HeapSize { SmallHeap, LargeHeap };
+    enum HeapType { SmallHeap, LargeHeap };
 
     class Heap {
         WTF_MAKE_NONCOPYABLE(Heap);
@@ -90,7 +89,7 @@ namespace JSC {
         static void writeBarrier(const JSCell*, JSCell*);
         static uint8_t* addressOfCardFor(JSCell*);
 
-        Heap(JSGlobalData*, HeapSize);
+        Heap(JSGlobalData*, HeapType);
         ~Heap();
         JS_EXPORT_PRIVATE void lastChanceToFinalize();
 
@@ -197,7 +196,8 @@ namespace JSC {
         RegisterFile& registerFile();
         BlockAllocator& blockAllocator();
 
-        const HeapSize m_heapSize;
+        const HeapType m_heapType;
+        const size_t m_ramSize;
         const size_t m_minBytesPerCycle;
         size_t m_sizeAfterLastCollect;
 
index dd03ab4e9dcc981ad8d6bc534f92b2c7e18addac..a13eb79c500d1cbe8e7dfb00a06b63c710b3cf62 100644 (file)
@@ -118,8 +118,8 @@ static bool enableAssembler(ExecutableAllocator& executableAllocator)
 }
 #endif
 
-JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize)
-    : heap(this, heapSize)
+JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapType heapType)
+    : heap(this, heapType)
     , globalDataType(globalDataType)
     , clientData(0)
     , topCallFrame(CallFrame::noCaller())
@@ -290,19 +290,19 @@ JSGlobalData::~JSGlobalData()
 #endif
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapSize heapSize)
+PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapType heapType)
 {
-    return adoptRef(new JSGlobalData(APIContextGroup, type, heapSize));
+    return adoptRef(new JSGlobalData(APIContextGroup, type, heapType));
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapSize heapSize)
+PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapType heapType)
 {
-    return adoptRef(new JSGlobalData(Default, type, heapSize));
+    return adoptRef(new JSGlobalData(Default, type, heapType));
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapSize heapSize)
+PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapType heapType)
 {
-    return create(type, heapSize);
+    return create(type, heapType);
 }
 
 bool JSGlobalData::sharedInstanceExists()
index c8efde77f6b131a9f11c042e32eefcabf3941a33..c39a01920283b5cc9552fee4cda6163272b5b826 100644 (file)
@@ -172,9 +172,9 @@ namespace JSC {
         static bool sharedInstanceExists();
         JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
 
-        JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap);
-        JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap);
-        static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapSize = SmallHeap);
+        JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapType = SmallHeap);
+        JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapType = SmallHeap);
+        static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapType = SmallHeap);
         JS_EXPORT_PRIVATE ~JSGlobalData();
 
         void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
@@ -405,7 +405,7 @@ namespace JSC {
     private:
         friend class LLIntOffsetsExtractor;
         
-        JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
+        JSGlobalData(GlobalDataType, ThreadStackType, HeapType);
         static JSGlobalData*& sharedInstanceInternal();
         void createNativeThunk();
 #if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
index 15816bca72f3118b9abd06fa7c9b189c301f959b..84dc62ce453804498076f1e7ecff053ae5e39d26 100644 (file)
@@ -1,3 +1,27 @@
+2012-05-21  Geoffrey Garen  <ggaren@apple.com>
+
+        GC allocation trigger should be tuned to system RAM
+        https://bugs.webkit.org/show_bug.cgi?id=87039
+
+        Reviewed by Darin Adler.
+
+        Added a helper function for measuring system RAM.
+
+        * GNUmakefile.list.am:
+        * WTF.gypi:
+        * WTF.pro:
+        * WTF.vcproj/WTF.vcproj:
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/AmountOfRAM.cpp: Added.
+        (WTF):
+        (WTF::computeAmountOfRAM):
+        (WTF::amountOfRAM):
+        * wtf/AmountOfRAM.h: Added.
+        (WTF):
+        * wtf/CMakeLists.txt:
+        * wtf/StdLibExtras.h:
+        (WTF):
+
 2012-05-22  Allan Sandfeld Jensen  <allan.jensen@nokia.com>
 
         GCC 4.7 and C++11 support.
index 3f9aea9eb8719a4c33f1098a20a9f531162c6c69..2267810cde01f28a70e51bc5c72f2c85ccba25e2 100644 (file)
@@ -85,6 +85,8 @@ wtf_sources += \
     Source/WTF/wtf/NullPtr.h \
     Source/WTF/wtf/NumberOfCores.cpp \
     Source/WTF/wtf/NumberOfCores.h \
+    Source/WTF/wtf/RAMSize.cpp \
+    Source/WTF/wtf/RAMSize.h \
     Source/WTF/wtf/OSAllocator.h \
     Source/WTF/wtf/OSRandomSource.cpp \
     Source/WTF/wtf/OSRandomSource.h \
index 60474edeb1d0d79f3a22e3c4efb7578c8af93962..8675855061d374efaffe7d62e153deb11bbad039 100644 (file)
             'wtf/NullPtr.cpp',
             'wtf/NumberOfCores.cpp',
             'wtf/NumberOfCores.h',
+            'wtf/RAMSize.cpp',
+            'wtf/RAMSize.h',
             'wtf/OSAllocatorPosix.cpp',
             'wtf/OSAllocatorWin.cpp',
             'wtf/OSRandomSource.cpp',
index 46cf7caed71f49a9378dffa6d4e36b37cb5dca44..06ba5cb7152c268d3e23459cf1e43a5c3e696551 100644 (file)
@@ -84,6 +84,7 @@ HEADERS += \
     NotFound.h \
     NullPtr.h \
     NumberOfCores.h \
+    RAMSize.h \
     OSAllocator.h \
     OSRandomSource.h \
     OwnArrayPtr.h \
@@ -191,6 +192,7 @@ SOURCES += \
     MetaAllocator.cpp \
     NullPtr.cpp \
     NumberOfCores.cpp \
+    RAMSize.cpp \
     OSRandomSource.cpp \
     qt/MainThreadQt.cpp \
     qt/StringQt.cpp \
index 0392a8d37ec38d7bad1d366c36060452e06b87ea..2190dae1effeae33953327e3cb73e77e6ee46d58 100644 (file)
                        RelativePath="..\wtf\NullPtr.h"
                        >
                </File>
+               <File
+                       RelativePath="..\wtf\RAMSize.cpp"
+                       >
+               </File>
+               <File
+                       RelativePath="..\wtf\RAMSize.h"
+                       >
+               </File>
                <File
                        RelativePath="..\wtf\NumberOfCores.cpp"
                        >
index e75142fa81a76ac5b82a8b4ad4c3ddbdd9b34593..ba457643fb3ba1d516b3ef91169aaa1bc70a557e 100644 (file)
@@ -7,6 +7,8 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143F611D1565F0F900DB514A /* RAMSize.cpp */; };
+               143F61201565F0F900DB514A /* RAMSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 143F611E1565F0F900DB514A /* RAMSize.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FD81AC5154FB22E00983E72 /* FastBitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD81AC4154FB22E00983E72 /* FastBitVector.h */; settings = {ATTRIBUTES = (); }; };
                4F0321BC156AA8D1006EBAF6 /* BitArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F0321BB156AA8D1006EBAF6 /* BitArray.h */; };
                A876DBD8151816E500DADB95 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = A876DBD7151816E500DADB95 /* Platform.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+               143F611D1565F0F900DB514A /* RAMSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RAMSize.cpp; sourceTree = "<group>"; };
+               143F611E1565F0F900DB514A /* RAMSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAMSize.h; sourceTree = "<group>"; };
                0FD81AC4154FB22E00983E72 /* FastBitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastBitVector.h; sourceTree = "<group>"; };
                4F0321BB156AA8D1006EBAF6 /* BitArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitArray.h; sourceTree = "<group>"; };
                5D247B6214689B8600E78B76 /* libWTF.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; };
                A876DBD6151816E500DADB95 /* wtf */ = {
                        isa = PBXGroup;
                        children = (
+                               143F611D1565F0F900DB514A /* RAMSize.cpp */,
+                               143F611E1565F0F900DB514A /* RAMSize.h */,
                                A8A47254151A825A004123FF /* Alignment.h */,
                                A8A47255151A825A004123FF /* AlwaysInline.h */,
                                A8A47256151A825A004123FF /* ArrayBuffer.cpp */,
                                A8A47480151A825B004123FF /* VMTags.h in Headers */,
                                A8A47487151A825B004123FF /* WTFThreadData.h in Headers */,
                                A8A4748C151A8264004123FF /* config.h in Headers */,
+                               143F61201565F0F900DB514A /* RAMSize.h in Headers */,
                                0FD81AC5154FB22E00983E72 /* FastBitVector.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                                A8A47477151A825B004123FF /* URLEscape.cpp in Sources */,
                                A8A4747B151A825B004123FF /* URLSegments.cpp in Sources */,
                                A8A47486151A825B004123FF /* WTFThreadData.cpp in Sources */,
+                               143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index cdcca680abb949699f1c50e93923ec84b2ff41ec..274f04c9749319aef480447916dd22827250868f 100644 (file)
@@ -52,6 +52,7 @@ SET(WTF_HEADERS
     NotFound.h
     NullPtr.h
     NumberOfCores.h
+    RAMSize.h
     OSAllocator.h
     OSRandomSource.h
     OwnArrayPtr.h
@@ -149,6 +150,7 @@ SET(WTF_SOURCES
     MetaAllocator.cpp
     OSRandomSource.cpp
     NumberOfCores.cpp
+    RAMSize.cpp
     PageAllocationAligned.cpp
     PageBlock.cpp
     ParallelJobsGeneric.cpp
diff --git a/Source/WTF/wtf/RAMSize.cpp b/Source/WTF/wtf/RAMSize.cpp
new file mode 100644 (file)
index 0000000..b93b7d8
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``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 ITS 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 "RAMSize.h"
+
+#include "StdLibExtras.h"
+#if OS(DARWIN)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#elif OS(UNIX)
+#include <unistd.h>
+#elif OS(WINDOWS)
+#include <windows.h>
+#endif
+
+namespace WTF {
+
+static const size_t ramSizeGuess = 128 * MB;
+
+static size_t computeRAMSize()
+{
+#if OS(DARWIN)
+    int mib[2];
+    int64_t ramSize;
+    size_t length;
+
+    mib[0] = CTL_HW;
+    mib[1] = HW_MEMSIZE;
+    length = sizeof(int64_t);
+    int sysctlResult = sysctl(mib, 2, &ramSize, &length, 0, 0);
+    if (sysctlResult == -1)
+        return ramSizeGuess;
+    return ramSize;
+#elif OS(UNIX)
+    long pages = sysconf(_SC_PHYS_PAGES);
+    long pageSize = sysconf(_SC_PAGE_SIZE);
+    if (pages == -1 || pageSize == -1)
+        return ramSizeGuess;
+    return pages * pageSize;
+#elif OS(WINDOWS)
+    MEMORYSTATUSEX status;
+    status.dwLength = sizeof(status);
+    bool result = GlobalMemoryStatusEx(&status);
+    if (!result)
+        return ramSizeGuess;
+    return status.ullTotalPhys;
+#endif
+}
+
+size_t ramSize()
+{
+    static const size_t ramSize = computeRAMSize();
+    return ramSize;
+}
+
+} // namespace WTF
diff --git a/Source/WTF/wtf/RAMSize.h b/Source/WTF/wtf/RAMSize.h
new file mode 100644 (file)
index 0000000..cafb4fa
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#ifndef RAMSize_h
+#define RAMSize_h
+
+namespace WTF {
+
+WTF_EXPORT_PRIVATE size_t ramSize();
+
+}
+
+using WTF::ramSize;
+
+#endif // RAMSize_h
index 8a3c3614aab0bc61565a7b2e2332470b5219c208..89e549893688bbf8be7072e4fca343385982e93c 100644 (file)
@@ -108,6 +108,7 @@ TypePtr reinterpret_cast_ptr(const void* ptr)
 namespace WTF {
 
 static const size_t KB = 1024;
+static const size_t MB = 1024 * 1024;
 
 inline bool isPointerAligned(void* p)
 {
@@ -304,6 +305,7 @@ inline void* operator new(size_t, NotNullTag, void* location)
 }
 
 using WTF::KB;
+using WTF::MB;
 using WTF::isPointerAligned;
 using WTF::is8ByteAligned;
 using WTF::binarySearch;