Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: refactor out some warnings from FillStatsArray and node_file.h #23793

Merged
merged 3 commits into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/internal/fs/watchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const errors = require('internal/errors');
const {
kFsStatsFieldsLength,
kFsStatsFieldsNumber,
StatWatcher: _StatWatcher
} = process.binding('fs');
const { FSEvent } = internalBinding('fs_event_wrap');
Expand Down Expand Up @@ -48,7 +48,7 @@ function onchange(newStatus, stats) {

self[kOldStatus] = newStatus;
self.emit('change', getStatsFromBinding(stats),
getStatsFromBinding(stats, kFsStatsFieldsLength));
getStatsFromBinding(stats, kFsStatsFieldsNumber));
}

// FIXME(joyeecheung): this method is not documented.
Expand Down
4 changes: 2 additions & 2 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ Environment::Environment(IsolateData* isolate_data,
trace_category_state_(isolate_, kTraceCategoryCount),
stream_base_state_(isolate_, StreamBase::kNumStreamBaseStateFields),
http_parser_buffer_(nullptr),
fs_stats_field_array_(isolate_, kFsStatsFieldsLength * 2),
fs_stats_field_bigint_array_(isolate_, kFsStatsFieldsLength * 2),
fs_stats_field_array_(isolate_, kFsStatsBufferLength),
fs_stats_field_bigint_array_(isolate_, kFsStatsBufferLength),
context_(context->GetIsolate(), context) {
// We'll be creating new objects so make sure we've entered the context.
v8::HandleScope handle_scope(isolate());
Expand Down
13 changes: 6 additions & 7 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,12 @@ struct PackageConfig {

// The number of items passed to push_values_to_array_function has diminishing
// returns around 8. This should be used at all call sites using said function.
#ifndef NODE_PUSH_VAL_TO_ARRAY_MAX
#define NODE_PUSH_VAL_TO_ARRAY_MAX 8
#endif
constexpr size_t NODE_PUSH_VAL_TO_ARRAY_MAX = 8;

// Stat fields buffers contain twice the number of entries in an uv_stat_t
// because `fs.StatWatcher` needs room to store 2 `fs.Stats` instances.
constexpr size_t kFsStatsFieldsNumber = 14;
constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;

// PER_ISOLATE_* macros: We have a lot of per-isolate properties
// and adding and maintaining their getters and setters by hand would be
Expand Down Expand Up @@ -710,10 +713,6 @@ class Environment {
inline AliasedBuffer<uint64_t, v8::BigUint64Array>*
fs_stats_field_bigint_array();

// stat fields contains twice the number of entries because `fs.StatWatcher`
// needs room to store data for *two* `fs.Stats` instances.
static const int kFsStatsFieldsLength = 14;

inline std::vector<std::unique_ptr<fs::FileHandleReadWrap>>&
file_handle_read_wrap_freelist();

Expand Down
18 changes: 9 additions & 9 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ void FSReqCallback::Reject(Local<Value> reject) {
}

void FSReqCallback::ResolveStat(const uv_stat_t* stat) {
Resolve(node::FillGlobalStatsArray(env(), stat, use_bigint()));
Resolve(FillGlobalStatsArray(env(), use_bigint(), stat));
}

void FSReqCallback::Resolve(Local<Value> value) {
Expand Down Expand Up @@ -949,8 +949,8 @@ static void Stat(const FunctionCallbackInfo<Value>& args) {
return; // error info is in ctx
}

Local<Value> arr = node::FillGlobalStatsArray(env,
static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr), use_bigint);
Local<Value> arr = FillGlobalStatsArray(env, use_bigint,
static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
args.GetReturnValue().Set(arr);
}
}
Expand Down Expand Up @@ -980,8 +980,8 @@ static void LStat(const FunctionCallbackInfo<Value>& args) {
return; // error info is in ctx
}

Local<Value> arr = node::FillGlobalStatsArray(env,
static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr), use_bigint);
Local<Value> arr = FillGlobalStatsArray(env, use_bigint,
static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
args.GetReturnValue().Set(arr);
}
}
Expand Down Expand Up @@ -1010,8 +1010,8 @@ static void FStat(const FunctionCallbackInfo<Value>& args) {
return; // error info is in ctx
}

Local<Value> arr = node::FillGlobalStatsArray(env,
static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr), use_bigint);
Local<Value> arr = FillGlobalStatsArray(env, use_bigint,
static_cast<const uv_stat_t*>(req_wrap_sync.req.ptr));
args.GetReturnValue().Set(arr);
}
}
Expand Down Expand Up @@ -2237,8 +2237,8 @@ void Initialize(Local<Object> target,
env->SetMethod(target, "mkdtemp", Mkdtemp);

target->Set(context,
FIXED_ONE_BYTE_STRING(isolate, "kFsStatsFieldsLength"),
Integer::New(isolate, env->kFsStatsFieldsLength))
FIXED_ONE_BYTE_STRING(isolate, "kFsStatsFieldsNumber"),
Integer::New(isolate, kFsStatsFieldsNumber))
.FromJust();

