src: fix internalModuleStat v8 fast path
PR-URL: https://github.com/nodejs/node/pull/58054 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com>
This commit is contained in:
parent
adc948af56
commit
5ed1bcbd9b
@ -1424,7 +1424,7 @@ function handleDirents({ result, currentPath, context }) {
|
|||||||
const dirent = getDirent(currentPath, names[i], types[i]);
|
const dirent = getDirent(currentPath, names[i], types[i]);
|
||||||
ArrayPrototypePush(context.readdirResults, dirent);
|
ArrayPrototypePush(context.readdirResults, dirent);
|
||||||
|
|
||||||
if (dirent.isDirectory() || binding.internalModuleStat(binding, fullPath) === 1) {
|
if (dirent.isDirectory() || binding.internalModuleStat(fullPath) === 1) {
|
||||||
ArrayPrototypePush(context.pathsQueue, fullPath);
|
ArrayPrototypePush(context.pathsQueue, fullPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1434,7 +1434,7 @@ function handleFilePaths({ result, currentPath, context }) {
|
|||||||
for (let i = 0; i < result.length; i++) {
|
for (let i = 0; i < result.length; i++) {
|
||||||
const resultPath = pathModule.join(currentPath, result[i]);
|
const resultPath = pathModule.join(currentPath, result[i]);
|
||||||
const relativeResultPath = pathModule.relative(context.basePath, resultPath);
|
const relativeResultPath = pathModule.relative(context.basePath, resultPath);
|
||||||
const stat = binding.internalModuleStat(binding, resultPath);
|
const stat = binding.internalModuleStat(resultPath);
|
||||||
ArrayPrototypePush(context.readdirResults, relativeResultPath);
|
ArrayPrototypePush(context.readdirResults, relativeResultPath);
|
||||||
|
|
||||||
if (stat === 1) {
|
if (stat === 1) {
|
||||||
|
@ -910,7 +910,7 @@ async function readdirRecursive(originalPath, options) {
|
|||||||
const { 0: path, 1: readdir } = ArrayPrototypePop(queue);
|
const { 0: path, 1: readdir } = ArrayPrototypePop(queue);
|
||||||
for (const ent of readdir) {
|
for (const ent of readdir) {
|
||||||
const direntPath = pathModule.join(path, ent);
|
const direntPath = pathModule.join(path, ent);
|
||||||
const stat = binding.internalModuleStat(binding, direntPath);
|
const stat = binding.internalModuleStat(direntPath);
|
||||||
ArrayPrototypePush(
|
ArrayPrototypePush(
|
||||||
result,
|
result,
|
||||||
pathModule.relative(originalPath, direntPath),
|
pathModule.relative(originalPath, direntPath),
|
||||||
|
@ -255,9 +255,9 @@ function stat(filename) {
|
|||||||
const result = statCache.get(filename);
|
const result = statCache.get(filename);
|
||||||
if (result !== undefined) { return result; }
|
if (result !== undefined) { return result; }
|
||||||
}
|
}
|
||||||
const result = internalFsBinding.internalModuleStat(internalFsBinding, filename);
|
const result = internalFsBinding.internalModuleStat(filename);
|
||||||
if (statCache !== null && result >= 0) {
|
if (statCache !== null && result >= 0) {
|
||||||
// Only set cache when `internalModuleStat(internalFsBinding, filename)` succeeds.
|
// Only set cache when `internalModuleStat(filename)` succeeds.
|
||||||
statCache.set(filename, result);
|
statCache.set(filename, result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -248,7 +248,6 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const stats = internalFsBinding.internalModuleStat(
|
const stats = internalFsBinding.internalModuleStat(
|
||||||
internalFsBinding,
|
|
||||||
StringPrototypeEndsWith(internalFsBinding, path, '/') ? StringPrototypeSlice(path, -1) : path,
|
StringPrototypeEndsWith(internalFsBinding, path, '/') ? StringPrototypeSlice(path, -1) : path,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -235,7 +235,6 @@ function getPackageJSONURL(specifier, base) {
|
|||||||
let lastPath;
|
let lastPath;
|
||||||
do {
|
do {
|
||||||
const stat = internalFsBinding.internalModuleStat(
|
const stat = internalFsBinding.internalModuleStat(
|
||||||
internalFsBinding,
|
|
||||||
StringPrototypeSlice(packageJSONPath, 0, packageJSONPath.length - 13),
|
StringPrototypeSlice(packageJSONPath, 0, packageJSONPath.length - 13),
|
||||||
);
|
);
|
||||||
// Check for !stat.isDirectory()
|
// Check for !stat.isDirectory()
|
||||||
|
@ -32,9 +32,8 @@ using CFunctionCallback = void (*)(v8::Local<v8::Value> unused,
|
|||||||
using CFunctionCallbackReturnDouble =
|
using CFunctionCallbackReturnDouble =
|
||||||
double (*)(v8::Local<v8::Object> unused, v8::Local<v8::Object> receiver);
|
double (*)(v8::Local<v8::Object> unused, v8::Local<v8::Object> receiver);
|
||||||
using CFunctionCallbackReturnInt32 =
|
using CFunctionCallbackReturnInt32 =
|
||||||
int32_t (*)(v8::Local<v8::Object> unused,
|
int32_t (*)(v8::Local<v8::Value> receiver,
|
||||||
v8::Local<v8::Object> receiver,
|
v8::Local<v8::Value> input,
|
||||||
const v8::FastOneByteString& input,
|
|
||||||
// NOLINTNEXTLINE(runtime/references) This is V8 api.
|
// NOLINTNEXTLINE(runtime/references) This is V8 api.
|
||||||
v8::FastApiCallbackOptions& options);
|
v8::FastApiCallbackOptions& options);
|
||||||
using CFunctionCallbackValueReturnDouble =
|
using CFunctionCallbackValueReturnDouble =
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "aliased_buffer-inl.h"
|
#include "aliased_buffer-inl.h"
|
||||||
#include "memory_tracker-inl.h"
|
#include "memory_tracker-inl.h"
|
||||||
#include "node_buffer.h"
|
#include "node_buffer.h"
|
||||||
|
#include "node_debug.h"
|
||||||
#include "node_errors.h"
|
#include "node_errors.h"
|
||||||
#include "node_external_reference.h"
|
#include "node_external_reference.h"
|
||||||
#include "node_file-inl.h"
|
#include "node_file-inl.h"
|
||||||
@ -63,8 +64,6 @@ using v8::BigInt;
|
|||||||
using v8::Context;
|
using v8::Context;
|
||||||
using v8::EscapableHandleScope;
|
using v8::EscapableHandleScope;
|
||||||
using v8::FastApiCallbackOptions;
|
using v8::FastApiCallbackOptions;
|
||||||
using v8::FastOneByteString;
|
|
||||||
using v8::Function;
|
|
||||||
using v8::FunctionCallbackInfo;
|
using v8::FunctionCallbackInfo;
|
||||||
using v8::FunctionTemplate;
|
using v8::FunctionTemplate;
|
||||||
using v8::HandleScope;
|
using v8::HandleScope;
|
||||||
@ -1056,9 +1055,9 @@ static void ExistsSync(const FunctionCallbackInfo<Value>& args) {
|
|||||||
static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
|
static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
|
||||||
CHECK_GE(args.Length(), 2);
|
CHECK_EQ(args.Length(), 1);
|
||||||
CHECK(args[1]->IsString());
|
CHECK(args[0]->IsString());
|
||||||
BufferValue path(env->isolate(), args[1]);
|
BufferValue path(env->isolate(), args[0]);
|
||||||
CHECK_NOT_NULL(*path);
|
CHECK_NOT_NULL(*path);
|
||||||
ToNamespacedPath(env, &path);
|
ToNamespacedPath(env, &path);
|
||||||
|
|
||||||
@ -1074,15 +1073,17 @@ static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int32_t FastInternalModuleStat(
|
static int32_t FastInternalModuleStat(
|
||||||
Local<Object> unused,
|
Local<Value> recv,
|
||||||
Local<Object> recv,
|
Local<Value> input_,
|
||||||
const FastOneByteString& input,
|
|
||||||
// NOLINTNEXTLINE(runtime/references) This is V8 api.
|
// NOLINTNEXTLINE(runtime/references) This is V8 api.
|
||||||
FastApiCallbackOptions& options) {
|
FastApiCallbackOptions& options) {
|
||||||
Environment* env = Environment::GetCurrent(options.isolate);
|
TRACK_V8_FAST_API_CALL("fs.internalModuleStat");
|
||||||
HandleScope scope(env->isolate());
|
HandleScope scope(options.isolate);
|
||||||
|
|
||||||
auto path = std::filesystem::path(input.data, input.data + input.length);
|
CHECK(input_->IsString());
|
||||||
|
Utf8Value input(options.isolate, input_.As<String>());
|
||||||
|
|
||||||
|
auto path = std::filesystem::path(input.ToStringView());
|
||||||
|
|
||||||
switch (std::filesystem::status(path).type()) {
|
switch (std::filesystem::status(path).type()) {
|
||||||
case std::filesystem::file_type::directory:
|
case std::filesystem::file_type::directory:
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Flags: --expose-internals --permission --allow-fs-read=test/common* --allow-fs-read=tools* --allow-fs-read=test/parallel* --allow-child-process
|
// Flags: --expose-internals --permission --allow-fs-read=test/common* --allow-fs-read=tools* --allow-fs-read=test/parallel* --allow-child-process --allow-natives-syntax
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
const { isMainThread } = require('worker_threads');
|
const { isMainThread } = require('worker_threads');
|
||||||
|
const { strictEqual } = require('assert');
|
||||||
|
|
||||||
if (!isMainThread) {
|
if (!isMainThread) {
|
||||||
common.skip('This test only works on a main thread');
|
common.skip('This test only works on a main thread');
|
||||||
@ -18,9 +19,20 @@ const fixtures = require('../common/fixtures');
|
|||||||
const blockedFile = fixtures.path('permission', 'deny', 'protected-file.md');
|
const blockedFile = fixtures.path('permission', 'deny', 'protected-file.md');
|
||||||
const internalFsBinding = internalBinding('fs');
|
const internalFsBinding = internalBinding('fs');
|
||||||
|
|
||||||
// Run this inside a for loop to trigger the fast API
|
strictEqual(internalFsBinding.internalModuleStat(blockedFile), 0);
|
||||||
for (let i = 0; i < 10_000; i++) {
|
|
||||||
// internalModuleStat does not use permission model.
|
// Only javascript methods can be optimized through %OptimizeFunctionOnNextCall
|
||||||
// doesNotThrow
|
// This is why we surround the C++ method we want to optimize with a JS function.
|
||||||
internalFsBinding.internalModuleStat(internalFsBinding, blockedFile);
|
function testFastPaths(file) {
|
||||||
|
return internalFsBinding.internalModuleStat(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
eval('%PrepareFunctionForOptimization(testFastPaths)');
|
||||||
|
testFastPaths(blockedFile);
|
||||||
|
eval('%OptimizeFunctionOnNextCall(testFastPaths)');
|
||||||
|
strictEqual(testFastPaths(blockedFile), 0);
|
||||||
|
|
||||||
|
if (common.isDebug) {
|
||||||
|
const { getV8FastApiCallCount } = internalBinding('debug');
|
||||||
|
strictEqual(getV8FastApiCallCount('fs.internalModuleStat'), 1);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user