src: prefer v8::Global over node::Persistent

`v8::Global` is essentially a nicer variant of `node::Persistent` that,
in addition to reset-on-destroy, also implements move semantics.

This commit makes the necessary replacements, removes
`node::Persistent` and (now-)unnecessary inclusions of the
`node_persistent.h` header, and makes some of the functions that
take Persistents as arguments more generic so that they work with all
`v8::PersistentBase` flavours.

PR-URL: https://github.com/nodejs/node/pull/27287
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Anna Henningsen 2019-04-17 23:16:22 +02:00
parent 095bd569ae
commit 723d5c058f
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9
23 changed files with 81 additions and 106 deletions

View File

@ -606,7 +606,6 @@
'src/node_options-inl.h', 'src/node_options-inl.h',
'src/node_perf.h', 'src/node_perf.h',
'src/node_perf_common.h', 'src/node_perf_common.h',
'src/node_persistent.h',
'src/node_platform.h', 'src/node_platform.h',
'src/node_process.h', 'src/node_process.h',
'src/node_revert.h', 'src/node_revert.h',

View File

@ -35,6 +35,7 @@ using v8::EscapableHandleScope;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope; using v8::HandleScope;
using v8::Integer; using v8::Integer;
using v8::Isolate; using v8::Isolate;
@ -346,8 +347,8 @@ class DestroyParam {
public: public:
double asyncId; double asyncId;
Environment* env; Environment* env;
Persistent<Object> target; Global<Object> target;
Persistent<Object> propBag; Global<Object> propBag;
}; };
void AsyncWrap::WeakCallback(const WeakCallbackInfo<DestroyParam>& info) { void AsyncWrap::WeakCallback(const WeakCallbackInfo<DestroyParam>& info) {

View File

@ -56,7 +56,7 @@ BaseObject::~BaseObject() {
} }
Persistent<v8::Object>& BaseObject::persistent() { v8::Global<v8::Object>& BaseObject::persistent() {
return persistent_handle_; return persistent_handle_;
} }

View File

@ -24,7 +24,6 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "node_persistent.h"
#include "memory_tracker-inl.h" #include "memory_tracker-inl.h"
#include "v8.h" #include "v8.h"
#include <type_traits> // std::remove_reference #include <type_traits> // std::remove_reference
@ -50,7 +49,7 @@ class BaseObject : public MemoryRetainer {
// is associated with the passed Isolate in debug mode. // is associated with the passed Isolate in debug mode.
inline v8::Local<v8::Object> object(v8::Isolate* isolate) const; inline v8::Local<v8::Object> object(v8::Isolate* isolate) const;
inline Persistent<v8::Object>& persistent(); inline v8::Global<v8::Object>& persistent();
inline Environment* env() const; inline Environment* env() const;
@ -62,7 +61,7 @@ class BaseObject : public MemoryRetainer {
template <typename T> template <typename T>
static inline T* FromJSObject(v8::Local<v8::Object> object); static inline T* FromJSObject(v8::Local<v8::Object> object);
// Make the `Persistent` a weak reference and, `delete` this object once // Make the `v8::Global` a weak reference and, `delete` this object once
// the JS object has been garbage collected. // the JS object has been garbage collected.
inline void MakeWeak(); inline void MakeWeak();
@ -96,7 +95,7 @@ class BaseObject : public MemoryRetainer {
friend int GenDebugSymbols(); friend int GenDebugSymbols();
friend class CleanupHookCallback; friend class CleanupHookCallback;
Persistent<v8::Object> persistent_handle_; v8::Global<v8::Object> persistent_handle_;
Environment* env_; Environment* env_;
}; };

View File

@ -929,7 +929,7 @@ class Environment : public MemoryRetainer {
std::unordered_map<uint32_t, contextify::ContextifyScript*> std::unordered_map<uint32_t, contextify::ContextifyScript*>
id_to_script_map; id_to_script_map;
std::unordered_set<CompileFnEntry*> compile_fn_entries; std::unordered_set<CompileFnEntry*> compile_fn_entries;
std::unordered_map<uint32_t, Persistent<v8::Function>> id_to_function_map; std::unordered_map<uint32_t, v8::Global<v8::Function>> id_to_function_map;
inline uint32_t get_next_module_id(); inline uint32_t get_next_module_id();
inline uint32_t get_next_script_id(); inline uint32_t get_next_script_id();
@ -1292,7 +1292,7 @@ class Environment : public MemoryRetainer {
template <typename T> template <typename T>
void ForEachBaseObject(T&& iterator); void ForEachBaseObject(T&& iterator);
#define V(PropertyName, TypeName) Persistent<TypeName> PropertyName ## _; #define V(PropertyName, TypeName) v8::Global<TypeName> PropertyName ## _;
ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
#undef V #undef V

View File

@ -8,6 +8,7 @@ using v8::EmbedderGraph;
using v8::EscapableHandleScope; using v8::EscapableHandleScope;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope; using v8::HandleScope;
using v8::HeapSnapshot; using v8::HeapSnapshot;
using v8::Isolate; using v8::Isolate;
@ -56,7 +57,7 @@ class JSGraphJSNode : public EmbedderGraph::Node {
}; };
private: private:
Persistent<Value> persistent_; Global<Value> persistent_;
}; };
class JSGraph : public EmbedderGraph { class JSGraph : public EmbedderGraph {

View File

@ -34,6 +34,7 @@ using node::FatalError;
using v8::Context; using v8::Context;
using v8::Function; using v8::Function;
using v8::Global;
using v8::HandleScope; using v8::HandleScope;
using v8::Isolate; using v8::Isolate;
using v8::Local; using v8::Local;
@ -834,7 +835,7 @@ void Agent::DisableAsyncHook() {
} }
void Agent::ToggleAsyncHook(Isolate* isolate, void Agent::ToggleAsyncHook(Isolate* isolate,
const node::Persistent<Function>& fn) { const Global<Function>& fn) {
CHECK(parent_env_->has_run_bootstrapping_code()); CHECK(parent_env_->has_run_bootstrapping_code());
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
CHECK(!fn.IsEmpty()); CHECK(!fn.IsEmpty());

View File

@ -7,7 +7,6 @@
#endif #endif
#include "node_options-inl.h" #include "node_options-inl.h"
#include "node_persistent.h"
#include "v8.h" #include "v8.h"
#include <cstddef> #include <cstddef>
@ -114,7 +113,7 @@ class Agent {
private: private:
void ToggleAsyncHook(v8::Isolate* isolate, void ToggleAsyncHook(v8::Isolate* isolate,
const node::Persistent<v8::Function>& fn); const v8::Global<v8::Function>& fn);
node::Environment* parent_env_; node::Environment* parent_env_;
// Encapsulates majority of the Inspector functionality // Encapsulates majority of the Inspector functionality
@ -133,8 +132,8 @@ class Agent {
bool pending_enable_async_hook_ = false; bool pending_enable_async_hook_ = false;
bool pending_disable_async_hook_ = false; bool pending_disable_async_hook_ = false;
node::Persistent<v8::Function> enable_async_hook_function_; v8::Global<v8::Function> enable_async_hook_function_;
node::Persistent<v8::Function> disable_async_hook_function_; v8::Global<v8::Function> disable_async_hook_function_;
}; };
} // namespace inspector } // namespace inspector

View File

@ -15,6 +15,7 @@ using v8::Context;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope; using v8::HandleScope;
using v8::Isolate; using v8::Isolate;
using v8::Local; using v8::Local;
@ -116,7 +117,7 @@ class JSBindingsConnection : public AsyncWrap {
private: private:
std::unique_ptr<InspectorSession> session_; std::unique_ptr<InspectorSession> session_;
Persistent<Function> callback_; Global<Function> callback_;
}; };
static bool InspectorEnabled(Environment* env) { static bool InspectorEnabled(Environment* env) {

View File

@ -29,7 +29,7 @@
namespace v8impl { namespace v8impl {
template <typename T> template <typename T>
using Persistent = node::Persistent<T>; using Persistent = v8::Global<T>;
using PersistentToLocal = node::PersistentToLocal; using PersistentToLocal = node::PersistentToLocal;

View File

@ -184,9 +184,9 @@ void MemoryTracker::TrackField(const char* edge_name,
TrackField(edge_name, value.Get(isolate_)); TrackField(edge_name, value.Get(isolate_));
} }
template <typename T, typename Traits> template <typename T>
void MemoryTracker::TrackField(const char* edge_name, void MemoryTracker::TrackField(const char* edge_name,
const v8::Persistent<T, Traits>& value, const v8::PersistentBase<T>& value,
const char* node_name) { const char* node_name) {
TrackField(edge_name, value.Get(isolate_)); TrackField(edge_name, value.Get(isolate_));
} }

View File

@ -90,9 +90,9 @@ class CleanupHookCallback;
* NonPointerRetainerClass non_pointer_retainer; * NonPointerRetainerClass non_pointer_retainer;
* InternalClass internal_member_; * InternalClass internal_member_;
* std::vector<uv_async_t> vector_; * std::vector<uv_async_t> vector_;
* node::Persistent<Object> target_; * v8::Global<Object> target_;
* *
* node::Persistent<Object> wrapped_; * v8::Global<Object> wrapped_;
* } * }
* *
* This creates the following graph: * This creates the following graph:
@ -185,9 +185,9 @@ class MemoryTracker {
void TrackField(const char* edge_name, void TrackField(const char* edge_name,
const v8::Eternal<T>& value, const v8::Eternal<T>& value,
const char* node_name); const char* node_name);
template <typename T, typename Traits> template <typename T>
inline void TrackField(const char* edge_name, inline void TrackField(const char* edge_name,
const v8::Persistent<T, Traits>& value, const v8::PersistentBase<T>& value,
const char* node_name = nullptr); const char* node_name = nullptr);
template <typename T> template <typename T>
inline void TrackField(const char* edge_name, inline void TrackField(const char* edge_name,

View File

@ -25,6 +25,7 @@ using v8::Context;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope; using v8::HandleScope;
using v8::Integer; using v8::Integer;
using v8::IntegrityLevel; using v8::IntegrityLevel;
@ -611,7 +612,7 @@ Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
env->exports_string()).ToLocal(&exports_v) && env->exports_string()).ToLocal(&exports_v) &&
(exports_v->IsObject() || exports_v->IsString() || (exports_v->IsObject() || exports_v->IsString() ||
exports_v->IsBoolean())) { exports_v->IsBoolean())) {
Persistent<Value> exports; Global<Value> exports;
exports.Reset(env->isolate(), exports_v); exports.Reset(env->isolate(), exports_v);
auto entry = env->package_json_cache.emplace(path, auto entry = env->package_json_cache.emplace(path,

View File

@ -75,11 +75,11 @@ class ModuleWrap : public BaseObject {
v8::Local<v8::Module> referrer); v8::Local<v8::Module> referrer);
static ModuleWrap* GetFromModule(node::Environment*, v8::Local<v8::Module>); static ModuleWrap* GetFromModule(node::Environment*, v8::Local<v8::Module>);
Persistent<v8::Module> module_; v8::Global<v8::Module> module_;
Persistent<v8::String> url_; v8::Global<v8::String> url_;
bool linked_ = false; bool linked_ = false;
std::unordered_map<std::string, Persistent<v8::Promise>> resolve_cache_; std::unordered_map<std::string, v8::Global<v8::Promise>> resolve_cache_;
Persistent<v8::Context> context_; v8::Global<v8::Context> context_;
uint32_t id_; uint32_t id_;
}; };

View File

@ -62,6 +62,7 @@ using v8::ArrayBufferView;
using v8::Context; using v8::Context;
using v8::EscapableHandleScope; using v8::EscapableHandleScope;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::Global;
using v8::Integer; using v8::Integer;
using v8::Isolate; using v8::Isolate;
using v8::Just; using v8::Just;
@ -99,7 +100,7 @@ class CallbackInfo {
FreeCallback callback, FreeCallback callback,
char* data, char* data,
void* hint); void* hint);
Persistent<ArrayBuffer> persistent_; Global<ArrayBuffer> persistent_;
FreeCallback const callback_; FreeCallback const callback_;
char* const data_; char* const data_;
void* const hint_; void* const hint_;

View File

@ -100,7 +100,7 @@ class ContextifyContext {
uint32_t index, uint32_t index,
const v8::PropertyCallbackInfo<v8::Boolean>& args); const v8::PropertyCallbackInfo<v8::Boolean>& args);
Environment* const env_; Environment* const env_;
Persistent<v8::Context> context_; v8::Global<v8::Context> context_;
}; };
class ContextifyScript : public BaseObject { class ContextifyScript : public BaseObject {
@ -129,7 +129,7 @@ class ContextifyScript : public BaseObject {
inline uint32_t id() { return id_; } inline uint32_t id() { return id_; }
private: private:
node::Persistent<v8::UnboundScript> script_; v8::Global<v8::UnboundScript> script_;
uint32_t id_; uint32_t id_;
}; };

View File

@ -321,8 +321,8 @@ class SSLWrap {
ClientHelloParser hello_parser_; ClientHelloParser hello_parser_;
Persistent<v8::ArrayBufferView> ocsp_response_; v8::Global<v8::ArrayBufferView> ocsp_response_;
Persistent<v8::Value> sni_context_; v8::Global<v8::Value> sni_context_;
friend class SecureContext; friend class SecureContext;
}; };