target->Set(context,
Expand Down
134 changes: 119 additions & 15 deletions src/node_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class FSContinuationData : public MemoryRetainer {

uv_fs_t* req;
int mode;
std::vector<std::string> paths;
std::vector<std::string> paths{};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ctor does not initialize paths"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like something we should address on the compiler side, rather than starting to fix up all of our code… it’s not like something bad is happening here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler can't tell if we want the default constructor or we forgot to initialize.
I'd rather be explicit, either here or in all the constructors.


void PushPath(std::string&& path) {
paths.emplace_back(std::move(path));
Expand Down Expand Up @@ -148,6 +148,92 @@ class FSReqCallback : public FSReqBase {
DISALLOW_COPY_AND_ASSIGN(FSReqCallback);
};

// Wordaround a GCC4.9 bug that C++14 N3652 was not implemented
// Refs: https://www.gnu.org/software/gcc/projects/cxx-status.html#cxx14
// Refs: https://isocpp.org/files/papers/N3652.html
#if __cpp_constexpr < 201304
# define constexpr inline
#endif

template <typename NativeT,
// SFINAE limit NativeT to arithmetic types
typename = std::enable_if<std::is_arithmetic<NativeT>::value>>
constexpr NativeT ToNative(uv_timespec_t ts) {
// This template has exactly two specializations below.
static_assert(std::is_arithmetic<NativeT>::value == false, "Not implemented");
UNREACHABLE();
}

template <>
constexpr double ToNative(uv_timespec_t ts) {
// We need to do a static_cast since the original FS values are ulong.
/* NOLINTNEXTLINE(runtime/int) */
const auto u_sec = static_cast<unsigned long>(ts.tv_sec);
const double full_sec = u_sec * 1000.0;
/* NOLINTNEXTLINE(runtime/int) */
const auto u_nsec = static_cast<unsigned long>(ts.tv_nsec);
const double full_nsec = u_nsec / 1000'000.0;
return full_sec + full_nsec;
}

template <>
constexpr uint64_t ToNative(uv_timespec_t ts) {
// We need to do a static_cast since the original FS values are ulong.
/* NOLINTNEXTLINE(runtime/int) */
const auto u_sec = static_cast<unsigned long>(ts.tv_sec);
const auto full_sec = static_cast<uint64_t>(u_sec) * 1000UL;
/* NOLINTNEXTLINE(runtime/int) */
const auto u_nsec = static_cast<unsigned long>(ts.tv_nsec);
const auto full_nsec = static_cast<uint64_t>(u_nsec) / 1000'000UL;
return full_sec + full_nsec;
}

#undef constexpr // end N3652 bug workaround

template <typename NativeT, typename V8T>
constexpr void FillStatsArray(AliasedBuffer<NativeT, V8T>* fields,
const uv_stat_t* s, const size_t offset = 0) {
fields->SetValue(offset + 0, s->st_dev);
fields->SetValue(offset + 1, s->st_mode);
fields->SetValue(offset + 2, s->st_nlink);
fields->SetValue(offset + 3, s->st_uid);
fields->SetValue(offset + 4, s->st_gid);
fields->SetValue(offset + 5, s->st_rdev);
#if defined(__POSIX__)
fields->SetValue(offset + 6, s->st_blksize);
#else
fields->SetValue(offset + 6, 0);
#endif
fields->SetValue(offset + 7, s->st_ino);
fields->SetValue(offset + 8, s->st_size);
#if defined(__POSIX__)
fields->SetValue(offset + 9, s->st_blocks);
#else
fields->SetValue(offset + 9, 0);
#endif
// Dates.
fields->SetValue(offset + 10, ToNative<NativeT>(s->st_atim));
fields->SetValue(offset + 11, ToNative<NativeT>(s->st_mtim));
fields->SetValue(offset + 12, ToNative<NativeT>(s->st_ctim));
fields->SetValue(offset + 13, ToNative<NativeT>(s->st_birthtim));
}

inline Local<Value> FillGlobalStatsArray(Environment* env,
const bool use_bigint,
const uv_stat_t* s,
const bool second = false) {
const ptrdiff_t offset = second ? kFsStatsFieldsNumber : 0;
if (use_bigint) {
auto* const arr = env->fs_stats_field_bigint_array();
FillStatsArray(arr, s, offset);
return arr->GetJSArray();
} else {
auto* const arr = env->fs_stats_field_array();
FillStatsArray(arr, s, offset);
return arr->GetJSArray();
}
}

template <typename NativeT = double, typename V8T = v8::Float64Array>
class FSReqPromise : public FSReqBase {
public:
Expand All @@ -157,10 +243,11 @@ class FSReqPromise : public FSReqBase {
->NewInstance(env->context()).ToLocalChecked(),
AsyncWrap::PROVIDER_FSREQPROMISE,
use_bigint),
stats_field_array_(env->isolate(), env->kFsStatsFieldsLength) {
auto resolver = Promise::Resolver::New(env->context()).ToLocalChecked();
object()->Set(env->context(), env->promise_string(),
resolver).FromJust();
stats_field_array_(env->isolate(), kFsStatsFieldsNumber) {
const auto resolver =
Promise::Resolver::New(env->context()).ToLocalChecked();
USE(object()->Set(env->context(), env->promise_string(),
resolver).FromJust());
}

~FSReqPromise() override {
Expand All @@ -176,7 +263,7 @@ class FSReqPromise : public FSReqBase {
object()->Get(env()->context(),
env()->promise_string()).ToLocalChecked();
Local<Promise::Resolver> resolver = value.As<Promise::Resolver>();
resolver->Reject(env()->context(), reject).FromJust();
USE(resolver->Reject(env()->context(), reject).FromJust());
}

void Resolve(Local<Value> value) override {
Expand All @@ -187,11 +274,12 @@ class FSReqPromise : public FSReqBase {
object()->Get(env()->context(),
env()->promise_string()).ToLocalChecked();
Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
resolver->Resolve(env()->context(), value).FromJust();
USE(resolver->Resolve(env()->context(), value).FromJust());
}

void ResolveStat(const uv_stat_t* stat) override {
Resolve(node::FillStatsArray(&stats_field_array_, stat));
FillStatsArray(&stats_field_array_, stat);
Resolve(stats_field_array_.GetJSArray());
}

void SetReturnValue(const FunctionCallbackInfo<Value>& args) override {
Expand All @@ -210,10 +298,14 @@ class FSReqPromise : public FSReqBase {
SET_MEMORY_INFO_NAME(FSReqPromise)
SET_SELF_SIZE(FSReqPromise)

FSReqPromise(const FSReqPromise&) = delete;
FSReqPromise& operator=(const FSReqPromise&) = delete;
FSReqPromise(const FSReqPromise&&) = delete;
FSReqPromise& operator=(const FSReqPromise&&) = delete;

private:
bool finished_ = false;
AliasedBuffer<NativeT, V8T> stats_field_array_;
DISALLOW_COPY_AND_ASSIGN(FSReqPromise);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain these changes? If we are getting warnings here, we might want to revert 97f1e94 instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It's a MACRO
  2. It in private
  3. Does not delete the moves

Copy link
Member

@joyeecheung joyeecheung Oct 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to use a macro if it reduces repetition, and it's also easier to search..about deleting move constructor&operator, why not just add another macro? (oops, I know)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The move variants are implicitly deleted, according to #23092

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I'm in favor being explicit over less-code-via-macros.

As for the move semantics, they are not generated, but are left undefined so it's a clang-tidy error, since the compiler can't say what we ment (not implement or forgot to implement).

#23092 is sort of Ok, since the MACRO is named DISALLOW_COPY_AND_ASSIGN not DISALLOW_COPY_AND_ASSIGN_AND_MOVE

P.S. C++20 might solve this with metaclasses

};

class FSReqAfterScope {
Expand All @@ -225,6 +317,11 @@ class FSReqAfterScope {

void Reject(uv_fs_t* req);

FSReqAfterScope(const FSReqAfterScope&) = delete;
FSReqAfterScope& operator=(const FSReqAfterScope&) = delete;
FSReqAfterScope(const FSReqAfterScope&&) = delete;
FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete;

private:
FSReqBase* wrap_ = nullptr;
uv_fs_t* req_ = nullptr;
Expand Down Expand Up @@ -301,6 +398,11 @@ class FileHandle : public AsyncWrap, public StreamBase {
SET_MEMORY_INFO_NAME(FileHandle)
SET_SELF_SIZE(FileHandle)

FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
FileHandle(const FileHandle&&) = delete;
FileHandle& operator=(const FileHandle&&) = delete;

private:
// Synchronous close that emits a warning
void Close();
Expand All @@ -319,7 +421,7 @@ class FileHandle : public AsyncWrap, public StreamBase {
ref_.Reset(env->isolate(), ref);
}

~CloseReq() {
~CloseReq() override {
uv_fs_req_cleanup(req());
promise_.Reset();
ref_.Reset();
Expand All @@ -343,9 +445,14 @@ class FileHandle : public AsyncWrap, public StreamBase {
return static_cast<CloseReq*>(ReqWrap::from_req(req));
}

CloseReq(const CloseReq&) = delete;
CloseReq& operator=(const CloseReq&) = delete;
CloseReq(const CloseReq&&) = delete;
CloseReq& operator=(const CloseReq&&) = delete;

private:
Persistent<Promise> promise_;
Persistent<Value> ref_;
Persistent<Promise> promise_{};
Persistent<Value> ref_{};
};

// Asynchronous close
Expand All @@ -359,9 +466,6 @@ class FileHandle : public AsyncWrap, public StreamBase {

bool reading_ = false;
std::unique_ptr<FileHandleReadWrap> current_read_ = nullptr;


DISALLOW_COPY_AND_ASSIGN(FileHandle);
};

} // namespace fs
Expand Down
52 changes: 0 additions & 52 deletions src/node_internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "uv.h"
#include "v8.h"
#include "tracing/trace_event.h"
#include "node_perf_common.h"
#include "node_api.h"

#include <stdint.h>
Expand Down Expand Up @@ -308,57 +307,6 @@ v8::Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
const char* warning,
const char* deprecation_code);

template <typename NativeT, typename V8T>
v8::Local<v8::Value> FillStatsArray(AliasedBuffer<NativeT, V8T>* fields_ptr,
const uv_stat_t* s, int offset = 0) {
AliasedBuffer<NativeT, V8T>& fields = *fields_ptr;
fields[offset + 0] = s->st_dev;
fields[offset + 1] = s->st_mode;
fields[offset + 2] = s->st_nlink;
fields[offset + 3] = s->st_uid;
fields[offset + 4] = s->st_gid;
fields[offset + 5] = s->st_rdev;
#if defined(__POSIX__)
fields[offset + 6] = s->st_blksize;
#else
fields[offset + 6] = 0;
#endif
fields[offset + 7] = s->st_ino;
fields[offset + 8] = s->st_size;
#if defined(__POSIX__)
fields[offset + 9] = s->st_blocks;
#else
fields[offset + 9] = 0;
#endif
// Dates.
// NO-LINT because the fields are 'long' and we just want to cast to `unsigned`
#define X(idx, name) \
/* NOLINTNEXTLINE(runtime/int) */ \
fields[offset + idx] = ((unsigned long)(s->st_##name.tv_sec) * 1e3) + \
/* NOLINTNEXTLINE(runtime/int) */ \
((unsigned long)(s->st_##name.tv_nsec) / 1e6); \

X(10, atim)
X(11, mtim)
X(12, ctim)
X(13, birthtim)
#undef X

return fields_ptr->GetJSArray();
}

inline v8::Local<v8::Value> FillGlobalStatsArray(Environment* env,
const uv_stat_t* s,
bool use_bigint = false,
int offset = 0) {
if (use_bigint) {
return node::FillStatsArray(
env->fs_stats_field_bigint_array(), s, offset);
} else {
return node::FillStatsArray(env->fs_stats_field_array(), s, offset);
}
}

void SetupBootstrapObject(Environment* env,
v8::Local<v8::Object> bootstrapper);
void SetupProcessObject(Environment* env,
Expand Down
Loading