diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index b39bfe078f450d..551367583e55a8 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -80,8 +80,6 @@ const rawMethods = internalBinding('process_methods'); const wrapped = perThreadSetup.wrapProcessMethods(rawMethods); process._rawDebug = wrapped._rawDebug; - process.hrtime = wrapped.hrtime; - process.hrtime.bigint = wrapped.hrtimeBigInt; process.cpuUsage = wrapped.cpuUsage; process.resourceUsage = wrapped.resourceUsage; process.memoryUsage = wrapped.memoryUsage; diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index b384349666d919..7e24bd16425b16 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -74,11 +74,19 @@ function prepareMainThreadExecution(expandArgv1 = false) { } function patchProcessObject(expandArgv1) { + const binding = internalBinding('process_methods'); + binding.patchProcessObject(process); + + // TODO(joyeecheung): snapshot fast APIs (which need to work with + // array buffers, whose connection with C++ needs to be rebuilt after + // deserialization). const { - patchProcessObject: patchProcessObjectNative - } = internalBinding('process_methods'); + hrtime, + hrtimeBigInt + } = require('internal/process/per_thread').getFastAPIs(binding); - patchProcessObjectNative(process); + process.hrtime = hrtime; + process.hrtime.bigint = hrtimeBigInt; ObjectDefineProperty(process, 'argv0', { enumerable: true, diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index 303e71703d2fe5..33104dfb3db11c 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -37,10 +37,56 @@ function assert(x, msg) { if (!x) throw new ERR_ASSERTION(msg || 'assertion error'); } +function getFastAPIs(binding) { + const { + hrtime: _hrtime + } = binding.getFastAPIs(); + + // The 3 entries filled in by the original process.hrtime contains + // the upper/lower 32 bits of the second part of the value, + // and the remaining nanoseconds of the value. + const hrValues = new Uint32Array(_hrtime.buffer); + + function hrtime(time) { + _hrtime.hrtime(); + + if (time !== undefined) { + if (!ArrayIsArray(time)) { + throw new ERR_INVALID_ARG_TYPE('time', 'Array', time); + } + if (time.length !== 2) { + throw new ERR_OUT_OF_RANGE('time', 2, time.length); + } + + const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - time[0]; + const nsec = hrValues[2] - time[1]; + const needsBorrow = nsec < 0; + return [needsBorrow ? sec - 1 : sec, needsBorrow ? nsec + 1e9 : nsec]; + } + + return [ + hrValues[0] * 0x100000000 + hrValues[1], + hrValues[2] + ]; + } + + // Use a BigUint64Array in the closure because this is actually a bit + // faster than simply returning a BigInt from C++ in V8 7.1. + const hrBigintValues = new BigUint64Array(_hrtime.buffer, 0, 1); + function hrtimeBigInt() { + _hrtime.hrtimeBigInt(); + return hrBigintValues[0]; + } + + return { + hrtime, + hrtimeBigInt, + }; +} + // The execution of this function itself should not cause any side effects. function wrapProcessMethods(binding) { const { - hrtime: _hrtime, cpuUsage: _cpuUsage, memoryUsage: _memoryUsage, resourceUsage: _resourceUsage @@ -109,42 +155,6 @@ function wrapProcessMethods(binding) { num >= 0; } - // The 3 entries filled in by the original process.hrtime contains - // the upper/lower 32 bits of the second part of the value, - // and the remaining nanoseconds of the value. - const hrValues = new Uint32Array(_hrtime.buffer); - - function hrtime(time) { - _hrtime.hrtime(); - - if (time !== undefined) { - if (!ArrayIsArray(time)) { - throw new ERR_INVALID_ARG_TYPE('time', 'Array', time); - } - if (time.length !== 2) { - throw new ERR_OUT_OF_RANGE('time', 2, time.length); - } - - const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - time[0]; - const nsec = hrValues[2] - time[1]; - const needsBorrow = nsec < 0; - return [needsBorrow ? sec - 1 : sec, needsBorrow ? nsec + 1e9 : nsec]; - } - - return [ - hrValues[0] * 0x100000000 + hrValues[1], - hrValues[2] - ]; - } - - // Use a BigUint64Array in the closure because this is actually a bit - // faster than simply returning a BigInt from C++ in V8 7.1. - const hrBigintValues = new BigUint64Array(_hrtime.buffer, 0, 1); - function hrtimeBigInt() { - _hrtime.hrtimeBigInt(); - return hrBigintValues[0]; - } - const memValues = new Float64Array(5); function memoryUsage() { _memoryUsage(memValues); @@ -225,8 +235,6 @@ function wrapProcessMethods(binding) { return { _rawDebug, - hrtime, - hrtimeBigInt, cpuUsage, resourceUsage, memoryUsage, @@ -356,6 +364,7 @@ function toggleTraceCategoryState(asyncHooksEnabled) { module.exports = { toggleTraceCategoryState, + getFastAPIs, assert, buildAllowedFlags, wrapProcessMethods diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index aa186185988a0a..e714cdd30f99b1 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -504,6 +504,16 @@ class FastHrtime : public BaseObject { std::shared_ptr backing_store_; }; +static void GetFastAPIs(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + Local ret = Object::New(env->isolate()); + ret->Set(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"), + FastHrtime::New(env)) + .ToChecked(); + args.GetReturnValue().Set(ret); +} + static void InitializeProcessMethods(Local target, Local unused, Local context, @@ -534,12 +544,7 @@ static void InitializeProcessMethods(Local target, env->SetMethod(target, "reallyExit", ReallyExit); env->SetMethodNoSideEffect(target, "uptime", Uptime); env->SetMethod(target, "patchProcessObject", PatchProcessObject); - - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"), - FastHrtime::New(env)) - .ToChecked(); + env->SetMethod(target, "getFastAPIs", GetFastAPIs); } } // namespace node diff --git a/test/cctest/test_base_object_ptr.cc b/test/cctest/test_base_object_ptr.cc index 9006ea2a3ba519..a3a8df98a9efc7 100644 --- a/test/cctest/test_base_object_ptr.cc +++ b/test/cctest/test_base_object_ptr.cc @@ -16,7 +16,7 @@ using v8::Object; // Environments may come with existing BaseObject instances. // This variable offsets the expected BaseObject counts. -static const int BASE_OBJECT_COUNT = 1; +static const int BASE_OBJECT_COUNT = 0; class BaseObjectPtrTest : public EnvironmentTestFixture {};