Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d8eef83

Browse filesBrowse files
committed
process: use v8 fast api calls for hrtime
Refs: #33374 PR-URL: #33600 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent e983b1c commit d8eef83
Copy full SHA for d8eef83

File tree

Expand file treeCollapse file tree

4 files changed

+136
-58
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+136
-58
lines changed
Open diff view settings
Collapse file

‎lib/internal/process/per_thread.js‎

Copy file name to clipboardExpand all lines: lib/internal/process/per_thread.js
+4-5Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ function assert(x, msg) {
4141
function wrapProcessMethods(binding) {
4242
const {
4343
hrtime: _hrtime,
44-
hrtimeBigInt: _hrtimeBigInt,
4544
cpuUsage: _cpuUsage,
4645
memoryUsage: _memoryUsage,
4746
resourceUsage: _resourceUsage
@@ -113,10 +112,10 @@ function wrapProcessMethods(binding) {
113112
// The 3 entries filled in by the original process.hrtime contains
114113
// the upper/lower 32 bits of the second part of the value,
115114
// and the remaining nanoseconds of the value.
116-
const hrValues = new Uint32Array(3);
115+
const hrValues = new Uint32Array(_hrtime.buffer);
117116

118117
function hrtime(time) {
119-
_hrtime(hrValues);
118+
_hrtime.hrtime();
120119

121120
if (time !== undefined) {
122121
if (!ArrayIsArray(time)) {
@@ -140,9 +139,9 @@ function wrapProcessMethods(binding) {
140139

141140
// Use a BigUint64Array in the closure because this is actually a bit
142141
// faster than simply returning a BigInt from C++ in V8 7.1.
143-
const hrBigintValues = new BigUint64Array(1);
142+
const hrBigintValues = new BigUint64Array(_hrtime.buffer, 0, 1);
144143
function hrtimeBigInt() {
145-
_hrtimeBigInt(hrBigintValues);
144+
_hrtime.hrtimeBigInt();
146145
return hrBigintValues[0];
147146
}
148147

Collapse file

‎src/api/environment.cc‎

Copy file name to clipboardExpand all lines: src/api/environment.cc
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
209209
// heap based on the actual physical memory.
210210
params->constraints.ConfigureDefaults(total_memory, 0);
211211
}
212+
params->embedder_wrapper_object_index = BaseObject::InternalFields::kSlot;
213+
params->embedder_wrapper_type_index = std::numeric_limits<int>::max();
212214
}
213215

214216
void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
Collapse file

‎src/node_process_methods.cc‎

Copy file name to clipboardExpand all lines: src/node_process_methods.cc
+98-33Lines changed: 98 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "node_process.h"
88
#include "util-inl.h"
99
#include "uv.h"
10+
#include "v8-fast-api-calls.h"
1011
#include "v8.h"
1112

1213
#include <vector>
@@ -33,7 +34,7 @@ namespace node {
3334

3435
using v8::Array;
3536
using v8::ArrayBuffer;
36-
using v8::BigUint64Array;
37+
using v8::BackingStore;
3738
using v8::Context;
3839
using v8::Float64Array;
3940
using v8::FunctionCallbackInfo;
@@ -46,7 +47,6 @@ using v8::Number;
4647
using v8::Object;
4748
using v8::String;
4849
using v8::Uint32;
49-
using v8::Uint32Array;
5050
using v8::Value;
5151

5252
namespace per_process {
@@ -131,35 +131,6 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
131131
args.GetReturnValue().Set(cwd);
132132
}
133133

134-
135-
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
136-
137-
// This is the legacy version of hrtime before BigInt was introduced in
138-
// JavaScript.
139-
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
140-
// so this function instead fills in an Uint32Array with 3 entries,
141-
// to avoid any integer overflow possibility.
142-
// The first two entries contain the second part of the value
143-
// broken into the upper/lower 32 bits to be converted back in JS,
144-
// because there is no Uint64Array in JS.
145-
// The third entry contains the remaining nanosecond part of the value.
146-
static void Hrtime(const FunctionCallbackInfo<Value>& args) {
147-
uint64_t t = uv_hrtime();
148-
149-
Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
150-
uint32_t* fields = static_cast<uint32_t*>(ab->GetBackingStore()->Data());
151-
152-
fields[0] = (t / NANOS_PER_SEC) >> 32;
153-
fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
154-
fields[2] = t % NANOS_PER_SEC;
155-
}
156-
157-
static void HrtimeBigInt(const FunctionCallbackInfo<Value>& args) {
158-
Local<ArrayBuffer> ab = args[0].As<BigUint64Array>()->Buffer();
159-
uint64_t* fields = static_cast<uint64_t*>(ab->GetBackingStore()->Data());
160-
fields[0] = uv_hrtime();
161-
}
162-
163134
static void Kill(const FunctionCallbackInfo<Value>& args) {
164135
Environment* env = Environment::GetCurrent(args);
165136
Local<Context> context = env->context();
@@ -452,6 +423,85 @@ static void ReallyExit(const FunctionCallbackInfo<Value>& args) {
452423
env->Exit(code);
453424
}
454425

426+
class FastHrtime : public BaseObject {
427+
public:
428+
static Local<Object> New(Environment* env) {
429+
Local<v8::ObjectTemplate> otmpl = v8::ObjectTemplate::New(env->isolate());
430+
otmpl->SetInternalFieldCount(FastHrtime::kInternalFieldCount);
431+
432+
auto create_func = [env](auto fast_func, auto slow_func) {
433+
auto cfunc = v8::CFunction::Make(fast_func);
434+
return v8::FunctionTemplate::New(env->isolate(),
435+
slow_func,
436+
Local<Value>(),
437+
Local<v8::Signature>(),
438+
0,
439+
v8::ConstructorBehavior::kThrow,
440+
v8::SideEffectType::kHasNoSideEffect,
441+
&cfunc);
442+
};
443+
444+
otmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"),
445+
create_func(FastNumber, SlowNumber));
446+
otmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "hrtimeBigInt"),
447+
create_func(FastBigInt, SlowBigInt));
448+
449+
Local<Object> obj = otmpl->NewInstance(env->context()).ToLocalChecked();
450+
451+
Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), 12);
452+
new FastHrtime(env, obj, ab->GetBackingStore());
453+
obj->Set(
454+
env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "buffer"), ab)
455+
.ToChecked();
456+
457+
return obj;
458+
}
459+
460+
private:
461+
FastHrtime(Environment* env,
462+
Local<Object> object,
463+
std::shared_ptr<v8::BackingStore> backing_store)
464+
: BaseObject(env, object), backing_store_(backing_store) {}
465+
466+
void MemoryInfo(MemoryTracker* tracker) const override {}
467+
468+
SET_MEMORY_INFO_NAME(FastHrtime)
469+
SET_SELF_SIZE(FastHrtime)
470+
471+
// This is the legacy version of hrtime before BigInt was introduced in
472+
// JavaScript.
473+
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
474+
// so this function instead fills in an Uint32Array with 3 entries,
475+
// to avoid any integer overflow possibility.
476+
// The first two entries contain the second part of the value
477+
// broken into the upper/lower 32 bits to be converted back in JS,
478+
// because there is no Uint64Array in JS.
479+
// The third entry contains the remaining nanosecond part of the value.
480+
static void FastNumber(FastHrtime* receiver) {
481+
uint64_t t = uv_hrtime();
482+
uint32_t* fields = static_cast<uint32_t*>(receiver->backing_store_->Data());
483+
fields[0] = (t / NANOS_PER_SEC) >> 32;
484+
fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
485+
fields[2] = t % NANOS_PER_SEC;
486+
}
487+
488+
static void SlowNumber(const FunctionCallbackInfo<Value>& args) {
489+
FastNumber(FromJSObject<FastHrtime>(args.Holder()));
490+
}
491+
492+
static void FastBigInt(FastHrtime* receiver) {
493+
uint64_t t = uv_hrtime();
494+
uint64_t* fields = static_cast<uint64_t*>(receiver->backing_store_->Data());
495+
fields[0] = t;
496+
}
497+
498+
static void SlowBigInt(const FunctionCallbackInfo<Value>& args) {
499+
FastBigInt(FromJSObject<FastHrtime>(args.Holder()));
500+
}
501+
502+
std::shared_ptr<BackingStore> backing_store_;
503+
};
504+
455505
static void InitializeProcessMethods(Local<Object> target,
456506
Local<Value> unused,
457507
Local<Context> context,
@@ -475,8 +525,6 @@ static void InitializeProcessMethods(Local<Object> target,
475525
env->SetMethod(target, "_rawDebug", RawDebug);
476526
env->SetMethod(target, "memoryUsage", MemoryUsage);
477527
env->SetMethod(target, "cpuUsage", CPUUsage);
478-
env->SetMethod(target, "hrtime", Hrtime);
479-
env->SetMethod(target, "hrtimeBigInt", HrtimeBigInt);
480528
env->SetMethod(target, "resourceUsage", ResourceUsage);
481529

482530
env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
@@ -488,9 +536,26 @@ static void InitializeProcessMethods(Local<Object> target,
488536
env->SetMethod(target, "reallyExit", ReallyExit);
489537
env->SetMethodNoSideEffect(target, "uptime", Uptime);
490538
env->SetMethod(target, "patchProcessObject", PatchProcessObject);
539+
540+
target
541+
->Set(env->context(),
542+
FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"),
543+
FastHrtime::New(env))
544+
.ToChecked();
491545
}
492546

493547
} // namespace node
494548

549+
namespace v8 {
550+
template <>
551+
class WrapperTraits<node::FastHrtime> {
552+
public:
553+
static const void* GetTypeInfo() {
554+
static const int tag = 0;
555+
return reinterpret_cast<const void*>(&tag);
556+
}
557+
};
558+
} // namespace v8
559+
495560
NODE_MODULE_CONTEXT_AWARE_INTERNAL(process_methods,
496561
node::InitializeProcessMethods)
Collapse file

‎test/cctest/test_base_object_ptr.cc‎

Copy file name to clipboardExpand all lines: test/cctest/test_base_object_ptr.cc
+32-20Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ using v8::Isolate;
1414
using v8::Local;
1515
using v8::Object;
1616

17+
// Environments may come with existing BaseObject instances.
18+
// This variable offsets the expected BaseObject counts.
19+
static const int BASE_OBJECT_COUNT = 1;
20+
1721
class BaseObjectPtrTest : public EnvironmentTestFixture {};
1822

1923
class DummyBaseObject : public BaseObject {
@@ -47,12 +51,12 @@ TEST_F(BaseObjectPtrTest, ScopedDetached) {
4751
Env env_{handle_scope, argv};
4852
Environment* env = *env_;
4953

50-
EXPECT_EQ(env->base_object_count(), 0);
54+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
5155
{
5256
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
53-
EXPECT_EQ(env->base_object_count(), 1);
57+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
5458
}
55-
EXPECT_EQ(env->base_object_count(), 0);
59+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
5660
}
5761

5862
TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
@@ -63,14 +67,14 @@ TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
6367

6468
BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
6569

66-
EXPECT_EQ(env->base_object_count(), 0);
70+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
6771
{
6872
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
6973
weak_ptr = ptr;
70-
EXPECT_EQ(env->base_object_count(), 1);
74+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
7175
}
7276
EXPECT_EQ(weak_ptr.get(), nullptr);
73-
EXPECT_EQ(env->base_object_count(), 0);
77+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
7478
}
7579

7680
TEST_F(BaseObjectPtrTest, Undetached) {
@@ -79,12 +83,16 @@ TEST_F(BaseObjectPtrTest, Undetached) {
7983
Env env_{handle_scope, argv};
8084
Environment* env = *env_;
8185

82-
node::AddEnvironmentCleanupHook(isolate_, [](void* arg) {
83-
EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(), 0);
84-
}, env);
86+
node::AddEnvironmentCleanupHook(
87+
isolate_,
88+
[](void* arg) {
89+
EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(),
90+
BASE_OBJECT_COUNT);
91+
},
92+
env);
8593

8694
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
87-
EXPECT_EQ(env->base_object_count(), 1);
95+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
8896
}
8997

9098
TEST_F(BaseObjectPtrTest, GCWeak) {
@@ -101,21 +109,21 @@ TEST_F(BaseObjectPtrTest, GCWeak) {
101109
weak_ptr = ptr;
102110
ptr->MakeWeak();
103111

104-
EXPECT_EQ(env->base_object_count(), 1);
112+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
105113
EXPECT_EQ(weak_ptr.get(), ptr.get());
106114
EXPECT_EQ(weak_ptr->persistent().IsWeak(), false);
107115

108116
ptr.reset();
109117
}
110118

111-
EXPECT_EQ(env->base_object_count(), 1);
119+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
112120
EXPECT_NE(weak_ptr.get(), nullptr);
113121
EXPECT_EQ(weak_ptr->persistent().IsWeak(), true);
114122

115123
v8::V8::SetFlagsFromString("--expose-gc");
116124
isolate_->RequestGarbageCollectionForTesting(Isolate::kFullGarbageCollection);
117125

118-
EXPECT_EQ(env->base_object_count(), 0);
126+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
119127
EXPECT_EQ(weak_ptr.get(), nullptr);
120128
}
121129

@@ -126,7 +134,7 @@ TEST_F(BaseObjectPtrTest, Moveable) {
126134
Environment* env = *env_;
127135

128136
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
129-
EXPECT_EQ(env->base_object_count(), 1);
137+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
130138
BaseObjectWeakPtr<DummyBaseObject> weak_ptr { ptr };
131139
EXPECT_EQ(weak_ptr.get(), ptr.get());
132140

@@ -137,12 +145,12 @@ TEST_F(BaseObjectPtrTest, Moveable) {
137145
BaseObjectWeakPtr<DummyBaseObject> weak_ptr2 = std::move(weak_ptr);
138146
EXPECT_EQ(weak_ptr2.get(), ptr2.get());
139147
EXPECT_EQ(weak_ptr.get(), nullptr);
140-
EXPECT_EQ(env->base_object_count(), 1);
148+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
141149

142150
ptr2.reset();
143151

144152
EXPECT_EQ(weak_ptr2.get(), nullptr);
145-
EXPECT_EQ(env->base_object_count(), 0);
153+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
146154
}
147155

148156
TEST_F(BaseObjectPtrTest, NestedClasses) {
@@ -163,14 +171,18 @@ TEST_F(BaseObjectPtrTest, NestedClasses) {
163171
Env env_{handle_scope, argv};
164172
Environment* env = *env_;
165173

166-
node::AddEnvironmentCleanupHook(isolate_, [](void* arg) {
167-
EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(), 0);
168-
}, env);
174+
node::AddEnvironmentCleanupHook(
175+
isolate_,
176+
[](void* arg) {
177+
EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(),
178+
BASE_OBJECT_COUNT);
179+
},
180+
env);
169181

170182
ObjectWithPtr* obj =
171183
new ObjectWithPtr(env, DummyBaseObject::MakeJSObject(env));
172184
obj->ptr1 = DummyBaseObject::NewDetached(env);
173185
obj->ptr2 = DummyBaseObject::New(env);
174186

175-
EXPECT_EQ(env->base_object_count(), 3);
187+
EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 3);
176188
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.