Add functions to measure memory footprint to JSC
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Sep 2018 00:42:29 +0000 (00:42 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Sep 2018 00:42:29 +0000 (00:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189768

Reviewed by Saam Barati.

Provide system memory metrics for the current process to aid in memory reduction measurement and
tuning using native JS tests.

* jsc.cpp:
(MemoryFootprint::now):
(MemoryFootprint::resetPeak):
(GlobalObject::finishCreation):
(JSCMemoryFootprint::JSCMemoryFootprint):
(JSCMemoryFootprint::createStructure):
(JSCMemoryFootprint::create):
(JSCMemoryFootprint::finishCreation):
(JSCMemoryFootprint::addProperty):
(functionResetMemoryPeak):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jsc.cpp

index 0a2708d..eaf909f 100644 (file)
@@ -1,3 +1,24 @@
+2018-09-19  Michael Saboff  <msaboff@apple.com>
+
+        Add functions to measure memory footprint to JSC
+        https://bugs.webkit.org/show_bug.cgi?id=189768
+
+        Reviewed by Saam Barati.
+
+        Provide system memory metrics for the current process to aid in memory reduction measurement and
+        tuning using native JS tests.
+
+        * jsc.cpp:
+        (MemoryFootprint::now):
+        (MemoryFootprint::resetPeak):
+        (GlobalObject::finishCreation):
+        (JSCMemoryFootprint::JSCMemoryFootprint):
+        (JSCMemoryFootprint::createStructure):
+        (JSCMemoryFootprint::create):
+        (JSCMemoryFootprint::finishCreation):
+        (JSCMemoryFootprint::addProperty):
+        (functionResetMemoryPeak):
+
 2018-09-19  Saam barati  <sbarati@apple.com>
 
         CheckStructureOrEmpty should pass in a tempGPR to emitStructureCheck since it may jump over that code
index 5311ac9..0d98b8b 100644 (file)
 #include <arm/arch.h>
 #endif
 
+#if __has_include(<WebKitAdditions/MemoryFootprint.h>)
+#include <WebKitAdditions/MemoryFootprint.h>
+#else
+struct MemoryFootprint {
+    uint64_t current;
+    uint64_t peak;
+    
+    static MemoryFootprint now()
+    {
+        return { 0L, 0L };
+    }
+    
+    static void resetPeak()
+    {
+    }
+};
+#endif
+
 #if !defined(PATH_MAX)
 #define PATH_MAX 4096
 #endif
@@ -267,6 +285,8 @@ static EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionForceGCSlowPaths(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateMemoryFootprint(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionResetMemoryPeak(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
@@ -484,6 +504,8 @@ protected:
         addFunction(vm, "edenGC", functionEdenGC, 0);
         addFunction(vm, "forceGCSlowPaths", functionForceGCSlowPaths, 0);
         addFunction(vm, "gcHeapSize", functionHeapSize, 0);
+        addFunction(vm, "MemoryFootprint", functionCreateMemoryFootprint, 0);
+        addFunction(vm, "resetMemoryPeak", functionResetMemoryPeak, 0);
         addFunction(vm, "addressOf", functionAddressOf, 1);
         addFunction(vm, "version", functionVersion, 1);
         addFunction(vm, "run", functionRun, 1);
@@ -1179,6 +1201,66 @@ EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState* exec)
     return JSValue::encode(jsNumber(vm.heap.size()));
 }
 
+class JSCMemoryFootprint : public JSNonFinalObject {
+    using Base = JSNonFinalObject;
+public:
+    JSCMemoryFootprint(VM& vm, Structure* structure)
+        : Base(vm, structure)
+    { }
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+    }
+
+    static JSCMemoryFootprint* create(VM& vm, JSGlobalObject* globalObject)
+    {
+        Structure* structure = createStructure(vm, globalObject, jsNull());
+        JSCMemoryFootprint* footprint = new (NotNull, allocateCell<JSCMemoryFootprint>(vm.heap, sizeof(JSCMemoryFootprint))) JSCMemoryFootprint(vm, structure);
+        footprint->finishCreation(vm);
+        return footprint;
+    }
+
+    void finishCreation(VM& vm)
+    {
+        Base::finishCreation(vm);
+
+        auto addProperty = [&] (VM& vm, const char* name, JSValue value) {
+            JSCMemoryFootprint::addProperty(vm, name, value);
+        };
+
+        MemoryFootprint footprint = MemoryFootprint::now();
+
+        // Report sizes in KBytes so that values up to GB are still integers.
+        addProperty(vm, "current", jsNumber(footprint.current / 1024));
+        addProperty(vm, "peak", jsNumber(footprint.peak / 1024));
+    }
+
+    DECLARE_INFO;
+
+private:
+    void addProperty(VM& vm, const char* name, JSValue value)
+    {
+        Identifier identifier = Identifier::fromString(&vm, name);
+        putDirect(vm, identifier, value);
+    }
+};
+
+const ClassInfo JSCMemoryFootprint::s_info = { "MemoryFootprint", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCMemoryFootprint) };
+
+EncodedJSValue JSC_HOST_CALL functionCreateMemoryFootprint(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    return JSValue::encode(JSCMemoryFootprint::create(vm, exec->lexicalGlobalObject()));
+}
+
+EncodedJSValue JSC_HOST_CALL functionResetMemoryPeak(ExecState*)
+{
+    MemoryFootprint::resetPeak();
+    return JSValue::encode(jsUndefined());
+}
+
 // This function is not generally very helpful in 64-bit code as the tag and payload
 // share a register. But in 32-bit JITed code the tag may not be checked if an
 // optimization removes type checking requirements, such as in ===.