Kaynağa Gözat

Add WScript.monotonicNow() (#6712)

* Add WScript.monotonicNow() high precision jitter-less timing method into ch, the chakra test harness.
This method is useful for benchmarks and tests requiring precision timing.
Please note this is only in the test harness and not included in the underlying chakracore library.

Closes #5271.
MadProbe 4 yıl önce
ebeveyn
işleme
0fc6103461

+ 23 - 23
bin/ch/262.js

@@ -1,31 +1,31 @@
 //-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
 R"====(
 var $262 = {
-  createRealm: function () {
-    return WScript.LoadScript('', 'samethread').$262;
-  },
-  global: this,
-  agent: {
-    start: function (src) {
-      WScript.LoadScript(
-        `
-        $262 = {
-          agent:{
-            receiveBroadcast: function(callback){ WScript.ReceiveBroadcast(callback); },
-            report: function(value){ WScript.Report(value); },
-            leaving: function(){ WScript.Leaving(); }
-          }
-        };
-        ${src}
-        `, 'crossthread');
-    },
-    broadcast: function (sab) { WScript.Broadcast(sab); },
-    sleep: function (timeout) { WScript.Sleep(timeout); },
-    getReport: function () { return WScript.GetReport(); },
-  },
+    createRealm: () => WScript.LoadScript('', 'samethread').$262,
+    global: this,
+    agent: {
+        start(src) {
+            WScript.LoadScript(`
+                $262 = {
+                    agent: {
+                        receiveBroadcast: WScript.ReceiveBroadcast,
+                        report: WScript.Report,
+                        leaving: WScript.Leaving,
+                        monotonicNow: WScript.monotonicNow
+                    }
+                };
+                ${ src }
+            `, 'crossthread');
+        },
+        broadcast: WScript.Broadcast,
+        sleep: WScript.Sleep,
+        getReport: WScript.GetReport,
+        monotonicNow: WScript.monotonicNow
+    }
 };
 )===="

+ 30 - 9
bin/ch/WScriptJsrt.cpp

@@ -5,7 +5,16 @@
 //-------------------------------------------------------------------------------------------------------
 #include "stdafx.h"
 #include "PlatformAgnostic/ChakraICU.h"
+#if defined(__APPLE__)
+#ifdef ctime
+#undef ctime
+#define CTIME_UNDEFED
+#endif
+#endif
 #include <vector>
+#include <ctime>
+#include <ratio>
+#include <chrono>
 
 #if defined(_X86_) || defined(_M_IX86)
 #define CPU_ARCH_TEXT "x86"
@@ -833,6 +842,26 @@ Error:
     return value;
 }
 
+JsValueRef WScriptJsrt::MonotonicNowCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
+{
+    LPCWSTR errorMessage = _u("invalid call to WScript.monotonicNow");
+    JsErrorCode errorCode = JsNoError;
+    HRESULT hr = S_OK;
+    JsValueRef result;
+    
+    IfJsrtErrorSetGo(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(std::chrono::steady_clock::now().time_since_epoch().count()) / 1e6 /* ns in ms */, &result));
+
+#ifdef CTIME_UNDEFED
+#define ctime PAL_ctime
+#undef CTIME_UNDEFED
+#endif
+    return result;
+
+Error:
+    SetExceptionIf(errorCode, errorMessage);
+    return JS_INVALID_REFERENCE;
+}
+
 JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
 {
     LPCWSTR errorMessage = _u("invalid call to WScript.SetTimeout");
@@ -1009,12 +1038,6 @@ JsValueRef WScriptJsrt::RequestAsyncBreakCallback(JsValueRef callee, bool isCons
     return JS_INVALID_REFERENCE;
 }
 
-JsValueRef WScriptJsrt::EmptyCallback(JsValueRef callee, bool isConstructCall,
-    JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
-{
-    return JS_INVALID_REFERENCE;
-}
-
 bool WScriptJsrt::CreateNamedFunction(const char* nameString, JsNativeFunction callback,
     JsValueRef* functionVar)
 {
@@ -1059,6 +1082,7 @@ bool WScriptJsrt::Initialize()
     JsValueRef wscript;
     IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&wscript), false);
 
+    IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "monotonicNow", MonotonicNowCallback));
     IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Echo", EchoCallback));
     IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Quit", QuitCallback));
     IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScriptFile", LoadScriptFileCallback));
@@ -1080,9 +1104,6 @@ bool WScriptJsrt::Initialize()
     IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SerializeObject", SerializeObject));
     IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Deserialize", Deserialize));
 
-    // ToDo Remove
-    IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Edit", EmptyCallback));
-
     // Platform
     JsValueRef platformObject;
     IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&platformObject), false);

+ 2 - 1
bin/ch/WScriptJsrt.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -121,6 +122,7 @@ private:
     static JsValueRef CALLBACK LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsValueRef CALLBACK LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsValueRef CALLBACK GetModuleNamespace(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
+    static JsValueRef CALLBACK MonotonicNowCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsValueRef CALLBACK SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsValueRef CALLBACK ClearTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsValueRef CALLBACK AttachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
@@ -128,7 +130,6 @@ private:
     static JsValueRef CALLBACK DumpFunctionPositionCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsValueRef CALLBACK RequestAsyncBreakCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
 
-    static JsValueRef CALLBACK EmptyCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
     static JsErrorCode CALLBACK LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName = nullptr, bool isFile = false);
 
     static JsValueRef CALLBACK LoadBinaryFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);

+ 14 - 0
test/Miscellaneous/monotonicNow.js

@@ -0,0 +1,14 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+const now = WScript.monotonicNow;
+
+// Using <= instead of < because output number precision might be lost
+if (now() <= now() && now() <= now()) {
+    print("pass");
+} else {
+    print("fail");
+}

+ 5 - 0
test/Miscellaneous/rlexe.xml

@@ -26,6 +26,11 @@
       <baseline>SetTimeout.baseline</baseline>
     </default>
   </test>
+  <test>
+    <default>
+      <files>monotonicNow.js</files>
+    </default>
+  </test>
   <test>
     <default>
       <files>nullByte-comment.js</files>