View File

@ -451,8 +451,8 @@ class FileHandle : public AsyncWrap, public StreamBase {
CloseReq& operator=(const CloseReq&&) = delete; CloseReq& operator=(const CloseReq&&) = delete;
private: private:
Persistent<Promise> promise_{}; v8::Global<Promise> promise_{};
Persistent<Value> ref_{}; v8::Global<Value> ref_{};
}; };
// Asynchronous close // Asynchronous close

View File

@ -28,7 +28,6 @@
#include "node.h" #include "node.h"
#include "node_binding.h" #include "node_binding.h"
#include "node_mutex.h" #include "node_mutex.h"
#include "node_persistent.h"
#include "tracing/trace_event.h" #include "tracing/trace_event.h"
#include "util-inl.h" #include "util-inl.h"
#include "uv.h" #include "uv.h"

View File

@ -1,66 +0,0 @@
#ifndef SRC_NODE_PERSISTENT_H_
#define SRC_NODE_PERSISTENT_H_
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "v8.h"
namespace node {
template <typename T>
struct ResetInDestructorPersistentTraits {
static const bool kResetInDestructor = true;
template <typename S, typename M>
// Disallow copy semantics by leaving this unimplemented.
inline static void Copy(
const v8::Persistent<S, M>&,
v8::Persistent<T, ResetInDestructorPersistentTraits<T>>*);
};
// v8::Persistent does not reset the object slot in its destructor. That is
// acknowledged as a flaw in the V8 API and expected to change in the future
// but for now node::Persistent is the easier and safer alternative.
template <typename T>
using Persistent = v8::Persistent<T, ResetInDestructorPersistentTraits<T>>;
class PersistentToLocal {
public:
// If persistent.IsWeak() == false, then do not call persistent.Reset()
// while the returned Local<T> is still in scope, it will destroy the
// reference to the object.
template <class TypeName>
static inline v8::Local<TypeName> Default(
v8::Isolate* isolate,
const Persistent<TypeName>& persistent) {
if (persistent.IsWeak()) {
return PersistentToLocal::Weak(isolate, persistent);
} else {
return PersistentToLocal::Strong(persistent);
}
}
// Unchecked conversion from a non-weak Persistent<T> to Local<T>,
// use with care!
//
// Do not call persistent.Reset() while the returned Local<T> is still in
// scope, it will destroy the reference to the object.
template <class TypeName>
static inline v8::Local<TypeName> Strong(
const Persistent<TypeName>& persistent) {
return *reinterpret_cast<v8::Local<TypeName>*>(
const_cast<Persistent<TypeName>*>(&persistent));
}
template <class TypeName>
static inline v8::Local<TypeName> Weak(
v8::Isolate* isolate,
const Persistent<TypeName>& persistent) {
return v8::Local<TypeName>::New(isolate, persistent);
}
};
} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif // SRC_NODE_PERSISTENT_H_

