Skip to content

Commit 0fc6103

Browse files
authored
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.
1 parent 8220c85 commit 0fc6103

File tree

5 files changed

+74
-33
lines changed

5 files changed

+74
-33
lines changed

bin/ch/262.js

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
//-------------------------------------------------------------------------------------------------------
2-
// Copyright (C) Microsoft. All rights reserved.
2+
// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
3+
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56

67
R"====(
78
var $262 = {
8-
createRealm: function () {
9-
return WScript.LoadScript('', 'samethread').$262;
10-
},
11-
global: this,
12-
agent: {
13-
start: function (src) {
14-
WScript.LoadScript(
15-
`
16-
$262 = {
17-
agent:{
18-
receiveBroadcast: function(callback){ WScript.ReceiveBroadcast(callback); },
19-
report: function(value){ WScript.Report(value); },
20-
leaving: function(){ WScript.Leaving(); }
21-
}
22-
};
23-
${src}
24-
`, 'crossthread');
25-
},
26-
broadcast: function (sab) { WScript.Broadcast(sab); },
27-
sleep: function (timeout) { WScript.Sleep(timeout); },
28-
getReport: function () { return WScript.GetReport(); },
29-
},
9+
createRealm: () => WScript.LoadScript('', 'samethread').$262,
10+
global: this,
11+
agent: {
12+
start(src) {
13+
WScript.LoadScript(`
14+
$262 = {
15+
agent: {
16+
receiveBroadcast: WScript.ReceiveBroadcast,
17+
report: WScript.Report,
18+
leaving: WScript.Leaving,
19+
monotonicNow: WScript.monotonicNow
20+
}
21+
};
22+
${ src }
23+
`, 'crossthread');
24+
},
25+
broadcast: WScript.Broadcast,
26+
sleep: WScript.Sleep,
27+
getReport: WScript.GetReport,
28+
monotonicNow: WScript.monotonicNow
29+
}
3030
};
3131
)===="

bin/ch/WScriptJsrt.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@
55
//-------------------------------------------------------------------------------------------------------
66
#include "stdafx.h"
77
#include "PlatformAgnostic/ChakraICU.h"
8+
#if defined(__APPLE__)
9+
#ifdef ctime
10+
#undef ctime
11+
#define CTIME_UNDEFED
12+
#endif
13+
#endif
814
#include <vector>
15+
#include <ctime>
16+
#include <ratio>
17+
#include <chrono>
918

1019
#if defined(_X86_) || defined(_M_IX86)
1120
#define CPU_ARCH_TEXT "x86"
@@ -833,6 +842,26 @@ JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
833842
return value;
834843
}
835844

845+
JsValueRef WScriptJsrt::MonotonicNowCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
846+
{
847+
LPCWSTR errorMessage = _u("invalid call to WScript.monotonicNow");
848+
JsErrorCode errorCode = JsNoError;
849+
HRESULT hr = S_OK;
850+
JsValueRef result;
851+
852+
IfJsrtErrorSetGo(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(std::chrono::steady_clock::now().time_since_epoch().count()) / 1e6 /* ns in ms */, &result));
853+
854+
#ifdef CTIME_UNDEFED
855+
#define ctime PAL_ctime
856+
#undef CTIME_UNDEFED
857+
#endif
858+
return result;
859+
860+
Error:
861+
SetExceptionIf(errorCode, errorMessage);
862+
return JS_INVALID_REFERENCE;
863+
}
864+
836865
JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
837866
{
838867
LPCWSTR errorMessage = _u("invalid call to WScript.SetTimeout");
@@ -1009,12 +1038,6 @@ JsValueRef WScriptJsrt::RequestAsyncBreakCallback(JsValueRef callee, bool isCons
10091038
return JS_INVALID_REFERENCE;
10101039
}
10111040

1012-
JsValueRef WScriptJsrt::EmptyCallback(JsValueRef callee, bool isConstructCall,
1013-
JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
1014-
{
1015-
return JS_INVALID_REFERENCE;
1016-
}
1017-
10181041
bool WScriptJsrt::CreateNamedFunction(const char* nameString, JsNativeFunction callback,
10191042
JsValueRef* functionVar)
10201043
{
@@ -1059,6 +1082,7 @@ bool WScriptJsrt::Initialize()
10591082
JsValueRef wscript;
10601083
IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&wscript), false);
10611084

1085+
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "monotonicNow", MonotonicNowCallback));
10621086
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Echo", EchoCallback));
10631087
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Quit", QuitCallback));
10641088
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScriptFile", LoadScriptFileCallback));
@@ -1080,9 +1104,6 @@ bool WScriptJsrt::Initialize()
10801104
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SerializeObject", SerializeObject));
10811105
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Deserialize", Deserialize));
10821106

1083-
// ToDo Remove
1084-
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Edit", EmptyCallback));
1085-
10861107
// Platform
10871108
JsValueRef platformObject;
10881109
IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&platformObject), false);

bin/ch/WScriptJsrt.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
3+
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#pragma once
@@ -121,14 +122,14 @@ class WScriptJsrt
121122
static JsValueRef CALLBACK LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
122123
static JsValueRef CALLBACK LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
123124
static JsValueRef CALLBACK GetModuleNamespace(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
125+
static JsValueRef CALLBACK MonotonicNowCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
124126
static JsValueRef CALLBACK SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
125127
static JsValueRef CALLBACK ClearTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
126128
static JsValueRef CALLBACK AttachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
127129
static JsValueRef CALLBACK DetachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
128130
static JsValueRef CALLBACK DumpFunctionPositionCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
129131
static JsValueRef CALLBACK RequestAsyncBreakCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
130132

131-
static JsValueRef CALLBACK EmptyCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
132133
static JsErrorCode CALLBACK LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName = nullptr, bool isFile = false);
133134

134135
static JsValueRef CALLBACK LoadBinaryFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);

test/Miscellaneous/monotonicNow.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
3+
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
4+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
5+
//-------------------------------------------------------------------------------------------------------
6+
7+
const now = WScript.monotonicNow;
8+
9+
// Using <= instead of < because output number precision might be lost
10+
if (now() <= now() && now() <= now()) {
11+
print("pass");
12+
} else {
13+
print("fail");
14+
}

test/Miscellaneous/rlexe.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
<baseline>SetTimeout.baseline</baseline>
2727
</default>
2828
</test>
29+
<test>
30+
<default>
31+
<files>monotonicNow.js</files>
32+
</default>
33+
</test>
2934
<test>
3035
<default>
3136
<files>nullByte-comment.js</files>

0 commit comments

Comments
 (0)