summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/internal/process/per_thread.js9
-rw-r--r--src/api/environment.cc2
-rw-r--r--src/node_process_methods.cc131
-rw-r--r--test/cctest/test_base_object_ptr.cc52
4 files changed, 136 insertions, 58 deletions
diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js
index d219cd7298..303e71703d 100644
--- a/lib/internal/process/per_thread.js
+++ b/lib/internal/process/per_thread.js
@@ -41,7 +41,6 @@ function assert(x, msg) {
function wrapProcessMethods(binding) {
const {
hrtime: _hrtime,
- hrtimeBigInt: _hrtimeBigInt,
cpuUsage: _cpuUsage,
memoryUsage: _memoryUsage,
resourceUsage: _resourceUsage
@@ -113,10 +112,10 @@ function wrapProcessMethods(binding) {
// 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(3);
+ const hrValues = new Uint32Array(_hrtime.buffer);
function hrtime(time) {
- _hrtime(hrValues);
+ _hrtime.hrtime();
if (time !== undefined) {
if (!ArrayIsArray(time)) {
@@ -140,9 +139,9 @@ function wrapProcessMethods(binding) {
// 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(1);
+ const hrBigintValues = new BigUint64Array(_hrtime.buffer, 0, 1);
function hrtimeBigInt() {
- _hrtimeBigInt(hrBigintValues);
+ _hrtime.hrtimeBigInt();
return hrBigintValues[0];
}
diff --git a/src/api/environment.cc b/src/api/environment.cc
index 5349657d4c..99b6d85561 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -209,6 +209,8 @@ void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
// heap based on the actual physical memory.
params->constraints.ConfigureDefaults(total_memory, 0);
}
+ params->embedder_wrapper_object_index = BaseObject::InternalFields::kSlot;
+ params->embedder_wrapper_type_index = std::numeric_limits<int>::max();
}
void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc
index 6013dbb86b..d580f74478 100644
--- a/src/node_process_methods.cc
+++ b/src/node_process_methods.cc
@@ -7,6 +7,7 @@
#include "node_process.h"
#include "util-inl.h"
#include "uv.h"
+#include "v8-fast-api-calls.h"
#include "v8.h"
#include <vector>
@@ -33,7 +34,7 @@ namespace node {
using v8::Array;
using v8::ArrayBuffer;
-using v8::BigUint64Array;
+using v8::BackingStore;
using v8::Context;
using v8::Float64Array;
using v8::FunctionCallbackInfo;
@@ -46,7 +47,6 @@ using v8::Number;
using v8::Object;
using v8::String;
using v8::Uint32;
-using v8::Uint32Array;
using v8::Value;
namespace per_process {
@@ -131,35 +131,6 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(cwd);
}
-
-// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
-
-// This is the legacy version of hrtime before BigInt was introduced in
-// JavaScript.
-// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
-// so this function instead fills in an Uint32Array with 3 entries,
-// to avoid any integer overflow possibility.
-// The first two entries contain the second part of the value
-// broken into the upper/lower 32 bits to be converted back in JS,
-// because there is no Uint64Array in JS.
-// The third entry contains the remaining nanosecond part of the value.
-static void Hrtime(const FunctionCallbackInfo<Value>& args) {
- uint64_t t = uv_hrtime();
-
- Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
- uint32_t* fields = static_cast<uint32_t*>(ab->GetBackingStore()->Data());
-
- fields[0] = (t / NANOS_PER_SEC) >> 32;
- fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
- fields[2] = t % NANOS_PER_SEC;
-}
-
-static void HrtimeBigInt(const FunctionCallbackInfo<Value>& args) {
- Local<ArrayBuffer> ab = args[0].As<BigUint64Array>()->Buffer();
- uint64_t* fields = static_cast<uint64_t*>(ab->GetBackingStore()->Data());
- fields[0] = uv_hrtime();
-}
-
static void Kill(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Local<Context> context = env->context();
@@ -452,6 +423,85 @@ static void ReallyExit(const FunctionCallbackInfo<Value>& args) {
env->Exit(code);
}
+class FastHrtime : public BaseObject {
+ public:
+ static Local<Object> New(Environment* env) {
+ Local<v8::ObjectTemplate> otmpl = v8::ObjectTemplate::New(env->isolate());
+ otmpl->SetInternalFieldCount(FastHrtime::kInternalFieldCount);
+
+ auto create_func = [env](auto fast_func, auto slow_func) {
+ auto cfunc = v8::CFunction::Make(fast_func);
+ return v8::FunctionTemplate::New(env->isolate(),
+ slow_func,
+ Local<Value>(),
+ Local<v8::Signature>(),
+ 0,
+ v8::ConstructorBehavior::kThrow,
+ v8::SideEffectType::kHasNoSideEffect,
+ &cfunc);
+ };
+
+ otmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"),
+ create_func(FastNumber, SlowNumber));
+ otmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "hrtimeBigInt"),
+ create_func(FastBigInt, SlowBigInt));
+
+ Local<Object> obj = otmpl->NewInstance(env->context()).ToLocalChecked();
+
+ Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), 12);
+ new FastHrtime(env, obj, ab->GetBackingStore());
+ obj->Set(
+ env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "buffer"), ab)
+ .ToChecked();
+
+ return obj;
+ }
+
+ private:
+ FastHrtime(Environment* env,
+ Local<Object> object,
+ std::shared_ptr<v8::BackingStore> backing_store)
+ : BaseObject(env, object), backing_store_(backing_store) {}
+
+ void MemoryInfo(MemoryTracker* tracker) const override {}
+
+ SET_MEMORY_INFO_NAME(FastHrtime)
+ SET_SELF_SIZE(FastHrtime)
+
+ // This is the legacy version of hrtime before BigInt was introduced in
+ // JavaScript.
+ // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
+ // so this function instead fills in an Uint32Array with 3 entries,
+ // to avoid any integer overflow possibility.
+ // The first two entries contain the second part of the value
+ // broken into the upper/lower 32 bits to be converted back in JS,
+ // because there is no Uint64Array in JS.
+ // The third entry contains the remaining nanosecond part of the value.
+ static void FastNumber(FastHrtime* receiver) {
+ uint64_t t = uv_hrtime();
+ uint32_t* fields = static_cast<uint32_t*>(receiver->backing_store_->Data());
+ fields[0] = (t / NANOS_PER_SEC) >> 32;
+ fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
+ fields[2] = t % NANOS_PER_SEC;
+ }
+
+ static void SlowNumber(const FunctionCallbackInfo<Value>& args) {
+ FastNumber(FromJSObject<FastHrtime>(args.Holder()));
+ }
+
+ static void FastBigInt(FastHrtime* receiver) {
+ uint64_t t = uv_hrtime();
+ uint64_t* fields = static_cast<uint64_t*>(receiver->backing_store_->Data());
+ fields[0] = t;
+ }
+
+ static void SlowBigInt(const FunctionCallbackInfo<Value>& args) {
+ FastBigInt(FromJSObject<FastHrtime>(args.Holder()));
+ }
+
+ std::shared_ptr<BackingStore> backing_store_;
+};
+
static void InitializeProcessMethods(Local<Object> target,
Local<Value> unused,
Local<Context> context,
@@ -475,8 +525,6 @@ static void InitializeProcessMethods(Local<Object> target,
env->SetMethod(target, "_rawDebug", RawDebug);
env->SetMethod(target, "memoryUsage", MemoryUsage);
env->SetMethod(target, "cpuUsage", CPUUsage);
- env->SetMethod(target, "hrtime", Hrtime);
- env->SetMethod(target, "hrtimeBigInt", HrtimeBigInt);
env->SetMethod(target, "resourceUsage", ResourceUsage);
env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
@@ -488,9 +536,26 @@ static void InitializeProcessMethods(Local<Object> 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();
}
} // namespace node
+namespace v8 {
+template <>
+class WrapperTraits<node::FastHrtime> {
+ public:
+ static const void* GetTypeInfo() {
+ static const int tag = 0;
+ return reinterpret_cast<const void*>(&tag);
+ }
+};
+} // namespace v8
+
NODE_MODULE_CONTEXT_AWARE_INTERNAL(process_methods,
node::InitializeProcessMethods)
diff --git a/test/cctest/test_base_object_ptr.cc b/test/cctest/test_base_object_ptr.cc
index 18e27edba8..9006ea2a3b 100644
--- a/test/cctest/test_base_object_ptr.cc
+++ b/test/cctest/test_base_object_ptr.cc
@@ -14,6 +14,10 @@ using v8::Isolate;
using v8::Local;
using v8::Object;
+// Environments may come with existing BaseObject instances.
+// This variable offsets the expected BaseObject counts.
+static const int BASE_OBJECT_COUNT = 1;
+
class BaseObjectPtrTest : public EnvironmentTestFixture {};
class DummyBaseObject : public BaseObject {
@@ -47,12 +51,12 @@ TEST_F(BaseObjectPtrTest, ScopedDetached) {
Env env_{handle_scope, argv};
Environment* env = *env_;
- EXPECT_EQ(env->base_object_count(), 0);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
{
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
}
- EXPECT_EQ(env->base_object_count(), 0);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
}
TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
@@ -63,14 +67,14 @@ TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
- EXPECT_EQ(env->base_object_count(), 0);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
{
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
weak_ptr = ptr;
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
}
EXPECT_EQ(weak_ptr.get(), nullptr);
- EXPECT_EQ(env->base_object_count(), 0);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
}
TEST_F(BaseObjectPtrTest, Undetached) {
@@ -79,12 +83,16 @@ TEST_F(BaseObjectPtrTest, Undetached) {
Env env_{handle_scope, argv};
Environment* env = *env_;
- node::AddEnvironmentCleanupHook(isolate_, [](void* arg) {
- EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(), 0);
- }, env);
+ node::AddEnvironmentCleanupHook(
+ isolate_,
+ [](void* arg) {
+ EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(),
+ BASE_OBJECT_COUNT);
+ },
+ env);
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
}
TEST_F(BaseObjectPtrTest, GCWeak) {
@@ -101,21 +109,21 @@ TEST_F(BaseObjectPtrTest, GCWeak) {
weak_ptr = ptr;
ptr->MakeWeak();
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
EXPECT_EQ(weak_ptr.get(), ptr.get());
EXPECT_EQ(weak_ptr->persistent().IsWeak(), false);
ptr.reset();
}
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
EXPECT_NE(weak_ptr.get(), nullptr);
EXPECT_EQ(weak_ptr->persistent().IsWeak(), true);
v8::V8::SetFlagsFromString("--expose-gc");
isolate_->RequestGarbageCollectionForTesting(Isolate::kFullGarbageCollection);
- EXPECT_EQ(env->base_object_count(), 0);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
EXPECT_EQ(weak_ptr.get(), nullptr);
}
@@ -126,7 +134,7 @@ TEST_F(BaseObjectPtrTest, Moveable) {
Environment* env = *env_;
BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
BaseObjectWeakPtr<DummyBaseObject> weak_ptr { ptr };
EXPECT_EQ(weak_ptr.get(), ptr.get());
@@ -137,12 +145,12 @@ TEST_F(BaseObjectPtrTest, Moveable) {
BaseObjectWeakPtr<DummyBaseObject> weak_ptr2 = std::move(weak_ptr);
EXPECT_EQ(weak_ptr2.get(), ptr2.get());
EXPECT_EQ(weak_ptr.get(), nullptr);
- EXPECT_EQ(env->base_object_count(), 1);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 1);
ptr2.reset();
EXPECT_EQ(weak_ptr2.get(), nullptr);
- EXPECT_EQ(env->base_object_count(), 0);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT);
}
TEST_F(BaseObjectPtrTest, NestedClasses) {
@@ -163,14 +171,18 @@ TEST_F(BaseObjectPtrTest, NestedClasses) {
Env env_{handle_scope, argv};
Environment* env = *env_;
- node::AddEnvironmentCleanupHook(isolate_, [](void* arg) {
- EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(), 0);
- }, env);
+ node::AddEnvironmentCleanupHook(
+ isolate_,
+ [](void* arg) {
+ EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(),
+ BASE_OBJECT_COUNT);
+ },
+ env);
ObjectWithPtr* obj =
new ObjectWithPtr(env, DummyBaseObject::MakeJSObject(env));
obj->ptr1 = DummyBaseObject::NewDetached(env);
obj->ptr2 = DummyBaseObject::New(env);
- EXPECT_EQ(env->base_object_count(), 3);
+ EXPECT_EQ(env->base_object_count(), BASE_OBJECT_COUNT + 3);
}