View File

@ -13,6 +13,7 @@ using v8::Context;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
using v8::Global;
using v8::IndexFilter; using v8::IndexFilter;
using v8::Integer; using v8::Integer;
using v8::Isolate; using v8::Isolate;
@ -189,7 +190,7 @@ class WeakReference : public BaseObject {
SET_NO_MEMORY_INFO() SET_NO_MEMORY_INFO()
private: private:
Persistent<Object> target_; Global<Object> target_;
}; };
static void GuessHandleType(const FunctionCallbackInfo<Value>& args) { static void GuessHandleType(const FunctionCallbackInfo<Value>& args) {

View File

@ -47,6 +47,7 @@ using v8::Context;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope; using v8::HandleScope;
using v8::Int32; using v8::Int32;
using v8::Integer; using v8::Integer;
@ -526,7 +527,7 @@ class CompressionStream : public AsyncWrap, public ThreadPoolWork {
bool closed_ = false; bool closed_ = false;
unsigned int refs_ = 0; unsigned int refs_ = 0;
uint32_t* write_result_ = nullptr; uint32_t* write_result_ = nullptr;
Persistent<Function> write_js_callback_; Global<Function> write_js_callback_;
std::atomic<ssize_t> unreported_allocations_{0}; std::atomic<ssize_t> unreported_allocations_{0};
size_t zlib_memory_ = 0; size_t zlib_memory_ = 0;

View File

@ -24,7 +24,6 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "node_persistent.h"
#include "v8.h" #include "v8.h"
#include <cassert> #include <cassert>
@ -669,6 +668,44 @@ class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0); const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
}; };
// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
// optimization for strong persistent handles.
class PersistentToLocal {
public:
// If persistent.IsWeak() == false, then do not call persistent.Reset()
// while the returned Local<T> is still in scope, it will destroy the
// reference to the object.
template <class TypeName>
static inline v8::Local<TypeName> Default(
v8::Isolate* isolate,
const v8::PersistentBase<TypeName>& persistent) {
if (persistent.IsWeak()) {
return PersistentToLocal::Weak(isolate, persistent);
} else {
return PersistentToLocal::Strong(persistent);
}
}
// Unchecked conversion from a non-weak Persistent<T> to Local<T>,
// use with care!
//
// Do not call persistent.Reset() while the returned Local<T> is still in
// scope, it will destroy the reference to the object.
template <class TypeName>
static inline v8::Local<TypeName> Strong(
const v8::PersistentBase<TypeName>& persistent) {
return *reinterpret_cast<v8::Local<TypeName>*>(
const_cast<v8::PersistentBase<TypeName>*>(&persistent));
}
template <class TypeName>
static inline v8::Local<TypeName> Weak(
v8::Isolate* isolate,
const v8::PersistentBase<TypeName>& persistent) {
return v8::Local<TypeName>::New(isolate, persistent);
}
};
} // namespace node } // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS